зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1174733 - Browser API: iframe.executeScript. r=kanru, r=bholley
This commit is contained in:
Родитель
3ff8c1f3fa
Коммит
dfe7fcd341
|
@ -143,6 +143,12 @@ this.PermissionsTable = { geolocation: {
|
||||||
privileged: ALLOW_ACTION,
|
privileged: ALLOW_ACTION,
|
||||||
certified: ALLOW_ACTION
|
certified: ALLOW_ACTION
|
||||||
},
|
},
|
||||||
|
"browser:universalxss": {
|
||||||
|
app: DENY_ACTION,
|
||||||
|
trusted: DENY_ACTION,
|
||||||
|
privileged: ALLOW_ACTION,
|
||||||
|
certified: ALLOW_ACTION
|
||||||
|
},
|
||||||
bluetooth: {
|
bluetooth: {
|
||||||
app: DENY_ACTION,
|
app: DENY_ACTION,
|
||||||
trusted: DENY_ACTION,
|
trusted: DENY_ACTION,
|
||||||
|
|
|
@ -238,6 +238,7 @@ BrowserElementChild.prototype = {
|
||||||
"find-all": this._recvFindAll.bind(this),
|
"find-all": this._recvFindAll.bind(this),
|
||||||
"find-next": this._recvFindNext.bind(this),
|
"find-next": this._recvFindNext.bind(this),
|
||||||
"clear-match": this._recvClearMatch.bind(this),
|
"clear-match": this._recvClearMatch.bind(this),
|
||||||
|
"execute-script": this._recvExecuteScript,
|
||||||
"get-audio-channel-volume": this._recvGetAudioChannelVolume,
|
"get-audio-channel-volume": this._recvGetAudioChannelVolume,
|
||||||
"set-audio-channel-volume": this._recvSetAudioChannelVolume,
|
"set-audio-channel-volume": this._recvSetAudioChannelVolume,
|
||||||
"get-audio-channel-muted": this._recvGetAudioChannelMuted,
|
"get-audio-channel-muted": this._recvGetAudioChannelMuted,
|
||||||
|
@ -984,6 +985,90 @@ BrowserElementChild.prototype = {
|
||||||
takeScreenshotClosure, maxDelayMS);
|
takeScreenshotClosure, maxDelayMS);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_recvExecuteScript: function(data) {
|
||||||
|
debug("Received executeScript message: (" + data.json.id + ")");
|
||||||
|
|
||||||
|
let domRequestID = data.json.id;
|
||||||
|
|
||||||
|
let sendError = errorMsg => sendAsyncMsg("execute-script-done", {
|
||||||
|
errorMsg,
|
||||||
|
id: domRequestID
|
||||||
|
});
|
||||||
|
|
||||||
|
let sendSuccess = successRv => sendAsyncMsg("execute-script-done", {
|
||||||
|
successRv,
|
||||||
|
id: domRequestID
|
||||||
|
});
|
||||||
|
|
||||||
|
let isJSON = obj => {
|
||||||
|
try {
|
||||||
|
JSON.stringify(obj);
|
||||||
|
} catch(e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let expectedOrigin = data.json.args.options.origin;
|
||||||
|
let expectedUrl = data.json.args.options.url;
|
||||||
|
|
||||||
|
if (expectedOrigin) {
|
||||||
|
if (expectedOrigin != content.location.origin) {
|
||||||
|
sendError("Origin mismatches");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expectedUrl) {
|
||||||
|
let expectedURI
|
||||||
|
try {
|
||||||
|
expectedURI = Services.io.newURI(expectedUrl, null, null);
|
||||||
|
} catch(e) {
|
||||||
|
sendError("Malformed URL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let currentURI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
|
||||||
|
if (!currentURI.equalsExceptRef(expectedURI)) {
|
||||||
|
sendError("URL mismatches");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let sandbox = new Cu.Sandbox([content], {
|
||||||
|
sandboxPrototype: content,
|
||||||
|
sandboxName: "browser-api-execute-script",
|
||||||
|
allowWaivers: false,
|
||||||
|
sameZoneAs: content
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
let sandboxRv = Cu.evalInSandbox(data.json.args.script, sandbox, "1.8");
|
||||||
|
if (sandboxRv instanceof Promise) {
|
||||||
|
sandboxRv.then(rv => {
|
||||||
|
if (isJSON(rv)) {
|
||||||
|
sendSuccess(rv);
|
||||||
|
} else {
|
||||||
|
sendError("Value returned (resolve) by promise is not a valid JSON object");
|
||||||
|
}
|
||||||
|
}, error => {
|
||||||
|
if (isJSON(error)) {
|
||||||
|
sendError(error);
|
||||||
|
} else {
|
||||||
|
sendError("Value returned (reject) by promise is not a valid JSON object");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (isJSON(sandboxRv)) {
|
||||||
|
sendSuccess(sandboxRv);
|
||||||
|
} else {
|
||||||
|
sendError("Script last expression must be a promise or a JSON object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
sendError(e.toString());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_recvGetContentDimensions: function(data) {
|
_recvGetContentDimensions: function(data) {
|
||||||
debug("Received getContentDimensions message: (" + data.json.id + ")");
|
debug("Received getContentDimensions message: (" + data.json.id + ")");
|
||||||
sendAsyncMsg('got-contentdimensions', {
|
sendAsyncMsg('got-contentdimensions', {
|
||||||
|
|
|
@ -207,6 +207,7 @@ BrowserElementParent.prototype = {
|
||||||
"scrollviewchange": this._handleScrollViewChange,
|
"scrollviewchange": this._handleScrollViewChange,
|
||||||
"caretstatechanged": this._handleCaretStateChanged,
|
"caretstatechanged": this._handleCaretStateChanged,
|
||||||
"findchange": this._handleFindChange,
|
"findchange": this._handleFindChange,
|
||||||
|
"execute-script-done": this._gotDOMRequestResult,
|
||||||
"got-audio-channel-volume": this._gotDOMRequestResult,
|
"got-audio-channel-volume": this._gotDOMRequestResult,
|
||||||
"got-set-audio-channel-volume": this._gotDOMRequestResult,
|
"got-set-audio-channel-volume": this._gotDOMRequestResult,
|
||||||
"got-audio-channel-muted": this._gotDOMRequestResult,
|
"got-audio-channel-muted": this._gotDOMRequestResult,
|
||||||
|
@ -692,6 +693,19 @@ BrowserElementParent.prototype = {
|
||||||
this._sendAsyncMsg('stop');
|
this._sendAsyncMsg('stop');
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
executeScript: function(script, options) {
|
||||||
|
if (!this._isAlive()) {
|
||||||
|
throw Components.Exception("Dead content process",
|
||||||
|
Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enforcing options.url or options.origin
|
||||||
|
if (!options.url && !options.origin) {
|
||||||
|
throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG);
|
||||||
|
}
|
||||||
|
return this._sendDOMRequest('execute-script', {script, options});
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent".
|
* The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent".
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* Any copyright is dedicated to the public domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Bug 1174733 - Browser API: iframe.executeScript
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
browserElementTestHelpers.setEnabledPref(true);
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
|
||||||
|
const origin = 'http://example.org';
|
||||||
|
const url = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_ExecuteScript.html';
|
||||||
|
|
||||||
|
// Test if all key=>value pairs in o1 are present in o2.
|
||||||
|
const c = (o1, o2) => Object.keys(o1).every(k => o1[k] == o2[k]);
|
||||||
|
|
||||||
|
let scriptId = 0;
|
||||||
|
|
||||||
|
const bail = () => {
|
||||||
|
ok(false, `scriptId: ${scriptId++}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpecialPowers.pushPermissions([
|
||||||
|
{type: 'browser', allow: 1, context: document},
|
||||||
|
{type: 'browser:universalxss', allow: 1, context: document}
|
||||||
|
], function() {
|
||||||
|
let iframe = document.createElement('iframe');
|
||||||
|
iframe.setAttribute('mozbrowser', 'true');
|
||||||
|
iframe.addEventListener('mozbrowserloadend', function onload() {
|
||||||
|
iframe.removeEventListener('mozbrowserloadend', onload);
|
||||||
|
onReady(iframe);
|
||||||
|
});
|
||||||
|
iframe.src = url;
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function onReady(iframe) {
|
||||||
|
iframe.executeScript('4 + 4', {url}).then(rv => {
|
||||||
|
is(rv, 8, `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('(() => {return {a:42}})()', {url})
|
||||||
|
}, bail).then(rv => {
|
||||||
|
ok(c(rv, {a:42}), `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('(() => {return {a:42}})()', {origin})
|
||||||
|
}, bail).then(rv => {
|
||||||
|
ok(c(rv, {a:42}), `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('(() => {return {a:42}})()', {origin, url})
|
||||||
|
}, bail).then(rv => {
|
||||||
|
ok(c(rv, {a:42}), `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript(`
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
resolve(document.body.textContent.trim());
|
||||||
|
});
|
||||||
|
`, {url})
|
||||||
|
}, bail).then(rv => {
|
||||||
|
is(rv, 'foo', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript(`
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
resolve({a:43,b:34});
|
||||||
|
});
|
||||||
|
`, {url})
|
||||||
|
}, bail).then(rv => {
|
||||||
|
ok(c(rv, {a:43,b:34}), `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript(`
|
||||||
|
… syntax error
|
||||||
|
`, {url});
|
||||||
|
}, bail).then(bail, (error) => {
|
||||||
|
is(error.name, 'SyntaxError: illegal character', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript(`
|
||||||
|
window
|
||||||
|
`, {url});
|
||||||
|
}).then(bail, (error) => {
|
||||||
|
is(error.name, 'Script last expression must be a promise or a JSON object', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript(`
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
reject('BOOM');
|
||||||
|
});
|
||||||
|
`, {url});
|
||||||
|
}).then(bail, (error) => {
|
||||||
|
is(error.name, 'BOOM', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript(`
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
resolve(window);
|
||||||
|
});
|
||||||
|
`, {url});
|
||||||
|
}).then(bail, (error) => {
|
||||||
|
is(error.name, 'Value returned (resolve) by promise is not a valid JSON object', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('window.btoa("a")', {url})
|
||||||
|
}, bail).then(rv => {
|
||||||
|
ok(c(rv, 'YQ=='), `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('window.wrappedJSObject.btoa("a")', {url})
|
||||||
|
}, bail).then(bail, (error) => {
|
||||||
|
is(error.name, 'TypeError: window.wrappedJSObject is undefined', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('42', {})
|
||||||
|
}).then(bail, error => {
|
||||||
|
is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('42');
|
||||||
|
}).then(bail, error => {
|
||||||
|
is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('43', { url: 'http://foo.com' });
|
||||||
|
}).then(bail, (error) => {
|
||||||
|
is(error.name, 'URL mismatches', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('43', { url: '_' });
|
||||||
|
}, bail).then(bail, (error) => {
|
||||||
|
is(error.name, 'Malformed URL', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('43', { origin: 'http://foo.com' });
|
||||||
|
}, bail).then(bail, (error) => {
|
||||||
|
is(error.name, 'Origin mismatches', `scriptId: ${scriptId++}`);
|
||||||
|
return iframe.executeScript('43', { origin: 'https://example.org' });
|
||||||
|
}, bail).then(bail, (error) => {
|
||||||
|
is(error.name, 'Origin mismatches', `scriptId: ${scriptId++}`);
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('testready', runTest);
|
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
window.btoa = () => "fake btoa";
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>foo</body>
|
||||||
|
</html>
|
|
@ -6,7 +6,9 @@
|
||||||
skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
|
skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
|
||||||
support-files =
|
support-files =
|
||||||
browserElement_OpenMixedProcess.js
|
browserElement_OpenMixedProcess.js
|
||||||
|
file_browserElement_ExecuteScript.html
|
||||||
file_browserElement_OpenMixedProcess.html
|
file_browserElement_OpenMixedProcess.html
|
||||||
|
browserElement_ExecuteScript.js
|
||||||
browserElement_Find.js
|
browserElement_Find.js
|
||||||
browserElement_OpenTab.js
|
browserElement_OpenTab.js
|
||||||
|
|
||||||
|
@ -42,6 +44,7 @@ skip-if = (toolkit == 'gonk' && !debug)
|
||||||
disabled = bug 1022281
|
disabled = bug 1022281
|
||||||
[test_browserElement_oop_ErrorSecurity.html]
|
[test_browserElement_oop_ErrorSecurity.html]
|
||||||
skip-if = (toolkit == 'gonk' && !debug)
|
skip-if = (toolkit == 'gonk' && !debug)
|
||||||
|
[test_browserElement_oop_ExecuteScript.html]
|
||||||
[test_browserElement_oop_Find.html]
|
[test_browserElement_oop_Find.html]
|
||||||
[test_browserElement_oop_FirstPaint.html]
|
[test_browserElement_oop_FirstPaint.html]
|
||||||
[test_browserElement_oop_ForwardName.html]
|
[test_browserElement_oop_ForwardName.html]
|
||||||
|
|
|
@ -28,6 +28,7 @@ support-files =
|
||||||
browserElement_DocumentFirstPaint.js
|
browserElement_DocumentFirstPaint.js
|
||||||
browserElement_Download.js
|
browserElement_Download.js
|
||||||
browserElement_ErrorSecurity.js
|
browserElement_ErrorSecurity.js
|
||||||
|
browserElement_ExecuteScript.js
|
||||||
browserElement_ExposableURI.js
|
browserElement_ExposableURI.js
|
||||||
browserElement_Find.js
|
browserElement_Find.js
|
||||||
browserElement_FirstPaint.js
|
browserElement_FirstPaint.js
|
||||||
|
@ -88,6 +89,7 @@ support-files =
|
||||||
file_browserElement_CloseFromOpener.html
|
file_browserElement_CloseFromOpener.html
|
||||||
file_browserElement_CookiesNotThirdParty.html
|
file_browserElement_CookiesNotThirdParty.html
|
||||||
file_browserElement_DisallowEmbedAppsInOOP.html
|
file_browserElement_DisallowEmbedAppsInOOP.html
|
||||||
|
file_browserElement_ExecuteScript.html
|
||||||
file_browserElement_ForwardName.html
|
file_browserElement_ForwardName.html
|
||||||
file_browserElement_FrameWrongURI.html
|
file_browserElement_FrameWrongURI.html
|
||||||
file_browserElement_LoadEvents.html
|
file_browserElement_LoadEvents.html
|
||||||
|
@ -163,6 +165,7 @@ skip-if = os == "android" || toolkit == 'gonk' # embed-apps doesn't work in the
|
||||||
[test_browserElement_inproc_DocumentFirstPaint.html]
|
[test_browserElement_inproc_DocumentFirstPaint.html]
|
||||||
[test_browserElement_inproc_Download.html]
|
[test_browserElement_inproc_Download.html]
|
||||||
disabled = bug 1022281
|
disabled = bug 1022281
|
||||||
|
[test_browserElement_inproc_ExecuteScript.html]
|
||||||
[test_browserElement_inproc_ExposableURI.html]
|
[test_browserElement_inproc_ExposableURI.html]
|
||||||
[test_browserElement_inproc_Find.html]
|
[test_browserElement_inproc_Find.html]
|
||||||
[test_browserElement_inproc_FirstPaint.html]
|
[test_browserElement_inproc_FirstPaint.html]
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1174733
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 1163961</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1174733">Mozilla Bug 1174733</a>
|
||||||
|
|
||||||
|
<script type="application/javascript;version=1.7" src="browserElement_ExecuteScript.js">
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1174733
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 1163961</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1174733">Mozilla Bug 1174733</a>
|
||||||
|
|
||||||
|
<script type="application/javascript;version=1.7" src="browserElement_ExecuteScript.js">
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports
|
||||||
* Interface to the BrowserElementParent implementation. All methods
|
* Interface to the BrowserElementParent implementation. All methods
|
||||||
* but setFrameLoader throw when the remote process is dead.
|
* but setFrameLoader throw when the remote process is dead.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(daa264b2-54df-4fc7-89b7-c9d02167c5d4)]
|
[scriptable, uuid(26a832d1-9d71-43ef-9d46-9d7c8ec33f00)]
|
||||||
interface nsIBrowserElementAPI : nsISupports
|
interface nsIBrowserElementAPI : nsISupports
|
||||||
{
|
{
|
||||||
const long FIND_CASE_SENSITIVE = 0;
|
const long FIND_CASE_SENSITIVE = 0;
|
||||||
|
@ -91,4 +91,6 @@ interface nsIBrowserElementAPI : nsISupports
|
||||||
nsIDOMDOMRequest isAudioChannelActive(in uint32_t audioChannel);
|
nsIDOMDOMRequest isAudioChannelActive(in uint32_t audioChannel);
|
||||||
|
|
||||||
void setNFCFocus(in boolean isFocus);
|
void setNFCFocus(in boolean isFocus);
|
||||||
|
|
||||||
|
nsIDOMDOMRequest executeScript(in DOMString script, in jsval options);
|
||||||
};
|
};
|
||||||
|
|
|
@ -678,4 +678,59 @@ nsBrowserElement::SetNFCFocus(bool aIsFocus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<DOMRequest>
|
||||||
|
nsBrowserElement::ExecuteScript(const nsAString& aScript,
|
||||||
|
const BrowserElementExecuteScriptOptions& aOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
|
||||||
|
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
|
||||||
|
|
||||||
|
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||||
|
if (!frameLoader) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMElement> ownerElement;
|
||||||
|
nsresult rv = frameLoader->GetOwnerElement(getter_AddRefs(ownerElement));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
aRv.Throw(rv);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsINode> node = do_QueryInterface(ownerElement);
|
||||||
|
nsCOMPtr<nsIPrincipal> principal = node->NodePrincipal();
|
||||||
|
|
||||||
|
if (!nsContentUtils::IsExactSitePermAllow(principal, "browser:universalxss")) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMDOMRequest> req;
|
||||||
|
nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
|
||||||
|
MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
|
||||||
|
AutoJSAPI jsapi;
|
||||||
|
jsapi.Init(wrappedObj->GetJSObject());
|
||||||
|
JSContext* cx = jsapi.cx();
|
||||||
|
JS::Rooted<JS::Value> options(cx);
|
||||||
|
if (!ToJSValue(cx, aOptions, &options)) {
|
||||||
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = mBrowserElementAPI->ExecuteScript(aScript, options, getter_AddRefs(req));
|
||||||
|
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
if (rv == NS_ERROR_INVALID_ARG) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||||
|
} else {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return req.forget().downcast<DOMRequest>();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace mozilla {
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
struct BrowserElementDownloadOptions;
|
struct BrowserElementDownloadOptions;
|
||||||
|
struct BrowserElementExecuteScriptOptions;
|
||||||
class BrowserElementNextPaintEventCallback;
|
class BrowserElementNextPaintEventCallback;
|
||||||
class DOMRequest;
|
class DOMRequest;
|
||||||
enum class BrowserFindCaseSensitivity: uint32_t;
|
enum class BrowserFindCaseSensitivity: uint32_t;
|
||||||
|
@ -100,6 +101,10 @@ public:
|
||||||
already_AddRefed<dom::DOMRequest> SetInputMethodActive(bool isActive,
|
already_AddRefed<dom::DOMRequest> SetInputMethodActive(bool isActive,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
already_AddRefed<dom::DOMRequest> ExecuteScript(const nsAString& aScript,
|
||||||
|
const dom::BrowserElementExecuteScriptOptions& aOptions,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
void SetNFCFocus(bool isFocus,
|
void SetNFCFocus(bool isFocus,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,11 @@ dictionary BrowserElementDownloadOptions {
|
||||||
DOMString? referrer;
|
DOMString? referrer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dictionary BrowserElementExecuteScriptOptions {
|
||||||
|
DOMString? url;
|
||||||
|
DOMString? origin;
|
||||||
|
};
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface BrowserElement {
|
interface BrowserElement {
|
||||||
};
|
};
|
||||||
|
@ -165,4 +170,11 @@ interface BrowserElementPrivileged {
|
||||||
CheckPermissions="browser"]
|
CheckPermissions="browser"]
|
||||||
void clearMatch();
|
void clearMatch();
|
||||||
|
|
||||||
|
// Additional |browser:universalxss| permission is required for executeScript API
|
||||||
|
[Throws,
|
||||||
|
Pref="dom.mozBrowserFramesEnabled",
|
||||||
|
CheckPermissions="browser"]
|
||||||
|
DOMRequest executeScript(DOMString script,
|
||||||
|
optional BrowserElementExecuteScriptOptions options);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче