diff --git a/Icon-64.png b/Icon-64.png new file mode 100644 index 0000000..cd98bee Binary files /dev/null and b/Icon-64.png differ diff --git a/Info.plist b/Info.plist new file mode 100644 index 0000000..2091c7c --- /dev/null +++ b/Info.plist @@ -0,0 +1,81 @@ + + + + + Author + Bountysource + Builder Version + 11601.7.7 + CFBundleDisplayName + Bountysource + CFBundleIdentifier + com.bountysource.safari-extension + CFBundleInfoDictionaryVersion + 6.0 + CFBundleShortVersionString + 0.0.14 + CFBundleVersion + 1 + Chrome + + Database Quota + 1048576 + Global Page + global.html + Toolbar Items + + + Command + show_popover + Identifier + bountysource-button + Image + data/images/thumbsup-16.png + Include By Default + + Label + 👍 + Palette Label + Bountysource exstension + + + + Content + + Scripts + + End + + data/get_safari_cookie.js + data/thumbs.js + + Start + + data/bountysource_client.js + + + Stylesheets + + data/stylesheets/thumbs.css + + + Description + Bountysource Browser Extension + DeveloperIdentifier + 0000000000 + ExtensionInfoDictionaryVersion + 1.0 + Permissions + + Website Access + + Include Secure Pages + + Level + All + + + Website + https://www.bountysource.com + + diff --git a/data/bountysource_client.js b/data/bountysource_client.js index 1223c41..0bdd5ba 100644 --- a/data/bountysource_client.js +++ b/data/bountysource_client.js @@ -1,6 +1,6 @@ // Cross-browser helpers to be used in popups and content-scripts var BountysourceClient = { - browser: typeof(chrome)!=='undefined' ? 'chrome' : 'firefox', + browser: typeof(chrome)!=='undefined' ? 'chrome' : typeof(safari)!=='undefined' ? 'safari' : 'firefox', // Computes path to extension hosted image imagePath: function(image) { @@ -8,6 +8,8 @@ var BountysourceClient = { return chrome.extension.getURL('data/images/' + image); } else if (self && self.options && self.options.image_base) { return self.options.image_base + image; + } else if (window.safari) { + return safari.extension.baseURI + 'data/images/' + image; } }, @@ -26,6 +28,30 @@ var BountysourceClient = { options.callback_str = "callback_" + (new Date()).getTime(); self.port.once(options.callback_str, callback); self.port.emit("message", options); + } else if (BountysourceClient.browser === 'safari') { + // Check if is sending from popover or normal page + if (safari.self.tab) { + // Is normal page + // Equivalent code of self.port.once + options.callback_str = "callback_" + (new Date()).getTime(); + var handler = function(event) { + if (event.name === options.callback_str) { + callback(event.message); + safari.self.removeEventListener('message', handler); + } + } + safari.self.addEventListener('message', handler, false); + safari.self.tab.dispatchMessage('message', options); + } else { + // Is popover + var BountysourceServer = safari.extension.globalPage.contentWindow.BountysourceServer; + BountysourceServer.get_access_token(function(access_token) { + options.access_token = access_token; + options.callback = callback; + + BountysourceServer[options.action](options); + }); + } } }, diff --git a/data/get_safari_cookie.js b/data/get_safari_cookie.js new file mode 100644 index 0000000..add318c --- /dev/null +++ b/data/get_safari_cookie.js @@ -0,0 +1,3 @@ +if (document.location.host === 'www.bountysource.com') { + safari.self.tab.dispatchMessage('cookie', document.cookie); +} \ No newline at end of file diff --git a/data/popup/application.js b/data/popup/application.js index aca52ab..bd4ed52 100644 --- a/data/popup/application.js +++ b/data/popup/application.js @@ -5,6 +5,8 @@ var BountysourcePopup = { BountysourcePopup.setupTabHandlers(); BountysourcePopup.setupFeedbackForm(); BountysourcePopup.loadThumbs(); + BountysourcePopup.setupLinks(); + BountysourcePopup.setupForms(); }, loadCurrentPerson: function() { @@ -122,6 +124,7 @@ var BountysourcePopup = { document.querySelector('#thumbs-message-none').classList.remove('hide'); } + BountysourcePopup.setupLinks(); BountysourcePopup.resizePopup(); }); }, @@ -183,6 +186,24 @@ var BountysourcePopup = { document.querySelector('#feedback-form').classList.add('hide'); BountysourcePopup.resizePopup(); }); + }, + + setupLinks: function() { + if ((typeof(safari) !== 'undefined')) { + var links = document.querySelectorAll('a[target="_blank"]'); + for (var i = 0; i < links.length; i++) { + links[i].removeAttribute('target'); + } + } + }, + + setupForms: function() { + if ((typeof(safari) !== 'undefined')) { + var links = document.querySelectorAll('form[target="_blank"]'); + for (var i = 0; i < links.length; i++) { + links[i].removeAttribute('target'); + } + } } }; diff --git a/data/popup/loader.js b/data/popup/loader.js index 18f5161..885be5a 100644 --- a/data/popup/loader.js +++ b/data/popup/loader.js @@ -3,7 +3,7 @@ (function() { var scripts = ['../bountysource_client.js', 'application.js']; - if (typeof(chrome) !== 'undefined') { + if (typeof(chrome) !== 'undefined' || typeof(safari) !== 'undefined') { for (var i=0; i < scripts.length; i++) { var script_tag = document.createElement('script'); script_tag.src = scripts[i]; diff --git a/global.html b/global.html new file mode 100644 index 0000000..9ceedda --- /dev/null +++ b/global.html @@ -0,0 +1,9 @@ + + + + global HTML page + + + + + \ No newline at end of file diff --git a/lib/bountysource_server.js b/lib/bountysource_server.js index 39bc55d..ad13fc4 100644 --- a/lib/bountysource_server.js +++ b/lib/bountysource_server.js @@ -9,7 +9,7 @@ if (typeof(localStorage) === 'undefined') { // global functions var BountysourceServer = { - browser: typeof(chrome)!=='undefined' ? 'chrome' : 'firefox', + browser: typeof(chrome)!=='undefined' ? 'chrome' : typeof(safari)!=='undefined' ? 'safari' : 'firefox', www_base: 'https://www.bountysource.com/', api_base: 'https://api.bountysource.com/', @@ -64,6 +64,24 @@ var BountysourceServer = { }); } }); + } else if (BountysourceServer.browser === 'safari') { + safari.application.addEventListener('message', function(event) { + if (event.name === 'message') { + BountysourceServer.get_access_token(function(access_token) { + var options = event.message; + options.access_token = access_token; + + // turn callback_str into function + options.callback = function(response) { + event.target.page.dispatchMessage(options.callback_str, response); + }; + + BountysourceServer[options.action](options); + }); + } else if (event.name === 'cookie') { + localStorage['safari_cookie'] = event.message; + } + }, false); } }, @@ -123,6 +141,26 @@ var BountysourceServer = { } } }); + } else if (BountysourceServer.browser === 'safari') { + safari.application.addEventListener('command', function(event) { + if (event.command === 'show_popover') { + var button; + for (var i = 0; i < safari.extension.toolbarItems.length; i++) { + if (safari.extension.toolbarItems[i].identifier === 'bountysource-button') { + button = safari.extension.toolbarItems[i]; + } + } + if (button.popover) { + button.popover.hide(); + button.popover = null; + safari.extension.removePopover('bountysource-popover'); + } + + popover = safari.extension.createPopover('bountysource-popover', safari.extension.baseURI + 'data/popup/application.html', 420); + button.popover = popover; + button.showPopover(); + } + }, false); } }, @@ -195,15 +233,9 @@ var BountysourceServer = { var cookieUri = ios.newURI(BountysourceServer.www_base, null, null); var cookieSvc = ff_chrome.components.classes["@mozilla.org/cookieService;1"].getService(ff_chrome.components.interfaces.nsICookieService); var cookie = cookieSvc.getCookieString(cookieUri, null); - var cookies = (cookie || '').split('; '); - for (var i=0; i < cookies.length; i++) { - var regex_match = cookies[i].match(/^v2_access_token=(.*)$/); - if (regex_match) { - callback(JSON.parse(decodeURIComponent(regex_match[1]))); - return; - } - } - callback(null); + callback(BountysourceServer.get_access_token_from_cookie(cookie)); + } else if (BountysourceServer.browser === 'safari') { + callback(BountysourceServer.get_access_token_from_cookie(localStorage['safari_cookie'] || null)); } }, @@ -261,6 +293,17 @@ var BountysourceServer = { }); xhr.open('GET', path, true); xhr.send(); + }, + + get_access_token_from_cookie: function(cookie) { + var cookies = (cookie || '').split('; '); + for (var i=0; i < cookies.length; i++) { + var regex_match = cookies[i].match(/^v2_access_token=(.*)$/); + if (regex_match) { + return JSON.parse(decodeURIComponent(regex_match[1])); + } + } + return null; } };