Bug 1174731 - patch 1 - Make searchParams attribute readonly, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 24 Jun 2015 12:15:59 -0700
changeset 280931 9c93813baadc699066a79ea770cf041975d61d56
parent 280930 60fe089face1b86480c1951c23234342607b0baa
child 280932 44002ebe4e2cf60cc69e1f0bf1388172b87c1836
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1174731
milestone41.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 1174731 - patch 1 - Make searchParams attribute readonly, r=smaug
caps/BasePrincipal.cpp
dom/base/Link.cpp
dom/base/Link.h
dom/base/URL.cpp
dom/base/URL.h
dom/base/URLSearchParams.cpp
dom/base/URLSearchParams.h
dom/base/test/test_urlSearchParams.html
dom/fetch/Fetch.cpp
dom/html/HTMLAreaElement.h
dom/webidl/URLUtils.webidl
dom/workers/URL.cpp
dom/workers/URL.h
dom/workers/test/urlSearchParams_worker.js
toolkit/components/places/tests/cpp/mock_Link.h
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -23,17 +23,17 @@ namespace mozilla {
 
 using dom::URLSearchParams;
 
 void
 OriginAttributes::CreateSuffix(nsACString& aStr) const
 {
   MOZ_RELEASE_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
 
-  nsRefPtr<URLSearchParams> usp = new URLSearchParams();
+  nsRefPtr<URLSearchParams> usp = new URLSearchParams(nullptr);
   nsAutoString value;
 
   if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
     value.AppendInt(mAppId);
     usp->Set(NS_LITERAL_STRING("appId"), value);
   }
 
   if (mInBrowser) {
@@ -103,18 +103,18 @@ OriginAttributes::PopulateFromSuffix(con
   if (aStr.IsEmpty()) {
     return true;
   }
 
   if (aStr[0] != '!') {
     return false;
   }
 
-  nsRefPtr<URLSearchParams> usp = new URLSearchParams();
-  usp->ParseInput(Substring(aStr, 1, aStr.Length() - 1), nullptr);
+  nsRefPtr<URLSearchParams> usp = new URLSearchParams(nullptr);
+  usp->ParseInput(Substring(aStr, 1, aStr.Length() - 1));
 
   PopulateFromSuffixIterator iterator(this);
   return usp->ForEach(iterator);
 }
 
 void
 OriginAttributes::CookieJar(nsACString& aStr)
 {
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -574,31 +574,16 @@ Link::SizeOfExcludingThis(mozilla::Mallo
 URLSearchParams*
 Link::SearchParams()
 {
   CreateSearchParamsIfNeeded();
   return mSearchParams;
 }
 
 void
-Link::SetSearchParams(URLSearchParams& aSearchParams)
-{
-  if (mSearchParams) {
-    mSearchParams->RemoveObserver(this);
-  }
-
-  mSearchParams = &aSearchParams;
-  mSearchParams->AddObserver(this);
-
-  nsAutoString search;
-  mSearchParams->Serialize(search);
-  SetSearchInternal(search);
-}
-
-void
 Link::URLSearchParamsUpdated(URLSearchParams* aSearchParams)
 {
   MOZ_ASSERT(mSearchParams);
   MOZ_ASSERT(mSearchParams == aSearchParams);
 
   nsString search;
   mSearchParams->Serialize(search);
   SetSearchInternal(search);
@@ -616,34 +601,32 @@ Link::UpdateURLSearchParams()
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
   if (url) {
     nsresult rv = url->GetQuery(search);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to get the query from a nsIURL.");
     }
   }
 
-  mSearchParams->ParseInput(search, this);
+  mSearchParams->ParseInput(search);
 }
 
 void
 Link::CreateSearchParamsIfNeeded()
 {
   if (!mSearchParams) {
-    mSearchParams = new URLSearchParams();
-    mSearchParams->AddObserver(this);
+    mSearchParams = new URLSearchParams(this);
     UpdateURLSearchParams();
   }
 }
 
 void
 Link::Unlink()
 {
   if (mSearchParams) {
-    mSearchParams->RemoveObserver(this);
     mSearchParams = nullptr;
   }
 }
 
 void
 Link::Traverse(nsCycleCollectionTraversalCallback &cb)
 {
   Link* tmp = this;
--- a/dom/base/Link.h
+++ b/dom/base/Link.h
@@ -59,17 +59,16 @@ public:
    */
   void SetProtocol(const nsAString &aProtocol, ErrorResult& aError);
   void SetUsername(const nsAString &aUsername, ErrorResult& aError);
   void SetPassword(const nsAString &aPassword, ErrorResult& aError);
   void SetHost(const nsAString &aHost, ErrorResult& aError);
   void SetHostname(const nsAString &aHostname, ErrorResult& aError);
   void SetPathname(const nsAString &aPathname, ErrorResult& aError);
   void SetSearch(const nsAString &aSearch, ErrorResult& aError);
-  void SetSearchParams(mozilla::dom::URLSearchParams& aSearchParams);
   void SetPort(const nsAString &aPort, ErrorResult& aError);
   void SetHash(const nsAString &aHash, ErrorResult& aError);
   void GetOrigin(nsAString &aOrigin, ErrorResult& aError);
   void GetProtocol(nsAString &_protocol, ErrorResult& aError);
   void GetUsername(nsAString &aUsername, ErrorResult& aError);
   void GetPassword(nsAString &aPassword, ErrorResult& aError);
   void GetHost(nsAString &_host, ErrorResult& aError);
   void GetHostname(nsAString &_hostname, ErrorResult& aError);
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -22,17 +22,16 @@
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(URL)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(URL)
   if (tmp->mSearchParams) {
-    tmp->mSearchParams->RemoveObserver(tmp);
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mSearchParams)
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(URL)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSearchParams)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -369,17 +368,17 @@ URL::UpdateURLSearchParams()
   nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
   if (url) {
     nsresult rv = url->GetQuery(search);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to get the query from a nsIURL.");
     }
   }
 
-  mSearchParams->ParseInput(search, this);
+  mSearchParams->ParseInput(search);
 }
 
 void
 URL::GetHostname(nsAString& aHostname, ErrorResult& aRv) const
 {
   aHostname.Truncate();
   nsContentUtils::GetHostOrIPv6WithBrackets(mURI, aHostname);
 }
@@ -496,32 +495,16 @@ URL::SetSearchInternal(const nsAString& 
 URLSearchParams*
 URL::SearchParams()
 {
   CreateSearchParamsIfNeeded();
   return mSearchParams;
 }
 
 void
-URL::SetSearchParams(URLSearchParams& aSearchParams)
-{
-  if (mSearchParams) {
-    mSearchParams->RemoveObserver(this);
-  }
-
-  // the observer will be cleared using the cycle collector.
-  mSearchParams = &aSearchParams;
-  mSearchParams->AddObserver(this);
-
-  nsAutoString search;
-  mSearchParams->Serialize(search);
-  SetSearchInternal(search);
-}
-
-void
 URL::GetHash(nsAString& aHash, ErrorResult& aRv) const
 {
   aHash.Truncate();
 
   nsAutoCString ref;
   nsresult rv = mURI->GetRef(ref);
   if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
     aHash.Assign(char16_t('#'));
@@ -545,16 +528,15 @@ bool IsChromeURI(nsIURI* aURI)
       return isChrome;
   return false;
 }
 
 void
 URL::CreateSearchParamsIfNeeded()
 {
   if (!mSearchParams) {
-    mSearchParams = new URLSearchParams();
-    mSearchParams->AddObserver(this);
+    mSearchParams = new URLSearchParams(this);
     UpdateURLSearchParams();
   }
 }
 
 }
 }
