Use HTML5 download instead of extension API

Benefits:
- Cross browser solution (however only for relatively new browsers)
- Doesn't need extra permission in Chrome

If the browser doesn't suppor the download attribute, then a new tab will
be opened with the exported data.

Other changes:
- Start the download only if the data is not empty (previously the
  download started anyway)
- Reorder code in vapi-client.js for Safari, so unnecessary code doesn't
  run on extension pages
This commit is contained in:
Deathamns 2014-10-20 19:05:12 +02:00
parent 2e787d8541
commit fbffc5b07e
7 changed files with 133 additions and 101 deletions

View File

@ -21,7 +21,6 @@
"permissions": [ "permissions": [
"contextMenus", "contextMenus",
"downloads",
"storage", "storage",
"tabs", "tabs",
"unlimitedStorage", "unlimitedStorage",

View File

@ -99,11 +99,14 @@ var startImportFilePicker = function() {
/******************************************************************************/ /******************************************************************************/
function exportUserFiltersToFile() { function exportUserFiltersToFile() {
chrome.downloads.download({ var val = uDom('#userFilters').val().trim();
'url': 'data:text/plain,' + encodeURIComponent(uDom('#userFilters').val()),
'filename': 'my-ublock-filters.txt', if (val) {
'saveAs': true vAPI.download({
}); 'url': 'data:text/plain,' + encodeURIComponent(val),
'filename': 'my-ublock-filters.txt'
});
}
} }
/******************************************************************************/ /******************************************************************************/

View File

@ -34,11 +34,14 @@ var messager = vAPI.messaging.channel('about.js');
var exportToFile = function() { var exportToFile = function() {
var onUserDataReady = function(userData) { var onUserDataReady = function(userData) {
chrome.downloads.download({ if (!userData) {
return;
}
vAPI.download({
'url': 'data:text/plain,' + encodeURIComponent(JSON.stringify(userData)), 'url': 'data:text/plain,' + encodeURIComponent(JSON.stringify(userData)),
'filename': 'ublock-backup.txt', 'filename': 'ublock-backup.txt'
'saveAs': true });
});
}; };
messager.send({ what: 'getUserData' }, onUserDataReady); messager.send({ what: 'getUserData' }, onUserDataReady);

View File

@ -95,6 +95,88 @@ if (window.chrome) {
} }
}; };
} else if (window.safari) { } else if (window.safari) {
// relevant?
// https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/MessagesandProxies/MessagesandProxies.html#//apple_ref/doc/uid/TP40009977-CH14-SW12
vAPI.messaging = {
requestId: 0,
listeners: {},
channels: {},
connector: messagingConnector,
setup: function() {
this._connector = function(msg) {
vAPI.messaging.connector(msg.message);
};
safari.self.addEventListener('message', this._connector, false);
this.channels['vAPI'] = {
listener: function(msg) {
if (msg.cmd === 'runScript' && msg.details.code) {
Function(msg.details.code).call(window);
}
}
};
},
close: function() {
if (this._connector) {
safari.self.removeEventListener('message', this._connector, false);
this.channels = this.listeners = null;
}
},
channel: function(name, callback) {
if (!name) {
return;
}
if (!this._connector) {
this.setup();
}
this.channels[name] = {
portName: name,
listener: typeof callback === 'function' ? callback : null,
send: function(message, callback) {
message = {
portName: this.portName,
msg: message
};
if (callback) {
message.requestId = ++vAPI.messaging.requestId;
vAPI.messaging.listeners[message.requestId] = callback;
}
if (safari.extension.globalPage) {
// popover content doesn't know messaging...
safari.extension.globalPage.contentWindow
.vAPI.messaging.connector({
name: 'message',
message: message,
target: {
page: {
dispatchMessage: function(name, msg) {
vAPI.messaging.connector(msg);
}
}
}
});
}
else {
safari.self.tab.dispatchMessage('message', message);
}
},
close: function() {
delete vAPI.messaging.channels[this.portName];
}
};
return this.channels[name];
}
};
if (location.protocol === "safari-extension:") {
return;
}
var linkHelper = document.createElement('a'); var linkHelper = document.createElement('a');
var onBeforeLoad = function(e, details) { var onBeforeLoad = function(e, details) {
if (e.url && e.url.slice(0, 5) === 'data:') { if (e.url && e.url.slice(0, 5) === 'data:') {
@ -176,12 +258,10 @@ if (window.chrome) {
} }
}; };
document.addEventListener('beforeload', onBeforeLoad, true);
// intercepting xhr requests // intercepting xhr requests
setTimeout(function() { setTimeout(function() {
if (location.protocol === "safari-extension:") {
return;
}
var randomEventName = parseInt(Math.random() * 1e15, 10).toString(36); var randomEventName = parseInt(Math.random() * 1e15, 10).toString(36);
var beforeLoadEvent = document.createEvent('Event'); var beforeLoadEvent = document.createEvent('Event');
beforeLoadEvent.initEvent('beforeload'); beforeLoadEvent.initEvent('beforeload');
@ -225,86 +305,6 @@ if (window.chrome) {
"})();"].join('')); "})();"].join(''));
}, 0); }, 0);
document.addEventListener('beforeload', onBeforeLoad, true);
// relevant?
// https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/MessagesandProxies/MessagesandProxies.html#//apple_ref/doc/uid/TP40009977-CH14-SW12
vAPI.messaging = {
requestId: 0,
listeners: {},
channels: {},
connector: messagingConnector,
setup: function() {
this._connector = function(msg) {
vAPI.messaging.connector(msg.message);
};
safari.self.addEventListener('message', this._connector, false);
this.channels['vAPI'] = {
listener: function(msg) {
if (msg.cmd === 'runScript' && msg.details.code) {
Function(msg.details.code).call(window);
}
}
};
},
close: function() {
if (this._connector) {
safari.self.removeEventListener('message', this._connector, false);
this.channels = this.listeners = null;
}
},
channel: function(name, callback) {
if (!name) {
return;
}
if (!this._connector) {
this.setup();
}
this.channels[name] = {
portName: name,
listener: typeof callback === 'function' ? callback : null,
send: function(message, callback) {
message = {
portName: this.portName,
msg: message
};
if (callback) {
message.requestId = ++vAPI.messaging.requestId;
vAPI.messaging.listeners[message.requestId] = callback;
}
if (safari.extension.globalPage) {
// popover content doesn't know messaging...
safari.extension.globalPage.contentWindow
.vAPI.messaging.connector({
name: 'message',
message: message,
target: {
page: {
dispatchMessage: function(name, msg) {
vAPI.messaging.connector(msg);
}
}
}
});
}
else {
safari.self.tab.dispatchMessage('message', message);
}
},
close: function() {
delete vAPI.messaging.channels[this.portName];
}
};
return this.channels[name];
}
};
var onContextMenu = function(e) { var onContextMenu = function(e) {
var details = { var details = {
tagName: e.target.tagName.toLowerCase(), tagName: e.target.tagName.toLowerCase(),

View File

@ -1,10 +1,35 @@
// only for background and other extension pages // could be used for background and other extension pages
(function() { (function() {
'use strict'; 'use strict';
window.vAPI = window.vAPI || {}; window.vAPI = window.vAPI || {};
vAPI.download = function(details) {
if (!details.url) {
return;
}
var a = document.createElement('a');
if ('download' in a) {
a.href = details.url;
a.setAttribute('download', details.filename || '');
a.dispatchEvent(new MouseEvent('click'));
}
else {
var messager = vAPI.messaging.channel('download');
messager.send({
what: 'gotoURL',
details: {
url: a.target.href,
index: -1
}
});
messager.close();
}
};
if (window.chrome) { if (window.chrome) {
var chrome = window.chrome; var chrome = window.chrome;

View File

@ -93,11 +93,14 @@ var startImportFilePicker = function() {
/******************************************************************************/ /******************************************************************************/
var exportWhitelistToFile = function() { var exportWhitelistToFile = function() {
chrome.downloads.download({ var val = uDom('#whitelist').val().trim();
'url': 'data:text/plain,' + encodeURIComponent(uDom('#whitelist').val()),
'filename': 'my-ublock-whitelist.txt', if (val) {
'saveAs': true vAPI.download({
}); 'url': 'data:text/plain,' + encodeURIComponent(val),
'filename': 'my-ublock-whitelist.txt'
});
}
}; };
/******************************************************************************/ /******************************************************************************/

View File

@ -21,7 +21,6 @@
"permissions": [ "permissions": [
"contextMenus", "contextMenus",
"downloads",
"storage", "storage",
"tabs", "tabs",
"unlimitedStorage", "unlimitedStorage",