Bug 916939 - Drop support for named and indexed access on cross-origin windows. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Wed, 18 Sep 2013 08:39:48 -0700
changeset 147721 86128d3eac885dc034eae05f4e8974006fe712e5
parent 147720 ed3db70c3f1e6ff87747852fa9c7d29fac638310
child 147722 86e17fd0298f20f064269bad1a1f7b0f7edf332a
push id33963
push userbobbyholley@gmail.com
push dateWed, 18 Sep 2013 15:40:15 +0000
treeherdermozilla-inbound@86128d3eac88 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs916939
milestone27.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
Bug 916939 - Drop support for named and indexed access on cross-origin windows. r=bz
docshell/test/navigation/NavigationUtils.js
docshell/test/navigation/test_bug13871.html
docshell/test/navigation/test_grandchild.html
docshell/test/navigation/test_sibling-off-domain.html
dom/tests/mochitest/bugs/iframe_bug440572.html
dom/tests/mochitest/bugs/test_bug850517.html
dom/tests/mochitest/whatwg/postMessage_onOther.html
js/xpconnect/tests/mochitest/test_sameOriginPolicy.html
js/xpconnect/wrappers/AccessCheck.cpp
--- a/docshell/test/navigation/NavigationUtils.js
+++ b/docshell/test/navigation/NavigationUtils.js
@@ -88,16 +88,20 @@ function isInaccessible(wnd, message) {
   try {
     wnd.document.body.innerHTML;
     ok(false, message);
   } catch(ex) {
     ok(true, message);
   }
 }
 