--- a/dom/base/URL.h
+++ b/dom/base/URL.h
@@ -114,18 +114,16 @@ public:
   void SetPathname(const nsAString& aPathname, ErrorResult& aRv);
 
   void GetSearch(nsAString& aRetval, ErrorResult& aRv) const;
 
   void SetSearch(const nsAString& aArg, ErrorResult& aRv);
 
   URLSearchParams* SearchParams();
 
-  void SetSearchParams(URLSearchParams& aSearchParams);
-
   void GetHash(nsAString& aRetval, ErrorResult& aRv) const;
 
   void SetHash(const nsAString& aArg, ErrorResult& aRv);
 
   void Stringify(nsAString& aRetval, ErrorResult& aRv) const
   {
     GetHref(aRetval, aRv);
   }
--- a/dom/base/URLSearchParams.cpp
+++ b/dom/base/URLSearchParams.cpp
@@ -7,26 +7,27 @@
 #include "URLSearchParams.h"
 #include "mozilla/dom/URLSearchParamsBinding.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "nsDOMString.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(URLSearchParams, mObservers)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(URLSearchParams, mObserver)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(URLSearchParams)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(URLSearchParams)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URLSearchParams)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-URLSearchParams::URLSearchParams()
+URLSearchParams::URLSearchParams(URLSearchParamsObserver* aObserver)
+  : mObserver(aObserver)
 {
 }
 
 URLSearchParams::~URLSearchParams()
 {
   DeleteAll();
 }
 
