2016-02-13 12:28:36 +01:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
(function(){
|
|
|
|
"use strict";
|
|
|
|
|
2017-06-25 22:22:17 +02:00
|
|
|
var scope;
|
|
|
|
if ((typeof exports) !== "undefined"){
|
|
|
|
scope = exports;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
window.scope.intercept = {};
|
|
|
|
scope = window.scope.intercept;
|
|
|
|
}
|
|
|
|
|
2016-08-06 19:17:36 +02:00
|
|
|
const {changedFunctions, setRandomSupply} = require("./modifiedAPI");
|
|
|
|
const randomSupplies = require("./randomSupplies");
|
2017-10-07 23:26:04 +02:00
|
|
|
const getWrapped = require("sdk/getWrapped");
|
2017-11-07 00:36:44 +01:00
|
|
|
const logging = require("./logging");
|
2017-12-04 00:26:26 +01:00
|
|
|
const settings = require("./settings");
|
2017-10-07 23:26:04 +02:00
|
|
|
|
2016-08-06 19:17:36 +02:00
|
|
|
setRandomSupply(randomSupplies.nonPersistent);
|
2016-02-13 12:28:36 +01:00
|
|
|
var apiNames = Object.keys(changedFunctions);
|
|
|
|
var undef;
|
2016-08-06 19:17:36 +02:00
|
|
|
function setRandomSupplyByType(type){
|
|
|
|
switch (type){
|
|
|
|
case "persistent":
|
|
|
|
setRandomSupply(randomSupplies.persistent);
|
|
|
|
break;
|
2017-08-07 17:43:57 +02:00
|
|
|
case "constant":
|
|
|
|
setRandomSupply(randomSupplies.constant);
|
|
|
|
break;
|
2017-11-24 17:06:43 +01:00
|
|
|
case "white":
|
|
|
|
setRandomSupply(randomSupplies.white);
|
|
|
|
break;
|
2016-08-06 19:17:36 +02:00
|
|
|
default:
|
|
|
|
setRandomSupply(randomSupplies.nonPersistent);
|
|
|
|
}
|
|
|
|
}
|
2017-06-25 22:22:17 +02:00
|
|
|
scope.setRandomSupplyByType = setRandomSupplyByType;
|
2017-01-31 20:00:02 +01:00
|
|
|
|
|
|
|
function getURL(window){
|
2017-07-18 16:14:03 +02:00
|
|
|
var href;
|
|
|
|
try {
|
|
|
|
href = window.location.href;
|
|
|
|
}
|
|
|
|
catch (e){
|
|
|
|
// unable to read location due to SOP
|
|
|
|
// since we are not able to do anything in that case we can allow everything
|
|
|
|
return "about:SOP";
|
|
|
|
}
|
|
|
|
if (!href || href === "about:blank"){
|
2017-01-31 20:00:02 +01:00
|
|
|
if (window !== window.parent){
|
|
|
|
return getURL(window.parent);
|
|
|
|
}
|
|
|
|
else if (window.opener){
|
|
|
|
return getURL(window.opener);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return window.location.href;
|
|
|
|
}
|
|
|
|
|
2017-12-04 00:26:26 +01:00
|
|
|
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(){
|
2017-12-11 20:59:56 +01:00
|
|
|
var url = getURL(window);
|
|
|
|
if (!url){
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
var error = new Error();
|
|
|
|
apis.notify({
|
|
|
|
url,
|
|
|
|
errorStack: error.stack,
|
|
|
|
messageId: "preBlock",
|
|
|
|
timestamp: new Date(),
|
|
|
|
functionName: name,
|
|
|
|
dataURL: false
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
// undoPreIntercept();
|
|
|
|
// settings.forceLoad();
|
|
|
|
// doRealIntercept();
|
|
|
|
// var descriptor = Object.getOwnPropertyDescriptor(constructor.prototype, name);
|
|
|
|
// return descriptor.value || descriptor.get();
|
2017-12-04 00:26:26 +01:00
|
|
|
}, 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();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-06-25 22:22:17 +02:00
|
|
|
scope.intercept = function intercept({subject: window}, {check, checkStack, ask, notify, prefs}){
|
2017-01-31 20:00:02 +01:00
|
|
|
var siteStatus = check({url: getURL(window)});
|
2017-11-07 00:36:44 +01:00
|
|
|
logging.verbose("status for page", window, siteStatus);
|
2016-11-19 15:35:00 +01:00
|
|
|
if (siteStatus.mode !== "allow"){
|
|
|
|
apiNames.forEach(function(name){
|
|
|
|
var changedFunction = changedFunctions[name];
|
2017-11-09 00:53:52 +01:00
|
|
|
var functionStatus = changedFunction.getStatus(undefined, siteStatus);
|
|
|
|
logging.verbose("status for", name, ":", functionStatus);
|
|
|
|
if (functionStatus.active){
|
2017-10-05 19:00:00 +02:00
|
|
|
(
|
|
|
|
Array.isArray(changedFunction.object)?
|
|
|
|
changedFunction.object:
|
|
|
|
[changedFunction.object]
|
|
|
|
).forEach(function(object){
|
2017-10-07 23:26:04 +02:00
|
|
|
var constructor = getWrapped(window)[object];
|
2017-02-22 17:46:17 +01:00
|
|
|
if (constructor){
|
|
|
|
var original = constructor.prototype[name];
|
|
|
|
|
|
|
|
Object.defineProperty(
|
|
|
|
constructor.prototype,
|
|
|
|
name,
|
|
|
|
{
|
|
|
|
enumerable: true,
|
2017-12-04 00:26:26 +01:00
|
|
|
configureable: true,
|
2017-06-25 22:33:12 +02:00
|
|
|
get: exportFunction(function(){
|
2017-02-22 17:46:17 +01:00
|
|
|
var url = getURL(window);
|
|
|
|
if (!url){
|
|
|
|
return undef;
|
2016-12-26 14:36:01 +01:00
|
|
|
}
|
2017-02-22 17:46:17 +01:00
|
|
|
var error = new Error();
|
|
|
|
if (checkStack(error.stack)){
|
|
|
|
return original;
|
|
|
|
}
|
|
|
|
var funcStatus = changedFunction.getStatus(this, siteStatus);
|
|
|
|
|
2017-10-06 16:06:31 +02:00
|
|
|
function notifyCallback(messageId){
|
|
|
|
notify({
|
|
|
|
url,
|
|
|
|
errorStack: error.stack,
|
|
|
|
messageId,
|
|
|
|
timestamp: new Date(),
|
|
|
|
functionName: name,
|
|
|
|
dataURL:
|
|
|
|
prefs("storeImageForInspection") &&
|
|
|
|
prefs("showNotifications")?
|
|
|
|
(
|
|
|
|
this instanceof HTMLCanvasElement?
|
|
|
|
this.toDataURL():
|
|
|
|
(
|
|
|
|
this.canvas instanceof HTMLCanvasElement?
|
|
|
|
this.canvas.toDataURL():
|
|
|
|
false
|
|
|
|
)
|
|
|
|
):
|
|
|
|
false
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-22 17:46:17 +01:00
|
|
|
if (funcStatus.active){
|
|
|
|
if (funcStatus.mode === "ask"){
|
2017-10-05 19:00:00 +02:00
|
|
|
funcStatus.mode = ask({
|
|
|
|
window: window,
|
|
|
|
type: changedFunction.type,
|
|
|
|
canvas: this,
|
|
|
|
errorStack: error.stack
|
|
|
|
});
|
2017-02-22 17:46:17 +01:00
|
|
|
}
|
|
|
|
switch (funcStatus.mode){
|
|
|
|
case "allow":
|
|
|
|
return original;
|
|
|
|
case "fake":
|
|
|
|
setRandomSupplyByType(prefs("rng"));
|
2017-10-06 16:06:31 +02:00
|
|
|
var fake = changedFunction.fakeGenerator(
|
|
|
|
prefs,
|
|
|
|
notifyCallback,
|
|
|
|
window,
|
|
|
|
original
|
|
|
|
);
|
2017-02-22 17:46:17 +01:00
|
|
|
switch (fake){
|
|
|
|
case true:
|
|
|
|
return original;
|
|
|
|
case false:
|
|
|
|
return undef;
|
|
|
|
default:
|
2017-10-07 23:26:04 +02:00
|
|
|
return exportFunction(fake, getWrapped(window));
|
2017-02-22 17:46:17 +01:00
|
|
|
}
|
|
|
|
//case "block":
|
|
|
|
default:
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return original;
|
2016-12-26 14:36:01 +01:00
|
|
|
}
|
2017-06-29 07:31:55 +02:00
|
|
|
}, window),
|
|
|
|
set: exportFunction(function(value){
|
|
|
|
Object.defineProperty(
|
|
|
|
constructor.prototype,
|
|
|
|
name,
|
2017-12-04 00:26:26 +01:00
|
|
|
{
|
|
|
|
value,
|
|
|
|
writable: true,
|
|
|
|
configurable: true,
|
|
|
|
enumerable: true
|
|
|
|
}
|
2017-06-29 07:31:55 +02:00
|
|
|
);
|
2017-06-25 22:22:17 +02:00
|
|
|
}, window)
|
2016-11-13 15:09:03 +01:00
|
|
|
}
|
2017-02-22 17:46:17 +01:00
|
|
|
);
|
|
|
|
}
|
2016-12-26 14:36:01 +01:00
|
|
|
});
|
2016-11-19 15:35:00 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-02-13 12:48:22 +01:00
|
|
|
};
|
2016-02-13 12:28:36 +01:00
|
|
|
}());
|