Bug 832014 part 8. Switch Location to WebIDL bindings. r=peterv,bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 11 Jul 2014 19:32:46 -0400
changeset 214508 fb30689a1d8c665db1df49529b44656351efa7fc
parent 214507 460159ffbb79a924d5de2f00145a642f9b0c97ec
child 214509 7ebd702e6442e43cefec06d319db29fe3cf1a101
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv, bholley
bugs832014
milestone33.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 832014 part 8. Switch Location to WebIDL bindings. r=peterv,bholley
dom/base/nsLocation.cpp
dom/base/nsLocation.h
dom/bindings/Bindings.conf
dom/tests/mochitest/bugs/test_bug291377.html
dom/tests/mochitest/bugs/test_bug541530.html
js/xpconnect/tests/mochitest/file_bug802557.html
js/xpconnect/tests/mochitest/test_bug793969.html
js/xpconnect/tests/mochitest/test_bug802557.html
js/xpconnect/tests/mochitest/test_bug870423.html
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -27,16 +27,17 @@
 #include "nsReadableUtils.h"
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "mozilla/Likely.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsNullPrincipal.h"
 #include "ScriptSettings.h"
+#include "mozilla/dom/LocationBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static nsresult
 GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
 {
   aCharset.Truncate();
@@ -55,16 +56,17 @@ GetDocumentCharacterSetForURI(const nsAS
   return NS_OK;
 }
 
 nsLocation::nsLocation(nsPIDOMWindow* aWindow, nsIDocShell *aDocShell)
   : mInnerWindow(aWindow)
 {
   MOZ_ASSERT(aDocShell);
   MOZ_ASSERT(mInnerWindow->IsInnerWindow());
+  SetIsDOMBinding();
 
   mDocShell = do_GetWeakReference(aDocShell);
 }
 
 nsLocation::~nsLocation()
 {
 }
 
@@ -1026,8 +1028,14 @@ nsLocation::CallerSubsumes()
   if (MOZ_UNLIKELY(!outer))
     return false;
   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(outer);
   bool subsumes = false;
   nsresult rv = nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(sop->GetPrincipal(), &subsumes);
   NS_ENSURE_SUCCESS(rv, false);
   return subsumes;
 }