@@ -36,34 +37,33 @@ URLSearchParams::WrapObject(JSContext* a
   return URLSearchParamsBinding::Wrap(aCx, this, aGivenProto);
 }
 
 /* static */ already_AddRefed<URLSearchParams>
 URLSearchParams::Constructor(const GlobalObject& aGlobal,
                              const nsAString& aInit,
                              ErrorResult& aRv)
 {
-  nsRefPtr<URLSearchParams> sp = new URLSearchParams();
-  sp->ParseInput(NS_ConvertUTF16toUTF8(aInit), nullptr);
+  nsRefPtr<URLSearchParams> sp = new URLSearchParams(nullptr);
+  sp->ParseInput(NS_ConvertUTF16toUTF8(aInit));
   return sp.forget();
 }
 
 /* static */ already_AddRefed<URLSearchParams>
 URLSearchParams::Constructor(const GlobalObject& aGlobal,
                              URLSearchParams& aInit,
                              ErrorResult& aRv)
 {
-  nsRefPtr<URLSearchParams> sp = new URLSearchParams();
+  nsRefPtr<URLSearchParams> sp = new URLSearchParams(nullptr);
   sp->mSearchParams = aInit.mSearchParams;
   return sp.forget();
 }
 
 void
-URLSearchParams::ParseInput(const nsACString& aInput,
-                            URLSearchParamsObserver* aObserver)
+URLSearchParams::ParseInput(const nsACString& aInput)
 {
   // Remove all the existing data before parsing a new input.
   DeleteAll();
 
   nsACString::const_iterator start, end;
   aInput.BeginReading(start);
   aInput.EndReading(end);
   nsACString::const_iterator iter(start);
@@ -103,18 +103,16 @@ URLSearchParams::ParseInput(const nsACSt
     nsAutoString decodedName;
     DecodeString(name, decodedName);
 
     nsAutoString decodedValue;
     DecodeString(value, decodedValue);
 
     AppendInternal(decodedName, decodedValue);
   }
-
-  NotifyObservers(aObserver);
 }
 
 void
 URLSearchParams::DecodeString(const nsACString& aInput, nsAString& aOutput)
 {
   nsACString::const_iterator start, end;
   aInput.BeginReading(start);
   aInput.EndReading(end);
@@ -204,37 +202,16 @@ URLSearchParams::ConvertString(const nsA
   }
 
   if (newOutputLength < outputLength) {
     aOutput.Truncate(newOutputLength);
   }
 }
 
 void
