зеркало из https://github.com/mozilla/gecko-dev.git
Bug 821809 - Using nsExpandedPrincipal for jetpack content-scripts. r=rFobic
This commit is contained in:
Родитель
8e7006914b
Коммит
74b2d314db
|
@ -38,6 +38,12 @@ const metadata = require('@loader/options').metadata;
|
|||
const permissions = (metadata && metadata['permissions']) || {};
|
||||
const EXPANDED_PRINCIPALS = permissions['cross-domain-content'] || [];
|
||||
|
||||
const waiveSecurityMembrane = !!permissions['unsafe-content-script'];
|
||||
|
||||
const nsIScriptSecurityManager = Ci.nsIScriptSecurityManager;
|
||||
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Ci.nsIScriptSecurityManager);
|
||||
|
||||
const JS_VERSION = '1.8';
|
||||
|
||||
const WorkerSandbox = Class({
|
||||
|
@ -96,8 +102,10 @@ const WorkerSandbox = Class({
|
|||
this.emit = this.emit.bind(this);
|
||||
this.emitSync = this.emitSync.bind(this);
|
||||
|
||||
// Eventually use expanded principal sandbox feature, if some are given.
|
||||
//
|
||||
// Use expanded principal for content-script if the content is a
|
||||
// regular web content for better isolation.
|
||||
// (This behavior can be turned off for now with the unsafe-content-script
|
||||
// flag to give addon developers time for making the necessary changes)
|
||||
// But prevent it when the Worker isn't used for a content script but for
|
||||
// injecting `addon` object into a Panel, Widget, ... scope.
|
||||
// That's because:
|
||||
|
@ -110,13 +118,18 @@ const WorkerSandbox = Class({
|
|||
// domain principal.
|
||||
let principals = window;
|
||||
let wantGlobalProperties = [];
|
||||
if (EXPANDED_PRINCIPALS.length > 0 && !requiresAddonGlobal(worker)) {
|
||||
principals = EXPANDED_PRINCIPALS.concat(window);
|
||||
let isSystemPrincipal = secMan.isSystemPrincipal(
|
||||
window.document.nodePrincipal);
|
||||
if (!isSystemPrincipal && !requiresAddonGlobal(worker)) {
|
||||
if (EXPANDED_PRINCIPALS.length > 0) {
|
||||
// We have to replace XHR constructor of the content document
|
||||
// with a custom cross origin one, automagically added by platform code:
|
||||
delete proto.XMLHttpRequest;
|
||||
wantGlobalProperties.push('XMLHttpRequest');
|
||||
}
|
||||
if (!waiveSecurityMembrane)
|
||||
principals = EXPANDED_PRINCIPALS.concat(window);
|
||||
}
|
||||
|
||||
// Instantiate trusted code in another Sandbox in order to prevent content
|
||||
// script from messing with standard classes used by proxy and API code.
|
||||
|
@ -129,6 +142,7 @@ const WorkerSandbox = Class({
|
|||
sandboxPrototype: proto,
|
||||
wantXrays: true,
|
||||
wantGlobalProperties: wantGlobalProperties,
|
||||
wantExportHelpers: !waiveSecurityMembrane,
|
||||
sameZoneAs: window,
|
||||
metadata: {
|
||||
SDKContentScript: true,
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/* 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/. */
|
||||
"use strict";
|
||||
|
||||
const { create: makeFrame } = require("sdk/frame/utils");
|
||||
const { window } = require("sdk/addon/window");
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const loader = Loader(module);
|
||||
const Worker = loader.require("sdk/content/worker").Worker;
|
||||
|
||||
exports.testMembranelessMode = function(assert, done) {
|
||||
|
||||
let url = "data:text/html;charset=utf-8," + encodeURIComponent(
|
||||
'<script>' +
|
||||
'function runTest() {' +
|
||||
' assert(fuu.bar == 42, "Content-script objects should be accessible to content with' +
|
||||
' the unsafe-content-script flag on.");' +
|
||||
'}' +
|
||||
'</script>'
|
||||
);
|
||||
|
||||
let element = makeFrame(window.document, {
|
||||
nodeName: "iframe",
|
||||
type: "content",
|
||||
allowJavascript: true,
|
||||
allowPlugins: true,
|
||||
allowAuth: true,
|
||||
uri: url
|
||||
});
|
||||
|
||||
element.addEventListener("DOMContentLoaded", onDOMReady, false);
|
||||
|
||||
function onDOMReady() {
|
||||
let worker = Worker({
|
||||
window: element.contentWindow,
|
||||
contentScript:
|
||||
'new ' + function () {
|
||||
var assert = function assert(v, msg) {
|
||||
self.port.emit("assert", { assertion: v, msg: msg });
|
||||
}
|
||||
var done = function done() {
|
||||
self.port.emit("done");
|
||||
}
|
||||
window.wrappedJSObject.fuu = { bar: 42 };
|
||||
window.wrappedJSObject.assert = assert;
|
||||
window.wrappedJSObject.runTest();
|
||||
done();
|
||||
}
|
||||
});
|
||||
worker.port.on("done", function () {
|
||||
element.parentNode.removeChild(element);
|
||||
done();
|
||||
});
|
||||
worker.port.on("assert", function (data) {
|
||||
assert.ok(data.assertion, data.msg);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
require("sdk/test/runner").runTestsFromModule(module);
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"id": "content-permissions",
|
||||
"permissions": {
|
||||
"unsafe-content-script": true
|
||||
}
|
||||
}
|
|
@ -842,4 +842,30 @@ exports["test MutationObvserver"] = createProxyTest(html, function (helper) {
|
|||
|
||||
});
|
||||
|
||||
let html = '<script>' +
|
||||
'var accessCheck = function() {' +
|
||||
' assert(true, "exporting function works");' +
|
||||
' try{' +
|
||||
' exportedObj.prop;' +
|
||||
' assert(false, "content should not have access to content-script");' +
|
||||
' } catch(e) {' +
|
||||
' assert(e.toString().indexOf("Permission denied") != -1,' +
|
||||
' "content should not have access to content-script");' +
|
||||
' }' +
|
||||
'}</script>';
|
||||
exports["test nsEp for content-script"] = createProxyTest(html, function (helper) {
|
||||
|
||||
helper.createWorker(
|
||||
'let glob = this; new ' + function ContentScriptScope() {
|
||||
|
||||
exportFunction(assert, unsafeWindow, { defineAs: "assert" });
|
||||
window.wrappedJSObject.assert(true, "assert exported");
|
||||
window.wrappedJSObject.exportedObj = { prop: 42 };
|
||||
window.wrappedJSObject.accessCheck();
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
require("test").run(exports);
|
||||
|
|
Загрузка…
Ссылка в новой задаче