dom/workers/URL.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/workers/URL.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,969 @@
     1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "URL.h"
    1.10 +
    1.11 +#include "nsIDocument.h"
    1.12 +#include "nsIDOMFile.h"
    1.13 +#include "nsIIOService.h"
    1.14 +#include "nsPIDOMWindow.h"
    1.15 +
    1.16 +#include "mozilla/dom/URL.h"
    1.17 +#include "mozilla/dom/URLBinding.h"
    1.18 +#include "mozilla/dom/URLSearchParams.h"
    1.19 +#include "nsGlobalWindow.h"
    1.20 +#include "nsHostObjectProtocolHandler.h"
    1.21 +#include "nsNetCID.h"
    1.22 +#include "nsServiceManagerUtils.h"
    1.23 +#include "nsThreadUtils.h"
    1.24 +
    1.25 +#include "File.h"
    1.26 +#include "WorkerPrivate.h"
    1.27 +#include "WorkerRunnable.h"
    1.28 +
    1.29 +BEGIN_WORKERS_NAMESPACE
    1.30 +using mozilla::dom::GlobalObject;
    1.31 +
    1.32 +class URLProxy MOZ_FINAL
    1.33 +{
    1.34 +public:
    1.35 +  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLProxy)
    1.36 +
    1.37 +  URLProxy(mozilla::dom::URL* aURL)
    1.38 +    : mURL(aURL)
    1.39 +  {
    1.40 +    AssertIsOnMainThread();
    1.41 +  }
    1.42 +
    1.43 +  mozilla::dom::URL* URL()
    1.44 +  {
    1.45 +    return mURL;
    1.46 +  }
    1.47 +
    1.48 +  nsIURI* URI()
    1.49 +  {
    1.50 +    return mURL->GetURI();
    1.51 +  }
    1.52 +
    1.53 +  void ReleaseURI()
    1.54 +  {
    1.55 +    AssertIsOnMainThread();
    1.56 +    mURL = nullptr;
    1.57 +  }
    1.58 +
    1.59 +private:
    1.60 +  // Private destructor, to discourage deletion outside of Release():
    1.61 +  ~URLProxy()
    1.62 +  {
    1.63 +     MOZ_ASSERT(!mURL);
    1.64 +  }
    1.65 +
    1.66 +  nsRefPtr<mozilla::dom::URL> mURL;
    1.67 +};
    1.68 +
    1.69 +// Base class for the URL runnable objects.
    1.70 +class URLRunnable : public nsRunnable
    1.71 +{
    1.72 +protected:
    1.73 +  WorkerPrivate* mWorkerPrivate;
    1.74 +  nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
    1.75 +
    1.76 +protected:
    1.77 +  URLRunnable(WorkerPrivate* aWorkerPrivate)
    1.78 +  : mWorkerPrivate(aWorkerPrivate)
    1.79 +  {
    1.80 +    mWorkerPrivate->AssertIsOnWorkerThread();
    1.81 +  }
    1.82 +
    1.83 +public:
    1.84 +  bool
    1.85 +  Dispatch(JSContext* aCx)
    1.86 +  {
    1.87 +    mWorkerPrivate->AssertIsOnWorkerThread();
    1.88 +
    1.89 +    AutoSyncLoopHolder syncLoop(mWorkerPrivate);
    1.90 +
    1.91 +    mSyncLoopTarget = syncLoop.EventTarget();
    1.92 +
    1.93 +    if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
    1.94 +      JS_ReportError(aCx, "Failed to dispatch to main thread!");
    1.95 +      return false;
    1.96 +    }
    1.97 +
    1.98 +    return syncLoop.Run();
    1.99 +  }
   1.100 +
   1.101 +private:
   1.102 +  NS_IMETHOD Run()
   1.103 +  {
   1.104 +    AssertIsOnMainThread();
   1.105 +
   1.106 +    MainThreadRun();
   1.107 +
   1.108 +    nsRefPtr<MainThreadStopSyncLoopRunnable> response =
   1.109 +      new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
   1.110 +                                         mSyncLoopTarget.forget(),
   1.111 +                                         true);
   1.112 +    if (!response->Dispatch(nullptr)) {
   1.113 +      NS_WARNING("Failed to dispatch response!");
   1.114 +    }
   1.115 +
   1.116 +    return NS_OK;
   1.117 +  }
   1.118 +
   1.119 +protected:
   1.120 +  virtual void
   1.121 +  MainThreadRun() = 0;
   1.122 +};
   1.123 +
   1.124 +// This class creates an URL from a DOM Blob on the main thread.
   1.125 +class CreateURLRunnable : public URLRunnable
   1.126 +{
   1.127 +private:
   1.128 +  nsIDOMBlob* mBlob;
   1.129 +  nsString& mURL;
   1.130 +
   1.131 +public:
   1.132 +  CreateURLRunnable(WorkerPrivate* aWorkerPrivate, nsIDOMBlob* aBlob,
   1.133 +                    const mozilla::dom::objectURLOptions& aOptions,
   1.134 +                    nsString& aURL)
   1.135 +  : URLRunnable(aWorkerPrivate),
   1.136 +    mBlob(aBlob),
   1.137 +    mURL(aURL)
   1.138 +  {
   1.139 +    MOZ_ASSERT(aBlob);
   1.140 +  }
   1.141 +
   1.142 +  void
   1.143 +  MainThreadRun()
   1.144 +  {
   1.145 +    AssertIsOnMainThread();
   1.146 +
   1.147 +    nsCOMPtr<nsIPrincipal> principal;
   1.148 +    nsIDocument* doc = nullptr;
   1.149 +
   1.150 +    nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
   1.151 +    if (window) {
   1.152 +      doc = window->GetExtantDoc();
   1.153 +      if (!doc) {
   1.154 +        SetDOMStringToNull(mURL);
   1.155 +        return;
   1.156 +      }
   1.157 +
   1.158 +      principal = doc->NodePrincipal();
   1.159 +    } else {
   1.160 +      MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker());
   1.161 +      principal = mWorkerPrivate->GetPrincipal();
   1.162 +    }
   1.163 +
   1.164 +    nsCString url;
   1.165 +    nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(
   1.166 +        NS_LITERAL_CSTRING(BLOBURI_SCHEME),
   1.167 +        mBlob, principal, url);
   1.168 +
   1.169 +    if (NS_FAILED(rv)) {
   1.170 +      NS_WARNING("Failed to add data entry for the blob!");
   1.171 +      SetDOMStringToNull(mURL);
   1.172 +      return;
   1.173 +    }
   1.174 +
   1.175 +    if (doc) {
   1.176 +      doc->RegisterHostObjectUri(url);
   1.177 +    } else {
   1.178 +      mWorkerPrivate->RegisterHostObjectURI(url);
   1.179 +    }
   1.180 +
   1.181 +    mURL = NS_ConvertUTF8toUTF16(url);
   1.182 +  }
   1.183 +};
   1.184 +
   1.185 +// This class revokes an URL on the main thread.
   1.186 +class RevokeURLRunnable : public URLRunnable
   1.187 +{
   1.188 +private:
   1.189 +  const nsString mURL;
   1.190 +
   1.191 +public:
   1.192 +  RevokeURLRunnable(WorkerPrivate* aWorkerPrivate,
   1.193 +                    const nsAString& aURL)
   1.194 +  : URLRunnable(aWorkerPrivate),
   1.195 +    mURL(aURL)
   1.196 +  {}
   1.197 +
   1.198 +  void
   1.199 +  MainThreadRun()
   1.200 +  {
   1.201 +    AssertIsOnMainThread();
   1.202 +
   1.203 +    nsCOMPtr<nsIPrincipal> principal;
   1.204 +    nsIDocument* doc = nullptr;
   1.205 +
   1.206 +    nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
   1.207 +    if (window) {
   1.208 +      doc = window->GetExtantDoc();
   1.209 +      if (!doc) {
   1.210 +        return;
   1.211 +      }
   1.212 +
   1.213 +      principal = doc->NodePrincipal();
   1.214 +    } else {
   1.215 +      MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker());
   1.216 +      principal = mWorkerPrivate->GetPrincipal();
   1.217 +    }
   1.218 +
   1.219 +    NS_ConvertUTF16toUTF8 url(mURL);
   1.220 +
   1.221 +    nsIPrincipal* urlPrincipal =
   1.222 +      nsHostObjectProtocolHandler::GetDataEntryPrincipal(url);
   1.223 +
   1.224 +    bool subsumes;
   1.225 +    if (urlPrincipal &&
   1.226 +        NS_SUCCEEDED(principal->Subsumes(urlPrincipal, &subsumes)) &&
   1.227 +        subsumes) {
   1.228 +      if (doc) {
   1.229 +        doc->UnregisterHostObjectUri(url);
   1.230 +      }
   1.231 +
   1.232 +      nsHostObjectProtocolHandler::RemoveDataEntry(url);
   1.233 +    }
   1.234 +
   1.235 +    if (!window) {
   1.236 +      mWorkerPrivate->UnregisterHostObjectURI(url);
   1.237 +    }
   1.238 +  }
   1.239 +};
   1.240 +
   1.241 +// This class creates a URL object on the main thread.
   1.242 +class ConstructorRunnable : public URLRunnable
   1.243 +{
   1.244 +private:
   1.245 +  const nsString mURL;
   1.246 +
   1.247 +  const nsString mBase;
   1.248 +  nsRefPtr<URLProxy> mBaseProxy;
   1.249 +  mozilla::ErrorResult& mRv;
   1.250 +
   1.251 +  nsRefPtr<URLProxy> mRetval;
   1.252 +
   1.253 +public:
   1.254 +  ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
   1.255 +                      const nsAString& aURL, const nsAString& aBase,
   1.256 +                      mozilla::ErrorResult& aRv)
   1.257 +  : URLRunnable(aWorkerPrivate)
   1.258 +  , mURL(aURL)
   1.259 +  , mBase(aBase)
   1.260 +  , mRv(aRv)
   1.261 +  {
   1.262 +    mWorkerPrivate->AssertIsOnWorkerThread();
   1.263 +  }
   1.264 +
   1.265 +  ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
   1.266 +                      const nsAString& aURL, URLProxy* aBaseProxy,
   1.267 +                      mozilla::ErrorResult& aRv)
   1.268 +  : URLRunnable(aWorkerPrivate)
   1.269 +  , mURL(aURL)
   1.270 +  , mBaseProxy(aBaseProxy)
   1.271 +  , mRv(aRv)
   1.272 +  {
   1.273 +    mWorkerPrivate->AssertIsOnWorkerThread();
   1.274 +  }
   1.275 +
   1.276 +  void
   1.277 +  MainThreadRun()
   1.278 +  {
   1.279 +    AssertIsOnMainThread();
   1.280 +
   1.281 +    nsresult rv;
   1.282 +    nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
   1.283 +    if (NS_FAILED(rv)) {
   1.284 +      mRv.Throw(rv);
   1.285 +      return;
   1.286 +    }
   1.287 +
   1.288 +    nsCOMPtr<nsIURI> baseURL;
   1.289 +
   1.290 +    if (!mBaseProxy) {
   1.291 +      rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mBase), nullptr, nullptr,
   1.292 +                             getter_AddRefs(baseURL));
   1.293 +      if (NS_FAILED(rv)) {
   1.294 +        mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   1.295 +        return;
   1.296 +      }
   1.297 +    } else {
   1.298 +      baseURL = mBaseProxy->URI();
   1.299 +    }
   1.300 +
   1.301 +    nsCOMPtr<nsIURI> url;
   1.302 +    rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mURL), nullptr, baseURL,
   1.303 +                           getter_AddRefs(url));
   1.304 +    if (NS_FAILED(rv)) {
   1.305 +      mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   1.306 +      return;
   1.307 +    }
   1.308 +
   1.309 +    mRetval = new URLProxy(new mozilla::dom::URL(url));
   1.310 +  }
   1.311 +
   1.312 +  URLProxy*
   1.313 +  GetURLProxy()
   1.314 +  {
   1.315 +    return mRetval;
   1.316 +  }
   1.317 +};
   1.318 +
   1.319 +class TeardownURLRunnable : public nsRunnable
   1.320 +{
   1.321 +public:
   1.322 +  TeardownURLRunnable(URLProxy* aURLProxy)
   1.323 +    : mURLProxy(aURLProxy)
   1.324 +  {
   1.325 +  }
   1.326 +
   1.327 +  NS_IMETHOD Run()
   1.328 +  {
   1.329 +    AssertIsOnMainThread();
   1.330 +
   1.331 +    mURLProxy->ReleaseURI();
   1.332 +    mURLProxy = nullptr;
   1.333 +
   1.334 +    return NS_OK;
   1.335 +  }
   1.336 +
   1.337 +private:
   1.338 +  nsRefPtr<URLProxy> mURLProxy;
   1.339 +};
   1.340 +
   1.341 +// This class is the generic getter for any URL property.
   1.342 +class GetterRunnable : public URLRunnable
   1.343 +{
   1.344 +public:
   1.345 +  enum GetterType {
   1.346 +    GetterHref,
   1.347 +    GetterOrigin,
   1.348 +    GetterProtocol,
   1.349 +    GetterUsername,
   1.350 +    GetterPassword,
   1.351 +    GetterHost,
   1.352 +    GetterHostname,
   1.353 +    GetterPort,
   1.354 +    GetterPathname,
   1.355 +    GetterSearch,
   1.356 +    GetterHash,
   1.357 +  };
   1.358 +
   1.359 +  GetterRunnable(WorkerPrivate* aWorkerPrivate,
   1.360 +                 GetterType aType, nsString& aValue,
   1.361 +                 URLProxy* aURLProxy)
   1.362 +  : URLRunnable(aWorkerPrivate)
   1.363 +  , mValue(aValue)
   1.364 +  , mType(aType)
   1.365 +  , mURLProxy(aURLProxy)
   1.366 +  {
   1.367 +    mWorkerPrivate->AssertIsOnWorkerThread();
   1.368 +  }
   1.369 +
   1.370 +  void
   1.371 +  MainThreadRun()
   1.372 +  {
   1.373 +    AssertIsOnMainThread();
   1.374 +
   1.375 +    switch (mType) {
   1.376 +      case GetterHref:
   1.377 +        mURLProxy->URL()->GetHref(mValue);
   1.378 +        break;
   1.379 +
   1.380 +      case GetterOrigin:
   1.381 +        mURLProxy->URL()->GetOrigin(mValue);
   1.382 +        break;
   1.383 +
   1.384 +      case GetterProtocol:
   1.385 +        mURLProxy->URL()->GetProtocol(mValue);
   1.386 +        break;
   1.387 +
   1.388 +      case GetterUsername:
   1.389 +        mURLProxy->URL()->GetUsername(mValue);
   1.390 +        break;
   1.391 +
   1.392 +      case GetterPassword:
   1.393 +        mURLProxy->URL()->GetPassword(mValue);
   1.394 +        break;
   1.395 +
   1.396 +      case GetterHost:
   1.397 +        mURLProxy->URL()->GetHost(mValue);
   1.398 +        break;
   1.399 +
   1.400 +      case GetterHostname:
   1.401 +        mURLProxy->URL()->GetHostname(mValue);
   1.402 +        break;
   1.403 +
   1.404 +      case GetterPort:
   1.405 +        mURLProxy->URL()->GetPort(mValue);
   1.406 +        break;
   1.407 +
   1.408 +      case GetterPathname:
   1.409 +        mURLProxy->URL()->GetPathname(mValue);
   1.410 +        break;
   1.411 +
   1.412 +      case GetterSearch:
   1.413 +        mURLProxy->URL()->GetSearch(mValue);
   1.414 +        break;
   1.415 +
   1.416 +      case GetterHash:
   1.417 +        mURLProxy->URL()->GetHash(mValue);
   1.418 +        break;
   1.419 +    }
   1.420 +  }
   1.421 +
   1.422 +private:
   1.423 +  nsString& mValue;
   1.424 +  GetterType mType;
   1.425 +  nsRefPtr<URLProxy> mURLProxy;
   1.426 +};
   1.427 +
   1.428 +// This class is the generic setter for any URL property.
   1.429 +class SetterRunnable : public URLRunnable
   1.430 +{
   1.431 +public:
   1.432 +  enum SetterType {
   1.433 +    SetterHref,
   1.434 +    SetterProtocol,
   1.435 +    SetterUsername,
   1.436 +    SetterPassword,
   1.437 +    SetterHost,
   1.438 +    SetterHostname,
   1.439 +    SetterPort,
   1.440 +    SetterPathname,
   1.441 +    SetterSearch,
   1.442 +    SetterHash,
   1.443 +  };
   1.444 +
   1.445 +  SetterRunnable(WorkerPrivate* aWorkerPrivate,
   1.446 +                 SetterType aType, const nsAString& aValue,
   1.447 +                 URLProxy* aURLProxy, mozilla::ErrorResult& aRv)
   1.448 +  : URLRunnable(aWorkerPrivate)
   1.449 +  , mValue(aValue)
   1.450 +  , mType(aType)
   1.451 +  , mURLProxy(aURLProxy)
   1.452 +  , mRv(aRv)
   1.453 +  {
   1.454 +    mWorkerPrivate->AssertIsOnWorkerThread();
   1.455 +  }
   1.456 +
   1.457 +  void
   1.458 +  MainThreadRun()
   1.459 +  {
   1.460 +    AssertIsOnMainThread();
   1.461 +
   1.462 +    switch (mType) {
   1.463 +      case SetterHref:
   1.464 +        mURLProxy->URL()->SetHref(mValue, mRv);
   1.465 +        break;
   1.466 +
   1.467 +      case SetterProtocol:
   1.468 +        mURLProxy->URL()->SetProtocol(mValue);
   1.469 +        break;
   1.470 +
   1.471 +      case SetterUsername:
   1.472 +        mURLProxy->URL()->SetUsername(mValue);
   1.473 +        break;
   1.474 +
   1.475 +      case SetterPassword:
   1.476 +        mURLProxy->URL()->SetPassword(mValue);
   1.477 +        break;
   1.478 +
   1.479 +      case SetterHost:
   1.480 +        mURLProxy->URL()->SetHost(mValue);
   1.481 +        break;
   1.482 +
   1.483 +      case SetterHostname:
   1.484 +        mURLProxy->URL()->SetHostname(mValue);
   1.485 +        break;
   1.486 +
   1.487 +      case SetterPort:
   1.488 +        mURLProxy->URL()->SetPort(mValue);
   1.489 +        break;
   1.490 +
   1.491 +      case SetterPathname:
   1.492 +        mURLProxy->URL()->SetPathname(mValue);
   1.493 +        break;
   1.494 +
   1.495 +      case SetterSearch:
   1.496 +        mURLProxy->URL()->SetSearch(mValue);
   1.497 +        break;
   1.498 +
   1.499 +      case SetterHash:
   1.500 +        mURLProxy->URL()->SetHash(mValue);
   1.501 +        break;
   1.502 +    }
   1.503 +  }
   1.504 +
   1.505 +private:
   1.506 +  const nsString mValue;
   1.507 +  SetterType mType;
   1.508 +  nsRefPtr<URLProxy> mURLProxy;
   1.509 +  mozilla::ErrorResult& mRv;
   1.510 +};
   1.511 +
   1.512 +NS_IMPL_CYCLE_COLLECTION(URL, mSearchParams)
   1.513 +
   1.514 +// The reason for using worker::URL is to have different refcnt logging than
   1.515 +// for main thread URL.
   1.516 +NS_IMPL_CYCLE_COLLECTING_ADDREF(workers::URL)
   1.517 +NS_IMPL_CYCLE_COLLECTING_RELEASE(workers::URL)
   1.518 +
   1.519 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL)
   1.520 +  NS_INTERFACE_MAP_ENTRY(nsISupports)
   1.521 +NS_INTERFACE_MAP_END
   1.522 +
   1.523 +// static
   1.524 +URL*
   1.525 +URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
   1.526 +                 URL& aBase, ErrorResult& aRv)
   1.527 +{
   1.528 +  JSContext* cx = aGlobal.GetContext();
   1.529 +  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   1.530 +
   1.531 +  nsRefPtr<ConstructorRunnable> runnable =
   1.532 +    new ConstructorRunnable(workerPrivate, aUrl, aBase.GetURLProxy(), aRv);
   1.533 +
   1.534 +  if (!runnable->Dispatch(cx)) {
   1.535 +    JS_ReportPendingException(cx);
   1.536 +  }
   1.537 +
   1.538 +  nsRefPtr<URLProxy> proxy = runnable->GetURLProxy();
   1.539 +  if (!proxy) {
   1.540 +    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   1.541 +    return nullptr;
   1.542 +  }
   1.543 +
   1.544 +  return new URL(workerPrivate, proxy);
   1.545 +}
   1.546 +
   1.547 +// static
   1.548 +URL*
   1.549 +URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
   1.550 +                 const nsAString& aBase, ErrorResult& aRv)
   1.551 +{
   1.552 +  JSContext* cx = aGlobal.GetContext();
   1.553 +  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   1.554 +
   1.555 +  nsRefPtr<ConstructorRunnable> runnable =
   1.556 +    new ConstructorRunnable(workerPrivate, aUrl, aBase, aRv);
   1.557 +
   1.558 +  if (!runnable->Dispatch(cx)) {
   1.559 +    JS_ReportPendingException(cx);
   1.560 +  }
   1.561 +
   1.562 +  nsRefPtr<URLProxy> proxy = runnable->GetURLProxy();
   1.563 +  if (!proxy) {
   1.564 +    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
   1.565 +    return nullptr;
   1.566 +  }
   1.567 +
   1.568 +  return new URL(workerPrivate, proxy);
   1.569 +}
   1.570 +
   1.571 +URL::URL(WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy)
   1.572 +  : mWorkerPrivate(aWorkerPrivate)
   1.573 +  , mURLProxy(aURLProxy)
   1.574 +{
   1.575 +  MOZ_COUNT_CTOR(workers::URL);
   1.576 +}
   1.577 +
   1.578 +URL::~URL()
   1.579 +{
   1.580 +  MOZ_COUNT_DTOR(workers::URL);
   1.581 +
   1.582 +  if (mURLProxy) {
   1.583 +    nsRefPtr<TeardownURLRunnable> runnable =
   1.584 +      new TeardownURLRunnable(mURLProxy);
   1.585 +    mURLProxy = nullptr;
   1.586 +
   1.587 +    if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
   1.588 +      NS_ERROR("Failed to dispatch teardown runnable!");
   1.589 +    }
   1.590 +  }
   1.591 +}
   1.592 +
   1.593 +JSObject*
   1.594 +URL::WrapObject(JSContext* aCx)
   1.595 +{
   1.596 +  return URLBinding_workers::Wrap(aCx, this);
   1.597 +}
   1.598 +
   1.599 +void
   1.600 +URL::GetHref(nsString& aHref) const
   1.601 +{
   1.602 +  nsRefPtr<GetterRunnable> runnable =
   1.603 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref,
   1.604 +                       mURLProxy);
   1.605 +
   1.606 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.607 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.608 +  }
   1.609 +}
   1.610 +
   1.611 +void
   1.612 +URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
   1.613 +{
   1.614 +  nsRefPtr<SetterRunnable> runnable =
   1.615 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref,
   1.616 +                       mURLProxy, aRv);
   1.617 +
   1.618 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.619 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.620 +  }
   1.621 +
   1.622 +  UpdateURLSearchParams();
   1.623 +}
   1.624 +
   1.625 +void
   1.626 +URL::GetOrigin(nsString& aOrigin) const
   1.627 +{
   1.628 +  nsRefPtr<GetterRunnable> runnable =
   1.629 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterOrigin, aOrigin,
   1.630 +                       mURLProxy);
   1.631 +
   1.632 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.633 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.634 +  }
   1.635 +}
   1.636 +
   1.637 +void
   1.638 +URL::GetProtocol(nsString& aProtocol) const
   1.639 +{
   1.640 +  nsRefPtr<GetterRunnable> runnable =
   1.641 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterProtocol, aProtocol,
   1.642 +                       mURLProxy);
   1.643 +
   1.644 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.645 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.646 +  }
   1.647 +}
   1.648 +
   1.649 +void
   1.650 +URL::SetProtocol(const nsAString& aProtocol)
   1.651 +{
   1.652 +  ErrorResult rv;
   1.653 +  nsRefPtr<SetterRunnable> runnable =
   1.654 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol,
   1.655 +                       aProtocol, mURLProxy, rv);
   1.656 +
   1.657 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.658 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.659 +  }
   1.660 +}
   1.661 +
   1.662 +void
   1.663 +URL::GetUsername(nsString& aUsername) const
   1.664 +{
   1.665 +  nsRefPtr<GetterRunnable> runnable =
   1.666 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterUsername, aUsername,
   1.667 +                       mURLProxy);
   1.668 +
   1.669 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.670 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.671 +  }
   1.672 +}
   1.673 +
   1.674 +void
   1.675 +URL::SetUsername(const nsAString& aUsername)
   1.676 +{
   1.677 +  ErrorResult rv;
   1.678 +  nsRefPtr<SetterRunnable> runnable =
   1.679 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterUsername,
   1.680 +                       aUsername, mURLProxy, rv);
   1.681 +
   1.682 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.683 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.684 +  }
   1.685 +}
   1.686 +
   1.687 +void
   1.688 +URL::GetPassword(nsString& aPassword) const
   1.689 +{
   1.690 +  nsRefPtr<GetterRunnable> runnable =
   1.691 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPassword, aPassword,
   1.692 +                       mURLProxy);
   1.693 +
   1.694 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.695 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.696 +  }
   1.697 +}
   1.698 +
   1.699 +void
   1.700 +URL::SetPassword(const nsAString& aPassword)
   1.701 +{
   1.702 +  ErrorResult rv;
   1.703 +  nsRefPtr<SetterRunnable> runnable =
   1.704 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPassword,
   1.705 +                       aPassword, mURLProxy, rv);
   1.706 +
   1.707 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.708 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.709 +  }
   1.710 +}
   1.711 +
   1.712 +void
   1.713 +URL::GetHost(nsString& aHost) const
   1.714 +{
   1.715 +  nsRefPtr<GetterRunnable> runnable =
   1.716 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHost, aHost,
   1.717 +                       mURLProxy);
   1.718 +
   1.719 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.720 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.721 +  }
   1.722 +}
   1.723 +
   1.724 +void
   1.725 +URL::SetHost(const nsAString& aHost)
   1.726 +{
   1.727 +  ErrorResult rv;
   1.728 +  nsRefPtr<SetterRunnable> runnable =
   1.729 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHost,
   1.730 +                       aHost, mURLProxy, rv);
   1.731 +
   1.732 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.733 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.734 +  }
   1.735 +}
   1.736 +
   1.737 +void
   1.738 +URL::GetHostname(nsString& aHostname) const
   1.739 +{
   1.740 +  nsRefPtr<GetterRunnable> runnable =
   1.741 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHostname, aHostname,
   1.742 +                       mURLProxy);
   1.743 +
   1.744 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.745 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.746 +  }
   1.747 +}
   1.748 +
   1.749 +void
   1.750 +URL::SetHostname(const nsAString& aHostname)
   1.751 +{
   1.752 +  ErrorResult rv;
   1.753 +  nsRefPtr<SetterRunnable> runnable =
   1.754 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHostname,
   1.755 +                       aHostname, mURLProxy, rv);
   1.756 +
   1.757 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.758 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.759 +  }
   1.760 +}
   1.761 +
   1.762 +void
   1.763 +URL::GetPort(nsString& aPort) const
   1.764 +{
   1.765 +  nsRefPtr<GetterRunnable> runnable =
   1.766 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPort, aPort,
   1.767 +                       mURLProxy);
   1.768 +
   1.769 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.770 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.771 +  }
   1.772 +}
   1.773 +
   1.774 +void
   1.775 +URL::SetPort(const nsAString& aPort)
   1.776 +{
   1.777 +  ErrorResult rv;
   1.778 +  nsRefPtr<SetterRunnable> runnable =
   1.779 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPort,
   1.780 +                       aPort, mURLProxy, rv);
   1.781 +
   1.782 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.783 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.784 +  }
   1.785 +}
   1.786 +
   1.787 +void
   1.788 +URL::GetPathname(nsString& aPathname) const
   1.789 +{
   1.790 +  nsRefPtr<GetterRunnable> runnable =
   1.791 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPathname, aPathname,
   1.792 +                       mURLProxy);
   1.793 +
   1.794 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.795 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.796 +  }
   1.797 +}
   1.798 +
   1.799 +void
   1.800 +URL::SetPathname(const nsAString& aPathname)
   1.801 +{
   1.802 +  ErrorResult rv;
   1.803 +  nsRefPtr<SetterRunnable> runnable =
   1.804 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPathname,
   1.805 +                       aPathname, mURLProxy, rv);
   1.806 +
   1.807 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.808 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.809 +  }
   1.810 +}
   1.811 +
   1.812 +void
   1.813 +URL::GetSearch(nsString& aSearch) const
   1.814 +{
   1.815 +  nsRefPtr<GetterRunnable> runnable =
   1.816 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterSearch, aSearch,
   1.817 +                       mURLProxy);
   1.818 +
   1.819 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.820 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.821 +  }
   1.822 +}
   1.823 +
   1.824 +void
   1.825 +URL::SetSearch(const nsAString& aSearch)
   1.826 +{
   1.827 +  SetSearchInternal(aSearch);
   1.828 +  UpdateURLSearchParams();
   1.829 +}
   1.830 +
   1.831 +void
   1.832 +URL::SetSearchInternal(const nsAString& aSearch)
   1.833 +{
   1.834 +  ErrorResult rv;
   1.835 +  nsRefPtr<SetterRunnable> runnable =
   1.836 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterSearch,
   1.837 +                       aSearch, mURLProxy, rv);
   1.838 +
   1.839 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.840 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.841 +  }
   1.842 +}
   1.843 +
   1.844 +mozilla::dom::URLSearchParams*
   1.845 +URL::SearchParams()
   1.846 +{
   1.847 +  CreateSearchParamsIfNeeded();
   1.848 +  return mSearchParams;
   1.849 +}
   1.850 +
   1.851 +void
   1.852 +URL::SetSearchParams(URLSearchParams& aSearchParams)
   1.853 +{
   1.854 +  if (mSearchParams) {
   1.855 +    mSearchParams->RemoveObserver(this);
   1.856 +  }
   1.857 +
   1.858 +  mSearchParams = &aSearchParams;
   1.859 +  mSearchParams->AddObserver(this);
   1.860 +
   1.861 +  nsString search;
   1.862 +  mSearchParams->Serialize(search);
   1.863 +  SetSearchInternal(search);
   1.864 +}
   1.865 +
   1.866 +void
   1.867 +URL::GetHash(nsString& aHash) const
   1.868 +{
   1.869 +  nsRefPtr<GetterRunnable> runnable =
   1.870 +    new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHash, aHash,
   1.871 +                       mURLProxy);
   1.872 +
   1.873 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.874 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.875 +  }
   1.876 +}
   1.877 +
   1.878 +void
   1.879 +URL::SetHash(const nsAString& aHash)
   1.880 +{
   1.881 +  ErrorResult rv;
   1.882 +  nsRefPtr<SetterRunnable> runnable =
   1.883 +    new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHash,
   1.884 +                       aHash, mURLProxy, rv);
   1.885 +
   1.886 +  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
   1.887 +    JS_ReportPendingException(mWorkerPrivate->GetJSContext());
   1.888 +  }
   1.889 +}
   1.890 +
   1.891 +// static
   1.892 +void
   1.893 +URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject* aBlob,
   1.894 +                     const mozilla::dom::objectURLOptions& aOptions,
   1.895 +                     nsString& aResult, mozilla::ErrorResult& aRv)
   1.896 +{
   1.897 +  JSContext* cx = aGlobal.GetContext();
   1.898 +  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   1.899 +
   1.900 +  nsCOMPtr<nsIDOMBlob> blob = file::GetDOMBlobFromJSObject(aBlob);
   1.901 +  if (!blob) {
   1.902 +    SetDOMStringToNull(aResult);
   1.903 +
   1.904 +    NS_NAMED_LITERAL_STRING(argStr, "Argument 1 of URL.createObjectURL");
   1.905 +    NS_NAMED_LITERAL_STRING(blobStr, "Blob");
   1.906 +    aRv.ThrowTypeError(MSG_DOES_NOT_IMPLEMENT_INTERFACE, &argStr, &blobStr);
   1.907 +    return;
   1.908 +  }
   1.909 +
   1.910 +  nsRefPtr<CreateURLRunnable> runnable =
   1.911 +    new CreateURLRunnable(workerPrivate, blob, aOptions, aResult);
   1.912 +
   1.913 +  if (!runnable->Dispatch(cx)) {
   1.914 +    JS_ReportPendingException(cx);
   1.915 +  }
   1.916 +}
   1.917 +
   1.918 +// static
   1.919 +void
   1.920 +URL::CreateObjectURL(const GlobalObject& aGlobal, JSObject& aBlob,
   1.921 +                     const mozilla::dom::objectURLOptions& aOptions,
   1.922 +                     nsString& aResult, mozilla::ErrorResult& aRv)
   1.923 +{
   1.924 +  return CreateObjectURL(aGlobal, &aBlob, aOptions, aResult, aRv);
   1.925 +}
   1.926 +
   1.927 +// static
   1.928 +void
   1.929 +URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl)
   1.930 +{
   1.931 +  JSContext* cx = aGlobal.GetContext();
   1.932 +  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   1.933 +
   1.934 +  nsRefPtr<RevokeURLRunnable> runnable =
   1.935 +    new RevokeURLRunnable(workerPrivate, aUrl);
   1.936 +
   1.937 +  if (!runnable->Dispatch(cx)) {
   1.938 +    JS_ReportPendingException(cx);
   1.939 +  }
   1.940 +}
   1.941 +
   1.942 +void
   1.943 +URL::URLSearchParamsUpdated()
   1.944 +{
   1.945 +  MOZ_ASSERT(mSearchParams);
   1.946 +
   1.947 +  nsString search;
   1.948 +  mSearchParams->Serialize(search);
   1.949 +  SetSearchInternal(search);
   1.950 +}
   1.951 +
   1.952 +void
   1.953 +URL::UpdateURLSearchParams()
   1.954 +{
   1.955 +  if (mSearchParams) {
   1.956 +    nsString search;
   1.957 +    GetSearch(search);
   1.958 +    mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)), this);
   1.959 +  }
   1.960 +}
   1.961 +
   1.962 +void
   1.963 +URL::CreateSearchParamsIfNeeded()
   1.964 +{
   1.965 +  if (!mSearchParams) {
   1.966 +    mSearchParams = new URLSearchParams();
   1.967 +    mSearchParams->AddObserver(this);
   1.968 +    UpdateURLSearchParams();
   1.969 +  }
   1.970 +}
   1.971 +
   1.972 +END_WORKERS_NAMESPACE

mercurial