Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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