From ce7dc1b42253360d78cf0335ab780f5cad845332 Mon Sep 17 00:00:00 2001 From: kkapsner Date: Mon, 4 Dec 2017 00:26:26 +0100 Subject: [PATCH] Only force setting loading when necessary May help for #160. --- lib/frame.js | 21 ++---------- lib/intercept.js | 87 ++++++++++++++++++++++++++++++++++++++++++++++-- lib/main.js | 3 +- lib/settings.js | 15 +++++++++ 4 files changed, 103 insertions(+), 23 deletions(-) diff --git a/lib/frame.js b/lib/frame.js index f536ca3..6eadb05 100644 --- a/lib/frame.js +++ b/lib/frame.js @@ -5,7 +5,7 @@ "use strict"; const settings = require("./settings"); - const {intercept} = require("./intercept.js"); + const {preIntercept: intercept} = require("./intercept.js"); const {ask} = require("./askForPermission.js"); const lists = require("./lists.js"); const {check: originalCheck, checkStack: originalCheckStack} = require("./check.js"); @@ -163,22 +163,5 @@ } }); - // need to wait for the settings to arrive! - while (settings.isStillDefault){ - logging.message("Starting synchronous request to wait for settings."); - try { - let xhr = new XMLHttpRequest(); - xhr.open("GET", "https://[::]", false); - xhr.send(); - xhr = null; - } - catch (e){ - logging.verbose("Error in XHR:", e); - } - logging.message("settings still default?", settings.isStillDefault); - } - - settings.onloaded(function(){ - interceptWindow(window); - }); + interceptWindow(window); }()); \ No newline at end of file diff --git a/lib/intercept.js b/lib/intercept.js index 5755e85..a792bd2 100644 --- a/lib/intercept.js +++ b/lib/intercept.js @@ -17,6 +17,7 @@ const randomSupplies = require("./randomSupplies"); const getWrapped = require("sdk/getWrapped"); const logging = require("./logging"); + const settings = require("./settings"); setRandomSupply(randomSupplies.nonPersistent); var apiNames = Object.keys(changedFunctions); @@ -59,6 +60,83 @@ return window.location.href; } + scope.preIntercept = function preIntercept({subject: window}, apis){ + if (!settings.isStillDefault){ + scope.intercept({subject: window}, apis); + } + else { + let preIntercepted = false; + let intercepted = false; + const forEachFunction = function(callback){ + apiNames.forEach(function(name){ + const changedFunction = changedFunctions[name]; + ( + Array.isArray(changedFunction.object)? + changedFunction.object: + [changedFunction.object] + ).forEach(function(object){ + var constructor = getWrapped(window)[object]; + if (constructor){ + callback({name, changedFunction, constructor}); + } + }); + }); + }; + let originalPropertyDescriptors = {}; + const doPreIntercept = function(){ + if (!preIntercepted){ + forEachFunction(function({name, constructor}){ + var map = originalPropertyDescriptors[name] || new WeakMap(); + originalPropertyDescriptors[name] = map; + map.set(constructor, Object.getOwnPropertyDescriptor(constructor.prototype, name)); + Object.defineProperty( + constructor.prototype, + name, + { + enumerable: true, + configureable: true, + get: exportFunction(function(){ + undoPreIntercept(); + settings.forceLoad(); + doRealIntercept(); + var descriptor = Object.getOwnPropertyDescriptor(constructor.prototype, name); + return descriptor.value || descriptor.get(); + }, window), + set: exportFunction(function(){}, window) + } + ); + }); + preIntercepted = true; + } + }; + const undoPreIntercept = function(){ + if (preIntercepted){ + preIntercepted = false; + forEachFunction(function({name, constructor}){ + Object.defineProperty( + constructor.prototype, + name, + originalPropertyDescriptors[name].get(constructor) + ); + }); + } + }; + const doRealIntercept = function(){ + if (!intercepted){ + scope.intercept({subject: window}, apis); + intercepted = true; + } + }; + + logging.verbose("pre intercept until settings are loaded"); + doPreIntercept(); + settings.onloaded(function(){ + undoPreIntercept(); + doRealIntercept(); + }); + } + }; + scope.intercept = function intercept({subject: window}, {check, checkStack, ask, notify, prefs}){ var siteStatus = check({url: getURL(window)}); logging.verbose("status for page", window, siteStatus); @@ -82,7 +160,7 @@ name, { enumerable: true, - configureable: false, + configureable: true, get: exportFunction(function(){ var url = getURL(window); if (!url){ @@ -158,7 +236,12 @@ Object.defineProperty( constructor.prototype, name, - {value} + { + value, + writable: true, + configurable: true, + enumerable: true + } ); }, window) } diff --git a/lib/main.js b/lib/main.js index 61f89fa..e18d2ac 100644 --- a/lib/main.js +++ b/lib/main.js @@ -105,9 +105,8 @@ js: [{ code: `(function(){ const settings = require("./settings"); - console.log(settings.init(${JSON.stringify(data)})); + settings.init(${JSON.stringify(data)}); }())` - // code: "(function(){const settings = require(\"./settings\");console.log(settings);}());" }] }).then(function(api){ logging.verbose("Content script registered."); diff --git a/lib/settings.js b/lib/settings.js index 599a9cc..36258e1 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -590,5 +590,20 @@ callback(); } }; + scope.forceLoad = function(){ + while (settings.isStillDefault){ + logging.message("Starting synchronous request to wait for settings."); + try { + let xhr = new XMLHttpRequest(); + xhr.open("GET", "https://[::]", false); + xhr.send(); + xhr = null; + } + catch (e){ + logging.verbose("Error in XHR:", e); + } + logging.message("settings still default?", settings.isStillDefault); + } + }; Object.seal(scope); }()); \ No newline at end of file