From a9e2da83ef9127fce2acd33f27d82ffbdcc2698e Mon Sep 17 00:00:00 2001 From: Ellis Tsung Date: Wed, 24 Jan 2018 16:15:45 -0500 Subject: [PATCH] Fix #88, catch up to 1.14.24 Use vAPI.getURL to filter details.file in vAPI.tabs.injectScript. Also moved some scripts around. --- platform/safari/Info.plist | 2 + platform/safari/vapi-background.js | 263 +-------------------------- platform/safari/vapi-cachestorage.js | 191 +++++++++++++++++++ platform/safari/vapi-client.js | 5 + platform/safari/vapi-common.js | 3 + platform/safari/vapi-webrequest.js | 114 ++++++++++++ tools/make-safari.sh | 9 +- 7 files changed, 324 insertions(+), 263 deletions(-) create mode 100644 platform/safari/vapi-cachestorage.js create mode 100644 platform/safari/vapi-webrequest.js diff --git a/platform/safari/Info.plist b/platform/safari/Info.plist index 069d8bd839c80..134f25237e438 100644 --- a/platform/safari/Info.plist +++ b/platform/safari/Info.plist @@ -6,6 +6,8 @@ Chris Aljoudi/Raymond Hill Builder Version 534.57.2 + DeveloperIdentifier + 3NU33NW2M3 CFBundleDisplayName {name} CFBundleIdentifier diff --git a/platform/safari/vapi-background.js b/platform/safari/vapi-background.js index ed798baaafce2..72a055f35f385 100644 --- a/platform/safari/vapi-background.js +++ b/platform/safari/vapi-background.js @@ -81,155 +81,6 @@ safari.extension.settings.addEventListener('change', function(e) { } }, false); -/******************************************************************************/ - -initStorageLib(); // Initialize storage library - -/******************************************************************************/ - -var storageQuota = 104857600; // copied from Info.plist -localforage.config({ - name: 'ublock', - size: storageQuota, - storeName: 'keyvaluepairs' -}); - -vAPI.cacheStorage = { - QUOTA_BYTES: storageQuota, // copied from Info.plist - - get: function(keys, callback) { - if ( typeof callback !== 'function' ) { - return; - } - - var result = {}; - - if ( keys === null ) { - localforage.iterate(function(value, key) { - if ( typeof value === 'string' ) { - result[key] = JSON.parse(value); - } - }, function() { - callback(result); - }); - } else if ( typeof keys === 'string' ) { - localforage.getItem(keys, function(err, value) { - if ( typeof value === 'string' ) { - result[keys] = JSON.parse(value); - } - callback(result); - }); - } else if ( Array.isArray(keys) ) { - var toSatisfy = keys.length, n = toSatisfy; - if ( n === 0 ) { - callback(result); - return; - } - var key; - for ( var i = 0; i < n; i++ ) { - key = keys[i]; - localforage.getItem(key, (function(key) { - return function(err, value) { - toSatisfy--; - if ( typeof value === 'string' ) { - result[key] = JSON.parse(value); - } - if ( toSatisfy === 0 ) { - callback(result); - } - } - })(key)); - } - } else if ( typeof keys === 'object' ) { - for ( var key in keys ) { - if ( !keys.hasOwnProperty(key) ) { - continue; - } - result[key] = keys[key]; - } - localforage.iterate(function(value, key) { - if ( !keys.hasOwnProperty(key) ) return; - if ( typeof value === 'string' ) { - result[key] = JSON.parse(value); - } - }, function() { - callback(result); - }); - } - }, - - set: function(details, callback) { - var key, toSatisfy = 0; - for ( key in details ) { - if ( !details.hasOwnProperty(key) ) { - continue; - } - toSatisfy++; - } - if ( toSatisfy === 0 ) { - // Nothing to set - callback && callback(); - return; - } - var callbackCaller = function() { - if ( --toSatisfy === 0 ) { - callback && callback(); - } - }; - for ( key in details ) { - if ( !details.hasOwnProperty(key) ) { - continue; - } - localforage.setItem(key, JSON.stringify(details[key]), callbackCaller); - } - }, - - remove: function(keys) { - if ( typeof keys === 'string' ) { - keys = [keys]; - } - - for ( var i = 0, n = keys.length; i < n; i++ ) { - localforage.removeItem(keys[i]); - } - }, - - clear: function(callback) { - localforage.clear(function() { - typeof callback === 'function' && callback(); - }); - }, - - getBytesInUse: function(keys, callback) { - if ( typeof callback !== 'function' ) { - return; - } - var size = 0; - if ( Array.isArray(keys) ) { - var toSatisfy = keys.length, n = toSatisfy; - if ( n === 0 ) { - callback(0); - return; - } - var callbackCaller = function(err, value) { - size += (value || '').length; - if ( --toSatisfy === 0 ) { - callback(size); - } - }; - for ( var i = 0; i < n; i++ ) { - localforage.getItem(keys[i], callbackCaller); - } - } else { - localforage.iterate(function(value, key) { - size += (value || '').length; - }, function() { - callback(size); - }); - } - } -}; - vAPI.storage = { _storage: safari.extension.settings, get: function(keys, callback) { @@ -538,6 +389,7 @@ vAPI.tabs.injectScript = function(tabId, details, callback) { } if ( details.file ) { + details.file = vAPI.getURL(details.file) var xhr = new XMLHttpRequest(); xhr.open('GET', details.file, true); xhr.addEventListener('readystatechange', function() { @@ -986,106 +838,6 @@ vAPI.messaging.broadcast = function(message) { /******************************************************************************/ -vAPI.net = {}; - -/******************************************************************************/ - -// Fast `contains` - -Array.prototype.contains = function(a) { - var b = this.length; - while ( b-- ) { - if ( this[b] === a ) { - return true; - } - } - return false; -}; - -/******************************************************************************/ - -vAPI.net.registerListeners = function() { - var µb = µBlock; - - // Until Safari has more specific events, those are instead handled - // in the onBeforeRequestAdapter; clean them up so they're garbage-collected - vAPI.net.onBeforeSendHeaders = null; - - var onBeforeRequest = vAPI.net.onBeforeRequest, - onBeforeRequestClient = onBeforeRequest.callback, - onHeadersReceivedClient = vAPI.net.onHeadersReceived.callback; - - // https://github.com/el1t/uBlock-Safari/issues/32 - // Ignore directives - var shouldBlockResponseHeader = { - script: /script-src/, - worker: /child-src/ - }; - - var onBeforeRequestAdapter = function(e) { - if ( e.name !== 'canLoad' ) { - return; - } - e.stopPropagation && e.stopPropagation(); - switch ( e.message.type ) { - case 'main_frame': - vAPI.tabs.onNavigation({ - url: e.message.url, - frameId: 0, - tabId: vAPI.tabs.getTabId(e.target).toString() - }); - e.message.hostname = µb.URI.hostnameFromURI(e.message.url); - e.message.tabId = vAPI.tabs.getTabId(e.target); - e.message.responseHeaders = []; - onBeforeRequestClient(e.message); - var blockVerdict = onHeadersReceivedClient(e.message); - blockVerdict = blockVerdict && blockVerdict.responseHeaders && blockVerdict.responseHeaders[0] && - shouldBlockResponseHeader.script.test(blockVerdict.responseHeaders[0].value); - e.message = { - shouldBlock: blockVerdict === true - }; - return; - case 'popup': - var openerTabId = vAPI.tabs.getTabId(e.target).toString(); - var shouldBlock = !!vAPI.tabs.onPopupUpdated('preempt', openerTabId, e.message.url); - if ( !shouldBlock ) { - vAPI.tabs.popupCandidate = openerTabId; - } - e.message = { - shouldBlock: shouldBlock - }; - break; - case 'popstate': - // No return value/message - vAPI.tabs.onUpdated(vAPI.tabs.getTabId(e.target), { - url: e.message.url - }, { - url: e.message.url - }); - break; - case 'worker': - e.message.type = 'sub_frame'; - e.message.hostname = µb.URI.hostnameFromURI(e.message.url); - e.message.tabId = vAPI.tabs.getTabId(e.target); - e.message.responseHeaders = []; - var blockVerdict = onHeadersReceivedClient(e.message); - blockVerdict = blockVerdict && blockVerdict.responseHeaders && blockVerdict.responseHeaders[0] && - shouldBlockResponseHeader.worker.test(blockVerdict.responseHeaders[0].value); - e.message = { - shouldBlock: blockVerdict === true - } - return; - default: - e.message.hostname = µb.URI.hostnameFromURI(e.message.url); - e.message.tabId = vAPI.tabs.getTabId(e.target); - var blockVerdict = onBeforeRequestClient(e.message) || {}; - blockVerdict.shouldBlock = blockVerdict.cancel === true || blockVerdict.redirectUrl !== undefined; - e.message = blockVerdict; - return; - } - }; - safari.application.addEventListener('message', onBeforeRequestAdapter, true); -}; /******************************************************************************/ @@ -1214,17 +966,4 @@ vAPI.adminStorage = { } }; -/******************************************************************************/ -/******************************************************************************/ - -function initStorageLib() { - /*! - localForage -- Offline Storage, Improved - Version 1.4.3 - https://localforage.github.io/localForage - (c) 2013-2016 Mozilla, Apache License 2.0 - */ - !function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.localforage=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=43)}}).catch(function(){return!1})}function n(a){return"boolean"==typeof ga?ia.resolve(ga):m(a).then(function(a){return ga=a})}function o(a){var b=ha[a.name],c={};c.promise=new ia(function(a){c.resolve=a}),b.deferredOperations.push(c),b.dbReady?b.dbReady=b.dbReady.then(function(){return c.promise}):b.dbReady=c.promise}function p(a){var b=ha[a.name],c=b.deferredOperations.pop();c&&c.resolve()}function q(a,b){return new ia(function(c,d){if(a.db){if(!b)return c(a.db);o(a),a.db.close()}var e=[a.name];b&&e.push(a.version);var f=fa.open.apply(fa,e);b&&(f.onupgradeneeded=function(b){var c=f.result;try{c.createObjectStore(a.storeName),b.oldVersion<=1&&c.createObjectStore(ja)}catch(c){if("ConstraintError"!==c.name)throw c;console.warn('The database "'+a.name+'" has been upgraded from version '+b.oldVersion+" to version "+b.newVersion+', but the storage "'+a.storeName+'" already exists.')}}),f.onerror=function(){d(f.error)},f.onsuccess=function(){c(f.result),p(a)}})}function r(a){return q(a,!1)}function s(a){return q(a,!0)}function t(a,b){if(!a.db)return!0;var c=!a.db.objectStoreNames.contains(a.storeName),d=a.versiona.db.version;if(d&&(a.version!==b&&console.warn('The database "'+a.name+"\" can't be downgraded from version "+a.db.version+" to version "+a.version+"."),a.version=a.db.version),e||c){if(c){var f=a.db.version+1;f>a.version&&(a.version=f)}return!0}return!1}function u(a){return new ia(function(b,c){var d=new FileReader;d.onerror=c,d.onloadend=function(c){var d=btoa(c.target.result||"");b({__local_forage_encoded_blob:!0,data:d,type:a.type})},d.readAsBinaryString(a)})}function v(a){var b=l(atob(a.data));return i([b],{type:a.type})}function w(a){return a&&a.__local_forage_encoded_blob}function x(a){var b=this,c=b._initReady().then(function(){var a=ha[b._dbInfo.name];if(a&&a.dbReady)return a.dbReady});return k(c,a,a),c}function y(a){function b(){return ia.resolve()}var c=this,d={db:null};if(a)for(var e in a)d[e]=a[e];ha||(ha={});var f=ha[d.name];f||(f={forages:[],db:null,dbReady:null,deferredOperations:[]},ha[d.name]=f),f.forages.push(c),c._initReady||(c._initReady=c.ready,c.ready=x);for(var g=[],h=0;h>4,k[i++]=(15&d)<<4|e>>2,k[i++]=(3&e)<<6|63&f;return j}function I(a){var b,c=new Uint8Array(a),d="";for(b=0;b>2],d+=ma[(3&c[b])<<4|c[b+1]>>4],d+=ma[(15&c[b+1])<<2|c[b+2]>>6],d+=ma[63&c[b+2]];return c.length%3===2?d=d.substring(0,d.length-1)+"=":c.length%3===1&&(d=d.substring(0,d.length-2)+"=="),d}function J(a,b){var c="";if(a&&(c=Da.call(a)),a&&("[object ArrayBuffer]"===c||a.buffer&&"[object ArrayBuffer]"===Da.call(a.buffer))){var d,e=pa;a instanceof ArrayBuffer?(d=a,e+=ra):(d=a.buffer,"[object Int8Array]"===c?e+=ta:"[object Uint8Array]"===c?e+=ua:"[object Uint8ClampedArray]"===c?e+=va:"[object Int16Array]"===c?e+=wa:"[object Uint16Array]"===c?e+=ya:"[object Int32Array]"===c?e+=xa:"[object Uint32Array]"===c?e+=za:"[object Float32Array]"===c?e+=Aa:"[object Float64Array]"===c?e+=Ba:b(new Error("Failed to get type for BinaryArray"))),b(e+I(d))}else if("[object Blob]"===c){var f=new FileReader;f.onload=function(){var c=na+a.type+"~"+I(this.result);b(pa+sa+c)},f.readAsArrayBuffer(a)}else try{b(JSON.stringify(a))}catch(c){console.error("Couldn't convert value into a JSON string: ",a),b(null,c)}}function K(a){if(a.substring(0,qa)!==pa)return JSON.parse(a);var b,c=a.substring(Ca),d=a.substring(qa,Ca);if(d===sa&&oa.test(c)){var e=c.match(oa);b=e[1],c=c.substring(e[0].length)}var f=H(c);switch(d){case ra:return f;case sa:return i([f],{type:b});case ta:return new Int8Array(f);case ua:return new Uint8Array(f);case va:return new Uint8ClampedArray(f);case wa:return new Int16Array(f);case ya:return new Uint16Array(f);case xa:return new Int32Array(f);case za:return new Uint32Array(f);case Aa:return new Float32Array(f);case Ba:return new Float64Array(f);default:throw new Error("Unkown type: "+d)}}function L(a){var b=this,c={db:null};if(a)for(var d in a)c[d]="string"!=typeof a[d]?a[d].toString():a[d];var e=new ia(function(a,d){try{c.db=openDatabase(c.name,String(c.version),c.description,c.size)}catch(a){return d(a)}c.db.transaction(function(e){e.executeSql("CREATE TABLE IF NOT EXISTS "+c.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],function(){b._dbInfo=c,a()},function(a,b){d(b)})})});return c.serializer=Ea,e}function M(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new ia(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName+" WHERE key = ? LIMIT 1",[a],function(a,c){var d=c.rows.length?c.rows.item(0).value:null;d&&(d=e.serializer.deserialize(d)),b(d)},function(a,b){d(b)})})}).catch(d)});return j(d,b),d}function N(a,b){var c=this,d=new ia(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName,[],function(c,d){for(var f=d.rows,g=f.length,h=0;h=0;c--){var d=localStorage.key(c);0===d.indexOf(a)&&localStorage.removeItem(d)}});return j(c,a),c}function W(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=c.ready().then(function(){var b=c._dbInfo,d=localStorage.getItem(b.keyPrefix+a);return d&&(d=b.serializer.deserialize(d)),d});return j(d,b),d}function X(a,b){var c=this,d=c.ready().then(function(){for(var b=c._dbInfo,d=b.keyPrefix,e=d.length,f=localStorage.length,g=1,h=0;h=43)}}).catch(function(){return!1})}function n(a){return"boolean"==typeof ga?ia.resolve(ga):m(a).then(function(a){return ga=a})}function o(a){var b=ha[a.name],c={};c.promise=new ia(function(a){c.resolve=a}),b.deferredOperations.push(c),b.dbReady?b.dbReady=b.dbReady.then(function(){return c.promise}):b.dbReady=c.promise}function p(a){var b=ha[a.name],c=b.deferredOperations.pop();c&&c.resolve()}function q(a,b){return new ia(function(c,d){if(a.db){if(!b)return c(a.db);o(a),a.db.close()}var e=[a.name];b&&e.push(a.version);var f=fa.open.apply(fa,e);b&&(f.onupgradeneeded=function(b){var c=f.result;try{c.createObjectStore(a.storeName),b.oldVersion<=1&&c.createObjectStore(ja)}catch(c){if("ConstraintError"!==c.name)throw c;console.warn('The database "'+a.name+'" has been upgraded from version '+b.oldVersion+" to version "+b.newVersion+', but the storage "'+a.storeName+'" already exists.')}}),f.onerror=function(){d(f.error)},f.onsuccess=function(){c(f.result),p(a)}})}function r(a){return q(a,!1)}function s(a){return q(a,!0)}function t(a,b){if(!a.db)return!0;var c=!a.db.objectStoreNames.contains(a.storeName),d=a.versiona.db.version;if(d&&(a.version!==b&&console.warn('The database "'+a.name+"\" can't be downgraded from version "+a.db.version+" to version "+a.version+"."),a.version=a.db.version),e||c){if(c){var f=a.db.version+1;f>a.version&&(a.version=f)}return!0}return!1}function u(a){return new ia(function(b,c){var d=new FileReader;d.onerror=c,d.onloadend=function(c){var d=btoa(c.target.result||"");b({__local_forage_encoded_blob:!0,data:d,type:a.type})},d.readAsBinaryString(a)})}function v(a){var b=l(atob(a.data));return i([b],{type:a.type})}function w(a){return a&&a.__local_forage_encoded_blob}function x(a){var b=this,c=b._initReady().then(function(){var a=ha[b._dbInfo.name];if(a&&a.dbReady)return a.dbReady});return k(c,a,a),c}function y(a){function b(){return ia.resolve()}var c=this,d={db:null};if(a)for(var e in a)d[e]=a[e];ha||(ha={});var f=ha[d.name];f||(f={forages:[],db:null,dbReady:null,deferredOperations:[]},ha[d.name]=f),f.forages.push(c),c._initReady||(c._initReady=c.ready,c.ready=x);for(var g=[],h=0;h>4,k[i++]=(15&d)<<4|e>>2,k[i++]=(3&e)<<6|63&f;return j}function I(a){var b,c=new Uint8Array(a),d="";for(b=0;b>2],d+=ma[(3&c[b])<<4|c[b+1]>>4],d+=ma[(15&c[b+1])<<2|c[b+2]>>6],d+=ma[63&c[b+2]];return c.length%3===2?d=d.substring(0,d.length-1)+"=":c.length%3===1&&(d=d.substring(0,d.length-2)+"=="),d}function J(a,b){var c="";if(a&&(c=Da.call(a)),a&&("[object ArrayBuffer]"===c||a.buffer&&"[object ArrayBuffer]"===Da.call(a.buffer))){var d,e=pa;a instanceof ArrayBuffer?(d=a,e+=ra):(d=a.buffer,"[object Int8Array]"===c?e+=ta:"[object Uint8Array]"===c?e+=ua:"[object Uint8ClampedArray]"===c?e+=va:"[object Int16Array]"===c?e+=wa:"[object Uint16Array]"===c?e+=ya:"[object Int32Array]"===c?e+=xa:"[object Uint32Array]"===c?e+=za:"[object Float32Array]"===c?e+=Aa:"[object Float64Array]"===c?e+=Ba:b(new Error("Failed to get type for BinaryArray"))),b(e+I(d))}else if("[object Blob]"===c){var f=new FileReader;f.onload=function(){var c=na+a.type+"~"+I(this.result);b(pa+sa+c)},f.readAsArrayBuffer(a)}else try{b(JSON.stringify(a))}catch(c){console.error("Couldn't convert value into a JSON string: ",a),b(null,c)}}function K(a){if(a.substring(0,qa)!==pa)return JSON.parse(a);var b,c=a.substring(Ca),d=a.substring(qa,Ca);if(d===sa&&oa.test(c)){var e=c.match(oa);b=e[1],c=c.substring(e[0].length)}var f=H(c);switch(d){case ra:return f;case sa:return i([f],{type:b});case ta:return new Int8Array(f);case ua:return new Uint8Array(f);case va:return new Uint8ClampedArray(f);case wa:return new Int16Array(f);case ya:return new Uint16Array(f);case xa:return new Int32Array(f);case za:return new Uint32Array(f);case Aa:return new Float32Array(f);case Ba:return new Float64Array(f);default:throw new Error("Unkown type: "+d)}}function L(a){var b=this,c={db:null};if(a)for(var d in a)c[d]="string"!=typeof a[d]?a[d].toString():a[d];var e=new ia(function(a,d){try{c.db=openDatabase(c.name,String(c.version),c.description,c.size)}catch(a){return d(a)}c.db.transaction(function(e){e.executeSql("CREATE TABLE IF NOT EXISTS "+c.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],function(){b._dbInfo=c,a()},function(a,b){d(b)})})});return c.serializer=Ea,e}function M(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new ia(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName+" WHERE key = ? LIMIT 1",[a],function(a,c){var d=c.rows.length?c.rows.item(0).value:null;d&&(d=e.serializer.deserialize(d)),b(d)},function(a,b){d(b)})})}).catch(d)});return j(d,b),d}function N(a,b){var c=this,d=new ia(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName,[],function(c,d){for(var f=d.rows,g=f.length,h=0;h=0;c--){var d=localStorage.key(c);0===d.indexOf(a)&&localStorage.removeItem(d)}});return j(c,a),c}function W(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=c.ready().then(function(){var b=c._dbInfo,d=localStorage.getItem(b.keyPrefix+a);return d&&(d=b.serializer.deserialize(d)),d});return j(d,b),d}function X(a,b){var c=this,d=c.ready().then(function(){for(var b=c._dbInfo,d=b.keyPrefix,e=d.length,f=localStorage.length,g=1,h=0;h /tmp/contentscript.js +echo >> /tmp/contentscript.js +grep -v "^'use strict';$" $DES/js/contentscript.js >> /tmp/contentscript.js +mv /tmp/contentscript.js $DES/js/contentscript.js +echo ' ✔' # https://github.com/el1t/uBlock-Safari/issues/4 echo -n '*** uBlock0.safariextension: Adding extensions to extensionless assets...'