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;
}
};