author | Kris Maglione <maglione.k@gmail.com> |
Tue, 13 Aug 2019 14:29:08 -0700 | |
changeset 488078 | f8e99bd2a193f00d159581d9dffeb5cd634ad624 |
parent 488077 | 4b826e607ca87939b656b62836721973c67dac71 |
child 488079 | 6692575191f32991dd8ceb2b108dd2adaba576f0 |
push id | 36435 |
push user | cbrindusan@mozilla.com |
push date | Thu, 15 Aug 2019 09:46:49 +0000 |
treeherder | mozilla-central@0db07ff50ab5 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mccr8 |
bugs | 1573247 |
milestone | 70.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/xpconnect/idl/xpccomponents.idl +++ b/js/xpconnect/idl/xpccomponents.idl @@ -411,16 +411,31 @@ interface nsIXPCComponents_Utils : nsISu * * Dead-wrapper objects hold no other objects alive (they have no outgoing * reference edges) and will throw if you touch them (e.g. by * reading/writing a property). */ bool isDeadWrapper(in jsval obj); /** + * Determines whether this value is a remote object proxy, such as + * RemoteWindowProxy or RemoteLocationProxy, for an out-of-process frame. + * + * Remote object proxies do not grant chrome callers the same exemptions + * to the same-origin-policy that in-process wrappers typically do, so + * this can be used to determine whether access to cross-origin proxies is + * safe: + * + * if (!Cu.isRemoteProxy(frame.contentWindow)) { + * frame.contentWindow.doCrossOriginThing(); + * } + */ + bool isRemoteProxy(in jsval val); + + /** * Determines whether this object is a cross-process wrapper. */ bool isCrossProcessWrapper(in jsval obj); /** * CPOWs can have user data attached to them. This data originates * in the local process via the * nsIRemoteTagService.getRemoteObjectTag method. It's sent along
--- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -25,16 +25,17 @@ #include "mozilla/Preferences.h" #include "nsJSEnvironment.h" #include "mozilla/TimeStamp.h" #include "mozilla/ResultExtensions.h" #include "mozilla/URLPreloader.h" #include "mozilla/dom/DOMException.h" #include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/RemoteObjectProxy.h" #include "mozilla/dom/StructuredCloneTags.h" #include "mozilla/dom/WindowBinding.h" #include "nsZipArchive.h" #include "nsWindowMemoryReporter.h" #include "nsICycleCollectorListener.h" #include "nsIException.h" #include "nsIScriptError.h" #include "nsISimpleEnumerator.h" @@ -1909,16 +1910,27 @@ nsXPCComponents_Utils::IsDeadWrapper(Han MOZ_ASSERT_IF(js::IsCrossCompartmentWrapper(&obj.toObject()), !JS_IsDeadWrapper(js::UncheckedUnwrap(&obj.toObject()))); *out = JS_IsDeadWrapper(&obj.toObject()); return NS_OK; } NS_IMETHODIMP +nsXPCComponents_Utils::IsRemoteProxy(HandleValue val, bool* out) { + if (val.isObject()) { + *out = dom::IsRemoteObjectProxy(UncheckedUnwrap(&val.toObject())); + ; + } else { + *out = false; + } + return NS_OK; +} + +NS_IMETHODIMP nsXPCComponents_Utils::IsCrossProcessWrapper(HandleValue obj, bool* out) { *out = false; if (obj.isPrimitive()) { return NS_ERROR_INVALID_ARG; } *out = jsipc::IsWrappedCPOW(&obj.toObject()); return NS_OK;
--- a/js/xpconnect/tests/mochitest/mochitest.ini +++ b/js/xpconnect/tests/mochitest/mochitest.ini @@ -110,16 +110,17 @@ skip-if = fission && webrender && debug [test_bug1158558.html] [test_bug1448048.html] [test_crosscompartment_weakmap.html] [test_frameWrapping.html] # The JS test component we use below is only available in debug builds. [test_getWebIDLCaller.html] skip-if = (debug == false) [test_getweakmapkeys.html] +[test_isRemoteProxy.html] [test_paris_weakmap_keys.html] skip-if = (debug == false) [test_nukeContentWindow.html] [test_sameOriginPolicy.html] [test_sandbox_fetch.html] support-files = ../../../../dom/tests/mochitest/fetch/test_fetch_basic.js [test_weakmaps.html]
new file mode 100644 --- /dev/null +++ b/js/xpconnect/tests/mochitest/test_isRemoteProxy.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Tests for Cu.isRemoteProxy</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<script> +/* eslint-disable prettier/prettier */ + +async function addFrame(url) { + let frame = document.createElement("iframe"); + frame.src = url; + document.body.appendChild(frame); + + await new Promise(resolve => { + frame.addEventListener("load", resolve, { once: true }); + }); + + return frame; +} + +add_task(async function() { + const { Cu } = SpecialPowers; + + let localFrame = await addFrame("file_empty.html"); + let remoteFrame = await addFrame( + SimpleTest.getTestFileURL("file_empty.html") + .replace("mochi.test:8888", "example.com")); + + ok(frames[0] === localFrame.contentWindow, "frames[0] is localFrame"); + ok(frames[1] === remoteFrame.contentWindow, "frames[1] is remoteFrame"); + + ok(!Cu.isRemoteProxy(window), "window is not a remote proxy"); + ok(!Cu.isRemoteProxy(location), "location is not a remote proxy"); + + ok(!Cu.isRemoteProxy(frames[0]), "frames[0] is not a remote proxy"); + ok( + !Cu.isRemoteProxy(frames[0].location), + "frames[0].location is not a remote proxy" + ); + + const { useRemoteSubframes } = SpecialPowers; + is(Cu.isRemoteProxy(frames[1]), useRemoteSubframes, + "frames[1] is a remote proxy if Fission is enabled"); + is(Cu.isRemoteProxy(frames[1].location), useRemoteSubframes, + "frames[1].location is a remote proxy if Fission is enabled"); +}); + +</script> +</body> +</html>