dom/base/URL.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "URL.h"
michael@0 7
michael@0 8 #include "nsGlobalWindow.h"
michael@0 9 #include "nsIDOMFile.h"
michael@0 10 #include "DOMMediaStream.h"
michael@0 11 #include "mozilla/dom/MediaSource.h"
michael@0 12 #include "mozilla/dom/URLBinding.h"
michael@0 13 #include "nsHostObjectProtocolHandler.h"
michael@0 14 #include "nsServiceManagerUtils.h"
michael@0 15 #include "nsIIOService.h"
michael@0 16 #include "nsEscape.h"
michael@0 17 #include "nsNetCID.h"
michael@0 18 #include "nsIURL.h"
michael@0 19
michael@0 20 namespace mozilla {
michael@0 21 namespace dom {
michael@0 22
michael@0 23 NS_IMPL_CYCLE_COLLECTION_CLASS(URL)
michael@0 24
michael@0 25 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(URL)
michael@0 26 if (tmp->mSearchParams) {
michael@0 27 tmp->mSearchParams->RemoveObserver(tmp);
michael@0 28 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSearchParams)
michael@0 29 }
michael@0 30 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 31
michael@0 32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(URL)
michael@0 33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSearchParams)
michael@0 34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 35
michael@0 36 NS_IMPL_CYCLE_COLLECTING_ADDREF(URL)
michael@0 37 NS_IMPL_CYCLE_COLLECTING_RELEASE(URL)
michael@0 38
michael@0 39 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL)
michael@0 40 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 41 NS_INTERFACE_MAP_END
michael@0 42
michael@0 43 URL::URL(nsIURI* aURI)
michael@0 44 : mURI(aURI)
michael@0 45 {
michael@0 46 }
michael@0 47
michael@0 48 JSObject*
michael@0 49 URL::WrapObject(JSContext* aCx)
michael@0 50 {
michael@0 51 return URLBinding::Wrap(aCx, this);
michael@0 52 }
michael@0 53
michael@0 54 /* static */ already_AddRefed<URL>
michael@0 55 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
michael@0 56 URL& aBase, ErrorResult& aRv)
michael@0 57 {
michael@0 58 nsresult rv;
michael@0 59 nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
michael@0 60 if (NS_FAILED(rv)) {
michael@0 61 aRv.Throw(rv);
michael@0 62 return nullptr;
michael@0 63 }
michael@0 64
michael@0 65 nsCOMPtr<nsIURI> uri;
michael@0 66 rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, aBase.GetURI(),
michael@0 67 getter_AddRefs(uri));
michael@0 68 if (NS_FAILED(rv)) {
michael@0 69 nsAutoString label(aUrl);
michael@0 70 aRv.ThrowTypeError(MSG_INVALID_URL, &label);
michael@0 71 return nullptr;
michael@0 72 }
michael@0 73
michael@0 74 nsRefPtr<URL> url = new URL(uri);
michael@0 75 return url.forget();
michael@0 76 }
michael@0 77
michael@0 78 /* static */ already_AddRefed<URL>
michael@0 79 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
michael@0 80 const nsAString& aBase, ErrorResult& aRv)
michael@0 81 {
michael@0 82 nsresult rv;
michael@0 83 nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
michael@0 84 if (NS_FAILED(rv)) {
michael@0 85 aRv.Throw(rv);
michael@0 86 return nullptr;
michael@0 87 }
michael@0 88
michael@0 89 nsCOMPtr<nsIURI> baseUri;
michael@0 90 rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aBase), nullptr, nullptr,
michael@0 91 getter_AddRefs(baseUri));
michael@0 92 if (NS_FAILED(rv)) {
michael@0 93 nsAutoString label(aBase);
michael@0 94 aRv.ThrowTypeError(MSG_INVALID_URL, &label);
michael@0 95 return nullptr;
michael@0 96 }
michael@0 97
michael@0 98 nsCOMPtr<nsIURI> uri;
michael@0 99 rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, baseUri,
michael@0 100 getter_AddRefs(uri));
michael@0 101 if (NS_FAILED(rv)) {
michael@0 102 nsAutoString label(aUrl);
michael@0 103 aRv.ThrowTypeError(MSG_INVALID_URL, &label);
michael@0 104 return nullptr;
michael@0 105 }
michael@0 106
michael@0 107 nsRefPtr<URL> url = new URL(uri);
michael@0 108 return url.forget();
michael@0 109 }
michael@0 110
michael@0 111 void
michael@0 112 URL::CreateObjectURL(const GlobalObject& aGlobal,
michael@0 113 nsIDOMBlob* aBlob,
michael@0 114 const objectURLOptions& aOptions,
michael@0 115 nsString& aResult,
michael@0 116 ErrorResult& aError)
michael@0 117 {
michael@0 118 CreateObjectURLInternal(aGlobal, aBlob,
michael@0 119 NS_LITERAL_CSTRING(BLOBURI_SCHEME), aOptions, aResult,
michael@0 120 aError);
michael@0 121 }
michael@0 122
michael@0 123 void
michael@0 124 URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
michael@0 125 const mozilla::dom::objectURLOptions& aOptions,
michael@0 126 nsString& aResult,
michael@0 127 ErrorResult& aError)
michael@0 128 {
michael@0 129 CreateObjectURLInternal(aGlobal, &aStream,
michael@0 130 NS_LITERAL_CSTRING(MEDIASTREAMURI_SCHEME), aOptions,
michael@0 131 aResult, aError);
michael@0 132 }
michael@0 133
michael@0 134 void
michael@0 135 URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
michael@0 136 const objectURLOptions& aOptions,
michael@0 137 nsString& aResult,
michael@0 138 ErrorResult& aError)
michael@0 139 {
michael@0 140 CreateObjectURLInternal(aGlobal, &aSource,
michael@0 141 NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME), aOptions,
michael@0 142 aResult, aError);
michael@0 143 }
michael@0 144
michael@0 145 void
michael@0 146 URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject,
michael@0 147 const nsACString& aScheme,
michael@0 148 const objectURLOptions& aOptions,
michael@0 149 nsString& aResult, ErrorResult& aError)
michael@0 150 {
michael@0 151 nsCOMPtr<nsIPrincipal> principal = nsContentUtils::GetObjectPrincipal(aGlobal.Get());
michael@0 152
michael@0 153 nsCString url;
michael@0 154 nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject,
michael@0 155 principal, url);
michael@0 156 if (NS_FAILED(rv)) {
michael@0 157 aError.Throw(rv);
michael@0 158 return;
michael@0 159 }
michael@0 160
michael@0 161 nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
michael@0 162 nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
michael@0 163
michael@0 164 if (window) {
michael@0 165 NS_PRECONDITION(window->IsInnerWindow(), "Should be inner window");
michael@0 166
michael@0 167 if (!window->GetExtantDoc()) {
michael@0 168 aError.Throw(NS_ERROR_INVALID_POINTER);
michael@0 169 return;
michael@0 170 }
michael@0 171
michael@0 172 nsIDocument* doc = window->GetExtantDoc();
michael@0 173 if (doc) {
michael@0 174 doc->RegisterHostObjectUri(url);
michael@0 175 }
michael@0 176 }
michael@0 177
michael@0 178 CopyASCIItoUTF16(url, aResult);
michael@0 179 }
michael@0 180
michael@0 181 void
michael@0 182 URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL)
michael@0 183 {
michael@0 184 nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(aGlobal.Get());
michael@0 185
michael@0 186 NS_LossyConvertUTF16toASCII asciiurl(aURL);
michael@0 187
michael@0 188 nsIPrincipal* urlPrincipal =
michael@0 189 nsHostObjectProtocolHandler::GetDataEntryPrincipal(asciiurl);
michael@0 190
michael@0 191 if (urlPrincipal && principal->Subsumes(urlPrincipal)) {
michael@0 192 nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
michael@0 193 nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
michael@0 194
michael@0 195 if (window && window->GetExtantDoc()) {
michael@0 196 window->GetExtantDoc()->UnregisterHostObjectUri(asciiurl);
michael@0 197 }
michael@0 198 nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl);
michael@0 199 }
michael@0 200 }
michael@0 201
michael@0 202 void
michael@0 203 URL::GetHref(nsString& aHref) const
michael@0 204 {
michael@0 205 aHref.Truncate();
michael@0 206
michael@0 207 nsAutoCString href;
michael@0 208 nsresult rv = mURI->GetSpec(href);
michael@0 209 if (NS_SUCCEEDED(rv)) {
michael@0 210 CopyUTF8toUTF16(href, aHref);
michael@0 211 }
michael@0 212 }
michael@0 213
michael@0 214 void
michael@0 215 URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
michael@0 216 {
michael@0 217 nsCString href = NS_ConvertUTF16toUTF8(aHref);
michael@0 218
michael@0 219 nsresult rv;
michael@0 220 nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
michael@0 221 if (NS_FAILED(rv)) {
michael@0 222 aRv.Throw(rv);
michael@0 223 return;
michael@0 224 }
michael@0 225
michael@0 226 nsCOMPtr<nsIURI> uri;
michael@0 227 rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
michael@0 228 if (NS_FAILED(rv)) {
michael@0 229 nsAutoString label(aHref);
michael@0 230 aRv.ThrowTypeError(MSG_INVALID_URL, &label);
michael@0 231 return;
michael@0 232 }
michael@0 233
michael@0 234 mURI = uri;
michael@0 235 UpdateURLSearchParams();
michael@0 236 }
michael@0 237
michael@0 238 void
michael@0 239 URL::GetOrigin(nsString& aOrigin) const
michael@0 240 {
michael@0 241 nsContentUtils::GetUTFNonNullOrigin(mURI, aOrigin);
michael@0 242 }
michael@0 243
michael@0 244 void
michael@0 245 URL::GetProtocol(nsString& aProtocol) const
michael@0 246 {
michael@0 247 nsCString protocol;
michael@0 248 if (NS_SUCCEEDED(mURI->GetScheme(protocol))) {
michael@0 249 aProtocol.Truncate();
michael@0 250 }
michael@0 251
michael@0 252 CopyASCIItoUTF16(protocol, aProtocol);
michael@0 253 aProtocol.Append(char16_t(':'));
michael@0 254 }
michael@0 255
michael@0 256 void
michael@0 257 URL::SetProtocol(const nsAString& aProtocol)
michael@0 258 {
michael@0 259 nsAString::const_iterator start, end;
michael@0 260 aProtocol.BeginReading(start);
michael@0 261 aProtocol.EndReading(end);
michael@0 262 nsAString::const_iterator iter(start);
michael@0 263
michael@0 264 FindCharInReadable(':', iter, end);
michael@0 265 mURI->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
michael@0 266 }
michael@0 267
michael@0 268 #define URL_GETTER( value, func ) \
michael@0 269 value.Truncate(); \
michael@0 270 nsAutoCString tmp; \
michael@0 271 nsresult rv = mURI->func(tmp); \
michael@0 272 if (NS_SUCCEEDED(rv)) { \
michael@0 273 CopyUTF8toUTF16(tmp, value); \
michael@0 274 }
michael@0 275
michael@0 276 void
michael@0 277 URL::GetUsername(nsString& aUsername) const
michael@0 278 {
michael@0 279 URL_GETTER(aUsername, GetUsername);
michael@0 280 }
michael@0 281
michael@0 282 void
michael@0 283 URL::SetUsername(const nsAString& aUsername)
michael@0 284 {
michael@0 285 mURI->SetUsername(NS_ConvertUTF16toUTF8(aUsername));
michael@0 286 }
michael@0 287
michael@0 288 void
michael@0 289 URL::GetPassword(nsString& aPassword) const
michael@0 290 {
michael@0 291 URL_GETTER(aPassword, GetPassword);
michael@0 292 }
michael@0 293
michael@0 294 void
michael@0 295 URL::SetPassword(const nsAString& aPassword)
michael@0 296 {
michael@0 297 mURI->SetPassword(NS_ConvertUTF16toUTF8(aPassword));
michael@0 298 }
michael@0 299
michael@0 300 void
michael@0 301 URL::GetHost(nsString& aHost) const
michael@0 302 {
michael@0 303 URL_GETTER(aHost, GetHostPort);
michael@0 304 }
michael@0 305
michael@0 306 void
michael@0 307 URL::SetHost(const nsAString& aHost)
michael@0 308 {
michael@0 309 mURI->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
michael@0 310 }
michael@0 311
michael@0 312 void
michael@0 313 URL::URLSearchParamsUpdated()
michael@0 314 {
michael@0 315 MOZ_ASSERT(mSearchParams);
michael@0 316
michael@0 317 nsAutoString search;
michael@0 318 mSearchParams->Serialize(search);
michael@0 319 SetSearchInternal(search);
michael@0 320 }
michael@0 321
michael@0 322 void
michael@0 323 URL::UpdateURLSearchParams()
michael@0 324 {
michael@0 325 if (!mSearchParams) {
michael@0 326 return;
michael@0 327 }
michael@0 328
michael@0 329 nsAutoCString search;
michael@0 330 nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
michael@0 331 if (url) {
michael@0 332 nsresult rv = url->GetQuery(search);
michael@0 333 if (NS_FAILED(rv)) {
michael@0 334 NS_WARNING("Failed to get the query from a nsIURL.");
michael@0 335 }
michael@0 336 }
michael@0 337
michael@0 338 mSearchParams->ParseInput(search, this);
michael@0 339 }
michael@0 340
michael@0 341 void
michael@0 342 URL::GetHostname(nsString& aHostname) const
michael@0 343 {
michael@0 344 URL_GETTER(aHostname, GetHost);
michael@0 345 }
michael@0 346
michael@0 347 void
michael@0 348 URL::SetHostname(const nsAString& aHostname)
michael@0 349 {
michael@0 350 // nsStandardURL returns NS_ERROR_UNEXPECTED for an empty hostname
michael@0 351 // The return code is silently ignored
michael@0 352 mURI->SetHost(NS_ConvertUTF16toUTF8(aHostname));
michael@0 353 }
michael@0 354
michael@0 355 void
michael@0 356 URL::GetPort(nsString& aPort) const
michael@0 357 {
michael@0 358 aPort.Truncate();
michael@0 359
michael@0 360 int32_t port;
michael@0 361 nsresult rv = mURI->GetPort(&port);
michael@0 362 if (NS_SUCCEEDED(rv) && port != -1) {
michael@0 363 nsAutoString portStr;
michael@0 364 portStr.AppendInt(port, 10);
michael@0 365 aPort.Assign(portStr);
michael@0 366 }
michael@0 367 }
michael@0 368
michael@0 369 void
michael@0 370 URL::SetPort(const nsAString& aPort)
michael@0 371 {
michael@0 372 nsresult rv;
michael@0 373 nsAutoString portStr(aPort);
michael@0 374 int32_t port = -1;
michael@0 375
michael@0 376 // nsIURI uses -1 as default value.
michael@0 377 if (!portStr.IsEmpty()) {
michael@0 378 port = portStr.ToInteger(&rv);
michael@0 379 if (NS_FAILED(rv)) {
michael@0 380 return;
michael@0 381 }
michael@0 382 }
michael@0 383
michael@0 384 mURI->SetPort(port);
michael@0 385 }
michael@0 386
michael@0 387 void
michael@0 388 URL::GetPathname(nsString& aPathname) const
michael@0 389 {
michael@0 390 aPathname.Truncate();
michael@0 391
michael@0 392 nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
michael@0 393 if (!url) {
michael@0 394 // Do not throw! Not having a valid URI or URL should result in an empty
michael@0 395 // string.
michael@0 396 return;
michael@0 397 }
michael@0 398
michael@0 399 nsAutoCString file;
michael@0 400 nsresult rv = url->GetFilePath(file);
michael@0 401 if (NS_SUCCEEDED(rv)) {
michael@0 402 CopyUTF8toUTF16(file, aPathname);
michael@0 403 }
michael@0 404 }
michael@0 405
michael@0 406 void
michael@0 407 URL::SetPathname(const nsAString& aPathname)
michael@0 408 {
michael@0 409 nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
michael@0 410 if (!url) {
michael@0 411 // Ignore failures to be compatible with NS4.
michael@0 412 return;
michael@0 413 }
michael@0 414
michael@0 415 url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname));
michael@0 416 }
michael@0 417
michael@0 418 void
michael@0 419 URL::GetSearch(nsString& aSearch) const
michael@0 420 {
michael@0 421 aSearch.Truncate();
michael@0 422
michael@0 423 nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
michael@0 424 if (!url) {
michael@0 425 // Do not throw! Not having a valid URI or URL should result in an empty
michael@0 426 // string.
michael@0 427 return;
michael@0 428 }
michael@0 429
michael@0 430 nsAutoCString search;
michael@0 431 nsresult rv = url->GetQuery(search);
michael@0 432 if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
michael@0 433 CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
michael@0 434 }
michael@0 435 }
michael@0 436
michael@0 437 void
michael@0 438 URL::SetSearch(const nsAString& aSearch)
michael@0 439 {
michael@0 440 SetSearchInternal(aSearch);
michael@0 441 UpdateURLSearchParams();
michael@0 442 }
michael@0 443
michael@0 444 void
michael@0 445 URL::SetSearchInternal(const nsAString& aSearch)
michael@0 446 {
michael@0 447 nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
michael@0 448 if (!url) {
michael@0 449 // Ignore failures to be compatible with NS4.
michael@0 450 return;
michael@0 451 }
michael@0 452
michael@0 453 url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
michael@0 454 }
michael@0 455
michael@0 456 URLSearchParams*
michael@0 457 URL::SearchParams()
michael@0 458 {
michael@0 459 CreateSearchParamsIfNeeded();
michael@0 460 return mSearchParams;
michael@0 461 }
michael@0 462
michael@0 463 void
michael@0 464 URL::SetSearchParams(URLSearchParams& aSearchParams)
michael@0 465 {
michael@0 466 if (mSearchParams) {
michael@0 467 mSearchParams->RemoveObserver(this);
michael@0 468 }
michael@0 469
michael@0 470 // the observer will be cleared using the cycle collector.
michael@0 471 mSearchParams = &aSearchParams;
michael@0 472 mSearchParams->AddObserver(this);
michael@0 473
michael@0 474 nsAutoString search;
michael@0 475 mSearchParams->Serialize(search);
michael@0 476 SetSearchInternal(search);
michael@0 477 }
michael@0 478
michael@0 479 void
michael@0 480 URL::GetHash(nsString& aHash) const
michael@0 481 {
michael@0 482 aHash.Truncate();
michael@0 483
michael@0 484 nsAutoCString ref;
michael@0 485 nsresult rv = mURI->GetRef(ref);
michael@0 486 if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
michael@0 487 NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
michael@0 488 aHash.Assign(char16_t('#'));
michael@0 489 AppendUTF8toUTF16(ref, aHash);
michael@0 490 }
michael@0 491 }
michael@0 492
michael@0 493 void
michael@0 494 URL::SetHash(const nsAString& aHash)
michael@0 495 {
michael@0 496 mURI->SetRef(NS_ConvertUTF16toUTF8(aHash));
michael@0 497 }
michael@0 498
michael@0 499 bool IsChromeURI(nsIURI* aURI)
michael@0 500 {
michael@0 501 bool isChrome = false;
michael@0 502 if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)))
michael@0 503 return isChrome;
michael@0 504 return false;
michael@0 505 }
michael@0 506
michael@0 507 void
michael@0 508 URL::CreateSearchParamsIfNeeded()
michael@0 509 {
michael@0 510 if (!mSearchParams) {
michael@0 511 mSearchParams = new URLSearchParams();
michael@0 512 mSearchParams->AddObserver(this);
michael@0 513 UpdateURLSearchParams();
michael@0 514 }
michael@0 515 }
michael@0 516
michael@0 517 }
michael@0 518 }

mercurial