+function getSubframe(win, i) {
+  return SpecialPowers.unwrap(SpecialPowers.wrap(win)[i]);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Functions that require UniversalXPConnect privilege
 ///////////////////////////////////////////////////////////////////////////
 
 function xpcEnumerateContentWindows(callback) {
 
   var Ci = SpecialPowers.Ci;
   var ww = SpecialPowers.Cc["@mozilla.org/embedcomp/window-watcher;1"]
--- a/docshell/test/navigation/test_bug13871.html
+++ b/docshell/test/navigation/test_bug13871.html
@@ -4,27 +4,28 @@
     <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     <script type="text/javascript" src="NavigationUtils.js"></script>        
     <style type="text/css">
       iframe { width: 90%; height: 50px; }
     </style>
 <script>
+
 window.onload = function () {
-  navigateByLocation(window0.frames[0]);
+  navigateByLocation(getSubframe(window0, 0));
   navigateByOpen("window1_child0");
   navigateByForm("window2_child0");
   navigateByHyperlink("window3_child0");
 
   xpcWaitForFinishedFrames(function() {
-    isInaccessible(window0.frames[0], "Should not be able to navigate off-domain frame by setting location.");
-    isInaccessible(window1.frames[0], "Should not be able to navigate off-domain frame by calling window.open.");
-    isInaccessible(window2.frames[0], "Should not be able to navigate off-domain frame by submitting form.");
-    isInaccessible(window3.frames[0], "Should not be able to navigate off-domain frame by targeted hyperlink.");
+    isInaccessible(getSubframe(window0, 0), "Should not be able to navigate off-domain frame by setting location.");
+    isInaccessible(getSubframe(window1, 0), "Should not be able to navigate off-domain frame by calling window.open.");
+    isInaccessible(getSubframe(window2, 0), "Should not be able to navigate off-domain frame by submitting form.");
+    isInaccessible(getSubframe(window3, 0), "Should not be able to navigate off-domain frame by targeted hyperlink.");
 
     window0.close();
     window1.close();
     window2.close();
     window3.close();
 
     xpcCleanupWindows();
     SimpleTest.finish();
--- a/docshell/test/navigation/test_grandchild.html
+++ b/docshell/test/navigation/test_grandchild.html
@@ -9,26 +9,26 @@
       iframe { width: 90%; height: 200px; }
     </style>
 <script>
 if (!navigator.platform.startsWith("Win")) {
   SimpleTest.expectAssertions(0, 1);
 }
 
 window.onload = function () {
-  navigateByLocation(frames[0].frames[0]);
+  navigateByLocation(getSubframe(getSubframe(frames, 0), 0));
   navigateByOpen("child1_child0");
   navigateByForm("child2_child0");
   navigateByHyperlink("child3_child0");
 
   xpcWaitForFinishedFrames(function() {
-    isNavigated(frames[0].frames[0], "Should be able to navigate off-domain grandchild by setting location.");
-    isNavigated(frames[1].frames[0], "Should be able to navigate off-domain grandchild by calling window.open.");
-    isNavigated(frames[2].frames[0], "Should be able to navigate off-domain grandchild by submitting form.");
-    isNavigated(frames[3].frames[0], "Should be able to navigate off-domain grandchild by targeted hyperlink.");
+    isNavigated(getSubframe(getSubframe(frames, 0), 0), "Should be able to navigate off-domain grandchild by setting location.");
+    isNavigated(getSubframe(getSubframe(frames, 1), 0), "Should be able to navigate off-domain grandchild by calling window.open.");
+    isNavigated(getSubframe(getSubframe(frames, 2), 0), "Should be able to navigate off-domain grandchild by submitting form.");
+    isNavigated(getSubframe(getSubframe(frames, 3), 0), "Should be able to navigate off-domain grandchild by targeted hyperlink.");
 
     xpcCleanupWindows();
     SimpleTest.finish();
   }, 4);
 }
 </script>
 </head>
 <body>
--- a/docshell/test/navigation/test_sibling-off-domain.html
+++ b/docshell/test/navigation/test_sibling-off-domain.html
@@ -6,17 +6,17 @@
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     <script type="text/javascript" src="NavigationUtils.js"></script>        
     <style type="text/css">
       iframe { width: 90%; height: 50px; }
     </style>
 <script>
 window.onload = function () {
   document.getElementById('active').innerHTML =
-      '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#parent.frames[0],location"></iframe>' +
+      '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#SpecialPowers.unwrap(SpecialPowers.wrap(parent).frames[0]),location"></iframe>' +
       '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child1,open"></iframe>' +
       '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child2,form"></iframe>' +
       '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child3,hyperlink"></iframe>';
 
   xpcWaitForFinishedFrames(function() {
     isBlank(frames[0], "Should not be able to navigate off-domain sibling by setting location.");
     isBlank(frames[1], "Should not be able to navigate off-domain sibling by calling window.open.");
     isBlank(frames[2], "Should not be able to navigate off-domain sibling by submitting form.");
--- a/dom/tests/mochitest/bugs/iframe_bug440572.html
+++ b/dom/tests/mochitest/bugs/iframe_bug440572.html
@@ -1,16 +1,16 @@
 <html>
 <body>
 <script>
 
 var success = 0;
 
 try {
-  parent[name].success = 1;
+  SpecialPowers.unwrap(SpecialPowers.wrap(parent)[name]).success = 1;
 } catch (e) {
   parent.postMessage(e, "http://mochi.test:8888");
 }
 
 parent.postMessage(success ? "success" : "failure", "http://mochi.test:8888");
 </script>
 <p>Move on, nothing to see here...</p>
 </body>
--- a/dom/tests/mochitest/bugs/test_bug850517.html
+++ b/dom/tests/mochitest/bugs/test_bug850517.html
@@ -11,28 +11,27 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript">
 
   /** Test for live updating of named child resolution. **/
   SimpleTest.waitForExplicitFinish();
 
   function go() {
     var ifrA = $('a');
     var ifrB = $('b');
-    var sb = new SpecialPowers.Cu.Sandbox('http://www.example.com');
+    var sb = new SpecialPowers.Cu.Sandbox(SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal());
     sb.win = window;
     sb.childA = ifrA.contentWindow;
     sb.childB = ifrB.contentWindow;
     sb.is = is;
     sb.ok = ok;
     is(window.theoneandonly.frameElement, ifrA, "Named child resolution works");
     SpecialPowers.Cu.evalInSandbox('is(win.theoneandonly, childA, "Named child resolution works via Xray");', sb);
     ifrA.removeAttribute('name');
     is(typeof window.theoneandonly, 'undefined', "Revocation works");
-    SpecialPowers.Cu.evalInSandbox('try { win.theoneandonly; ok(false, "Should have thrown"); } ' +
-                                   'catch (e) {ok(!!/denied/.exec(e) && !!/theoneandonly/.exec(e), "Revocation works via Xray");};', sb);
+    SpecialPowers.Cu.evalInSandbox('is(typeof win.theoneandonly, "undefined", "Revocation works via Xray");', sb);
     ifrB.setAttribute('name', 'theoneandonly');
     is(window.theoneandonly.frameElement, ifrB, "Another mule kicking in the same old stall");
     SpecialPowers.Cu.evalInSandbox('is(win.theoneandonly, childB, "Another mule via Xray");', sb);
     SimpleTest.finish();
   }
 
   </script>
 </head>
--- a/dom/tests/mochitest/whatwg/postMessage_onOther.html
+++ b/dom/tests/mochitest/whatwg/postMessage_onOther.html
@@ -45,52 +45,55 @@
     //   http://test1.example.com
     //
     // and not
     //
     //   http://example.com
 
     function receiveSubDomain(evt)
     {
+      var topframe =
+        SpecialPowers.unwrap(SpecialPowers.wrap(window).parent.topDomainFrame);
       if (evt.origin !== "http://mochi.test:8888")
       {
         fail("wrong top-domain origin: " + evt.origin);
         return;
       }
       if (evt.data !== "start-test")
       {
         fail("wrong top-domain message: " + evt.origin);
         return;
       }
 
       document.domain = "example.com";
-      window.parent.topDomainFrame.postMessage("domain-switch",
-                                               "http://example.com");
+      topframe.postMessage("domain-switch", "http://example.com");
     }
     
     function receiveTopDomain(evt)
     {
+      var subframe =
+        SpecialPowers.unwrap(SpecialPowers.wrap(window).parent.subDomainFrame);
       if (evt.origin !== "http://test1.example.com")
       {
         fail("wrong subdomain origin: " + evt.origin);
         return;
       }
       if (evt.data !== "domain-switch")
       {
         fail("wrong subdomain message: " + evt.origin);
         return;
       }
-      if (evt.source !== window.parent.subDomainFrame)
+      if (evt.source !== subframe)
       {
         fail("wrong source on message from subdomain");
         return;
       }
 
       document.domain = "example.com";
-      window.parent.subDomainFrame.testSiblingPostMessage();
+      subframe.testSiblingPostMessage();
     }
 
     function testSiblingPostMessage()
     {
       window.parent.postMessage("test-finished", "http://mochi.test:8888");
     }
 
     function setup()
--- a/js/xpconnect/tests/mochitest/test_sameOriginPolicy.html
+++ b/js/xpconnect/tests/mochitest/test_sameOriginPolicy.html
@@ -35,19 +35,17 @@ function check(obj, prop, allowed, write
     accessed = true;
   } catch (e) {}
   is(accessed, allowed, prop + " is correctly (in)accessible for " + (write ? 'write' : 'read'));
 }
 
 var crossOriginReadableWindowProps = ['blur', 'close', 'closed', 'focus',
                                       'frames', 'location', 'length',
                                       'opener', 'parent', 'postMessage',
-                                      'self', 'top', 'window',
-                                      /* indexed and named accessors */
-                                      '0', 'subframe'];
+                                      'self', 'top', 'window'];
 
 function isCrossOriginReadable(obj, prop) {
   if (obj == "Window")
     return crossOriginReadableWindowProps.indexOf(prop) != -1;
   if (obj == "Location")
     return prop == 'replace';
   return false;
 }
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -160,59 +160,16 @@ IsPermitted(const char *name, JSFlatStri
     return false;
 }
 
 #undef NAME
 #undef RW
 #undef R
 #undef W
 
-static bool
-IsFrameId(JSContext *cx, JSObject *objArg, jsid idArg)
-{
-    RootedObject obj(cx, objArg);
-    RootedId id(cx, idArg);
-
-    obj = JS_ObjectToInnerObject(cx, obj);
-    MOZ_ASSERT(!js::IsWrapper(obj));
-    XPCWrappedNative *wn = IS_WN_REFLECTOR(obj) ? XPCWrappedNative::Get(obj)
-                                                : nullptr;
-    if (!wn) {
-        return false;
-    }
-
-    nsCOMPtr<nsIDOMWindow> domwin(do_QueryWrappedNative(wn));
-    if (!domwin) {
-        return false;
-    }
-
-    nsCOMPtr<nsIDOMWindowCollection> col;
-    domwin->GetFrames(getter_AddRefs(col));
-    if (!col) {
-        return false;
-    }
-
-    if (JSID_IS_INT(id)) {
-        col->Item(JSID_TO_INT(id), getter_AddRefs(domwin));
-    } else if (JSID_IS_STRING(id)) {
-        nsAutoString str(JS_GetInternedStringChars(JSID_TO_STRING(id)));
-        col->NamedItem(str, getter_AddRefs(domwin));
-    } else {
-        return false;
-    }
-
-    return domwin != nullptr;
-}
-
-static bool
-IsWindow(const char *name)
-{
-    return name[0] == 'W' && !strcmp(name, "Window");
-}
-
 bool
 AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapperArg, jsid idArg,
                                           Wrapper::Action act)
 {
     if (!XPCWrapper::GetSecurityManager())
         return true;
 
     if (act == Wrapper::CALL)
@@ -238,32 +195,16 @@ AccessCheck::isCrossOriginAccessPermitte
     else
         name = clasp->name;
 
     if (JSID_IS_STRING(id)) {
         if (IsPermitted(name, JSID_TO_FLAT_STRING(id), act == Wrapper::SET))
             return true;
     }
 
-    if (act != Wrapper::GET)
-        return false;
-
-    // Check for frame IDs. If we're resolving named frames, make sure to only
-    // resolve ones that don't shadow native properties. See bug 860494.
-    if (IsWindow(name)) {
-        if (JSID_IS_STRING(id) && !XrayUtils::IsXrayResolving(cx, wrapper, id)) {
-            bool wouldShadow = false;
-            if (!XrayUtils::HasNativeProperty(cx, wrapper, id, &wouldShadow) ||
-                wouldShadow)
-            {
-                return false;
-            }
-        }
-        return IsFrameId(cx, obj, id);
-    }
     return false;
 }
 
 bool
 AccessCheck::needsSystemOnlyWrapper(JSObject *obj)
 {
     JSObject* wrapper = obj;
     if (dom::GetSameCompartmentWrapperForDOMBinding(wrapper))