-URLSearchParams::AddObserver(URLSearchParamsObserver* aObserver)
-{
-  MOZ_ASSERT(aObserver);
-  MOZ_ASSERT(!mObservers.Contains(aObserver));
-  mObservers.AppendElement(aObserver);
-}
-
-void
-URLSearchParams::RemoveObserver(URLSearchParamsObserver* aObserver)
-{
-  MOZ_ASSERT(aObserver);
-  mObservers.RemoveElement(aObserver);
-}
-
-void
-URLSearchParams::RemoveObservers()
-{
-  mObservers.Clear();
-}
-
-void
 URLSearchParams::Get(const nsAString& aName, nsString& aRetval)
 {
   SetDOMStringToNull(aRetval);
 
   for (uint32_t i = 0, len = mSearchParams.Length(); i < len; ++i) {
     if (mSearchParams[i].mKey.Equals(aName)) {
       aRetval.Assign(mSearchParams[i].mValue);
       break;
@@ -275,24 +252,24 @@ URLSearchParams::Set(const nsAString& aN
 
   if (!param) {
     param = mSearchParams.AppendElement();
     param->mKey = aName;
   }
 
   param->mValue = aValue;
 
-  NotifyObservers(nullptr);
+  NotifyObserver();
 }
 
 void
 URLSearchParams::Append(const nsAString& aName, const nsAString& aValue)
 {
   AppendInternal(aName, aValue);
-  NotifyObservers(nullptr);
+  NotifyObserver();
 }
 
 void
 URLSearchParams::AppendInternal(const nsAString& aName, const nsAString& aValue)
 {
   Param* param = mSearchParams.AppendElement();
   param->mKey = aName;
   param->mValue = aValue;
@@ -319,17 +296,17 @@ URLSearchParams::Delete(const nsAString&
       mSearchParams.RemoveElementAt(i);
       found = true;
     } else {
       ++i;
     }
   }
 
   if (found) {
-    NotifyObservers(nullptr);
+    NotifyObserver();
   }
 }
 
 void
 URLSearchParams::DeleteAll()
 {
   mSearchParams.Clear();
 }
@@ -375,19 +352,17 @@ URLSearchParams::Serialize(nsAString& aV
 
     SerializeString(NS_ConvertUTF16toUTF8(mSearchParams[i].mKey), aValue);
     aValue.Append('=');
     SerializeString(NS_ConvertUTF16toUTF8(mSearchParams[i].mValue), aValue);
   }
 }
 
 void
-URLSearchParams::NotifyObservers(URLSearchParamsObserver* aExceptObserver)
+URLSearchParams::NotifyObserver()
 {
-  for (uint32_t i = 0; i < mObservers.Length(); ++i) {
-    if (mObservers[i] != aExceptObserver) {
-      mObservers[i]->URLSearchParamsUpdated(this);
-    }
+  if (mObserver) {
+    mObserver->URLSearchParamsUpdated(this);
   }
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/URLSearchParams.h
+++ b/dom/base/URLSearchParams.h
@@ -35,17 +35,17 @@ class URLSearchParams final : public nsI
                               public nsWrapperCache
 {
   ~URLSearchParams();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(URLSearchParams)
 
-  URLSearchParams();
+  explicit URLSearchParams(URLSearchParamsObserver* aObserver);
 
   // WebIDL methods
   nsISupports* GetParentObject() const
   {
     return nullptr;
   }
 
   virtual JSObject*
@@ -54,22 +54,17 @@ public:
   static already_AddRefed<URLSearchParams>
   Constructor(const GlobalObject& aGlobal, const nsAString& aInit,
               ErrorResult& aRv);
 
   static already_AddRefed<URLSearchParams>
   Constructor(const GlobalObject& aGlobal, URLSearchParams& aInit,
               ErrorResult& aRv);
 
-  void ParseInput(const nsACString& aInput,
-                  URLSearchParamsObserver* aObserver);
-
-  void AddObserver(URLSearchParamsObserver* aObserver);
-  void RemoveObserver(URLSearchParamsObserver* aObserver);
-  void RemoveObservers();
+  void ParseInput(const nsACString& aInput);
 
   void Serialize(nsAString& aValue) const;
 
   void Get(const nsAString& aName, nsString& aRetval);
 
   void GetAll(const nsAString& aName, nsTArray<nsString >& aRetval);
 
   void Set(const nsAString& aName, const nsAString& aValue);
@@ -108,26 +103,26 @@ public:
 private:
   void AppendInternal(const nsAString& aName, const nsAString& aValue);
 
   void DeleteAll();
 
   void DecodeString(const nsACString& aInput, nsAString& aOutput);
   void ConvertString(const nsACString& aInput, nsAString& aOutput);
 
-  void NotifyObservers(URLSearchParamsObserver* aExceptObserver);
+  void NotifyObserver();
 
   struct Param
   {
     nsString mKey;
     nsString mValue;
   };
 
   nsTArray<Param> mSearchParams;
 
-  nsTArray<nsRefPtr<URLSearchParamsObserver>> mObservers;
+  nsRefPtr<URLSearchParamsObserver> mObserver;
   nsCOMPtr<nsIUnicodeDecoder> mDecoder;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_URLSearchParams_h */
--- a/dom/base/test/test_urlSearchParams.html
+++ b/dom/base/test/test_urlSearchParams.html
@@ -119,140 +119,51 @@ https://bugzilla.mozilla.org/show_bug.cg
     ok(url.searchParams.has('a'), "URL.searchParams.has('a')");
     is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')");
     ok(url.searchParams.has('c'), "URL.searchParams.has('c')");
     is(url.searchParams.get('c'), 'd', "URL.searchParams.get('c')");
 
     url.searchParams.set('e', 'f');
     ok(url.href.indexOf('e=f') != 1, 'URL right');
 
-    var u = new URLSearchParams();
-    u.append('foo', 'bar');
-    url.searchParams = u;
-    is(url.searchParams, u, "URL.searchParams is the same object");
-    is(url.searchParams.get('foo'), 'bar', "URL.searchParams.get('foo')");
-    is(url.href, 'http://www.example.net/?foo=bar', 'URL right');
-
-    try {
-      url.searchParams = null;
-      ok(false, "URLSearchParams is not nullable");
-    } catch(e) {
-      ok(true, "URLSearchParams is not nullable");
-    }
-
-    var url2 = new URL('http://www.example.net?e=f');
-    url.searchParams = url2.searchParams;
-    is(url.searchParams, url2.searchParams, "URL.searchParams is not the same object");
-    is(url.searchParams.get('e'), 'f', "URL.searchParams.get('e')");
-
-    url.href = "http://www.example.net?bar=foo";
-    is(url.searchParams.get('bar'), 'foo', "URL.searchParams.get('bar')");
-
     runTest();
   }
 
   function testElement(e) {
     ok(e, 'element exists');
     ok(e.searchParams, "e.searchParams exists!");
     ok(e.searchParams.has('a'), "e.searchParams.has('a')");
     is(e.searchParams.get('a'), 'b', "e.searchParams.get('a')");
     ok(e.searchParams.has('c'), "e.searchParams.has('c')");
     is(e.searchParams.get('c'), 'd', "e.searchParams.get('c')");
 
     e.searchParams.set('e', 'f');
     ok(e.href.indexOf('e=f') != 1, 'e is right');
 
-    var u = new URLSearchParams();
-    u.append('foo', 'bar');
-    e.searchParams = u;
-    is(e.searchParams, u, "e.searchParams is the same object");
-    is(e.searchParams.get('foo'), 'bar', "e.searchParams.get('foo')");
-    is(e.href, 'http://www.example.net/?foo=bar', 'e is right');
-
-    try {
-      e.searchParams = null;
-      ok(false, "URLSearchParams is not nullable");
-    } catch(e) {
-      ok(true, "URLSearchParams is not nullable");
-    }
-
-    var url2 = new URL('http://www.example.net?e=f');
-    e.searchParams = url2.searchParams;
-    is(e.searchParams, url2.searchParams, "e.searchParams is not the same object");
-    is(e.searchParams.get('e'), 'f', "e.searchParams.get('e')");
-
-    e.href = "http://www.example.net?bar=foo";
-    is(e.searchParams.get('bar'), 'foo', "e.searchParams.get('bar')");
-
-    e.setAttribute('href', "http://www.example.net?bar2=foo2");
-    is(e.searchParams.get('bar2'), 'foo2', "e.searchParams.get('bar2')");
-
     runTest();
   }
 
   function testEncoding() {
     var encoding = [ [ '1', '1' ],
                      [ 'a b', 'a+b' ],
                      [ '<>', '%3C%3E' ],
                      [ '\u0541', '%D5%81'] ];
 
     for (var i = 0; i < encoding.length; ++i) {
-      var a = new URLSearchParams();
-      a.set('a', encoding[i][0]);
-
       var url = new URL('http://www.example.net');
-      url.searchParams = a;
+      url.searchParams.set('a', encoding[i][0]);
       is(url.href, 'http://www.example.net/?a=' + encoding[i][1]);
 
       var url2 = new URL(url.href);
       is(url2.searchParams.get('a'), encoding[i][0], 'a is still there');
     }
 
     runTest();
   }
 
-  function testMultiURL() {
-    var a = new URL('http://www.example.net?a=b&c=d');
-    var b = new URL('http://www.example.net?e=f');
-    var c = document.createElement('a');
-    var d = document.createElement('area');
-    ok(a.searchParams.has('a'), "a.searchParams.has('a')");
-    ok(a.searchParams.has('c'), "a.searchParams.has('c')");
-    ok(b.searchParams.has('e'), "b.searchParams.has('e')");
-    ok(c.searchParams, "c.searchParams");
-    ok(d.searchParams, "d.searchParams");
-
-    var u = new URLSearchParams();
-    a.searchParams = b.searchParams = c.searchParams = d.searchParams = u;
-    is(a.searchParams, u, "a.searchParams === u");
-    is(b.searchParams, u, "b.searchParams === u");
-    is(c.searchParams, u, "c.searchParams === u");
-    is(d.searchParams, u, "d.searchParams === u");
-    ok(!a.searchParams.has('a'), "!a.searchParams.has('a')");
-    ok(!a.searchParams.has('c'), "!a.searchParams.has('c')");
-    ok(!b.searchParams.has('e'), "!b.searchParams.has('e')");
-
-    u.append('foo', 'bar');
-    is(a.searchParams.get('foo'), 'bar', "a has foo=bar");
-    is(b.searchParams.get('foo'), 'bar', "b has foo=bar");
-    is(c.searchParams.get('foo'), 'bar', "c has foo=bar");
-    is(d.searchParams.get('foo'), 'bar', "d has foo=bar");
-    is(a + "", b + "", "stringify a == b");
-    is(c.searchParams + "", b.searchParams + "", "stringify c.searchParams == b.searchParams");
-    is(d.searchParams + "", b.searchParams + "", "stringify d.searchParams == b.searchParams");
-
-    a.search = "?bar=foo";
-    is(a.searchParams.get('bar'), 'foo', "a has bar=foo");
-    is(b.searchParams.get('bar'), 'foo', "b has bar=foo");
-    is(c.searchParams.get('bar'), 'foo', "c has bar=foo");
-    is(d.searchParams.get('bar'), 'foo', "d has bar=foo");
-
-    runTest();
-  }
-
   function testOrdering() {
     var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6");
     is(a.toString(), "a=1&a=2&b=3&c=4&c=5&a=6", "Order is correct");
     is(a.getAll('a').length, 3, "Correct length of getAll()");
 
     var b = new URLSearchParams();
     b.append('a', '1');
     b.append('b', '2');
@@ -329,17 +240,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   var tests = [
     testSimpleURLSearchParams,
     testCopyURLSearchParams,
     testParserURLSearchParams,
     testURL,
     function() { testElement(document.getElementById('anchor')) },
     function() { testElement(document.getElementById('area')) },
     testEncoding,
-    testMultiURL,
     testOrdering,
     testDelete,
     testGetNULL,
     testSet
   ];
 
   function runTest() {
     if (!tests.length) {
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -1595,18 +1595,18 @@ FetchBody<Derived>::ContinueConsumeBody(
         NS_NAMED_LITERAL_CSTRING(urlDataMimeType, "application/x-www-form-urlencoded");
         bool isValidUrlEncodedMimeType = StringBeginsWith(mMimeType, urlDataMimeType);
 
         if (isValidUrlEncodedMimeType && mMimeType.Length() > urlDataMimeType.Length()) {
           isValidUrlEncodedMimeType = mMimeType[urlDataMimeType.Length()] == ';';
         }
 
         if (isValidUrlEncodedMimeType) {
-          nsRefPtr<URLSearchParams> params = new URLSearchParams();
-          params->ParseInput(data, /* aObserver */ nullptr);
+          nsRefPtr<URLSearchParams> params = new URLSearchParams(nullptr);
+          params->ParseInput(data);
 
           nsRefPtr<nsFormData> fd = new nsFormData(DerivedClass()->GetParentObject());
           FillFormIterator iterator(fd);
           DebugOnly<bool> status = params->ForEach(iterator);
           MOZ_ASSERT(status);
 
           localPromise->MaybeResolve(fd);
         } else {
--- a/dom/html/HTMLAreaElement.h
+++ b/dom/html/HTMLAreaElement.h
@@ -153,17 +153,16 @@ public:
 
   using Link::GetSearch;
   using Link::SetSearch;
 
   using Link::GetHash;
   using Link::SetHash;
 
   // The Link::GetSearchParams is OK for us
-  // The Link::SetSearchParams is OK for us
 
   bool NoHref() const
   {
     return GetBoolAttr(nsGkAtoms::nohref);
   }
 
   void SetNoHref(bool aValue, ErrorResult& aError)
   {
--- a/dom/webidl/URLUtils.webidl
+++ b/dom/webidl/URLUtils.webidl
@@ -46,10 +46,10 @@ interface URLUtils {
   // Bug 824857 should remove this.
   [Throws]
   stringifier;
 };
 
 [NoInterfaceObject,
  Exposed=(Window, Worker)]
 interface URLUtilsSearchParams {
-           attribute URLSearchParams searchParams;
+ readonly attribute URLSearchParams searchParams;
 };
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -834,31 +834,16 @@ URL::SetSearchInternal(const nsAString& 
 mozilla::dom::URLSearchParams*
 URL::SearchParams()
 {
   CreateSearchParamsIfNeeded();
   return mSearchParams;
 }
 
 void
-URL::SetSearchParams(URLSearchParams& aSearchParams)
-{
-  if (mSearchParams) {
-    mSearchParams->RemoveObserver(this);
-  }
-
-  mSearchParams = &aSearchParams;
-  mSearchParams->AddObserver(this);
-
-  nsAutoString search;
-  mSearchParams->Serialize(search);
-  SetSearchInternal(search);
-}
-
-void
 URL::GetHash(nsAString& aHash, ErrorResult& aRv) const
 {
   nsRefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHash, aHash,
                        mURLProxy);
 
   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
@@ -954,23 +939,22 @@ URL::URLSearchParamsUpdated(URLSearchPar
 
 void
 URL::UpdateURLSearchParams()
 {
   if (mSearchParams) {
     nsAutoString search;
     ErrorResult rv;
     GetSearch(search, rv);
-    mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)), this);
+    mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)));
   }
 }
 
 void
 URL::CreateSearchParamsIfNeeded()
 {
   if (!mSearchParams) {
-    mSearchParams = new URLSearchParams();
-    mSearchParams->AddObserver(this);
+    mSearchParams = new URLSearchParams(this);
     UpdateURLSearchParams();
   }
 }
 
 END_WORKERS_NAMESPACE
--- a/dom/workers/URL.h
+++ b/dom/workers/URL.h
@@ -103,18 +103,16 @@ public:
   void SetPathname(const nsAString& aPathname, ErrorResult& aRv);
 
   void GetSearch(nsAString& aSearch, ErrorResult& aRv) const;
 
   void SetSearch(const nsAString& aSearch, ErrorResult& aRv);
 
   URLSearchParams* SearchParams();
 
-  void SetSearchParams(URLSearchParams& aSearchParams);
-
   void GetHash(nsAString& aHost, ErrorResult& aRv) const;
 
   void SetHash(const nsAString& aHash, ErrorResult& aRv);
 
   void Stringify(nsAString& aRetval, ErrorResult& aRv) const
   {
     GetHref(aRetval, aRv);
   }
--- a/dom/workers/test/urlSearchParams_worker.js
+++ b/dom/workers/test/urlSearchParams_worker.js
@@ -111,95 +111,43 @@ onmessage = function() {
     ok(url.searchParams.has('a'), "URL.searchParams.has('a')");
     is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')");
     ok(url.searchParams.has('c'), "URL.searchParams.has('c')");
     is(url.searchParams.get('c'), 'd', "URL.searchParams.get('c')");
 
     url.searchParams.set('e', 'f');
     ok(url.href.indexOf('e=f') != 1, 'URL right');
 
-    var u = new URLSearchParams();
-    u.append('foo', 'bar');
-    url.searchParams = u;
-    is(url.searchParams, u, "URL.searchParams is the same object");
-    is(url.searchParams.get('foo'), 'bar', "URL.searchParams.get('foo')");
-    is(url.href, 'http://www.example.net/?foo=bar', 'URL right');
-
-    try {
-      url.searchParams = null;
-      ok(false, "URLSearchParams is not nullable");
-    } catch(e) {
-      ok(true, "URLSearchParams is not nullable");
-    }
-
-    var url2 = new URL('http://www.example.net?e=f');
-    url.searchParams = url2.searchParams;
-    is(url.searchParams, url2.searchParams, "URL.searchParams is not the same object");
-    is(url.searchParams.get('e'), 'f', "URL.searchParams.get('e')");
-
-    url.href = "http://www.example.net?bar=foo";
-    is(url.searchParams.get('bar'), 'foo', "URL.searchParams.get('bar')");
-
     runTest();
   }
 
   function testEncoding() {
     var encoding = [ [ '1', '1' ],
                      [ 'a b', 'a+b' ],
                      [ '<>', '%3C%3E' ],
                      [ '\u0541', '%D5%81'] ];
 
     for (var i = 0; i < encoding.length; ++i) {
-      var a = new URLSearchParams();
-      a.set('a', encoding[i][0]);
-
       var url = new URL('http://www.example.net');
-      url.searchParams = a;
+      url.searchParams.set('a', encoding[i][0]);
       is(url.href, 'http://www.example.net/?a=' + encoding[i][1]);
 
       var url2 = new URL(url.href);
       is(url2.searchParams.get('a'), encoding[i][0], 'a is still there');
     }
 
     runTest();
   }
 
-  function testMultiURL() {
-    var a = new URL('http://www.example.net?a=b&c=d');
-    var b = new URL('http://www.example.net?e=f');
-    ok(a.searchParams.has('a'), "a.searchParams.has('a')");
-    ok(a.searchParams.has('c'), "a.searchParams.has('c')");
-    ok(b.searchParams.has('e'), "b.searchParams.has('e')");
-
-    var u = new URLSearchParams();
-    a.searchParams = b.searchParams = u;
-    is(a.searchParams, u, "a.searchParams === u");
-    is(b.searchParams, u, "b.searchParams === u");
-    ok(!a.searchParams.has('a'), "!a.searchParams.has('a')");
-    ok(!a.searchParams.has('c'), "!a.searchParams.has('c')");
-    ok(!b.searchParams.has('e'), "!b.searchParams.has('e')");
-
-    u.append('foo', 'bar');
-    is(a.searchParams.get('foo'), 'bar', "a has foo=bar");
-    is(b.searchParams.get('foo'), 'bar', "b has foo=bar");
-    is(a + "", b + "", "stringify a == b");
-
-    a.search = "?bar=foo";
-    is(a.searchParams.get('bar'), 'foo', "a has bar=foo");
-    is(b.searchParams.get('bar'), 'foo', "b has bar=foo");
-
-    runTest();
-  }
   var tests = [
     testSimpleURLSearchParams,
     testCopyURLSearchParams,
     testParserURLSearchParams,
     testURL,
     testEncoding,
-    testMultiURL
   ];
 
   function runTest() {
     if (!tests.length) {
       postMessage({type: 'finish' });
       return;
     }
 
--- a/toolkit/components/places/tests/cpp/mock_Link.h
+++ b/toolkit/components/places/tests/cpp/mock_Link.h
@@ -140,50 +140,37 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(URLSearc
 NS_IMPL_CYCLE_COLLECTING_RELEASE(URLSearchParams)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URLSearchParams)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 
-URLSearchParams::URLSearchParams()
+URLSearchParams::URLSearchParams(URLSearchParamsObserver* aObserver)
 {
 }
 
 URLSearchParams::~URLSearchParams()
 {
 }
 
 JSObject*
 URLSearchParams::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return nullptr;
 }
 
 void
-URLSearchParams::ParseInput(const nsACString& aInput,
-                            URLSearchParamsObserver* aObserver)
+URLSearchParams::ParseInput(const nsACString& aInput)
 {
   NS_NOTREACHED("Unexpected call to URLSearchParams::ParseInput");
 }
 
 void
-URLSearchParams::AddObserver(URLSearchParamsObserver* aObserver)
-{
-  NS_NOTREACHED("Unexpected call to URLSearchParams::SetObserver");
-}
-
-void
-URLSearchParams::RemoveObserver(URLSearchParamsObserver* aObserver)
-{
-  NS_NOTREACHED("Unexpected call to URLSearchParams::SetObserver");
-}
-
-void
 URLSearchParams::Serialize(nsAString& aValue) const
 {
   NS_NOTREACHED("Unexpected call to URLSearchParams::Serialize");
 }
 
 void
 URLSearchParams::Get(const nsAString& aName, nsString& aRetval)
 {
@@ -229,17 +216,17 @@ URLSearchParams::Delete(const nsAString&
 
 void
 URLSearchParams::DeleteAll()
 {
   NS_NOTREACHED("Unexpected call to URLSearchParams::DeleteAll");
 }
 
 void
-URLSearchParams::NotifyObservers(URLSearchParamsObserver* aExceptObserver)
+URLSearchParams::NotifyObserver()
 {
-  NS_NOTREACHED("Unexpected call to URLSearchParams::NotifyObservers");
+  NS_NOTREACHED("Unexpected call to URLSearchParams::NotifyObserver");
 }
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mock_Link_h__