dom/base/URL.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/base/URL.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,518 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     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 "nsGlobalWindow.h"
    1.12 +#include "nsIDOMFile.h"
    1.13 +#include "DOMMediaStream.h"
    1.14 +#include "mozilla/dom/MediaSource.h"
    1.15 +#include "mozilla/dom/URLBinding.h"
    1.16 +#include "nsHostObjectProtocolHandler.h"
    1.17 +#include "nsServiceManagerUtils.h"
    1.18 +#include "nsIIOService.h"
    1.19 +#include "nsEscape.h"
    1.20 +#include "nsNetCID.h"
    1.21 +#include "nsIURL.h"
    1.22 +
    1.23 +namespace mozilla {
    1.24 +namespace dom {
    1.25 +
    1.26 +NS_IMPL_CYCLE_COLLECTION_CLASS(URL)
    1.27 +
    1.28 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(URL)
    1.29 +  if (tmp->mSearchParams) {
    1.30 +    tmp->mSearchParams->RemoveObserver(tmp);
    1.31 +    NS_IMPL_CYCLE_COLLECTION_UNLINK(mSearchParams)
    1.32 +  }
    1.33 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1.34 +
    1.35 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(URL)
    1.36 +  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSearchParams)
    1.37 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1.38 +
    1.39 +NS_IMPL_CYCLE_COLLECTING_ADDREF(URL)
    1.40 +NS_IMPL_CYCLE_COLLECTING_RELEASE(URL)
    1.41 +
    1.42 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL)
    1.43 +  NS_INTERFACE_MAP_ENTRY(nsISupports)
    1.44 +NS_INTERFACE_MAP_END
    1.45 +
    1.46 +URL::URL(nsIURI* aURI)
    1.47 +  : mURI(aURI)
    1.48 +{
    1.49 +}
    1.50 +
    1.51 +JSObject*
    1.52 +URL::WrapObject(JSContext* aCx)
    1.53 +{
    1.54 +  return URLBinding::Wrap(aCx, this);
    1.55 +}
    1.56 +
    1.57 +/* static */ already_AddRefed<URL>
    1.58 +URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
    1.59 +                 URL& aBase, ErrorResult& aRv)
    1.60 +{
    1.61 +  nsresult rv;
    1.62 +  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
    1.63 +  if (NS_FAILED(rv)) {
    1.64 +    aRv.Throw(rv);
    1.65 +    return nullptr;
    1.66 +  }
    1.67 +
    1.68 +  nsCOMPtr<nsIURI> uri;
    1.69 +  rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, aBase.GetURI(),
    1.70 +                         getter_AddRefs(uri));
    1.71 +  if (NS_FAILED(rv)) {
    1.72 +    nsAutoString label(aUrl);
    1.73 +    aRv.ThrowTypeError(MSG_INVALID_URL, &label);
    1.74 +    return nullptr;
    1.75 +  }
    1.76 +
    1.77 +  nsRefPtr<URL> url = new URL(uri);
    1.78 +  return url.forget();
    1.79 +}
    1.80 +
    1.81 +/* static */ already_AddRefed<URL>
    1.82 +URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
    1.83 +                  const nsAString& aBase, ErrorResult& aRv)
    1.84 +{
    1.85 +  nsresult rv;
    1.86 +  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
    1.87 +  if (NS_FAILED(rv)) {
    1.88 +    aRv.Throw(rv);
    1.89 +    return nullptr;
    1.90 +  }
    1.91 +
    1.92 +  nsCOMPtr<nsIURI> baseUri;
    1.93 +  rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aBase), nullptr, nullptr,
    1.94 +                         getter_AddRefs(baseUri));
    1.95 +  if (NS_FAILED(rv)) {
    1.96 +    nsAutoString label(aBase);
    1.97 +    aRv.ThrowTypeError(MSG_INVALID_URL, &label);
    1.98 +    return nullptr;
    1.99 +  }
   1.100 +
   1.101 +  nsCOMPtr<nsIURI> uri;
   1.102 +  rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, baseUri,
   1.103 +                         getter_AddRefs(uri));
   1.104 +  if (NS_FAILED(rv)) {
   1.105 +    nsAutoString label(aUrl);
   1.106 +    aRv.ThrowTypeError(MSG_INVALID_URL, &label);
   1.107 +    return nullptr;
   1.108 +  }
   1.109 +
   1.110 +  nsRefPtr<URL> url = new URL(uri);
   1.111 +  return url.forget();
   1.112 +}
   1.113 +
   1.114 +void
   1.115 +URL::CreateObjectURL(const GlobalObject& aGlobal,
   1.116 +                     nsIDOMBlob* aBlob,
   1.117 +                     const objectURLOptions& aOptions,
   1.118 +                     nsString& aResult,
   1.119 +                     ErrorResult& aError)
   1.120 +{
   1.121 +  CreateObjectURLInternal(aGlobal, aBlob,
   1.122 +                          NS_LITERAL_CSTRING(BLOBURI_SCHEME), aOptions, aResult,
   1.123 +                          aError);
   1.124 +}
   1.125 +
   1.126 +void
   1.127 +URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
   1.128 +                     const mozilla::dom::objectURLOptions& aOptions,
   1.129 +                     nsString& aResult,
   1.130 +                     ErrorResult& aError)
   1.131 +{
   1.132 +  CreateObjectURLInternal(aGlobal, &aStream,
   1.133 +                          NS_LITERAL_CSTRING(MEDIASTREAMURI_SCHEME), aOptions,
   1.134 +                          aResult, aError);
   1.135 +}
   1.136 +
   1.137 +void
   1.138 +URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
   1.139 +                     const objectURLOptions& aOptions,
   1.140 +                     nsString& aResult,
   1.141 +                     ErrorResult& aError)
   1.142 +{
   1.143 +  CreateObjectURLInternal(aGlobal, &aSource,
   1.144 +                          NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME), aOptions,
   1.145 +                          aResult, aError);
   1.146 +}
   1.147 +
   1.148 +void
   1.149 +URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject,
   1.150 +                             const nsACString& aScheme,
   1.151 +                             const objectURLOptions& aOptions,
   1.152 +                             nsString& aResult, ErrorResult& aError)
   1.153 +{
   1.154 +  nsCOMPtr<nsIPrincipal> principal = nsContentUtils::GetObjectPrincipal(aGlobal.Get());
   1.155 +
   1.156 +  nsCString url;
   1.157 +  nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject,
   1.158 +                                                          principal, url);
   1.159 +  if (NS_FAILED(rv)) {
   1.160 +    aError.Throw(rv);
   1.161 +    return;
   1.162 +  }
   1.163 +
   1.164 +  nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
   1.165 +  nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
   1.166 +
   1.167 +  if (window) {
   1.168 +    NS_PRECONDITION(window->IsInnerWindow(), "Should be inner window");
   1.169 +
   1.170 +    if (!window->GetExtantDoc()) {
   1.171 +      aError.Throw(NS_ERROR_INVALID_POINTER);
   1.172 +      return;
   1.173 +    }
   1.174 +
   1.175 +    nsIDocument* doc = window->GetExtantDoc();
   1.176 +    if (doc) {
   1.177 +      doc->RegisterHostObjectUri(url);
   1.178 +    }
   1.179 +  }
   1.180 +
   1.181 +  CopyASCIItoUTF16(url, aResult);
   1.182 +}
   1.183 +
   1.184 +void
   1.185 +URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL)
   1.186 +{
   1.187 +  nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(aGlobal.Get());
   1.188 +
   1.189 +  NS_LossyConvertUTF16toASCII asciiurl(aURL);
   1.190 +
   1.191 +  nsIPrincipal* urlPrincipal =
   1.192 +    nsHostObjectProtocolHandler::GetDataEntryPrincipal(asciiurl);
   1.193 +
   1.194 +  if (urlPrincipal && principal->Subsumes(urlPrincipal)) {
   1.195 +    nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
   1.196 +    nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
   1.197 +
   1.198 +    if (window && window->GetExtantDoc()) {
   1.199 +      window->GetExtantDoc()->UnregisterHostObjectUri(asciiurl);
   1.200 +    }
   1.201 +    nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl);
   1.202 +  }
   1.203 +}
   1.204 +
   1.205 +void
   1.206 +URL::GetHref(nsString& aHref) const
   1.207 +{
   1.208 +  aHref.Truncate();
   1.209 +
   1.210 +  nsAutoCString href;
   1.211 +  nsresult rv = mURI->GetSpec(href);
   1.212 +  if (NS_SUCCEEDED(rv)) {
   1.213 +    CopyUTF8toUTF16(href, aHref);
   1.214 +  }
   1.215 +}
   1.216 +
   1.217 +void
   1.218 +URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
   1.219 +{
   1.220 +  nsCString href = NS_ConvertUTF16toUTF8(aHref);
   1.221 +
   1.222 +  nsresult rv;
   1.223 +  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
   1.224 +  if (NS_FAILED(rv)) {
   1.225 +    aRv.Throw(rv);
   1.226 +    return;
   1.227 +  }
   1.228 +
   1.229 +  nsCOMPtr<nsIURI> uri;
   1.230 +  rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
   1.231 +  if (NS_FAILED(rv)) {
   1.232 +    nsAutoString label(aHref);
   1.233 +    aRv.ThrowTypeError(MSG_INVALID_URL, &label);
   1.234 +    return;
   1.235 +  }
   1.236 +
   1.237 +  mURI = uri;
   1.238 +  UpdateURLSearchParams();
   1.239 +}
   1.240 +
   1.241 +void
   1.242 +URL::GetOrigin(nsString& aOrigin) const
   1.243 +{
   1.244 +  nsContentUtils::GetUTFNonNullOrigin(mURI, aOrigin);
   1.245 +}
   1.246 +
   1.247 +void
   1.248 +URL::GetProtocol(nsString& aProtocol) const
   1.249 +{
   1.250 +  nsCString protocol;
   1.251 +  if (NS_SUCCEEDED(mURI->GetScheme(protocol))) {
   1.252 +    aProtocol.Truncate();
   1.253 +  }
   1.254 +
   1.255 +  CopyASCIItoUTF16(protocol, aProtocol);
   1.256 +  aProtocol.Append(char16_t(':'));
   1.257 +}
   1.258 +
   1.259 +void
   1.260 +URL::SetProtocol(const nsAString& aProtocol)
   1.261 +{
   1.262 +  nsAString::const_iterator start, end;
   1.263 +  aProtocol.BeginReading(start);
   1.264 +  aProtocol.EndReading(end);
   1.265 +  nsAString::const_iterator iter(start);
   1.266 +
   1.267 +  FindCharInReadable(':', iter, end);
   1.268 +  mURI->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
   1.269 +}
   1.270 +
   1.271 +#define URL_GETTER( value, func ) \
   1.272 +  value.Truncate();               \
   1.273 +  nsAutoCString tmp;              \
   1.274 +  nsresult rv = mURI->func(tmp);  \
   1.275 +  if (NS_SUCCEEDED(rv)) {         \
   1.276 +    CopyUTF8toUTF16(tmp, value);  \
   1.277 +  }
   1.278 +
   1.279 +void
   1.280 +URL::GetUsername(nsString& aUsername) const
   1.281 +{
   1.282 +  URL_GETTER(aUsername, GetUsername);
   1.283 +}
   1.284 +
   1.285 +void
   1.286 +URL::SetUsername(const nsAString& aUsername)
   1.287 +{
   1.288 +  mURI->SetUsername(NS_ConvertUTF16toUTF8(aUsername));
   1.289 +}
   1.290 +
   1.291 +void
   1.292 +URL::GetPassword(nsString& aPassword) const
   1.293 +{
   1.294 +  URL_GETTER(aPassword, GetPassword);
   1.295 +}
   1.296 +
   1.297 +void
   1.298 +URL::SetPassword(const nsAString& aPassword)
   1.299 +{
   1.300 +  mURI->SetPassword(NS_ConvertUTF16toUTF8(aPassword));
   1.301 +}
   1.302 +
   1.303 +void
   1.304 +URL::GetHost(nsString& aHost) const
   1.305 +{
   1.306 +  URL_GETTER(aHost, GetHostPort);
   1.307 +}
   1.308 +
   1.309 +void
   1.310 +URL::SetHost(const nsAString& aHost)
   1.311 +{
   1.312 +  mURI->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
   1.313 +}
   1.314 +
   1.315 +void
   1.316 +URL::URLSearchParamsUpdated()
   1.317 +{
   1.318 +  MOZ_ASSERT(mSearchParams);
   1.319 +
   1.320 +  nsAutoString search;
   1.321 +  mSearchParams->Serialize(search);
   1.322 +  SetSearchInternal(search);
   1.323 +}
   1.324 +
   1.325 +void
   1.326 +URL::UpdateURLSearchParams()
   1.327 +{
   1.328 +  if (!mSearchParams) {
   1.329 +    return;
   1.330 +  }
   1.331 +
   1.332 +  nsAutoCString search;
   1.333 +  nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
   1.334 +  if (url) {
   1.335 +    nsresult rv = url->GetQuery(search);
   1.336 +    if (NS_FAILED(rv)) {
   1.337 +      NS_WARNING("Failed to get the query from a nsIURL.");
   1.338 +    }
   1.339 +  }
   1.340 +
   1.341 +  mSearchParams->ParseInput(search, this);
   1.342 +}
   1.343 +
   1.344 +void
   1.345 +URL::GetHostname(nsString& aHostname) const
   1.346 +{
   1.347 +  URL_GETTER(aHostname, GetHost);
   1.348 +}
   1.349 +
   1.350 +void
   1.351 +URL::SetHostname(const nsAString& aHostname)
   1.352 +{
   1.353 +  // nsStandardURL returns NS_ERROR_UNEXPECTED for an empty hostname
   1.354 +  // The return code is silently ignored
   1.355 +  mURI->SetHost(NS_ConvertUTF16toUTF8(aHostname));
   1.356 +}
   1.357 +
   1.358 +void
   1.359 +URL::GetPort(nsString& aPort) const
   1.360 +{
   1.361 +  aPort.Truncate();
   1.362 +
   1.363 +  int32_t port;
   1.364 +  nsresult rv = mURI->GetPort(&port);
   1.365 +  if (NS_SUCCEEDED(rv) && port != -1) {
   1.366 +    nsAutoString portStr;
   1.367 +    portStr.AppendInt(port, 10);
   1.368 +    aPort.Assign(portStr);
   1.369 +  }
   1.370 +}
   1.371 +
   1.372 +void
   1.373 +URL::SetPort(const nsAString& aPort)
   1.374 +{
   1.375 +  nsresult rv;
   1.376 +  nsAutoString portStr(aPort);
   1.377 +  int32_t port = -1;
   1.378 +
   1.379 +  // nsIURI uses -1 as default value.
   1.380 +  if (!portStr.IsEmpty()) {
   1.381 +    port = portStr.ToInteger(&rv);
   1.382 +    if (NS_FAILED(rv)) {
   1.383 +      return;
   1.384 +    }
   1.385 +  }
   1.386 +
   1.387 +  mURI->SetPort(port);
   1.388 +}
   1.389 +
   1.390 +void
   1.391 +URL::GetPathname(nsString& aPathname) const
   1.392 +{
   1.393 +  aPathname.Truncate();
   1.394 +
   1.395 +  nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
   1.396 +  if (!url) {
   1.397 +    // Do not throw!  Not having a valid URI or URL should result in an empty
   1.398 +    // string.
   1.399 +    return;
   1.400 +  }
   1.401 +
   1.402 +  nsAutoCString file;
   1.403 +  nsresult rv = url->GetFilePath(file);
   1.404 +  if (NS_SUCCEEDED(rv)) {
   1.405 +    CopyUTF8toUTF16(file, aPathname);
   1.406 +  }
   1.407 +}
   1.408 +
   1.409 +void
   1.410 +URL::SetPathname(const nsAString& aPathname)
   1.411 +{
   1.412 +  nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
   1.413 +  if (!url) {
   1.414 +    // Ignore failures to be compatible with NS4.
   1.415 +    return;
   1.416 +  }
   1.417 +
   1.418 +  url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname));
   1.419 +}
   1.420 +
   1.421 +void
   1.422 +URL::GetSearch(nsString& aSearch) const
   1.423 +{
   1.424 +  aSearch.Truncate();
   1.425 +
   1.426 +  nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
   1.427 +  if (!url) {
   1.428 +    // Do not throw!  Not having a valid URI or URL should result in an empty
   1.429 +    // string.
   1.430 +    return;
   1.431 +  }
   1.432 +
   1.433 +  nsAutoCString search;
   1.434 +  nsresult rv = url->GetQuery(search);
   1.435 +  if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
   1.436 +    CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
   1.437 +  }
   1.438 +}
   1.439 +
   1.440 +void
   1.441 +URL::SetSearch(const nsAString& aSearch)
   1.442 +{
   1.443 +  SetSearchInternal(aSearch);
   1.444 +  UpdateURLSearchParams();
   1.445 +}
   1.446 +
   1.447 +void
   1.448 +URL::SetSearchInternal(const nsAString& aSearch)
   1.449 +{
   1.450 +  nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
   1.451 +  if (!url) {
   1.452 +    // Ignore failures to be compatible with NS4.
   1.453 +    return;
   1.454 +  }
   1.455 +
   1.456 +  url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
   1.457 +}
   1.458 +
   1.459 +URLSearchParams*
   1.460 +URL::SearchParams()
   1.461 +{
   1.462 +  CreateSearchParamsIfNeeded();
   1.463 +  return mSearchParams;
   1.464 +}
   1.465 +
   1.466 +void
   1.467 +URL::SetSearchParams(URLSearchParams& aSearchParams)
   1.468 +{
   1.469 +  if (mSearchParams) {
   1.470 +    mSearchParams->RemoveObserver(this);
   1.471 +  }
   1.472 +
   1.473 +  // the observer will be cleared using the cycle collector.
   1.474 +  mSearchParams = &aSearchParams;
   1.475 +  mSearchParams->AddObserver(this);
   1.476 +
   1.477 +  nsAutoString search;
   1.478 +  mSearchParams->Serialize(search);
   1.479 +  SetSearchInternal(search);
   1.480 +}
   1.481 +
   1.482 +void
   1.483 +URL::GetHash(nsString& aHash) const
   1.484 +{
   1.485 +  aHash.Truncate();
   1.486 +
   1.487 +  nsAutoCString ref;
   1.488 +  nsresult rv = mURI->GetRef(ref);
   1.489 +  if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
   1.490 +    NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
   1.491 +    aHash.Assign(char16_t('#'));
   1.492 +    AppendUTF8toUTF16(ref, aHash);
   1.493 +  }
   1.494 +}
   1.495 +
   1.496 +void
   1.497 +URL::SetHash(const nsAString& aHash)
   1.498 +{
   1.499 +  mURI->SetRef(NS_ConvertUTF16toUTF8(aHash));
   1.500 +}
   1.501 +
   1.502 +bool IsChromeURI(nsIURI* aURI)
   1.503 +{
   1.504 +  bool isChrome = false;
   1.505 +  if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)))
   1.506 +      return isChrome;
   1.507 +  return false;
   1.508 +}
   1.509 +
   1.510 +void
   1.511 +URL::CreateSearchParamsIfNeeded()
   1.512 +{
   1.513 +  if (!mSearchParams) {
   1.514 +    mSearchParams = new URLSearchParams();
   1.515 +    mSearchParams->AddObserver(this);
   1.516 +    UpdateURLSearchParams();
   1.517 +  }
   1.518 +}
   1.519 +
   1.520 +}
   1.521 +}

mercurial