+
+JSObject*
+nsLocation::WrapObject(JSContext* aCx)
+{
+  return LocationBinding::Wrap(aCx, this);
+}
--- a/dom/base/nsLocation.h
+++ b/dom/base/nsLocation.h
@@ -129,16 +129,17 @@ public:
   void Stringify(nsAString& aRetval, ErrorResult& aError)
   {
     GetHref(aRetval, aError);
   }
   nsPIDOMWindow* GetParentObject() const
   {
     return mInnerWindow;
   }
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
 protected:
   virtual ~nsLocation();
 
   // In the case of jar: uris, we sometimes want the place the jar was
   // fetched from as the URI instead of the jar: uri itself.  Pass in
   // true for aGetInnermostURI when that's the case.
   nsresult GetURI(nsIURI** aURL, bool aGetInnermostURI = false);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -737,21 +737,17 @@ DOMInterfaces = {
 },
 
 'LocalMediaStream': {
     'headerFile': 'DOMMediaStream.h',
     'nativeType': 'mozilla::DOMLocalMediaStream'
 },
 
 'Location': {
-    # NOTE: Before you turn on codegen for Location, make sure all the
-    # Unforgeable stuff is dealt with.
     'nativeType': 'nsLocation',
-    'skipGen': True,
-    'register': False
 },
 
 'MediaList': {
     'nativeType': 'nsMediaList',
     'headerFile': 'nsIMediaList.h',
 },
 
 'MediaSource': [{
--- a/dom/tests/mochitest/bugs/test_bug291377.html
+++ b/dom/tests/mochitest/bugs/test_bug291377.html
@@ -21,20 +21,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 var threw = true;
 try {
   window.location.port = -2;
   threw = false;
 } catch (e) {
   /* Check that we can touch various properties */
   isnot(e.lineNumber, undefined, "Unexpected line number"); //This line number is dependent on the implementation of the SpecialPowers API
   is(e.name, "NS_ERROR_MALFORMED_URI", "Unexpected exception name");
-  isnot(e.message, "", "Should have a message");
+  ise(e.message, "", "Should not have a message for this case");
   isnot(e.result, 0, "Should have a result");
   
   is(e.result, SpecialPowers.Cr.NS_ERROR_MALFORMED_URI);
 }
 
-is(threw, true, "Not enough arguments to a call should throw");
+is(threw, true, "We need a different testcase for XPConnect exceptions?");
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/tests/mochitest/bugs/test_bug541530.html
+++ b/dom/tests/mochitest/bugs/test_bug541530.html
@@ -45,38 +45,39 @@ try {
     ok(false, "should not be able to defineGetter(window.location)");
 } catch (e) {
 }
 
 try {
     this.__defineGetter__.call(window.location, 'href', function(){});
     ok(false, "shouldn't be able to override location.href");
 } catch (e) {
-    ok(/shadow/.exec(e.message), "Should be caught by the anti-shadow mechanism.");
+    ok(/shadow/.exec(e.message) ||
+       /can't redefine non-configurable/.exec(e.message),
+       "Should be caught by the anti-shadow mechanism.");
 }
 
 // Try deleting the property.
 delete window.location.href;
 ok(typeof window.location.href !== 'undefined',
    "shouldn't be able to delete the inherited property");
 delete Object.getPrototypeOf(window.location).href;
 ok(typeof window.location.href !== 'undefined',
    "shouldn't be able to delete the property off of the prototype");
 
-try {
-    this.__defineGetter__.call(Object.getPrototypeOf(window.location), 'href', function(){});
-    ok(false, "shouldn't be able to use the prototype");
-} catch (e) {
-}
+this.__defineGetter__.call(Object.getPrototypeOf(window.location), 'href', function(){});
+ok(true, "should be able to define things on the prototype");
 
 try {
     this.__defineSetter__.call(window.location, 'href', function(){});
     ok(false, "overrode a setter for location.href?");
 } catch (e) {
-    ok(/shadow/.exec(e.message), "Should be caught by the anti-shadow mechanism.");
+    ok(/shadow/.exec(e.message) ||
+       /can't redefine non-configurable/.exec(e.message),
+       "Should be caught by the anti-shadow mechanism.");
 }
 
 try {
     this.__defineGetter__.call(document, 'location', function(){});
     ok(false, "shouldn't be able to override document.location");
 } catch (e) {
 }
 
--- a/js/xpconnect/tests/mochitest/file_bug802557.html
+++ b/js/xpconnect/tests/mochitest/file_bug802557.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script>
 var gTS = window.location.toString;
-var gGHR = Object.__lookupGetter__.call(window.location, 'href');
+var gGHR = Object.getOwnPropertyDescriptor(window.location, 'href').get;
 function getTests(fromOuter) {
 
   function loc() fromOuter ? window.location : location;
   return {
     getLocationImplicit: function() {
       return loc() + "";
     },
     getLocationExplicit: function() {
@@ -18,28 +18,22 @@ function getTests(fromOuter) {
       return gTS.call(loc());
     },
     getLocationApply2: function() {
       return gTS.apply(loc(), []);
     },
     getLocationApply3: function() {
       return Function.call.apply(gTS, [loc()]);
     },
-    getLocationViaPrototype: function() {
-      return Location.prototype.toString.call(loc());
-    },
     getHref: function() {
       return loc().href;
     },
     getHrefViaApply: function() {
       return Function.call.apply(gGHR, [loc()]);
     },
-    getHrefViaPrototype: function() {
-      return Object.getOwnPropertyDescriptor(Location.prototype, 'href').get.call(loc());
-    }
   }
 };
 
 function mungeNames(obj, suffix) {
   var rv = {};
   Object.getOwnPropertyNames(obj)
         .forEach(function (name) rv[name + suffix] = obj[name]);
   return rv;
--- a/js/xpconnect/tests/mochitest/test_bug793969.html
+++ b/js/xpconnect/tests/mochitest/test_bug793969.html
@@ -21,39 +21,30 @@ https://bugzilla.mozilla.org/show_bug.cg
 /** Test for Bug 793969 **/
 function checkThrows(f, desc, skipMessageCheck) {
   try {
     f();
     ok(false, "Should have thrown for " + desc);
   } catch (e) {
     ok(true, "threw correctly");
     if (!skipMessageCheck)
-      ok(/denied/.exec(e), "Correctly threw a security exception: " + e);
+      ok(/denied/.exec(e) ||
+         /can't redefine non-configurable property/.exec(e),
+         "Correctly threw a security exception: " + e);
   }
 }
 
 // NB: These sets will be no-ops (throw in strict mode) because setting an inherited readonly value prop has those semantics.
 checkThrows(function() { "use strict"; location.valueOf = 'hah'; }, 'Shadow with string', /* skipMessageCheck = */ true);
 checkThrows(function() { "use strict"; location.valueOf = function() { return {a: 'hah'};} }, 'Shadow with function', /* skipMessageCheck = */ true);
 checkThrows(function() { Object.defineProperty(location, 'valueOf', { value: function() { return 'hah'; } }); }, 'defineProperty with value');
 checkThrows(function() { delete location.valueOf; Object.defineProperty(location, 'valueOf', { value: function() { return 'hah'; } }); }, 'delete + defineProperty with value');
-checkThrows(function() { Object.defineProperty(location, 'valueOf', { getter: function() { return 'hah'; } }); }, 'defineProperty with getter');
-checkThrows(function() { delete location.valueOf; Object.defineProperty(location, 'valueOf', { getter: function() { return 'hah'; } }); }, 'delete + defineProperty with getter');
+checkThrows(function() { Object.defineProperty(location, 'valueOf', { get: function() { return 'hah'; } }); }, 'defineProperty with getter');
+checkThrows(function() { delete location.valueOf; Object.defineProperty(location, 'valueOf', { get: function() { return 'hah'; } }); }, 'delete + defineProperty with getter');
 
 Object.prototype.valueOf = function() { return 'hah'; };
 is(({}).valueOf(), 'hah', "Shadowing on Object.prototype works for vanilla objects");
 is(location.valueOf(), location, "Shadowing on Object.prototype and Location.prototype doesn't for location objects");
 
-// Make sure that Location.prototype can't be mucked with.
-function checkProto() {
-  "use strict"
-  checkThrows(function() { Location.prototype.foo = 'hah'; }, 'adding new property to Location.prototype', /* skipMessageCheck = */ true);
-  checkThrows(function() { Location.prototype.valueOf = 'hah'; }, 'defining valueOf on Location.prototype', /* skipMessageCheck = */ true);
-  checkThrows(function() { delete Location.prototype.toString; }, 'deleting property on Location.prototype', /* skipMessageCheck = */ true);
-  checkThrows(function() { Location.prototype.toString = 'hah'; }, 'setting property on Location.prototype', /* skipMessageCheck = */ true);
-  checkThrows(function() { Object.defineProperty(Location.prototype, 'toString', {value: 'hah'}); }, 'defining property on Location.prototype', /* skipMessageCheck = */ true);
-};
-checkProto();
-
 </script>
 </pre>
 </body>
 </html>
--- a/js/xpconnect/tests/mochitest/test_bug802557.html
+++ b/js/xpconnect/tests/mochitest/test_bug802557.html
@@ -30,22 +30,20 @@ https://bugzilla.mozilla.org/show_bug.cg
     window.iWin = ifr.contentWindow;
 
     if (loadCount == 1) {
       gLoc = iWin.location;
       // Note that accessors pulled off Xrays are currently bound. This is bug 658909.
       // [getter, description, locationObj, bound]
       gGetters = [[ location.toString, 'toString from LW' ],
                   [ gLoc.toString, 'toString from XLW' ],
-                  [ Location.prototype.toString, 'toString from Location.prototype' ],
-                  [ iWin.Location.prototype.toString, 'toString from iWin.Location.prototype' ],
                   [ Object.__lookupGetter__.call(location, 'href'), 'href getter from LW' ],
                   [ Object.__lookupGetter__.call(gLoc, 'href'), 'href getter from XLW' ],
-                  [ Object.getOwnPropertyDescriptor(Location.prototype, 'href').get, 'href getter from Location.prototype' ],
-                  [ Object.getOwnPropertyDescriptor(iWin.Location.prototype, 'href').get, 'href getter from iWin.Location.prototype' ],
+                  [ Object.getOwnPropertyDescriptor(location, 'href').get, 'href getter from location' ],
+                  [ Object.getOwnPropertyDescriptor(gLoc, 'href').get, 'href getter from iWin.location' ],
                   [ function() { return this + ''; }, 'implicit conversion via [[DefaultValue]]', /* doMessageCheck = */ true ]];
       gGetters.forEach(function(item) {
         try {
           is(item[0].call(location), location.toString(), 'Same-origin LW: ' + item[1]);
           is(item[0].call(gLoc), gLoc.toString(), 'Same-origin XLW: ' + item[1]);
         } catch (e) {
           ok(false, "Threw while applying " + item[1] + " to same-origin location object: " + e);
         }
@@ -66,16 +64,42 @@ https://bugzilla.mozilla.org/show_bug.cg
          is(gTestFunctions[fun](), win.location.toString(), "allowed via " + fun);
       win.location = 'http://example.org/tests/js/xpconnect/tests/mochitest/file_bug802557.html';
     }
     else if (loadCount == 4) {
       for (fun in gTestFunctions) {
         var f = gTestFunctions[fun];
         checkThrows(f, "calling " + fun);
       }
+
+      // Verify that URL.prototype.toString can't be applied to Location
+      var threw = false;
+      try {
+        URL.prototype.toString.call(location);
+      } catch (e) {
+        threw = true;
+      }
+      ok(threw,
+         "Should not be able to use URL.prototype.toString on a Location instance");
+  
+      // Verify that URL.prototype.href getter can't be applied to Location
+      threw = false;
+      var reachedTest = false;
+      try {
+        var get = Object.getOwnPropertyDescriptor(URL.prototype, "href").get;
+        is(typeof(get), "function", "Should have an href getter on URL.prototype");
+        var reachedTest = true;
+        get.call(location);
+      } catch (e) {
+        threw = true;
+      }
+      ok(reachedTest,
+         "Should not be able to find URL.prototype.href getter");
+      ok(threw,
+         "Should not be able to use URL.prototype.href getter on a Location instance");
       SimpleTest.finish();
     }
   }
 
 
 
 </script>
 </head>
--- a/js/xpconnect/tests/mochitest/test_bug870423.html
+++ b/js/xpconnect/tests/mochitest/test_bug870423.html
@@ -18,17 +18,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     var xowin = $('xoifr').contentWindow;
 
     check(window, sowin, 'HTMLBodyElement', function(win) { return win.document.body; });
     check(window, sowin, 'HTMLDocument', function(win) { return win.document; });
     check(window, sowin, 'Window', function(win) { return win; });
     check(window, sowin, 'Location', function(win) { return win.location; });
 
     ok(xowin instanceof Window, "Cross-origin instanceof should work");
-    todo(xowin.location instanceof Location, "Cross-origin instanceof should work");
+    ok(xowin.location instanceof Location, "Cross-origin instanceof should work");
 
     SimpleTest.finish();
   }
 
   function check(win1, win2, constructorName, getInstance) {
     ok(getInstance(win1) instanceof win2[constructorName],
        "Cross-Scope instanceof works: " + constructorName + ", " + win1.location + ", " + win2.location);
     ok(getInstance(win2) instanceof win1[constructorName],