dom/workers/URL.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "URL.h"
     8 #include "nsIDocument.h"
     9 #include "nsIDOMFile.h"
    10 #include "nsIIOService.h"
    11 #include "nsPIDOMWindow.h"
    13 #include "mozilla/dom/URL.h"
    14 #include "mozilla/dom/URLBinding.h"
    15 #include "mozilla/dom/URLSearchParams.h"
    16 #include "nsGlobalWindow.h"
    17 #include "nsHostObjectProtocolHandler.h"
    18 #include "nsNetCID.h"
    19 #include "nsServiceManagerUtils.h"
    20 #include "nsThreadUtils.h"
    22 #include "File.h"
    23 #include "WorkerPrivate.h"
    24 #include "WorkerRunnable.h"
    26 BEGIN_WORKERS_NAMESPACE
    27 using mozilla::dom::GlobalObject;
    29 class URLProxy MOZ_FINAL
    30 {
    31 public:
    32   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLProxy)
    34   URLProxy(mozilla::dom::URL* aURL)
    35     : mURL(aURL)
    36   {
    37     AssertIsOnMainThread();
    38   }
    40   mozilla::dom::URL* URL()
    41   {
    42     return mURL;
    43   }
    45   nsIURI* URI()
    46   {
    47     return mURL->GetURI();
    48   }
    50   void ReleaseURI()
    51   {
    52     AssertIsOnMainThread();
    53     mURL = nullptr;
    54   }
    56 private:
    57   // Private destructor, to discourage deletion outside of Release():
    58   ~URLProxy()
    59   {
    60      MOZ_ASSERT(!mURL);
    61   }
    63   nsRefPtr<mozilla::dom::URL> mURL;
    64 };
    66 // Base class for the URL runnable objects.
    67 class URLRunnable : public nsRunnable
    68 {
    69 protected:
    70   WorkerPrivate* mWorkerPrivate;
    71   nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
    73 protected:
    74   URLRunnable(WorkerPrivate* aWorkerPrivate)
    75   : mWorkerPrivate(aWorkerPrivate)
    76   {
    77     mWorkerPrivate->AssertIsOnWorkerThread();
    78   }
    80 public:
    81   bool
    82   Dispatch(JSContext* aCx)
    83   {
    84     mWorkerPrivate->AssertIsOnWorkerThread();
    86     AutoSyncLoopHolder syncLoop(mWorkerPrivate);
    88     mSyncLoopTarget = syncLoop.EventTarget();
    90     if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
    91       JS_ReportError(aCx, "Failed to dispatch to main thread!");
    92       return false;
    93     }
    95     return syncLoop.Run();
    96   }
    98 private:
    99   NS_IMETHOD Run()
   100   {
   101     AssertIsOnMainThread();
   103     MainThreadRun();
   105     nsRefPtr<MainThreadStopSyncLoopRunnable> response =
   106       new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
   107                                          mSyncLoopTarget.forget(),
   108                                          true);
   109     if (!response->Dispatch(nullptr)) {
   110       NS_WARNING("Failed to dispatch response!");
   111     }
   113     return NS_OK;
   114   }
   116 protected:
   117   virtual void
   118   MainThreadRun() = 0;
   119 };
   121 // This class creates an URL from a DOM Blob on the main thread.
   122 class CreateURLRunnable : public URLRunnable
   123 {
   124 private:
   125   nsIDOMBlob* mBlob;
   126   nsString& mURL;
   128 public:
   129   CreateURLRunnable(WorkerPrivate* aWorkerPrivate, nsIDOMBlob* aBlob,
   130                     const mozilla::dom::objectURLOptions& aOptions,
   131                     nsString& aURL)
   132   : URLRunnable(aWorkerPrivate),
   133     mBlob(aBlob),
   134     mURL(aURL)
   135   {
   136     MOZ_ASSERT(aBlob);
   137   }
   139   void
   140   MainThreadRun()
   141   {
   142     AssertIsOnMainThread();
   144     nsCOMPtr<nsIPrincipal> principal;
   145     nsIDocument* doc = nullptr;
   147     nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
   148     if (window) {
   149       doc = window->GetExtantDoc();
   150       if (!doc) {
   151         SetDOMStringToNull(mURL);
   152         return;
   153       }
   155       principal = doc->NodePrincipal();
   156     } else {
   157       MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker());
   158       principal = mWorkerPrivate->GetPrincipal();
   159     }
   161     nsCString url;
   162     nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(
   163         NS_LITERAL_CSTRING(BLOBURI_SCHEME),
   164         mBlob, principal, url);
   166     if (NS_FAILED(rv)) {
   167       NS_WARNING("Failed to add data entry for the blob!");
   168       SetDOMStringToNull(mURL);
   169       return;
   170     }
   172     if (doc) {
   173       doc->RegisterHostObjectUri(url);
   174     } else {
   175       mWorkerPrivate->RegisterHostObjectURI(url);
   176     }
   178     mURL = NS_ConvertUTF8toUTF16(url);
   179   }
   180 };
   182 // This class revokes an URL on the main thread.
   183 class RevokeURLRunnable : public URLRunnable
   184 {
   185 private:
   186   const nsString mURL;
   188 public:
   189   RevokeURLRunnable(WorkerPrivate* aWorkerPrivate,
   190                     const nsAString& aURL)
   191   : URLRunnable(aWorkerPrivate),
   192     mURL(aURL)
   193   {}
   195   void
   196   MainThreadRun()
   197   {
   198     AssertIsOnMainThread();
   200     nsCOMPtr<nsIPrincipal> principal;
   201     nsIDocument* doc = nullptr;
   203     nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
   204     if (window) {
   205       doc = window->GetExtantDoc();
   206       if (!doc) {
   207         return;
   208       }
   210       principal = doc->NodePrincipal();
   211     } else {
   212       MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker());
   213       principal = mWorkerPrivate->GetPrincipal();
   214     }
   216     NS_ConvertUTF16toUTF8 url(mURL);
   218     nsIPrincipal* urlPrincipal =
   219       nsHostObjectProtocolHandler::GetDataEntryPrincipal(url);
   221     bool subsumes;
   222     if (urlPrincipal &&
   223         NS_SUCCEEDED(principal->Subsumes(urlPrincipal, &subsumes)) &&
   224         subsumes) {
   225       if (doc) {
   226         doc->UnregisterHostObjectUri(url);
   227       }
   229       nsHostObjectProtocolHandler::RemoveDataEntry(url);
   230     }
   232     if (!window) {
   233       mWorkerPrivate->UnregisterHostObjectURI(url);
   234     }
   235   }
   236 };
   238 // This class creates a URL object on the main thread.
   239 class ConstructorRunnable : public URLRunnable
   240 {
   241 private:
   242   const nsString mURL;
   244   const nsString mBase;
   245   nsRefPtr<URLProxy> mBaseProxy;
   246   mozilla::ErrorResult& mRv;
   248   nsRefPtr<URLProxy> mRetval;
   250 public:
   251   ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
   252                       const nsAString& aURL, const nsAString& aBase,
   253                       mozilla::ErrorResult& aRv)
   254   : URLRunnable(aWorkerPrivate)
   255   , mURL(aURL)
   256   , mBase(aBase)
   257   , mRv(aRv)
   258   {
   259     mWorkerPrivate->AssertIsOnWorkerThread();
   260   }
   262   ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
   263                       const nsAString& aURL, URLProxy* aBaseProxy,
   264                       mozilla::ErrorResult& aRv)
   265   : URLRunnable(aWorkerPrivate)
   266   , mURL(aURL)
   267   , mBaseProxy(aBaseProxy)
   268   , mRv(aRv)
   269   {
   270     mWorkerPrivate->AssertIsOnWorkerThread();
   271   }
   273   void
   274   MainThreadRun()
   275   {
   276     AssertIsOnMainThread();
   278     nsresult rv;
   279     nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
   280     if (NS_FAILED(rv)) {
   281       mRv.Throw(rv);
   282       return;
   283     }
   285     nsCOMPtr<nsIURI> baseURL;
   287     if (!mBaseProxy) {
   288       rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mBase), nullptr, nullptr,
   289                              getter_AddRefs(baseURL));
   290       if (NS_FAILED(rv)) {
   291         mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   292         return;
   293       }
   294     } else {
   295       baseURL = mBaseProxy->URI();
   296     }
   298     nsCOMPtr<nsIURI> url;
   299     rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mURL), nullptr, baseURL,
   300                            getter_AddRefs(url));
   301     if (NS_FAILED(rv)) {
   302       mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   303       return;
   304     }
   306     mRetval = new URLProxy(new mozilla::dom::URL(url));
   307   }
   309   URLProxy*
   310   GetURLProxy()
   311   {
   312     return mRetval;
   313   }
   314 };
   316 class TeardownURLRunnable : public nsRunnable
   317 {
   318 public:
   319   TeardownURLRunnable(URLProxy* aURLProxy)
   320     : mURLProxy(aURLProxy)
   321   {
   322   }
   324   NS_IMETHOD Run()
   325   {
   326     AssertIsOnMainThread();
   328     mURLProxy->ReleaseURI();
   329     mURLProxy = nullptr;
   331     return NS_OK;
   332   }
   334 private:
   335   nsRefPtr<URLProxy> mURLProxy;
   336 };
   338 // This class is the generic getter for any URL property.
   339 class GetterRunnable : public URLRunnable
   340 {
   341 public:
   342   enum GetterType {
   343     GetterHref,
   344     GetterOrigin,
   345     GetterProtocol,
   346     GetterUsername,
   347     GetterPassword,
   348     GetterHost,
   349     GetterHostname,
   350     GetterPort,
   351     GetterPathname,
   352     GetterSearch,
   353     GetterHash,
   354   };
   356   GetterRunnable(WorkerPrivate* aWorkerPrivate,
   357                  GetterType aType, nsString& aValue,
   358                  URLProxy* aURLProxy)
   359   : URLRunnable(aWorkerPrivate)
   360   , mValue(aValue)
   361   , mType(aType)
   362   , mURLProxy(aURLProxy)
   363   {
   364     mWorkerPrivate->AssertIsOnWorkerThread();
   365   }
   367   void
   368   MainThreadRun()
   369   {
   370     AssertIsOnMainThread();
   372     switch (mType) {
   373       case GetterHref:
   374         mURLProxy->URL()->GetHref(mValue);
   375         break;
   377       case GetterOrigin:
   378         mURLProxy->URL()->GetOrigin(mValue);
   379         break;
   381       case GetterProtocol:
   382         mURLProxy->URL()->GetProtocol(mValue);
   383         break;
   385       case GetterUsername:
   386         mURLProxy->URL()->GetUsername(mValue);
   387         break;
   389       case GetterPassword:
   390         mURLProxy->URL()->GetPassword(mValue);
   391         break;
   393       case GetterHost:
   394         mURLProxy->URL()->GetHost(mValue);
   395         break;
   397       case GetterHostname:
   398         mURLProxy->URL()->GetHostname(mValue);
   399         break;
   401       case GetterPort:
   402         mURLProxy->URL()->GetPort(mValue);
   403         break;
   405       case GetterPathname:
   406         mURLProxy->URL()->GetPathname(mValue);
   407         break;
   409       case GetterSearch:
   410         mURLProxy->URL()->GetSearch(mValue);
   411         break;
   413       case GetterHash:
   414         mURLProxy->URL()->GetHash(mValue);
   415         break;
   416     }
   417   }
   419 private:
   420   nsString& mValue;
   421   GetterType mType;
   422   nsRefPtr<URLProxy> mURLProxy;
   423 };
   425 // This class is the generic setter for any URL property.
   426 class SetterRunnable : public URLRunnable
   427 {
   428 public:
   429   enum SetterType {
   430     SetterHref,
   431     SetterProtocol,
   432     SetterUsername,
   433     SetterPassword,
   434     SetterHost,
   435     SetterHostname,
   436     SetterPort,
   437     SetterPathname,
   438     SetterSearch,
   439     SetterHash,
   440   };
   442   SetterRunnable(WorkerPrivate* aWorkerPrivate,
   443                  SetterType aType, const nsAString& aValue,
   444                  URLProxy* aURLProxy, mozilla::ErrorResult& aRv)
   445   : URLRunnable(aWorkerPrivate)
   446   , mValue(aValue)
   447   , mType(aType)
   448   , mURLProxy(aURLProxy)
   449   , mRv(aRv)
   450   {
   451     mWorkerPrivate->AssertIsOnWorkerThread();
   452   }
   454   void
   455   MainThreadRun()
   456   {
   457     AssertIsOnMainThread();
   459     switch (mType) {
   460       case SetterHref:
   461         mURLProxy->URL()->SetHref(mValue, mRv);
   462         break;
   464       case SetterProtocol:
   465         mURLProxy->URL()->SetProtocol(mValue);
   466         break;
   468       case SetterUsername:
   469         mURLProxy->URL()->SetUsername(mValue);
   470         break;
   472       case SetterPassword:
   473         mURLProxy->URL()->SetPassword(mValue);
   474         break;
   476       case SetterHost:
   477         mURLProxy->URL()->SetHost(mValue);
   478         break;
   480       case SetterHostname:
   481         mURLProxy->URL()->SetHostname(mValue);
   482         break;
   484       case SetterPort:
   485         mURLProxy->URL()->SetPort(mValue);
   486         break;
   488       case SetterPathname:
   489         mURLProxy->URL()->SetPathname(mValue);
   490         break;
   492       case SetterSearch:
   493         mURLProxy->URL()->SetSearch(mValue);
   494         break;
   496       case SetterHash:
   497         mURLProxy->URL()->SetHash(mValue);
   498         break;
   499     }
   500   }
   502 private:
   503   const nsString mValue;
   504   SetterType mType;
   505   nsRefPtr<URLProxy> mURLProxy;
   506   mozilla::ErrorResult& mRv;
   507 };
   509 NS_IMPL_CYCLE_COLLECTION(URL, mSearchParams)
   511 // The reason for using worker::URL is to have different refcnt logging than
   512 // for main thread URL.
   513 NS_IMPL_CYCLE_COLLECTING_ADDREF(workers::URL)
   514 NS_IMPL_CYCLE_COLLECTING_RELEASE(workers::URL)
   516 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL)
   517   NS_INTERFACE_MAP_ENTRY(nsISupports)
   518 NS_INTERFACE_MAP_END
   520 // static
   521 URL*
   522 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
   523                  URL& aBase, ErrorResult& aRv)
   524 {
   525   JSContext* cx = aGlobal.GetContext();
   526   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   528   nsRefPtr<ConstructorRunnable> runnable =
   529     new ConstructorRunnable(workerPrivate, aUrl, aBase.GetURLProxy(), aRv);
   531   if (!runnable->Dispatch(cx)) {
   532     JS_ReportPendingException(cx);
   533   }
   535   nsRefPtr<URLProxy> proxy = runnable->GetURLProxy();
   536   if (!proxy) {
   537     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   538     return nullptr;
   539   }
   541   return new URL(workerPrivate, proxy);
   542 }
   544 // static
   545 URL*
   546 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
   547                  const nsAString& aBase, ErrorResult& aRv)
   548 {
   549   JSContext* cx = aGlobal.GetContext();
   550   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   552   nsRefPtr<ConstructorRunnable> runnable =
   553     new ConstructorRunnable(workerPrivate, aUrl, aBase, aRv);
   555   if (!runnable->Dispatch(cx)) {
   556     JS_ReportPendingException(cx);
   557   }
   559   nsRefPtr<URLProxy> proxy = runnable->GetURLProxy();
   560   if (!proxy) {
   561     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   562     return nullptr;
   563   }
   565   return new URL(workerPrivate, proxy);
   566 }
   568 URL::URL(WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy)
   569   : mWorkerPrivate(aWorkerPrivate)
   570   , mURLProxy(aURLProxy)
   571 {
   572   MOZ_COUNT_CTOR(workers::URL);
   573 }
   575 URL::~URL()
   576 {
   577   MOZ_COUNT_DTOR(workers::URL);
   579   if (mURLProxy) {
   580     nsRefPtr<TeardownURLRunnable> runnable =
   581       new TeardownURLRunnable(mURLProxy);
   582     mURLProxy = nullptr;
   584     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
   585       NS_ERROR("Failed to dispatch teardown runnable!");
   586     }
   587   }
   588 }
   590 JSObject*
   591 URL::WrapObject(JSContext* aCx)
   592 {
   593   return URLBinding_workers::Wrap(aCx, this);
   594 }
   596 void
   597 URL::GetHref(nsString& aHref) const
   598 {
   599   nsRefPtr<GetterRunnable> runnable =
   600     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref,
   601                        mURLProxy);
   603   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   604     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   605   }
   606 }
   608 void
   609 URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
   610 {
   611   nsRefPtr<SetterRunnable> runnable =
   612     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref,
   613                        mURLProxy, aRv);
   615   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   616     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   617   }
   619   UpdateURLSearchParams();
   620 }
   622 void
   623 URL::GetOrigin(nsString& aOrigin) const
   624 {
   625   nsRefPtr<GetterRunnable> runnable =
   626     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterOrigin, aOrigin,
   627                        mURLProxy);
   629   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   630     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   631   }
   632 }
   634 void
   635 URL::GetProtocol(nsString& aProtocol) const
   636 {
   637   nsRefPtr<GetterRunnable> runnable =
   638     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterProtocol, aProtocol,
   639                        mURLProxy);
   641   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   642     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   643   }
   644 }
   646 void
   647 URL::SetProtocol(const nsAString& aProtocol)
   648 {
   649   ErrorResult rv;
   650   nsRefPtr<SetterRunnable> runnable =
   651     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol,
   652                        aProtocol, mURLProxy, rv);
   654   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   655     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   656   }
   657 }
   659 void
   660 URL::GetUsername(nsString& aUsername) const
   661 {
   662   nsRefPtr<GetterRunnable> runnable =
   663     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterUsername, aUsername,
   664                        mURLProxy);
   666   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   667     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   668   }
   669 }
   671 void
   672 URL::SetUsername(const nsAString& aUsername)
   673 {
   674   ErrorResult rv;
   675   nsRefPtr<SetterRunnable> runnable =
   676     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterUsername,
   677                        aUsername, mURLProxy, rv);
   679   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   680     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   681   }
   682 }
   684 void
   685 URL::GetPassword(nsString& aPassword) const
   686 {
   687   nsRefPtr<GetterRunnable> runnable =
   688     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPassword, aPassword,
   689                        mURLProxy);
   691   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   692     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   693   }
   694 }
   696 void
   697 URL::SetPassword(const nsAString& aPassword)
   698 {
   699   ErrorResult rv;
   700   nsRefPtr<SetterRunnable> runnable =
   701     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPassword,
   702                        aPassword, mURLProxy, rv);
   704   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   705     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   706   }
   707 }
   709 void
   710 URL::GetHost(nsString& aHost) const
   711 {
   712   nsRefPtr<GetterRunnable> runnable =
   713     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHost, aHost,
   714                        mURLProxy);
   716   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   717     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   718   }
   719 }
   721 void
   722 URL::SetHost(const nsAString& aHost)
   723 {
   724   ErrorResult rv;
   725   nsRefPtr<SetterRunnable> runnable =
   726     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHost,
   727                        aHost, mURLProxy, rv);
   729   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   730     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   731   }
   732 }
   734 void
   735 URL::GetHostname(nsString& aHostname) const
   736 {
   737   nsRefPtr<GetterRunnable> runnable =
   738     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHostname, aHostname,
   739                        mURLProxy);
   741   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   742     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   743   }
   744 }
   746 void
   747 URL::SetHostname(const nsAString& aHostname)
   748 {
   749   ErrorResult rv;
   750   nsRefPtr<SetterRunnable> runnable =
   751     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHostname,
   752                        aHostname, mURLProxy, rv);
   754   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   755     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   756   }
   757 }
   759 void
   760 URL::GetPort(nsString& aPort) const
   761 {
   762   nsRefPtr<GetterRunnable> runnable =
   763     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPort, aPort,
   764                        mURLProxy);
   766   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   767     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   768   }
   769 }
   771 void
   772 URL::SetPort(const nsAString& aPort)
   773 {
   774   ErrorResult rv;
   775   nsRefPtr<SetterRunnable> runnable =
   776     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPort,
   777                        aPort, mURLProxy, rv);
   779   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   780     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   781   }
   782 }
   784 void
   785 URL::GetPathname(nsString& aPathname) const
   786 {
   787   nsRefPtr<GetterRunnable> runnable =
   788     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPathname, aPathname,
   789                        mURLProxy);
   791   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   792     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   793   }
   794 }
   796 void
   797 URL::SetPathname(const nsAString& aPathname)
   798 {
   799   ErrorResult rv;
   800   nsRefPtr<SetterRunnable> runnable =
   801     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPathname,
   802                        aPathname, mURLProxy, rv);
   804   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   805     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   806   }
   807 }
   809 void
   810 URL::GetSearch(nsString& aSearch) const
   811 {
   812   nsRefPtr<GetterRunnable> runnable =
   813     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterSearch, aSearch,
   814                        mURLProxy);
   816   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   817     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   818   }
   819 }
   821 void
   822 URL::SetSearch(const nsAString& aSearch)
   823 {
   824   SetSearchInternal(aSearch);
   825   UpdateURLSearchParams();
   826 }
   828 void
   829 URL::SetSearchInternal(const nsAString& aSearch)
   830 {
   831   ErrorResult rv;
   832   nsRefPtr<SetterRunnable> runnable =
   833     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterSearch,
   834                        aSearch, mURLProxy, rv);
   836   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   837     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   838   }
   839 }
   841 mozilla::dom::URLSearchParams*
   842 URL::SearchParams()
   843 {
   844   CreateSearchParamsIfNeeded();
   845   return mSearchParams;
   846 }
   848 void
   849 URL::SetSearchParams(URLSearchParams& aSearchParams)
   850 {
   851   if (mSearchParams) {
   852     mSearchParams->RemoveObserver(this);
   853   }
   855   mSearchParams = &aSearchParams;
   856   mSearchParams->AddObserver(this);
   858   nsString search;
   859   mSearchParams->Serialize(search);
   860   SetSearchInternal(search);
   861 }
   863 void
   864 URL::GetHash(nsString& aHash) const
   865 {
   866   nsRefPtr<GetterRunnable> runnable =
   867     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHash, aHash,
   868                        mURLProxy);
   870   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   871     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   872   }
   873 }
   875 void
   876 URL::SetHash(const nsAString& aHash)
   877 {
   878   ErrorResult rv;
   879   nsRefPtr<SetterRunnable> runnable =
   880     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHash,
   881                        aHash, mURLProxy, rv);
   883   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   884     JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   885   }
   886 }
   888 // static
   889 void
   890 URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject* aBlob,
   891                      const mozilla::dom::objectURLOptions& aOptions,
   892                      nsString& aResult, mozilla::ErrorResult& aRv)
   893 {
   894   JSContext* cx = aGlobal.GetContext();
   895   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   897   nsCOMPtr<nsIDOMBlob> blob = file::GetDOMBlobFromJSObject(aBlob);
   898   if (!blob) {
   899     SetDOMStringToNull(aResult);
   901     NS_NAMED_LITERAL_STRING(argStr, "Argument 1 of URL.createObjectURL");
   902     NS_NAMED_LITERAL_STRING(blobStr, "Blob");
   903     aRv.ThrowTypeError(MSG_DOES_NOT_IMPLEMENT_INTERFACE, &argStr, &blobStr);
   904     return;
   905   }
   907   nsRefPtr<CreateURLRunnable> runnable =
   908     new CreateURLRunnable(workerPrivate, blob, aOptions, aResult);
   910   if (!runnable->Dispatch(cx)) {
   911     JS_ReportPendingException(cx);
   912   }
   913 }
   915 // static
   916 void
   917 URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject& aBlob,
   918                      const mozilla::dom::objectURLOptions& aOptions,
   919                      nsString& aResult, mozilla::ErrorResult& aRv)
   920 {
   921   return CreateObjectURL(aGlobal, &aBlob, aOptions, aResult, aRv);
   922 }
   924 // static
   925 void
   926 URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl)
   927 {
   928   JSContext* cx = aGlobal.GetContext();
   929   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   931   nsRefPtr<RevokeURLRunnable> runnable =
   932     new RevokeURLRunnable(workerPrivate, aUrl);
   934   if (!runnable->Dispatch(cx)) {
   935     JS_ReportPendingException(cx);
   936   }
   937 }
   939 void
   940 URL::URLSearchParamsUpdated()
   941 {
   942   MOZ_ASSERT(mSearchParams);
   944   nsString search;
   945   mSearchParams->Serialize(search);
   946   SetSearchInternal(search);
   947 }
   949 void
   950 URL::UpdateURLSearchParams()
   951 {
   952   if (mSearchParams) {
   953     nsString search;
   954     GetSearch(search);
   955     mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)), this);
   956   }
   957 }
   959 void
   960 URL::CreateSearchParamsIfNeeded()
   961 {
   962   if (!mSearchParams) {
   963     mSearchParams = new URLSearchParams();
   964     mSearchParams->AddObserver(this);
   965     UpdateURLSearchParams();
   966   }
   967 }
   969 END_WORKERS_NAMESPACE

mercurial