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/. */
9 #include "nsTraceRefcnt.h"
11 #include "WorkerPrivate.h"
12 #include "nsThreadUtils.h"
14 #include "nsPIDOMWindow.h"
15 #include "nsGlobalWindow.h"
16 #include "nsHostObjectProtocolHandler.h"
18 #include "nsIDocument.h"
19 #include "nsIDOMFile.h"
21 USING_WORKERS_NAMESPACE
22 using mozilla::dom::WorkerGlobalObject
;
24 // Base class for the Revoke and Create runnable objects.
25 class URLRunnable
: public nsRunnable
28 WorkerPrivate
* mWorkerPrivate
;
29 uint32_t mSyncQueueKey
;
32 class ResponseRunnable
: public WorkerSyncRunnable
34 uint32_t mSyncQueueKey
;
37 ResponseRunnable(WorkerPrivate
* aWorkerPrivate
,
38 uint32_t aSyncQueueKey
)
39 : WorkerSyncRunnable(aWorkerPrivate
, aSyncQueueKey
, false),
40 mSyncQueueKey(aSyncQueueKey
)
42 NS_ASSERTION(aWorkerPrivate
, "Don't hand me a null WorkerPrivate!");
46 WorkerRun(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
)
48 aWorkerPrivate
->StopSyncLoop(mSyncQueueKey
, true);
53 PreDispatch(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
)
55 AssertIsOnMainThread();
60 PostDispatch(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
,
63 AssertIsOnMainThread();
68 URLRunnable(WorkerPrivate
* aWorkerPrivate
)
69 : mWorkerPrivate(aWorkerPrivate
)
71 mWorkerPrivate
->AssertIsOnWorkerThread();
76 Dispatch(JSContext
* aCx
)
78 mWorkerPrivate
->AssertIsOnWorkerThread();
79 mSyncQueueKey
= mWorkerPrivate
->CreateNewSyncLoop();
81 if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL
))) {
82 JS_ReportError(aCx
, "Failed to dispatch to main thread!");
83 mWorkerPrivate
->StopSyncLoop(mSyncQueueKey
, false);
87 return mWorkerPrivate
->RunSyncLoop(aCx
, mSyncQueueKey
);
93 AssertIsOnMainThread();
97 nsRefPtr
<ResponseRunnable
> response
=
98 new ResponseRunnable(mWorkerPrivate
, mSyncQueueKey
);
99 if (!response
->Dispatch(nullptr)) {
100 NS_WARNING("Failed to dispatch response!");
111 // This class creates an URL from a DOM Blob on the main thread.
112 class CreateURLRunnable
: public URLRunnable
119 CreateURLRunnable(WorkerPrivate
* aWorkerPrivate
, nsIDOMBlob
* aBlob
,
120 const mozilla::dom::objectURLOptionsWorkers
& aOptions
,
122 : URLRunnable(aWorkerPrivate
),
132 AssertIsOnMainThread();
134 nsCOMPtr
<nsIPrincipal
> principal
;
135 nsIDocument
* doc
= nullptr;
137 nsCOMPtr
<nsPIDOMWindow
> window
= mWorkerPrivate
->GetWindow();
139 doc
= window
->GetExtantDoc();
141 SetDOMStringToNull(mURL
);
145 principal
= doc
->NodePrincipal();
147 MOZ_ASSERT(mWorkerPrivate
->IsChromeWorker());
148 principal
= mWorkerPrivate
->GetPrincipal();
152 nsresult rv
= nsHostObjectProtocolHandler::AddDataEntry(
153 NS_LITERAL_CSTRING(BLOBURI_SCHEME
),
154 mBlob
, principal
, url
);
157 NS_WARNING("Failed to add data entry for the blob!");
158 SetDOMStringToNull(mURL
);
163 doc
->RegisterHostObjectUri(url
);
165 mWorkerPrivate
->RegisterHostObjectURI(url
);
168 mURL
= NS_ConvertUTF8toUTF16(url
);
172 // This class revokes an URL on the main thread.
173 class RevokeURLRunnable
: public URLRunnable
179 RevokeURLRunnable(WorkerPrivate
* aWorkerPrivate
,
180 const nsAString
& aURL
)
181 : URLRunnable(aWorkerPrivate
),
188 AssertIsOnMainThread();
190 nsCOMPtr
<nsIPrincipal
> principal
;
191 nsIDocument
* doc
= nullptr;
193 nsCOMPtr
<nsPIDOMWindow
> window
= mWorkerPrivate
->GetWindow();
195 doc
= window
->GetExtantDoc();
200 principal
= doc
->NodePrincipal();
202 MOZ_ASSERT(mWorkerPrivate
->IsChromeWorker());
203 principal
= mWorkerPrivate
->GetPrincipal();
206 NS_ConvertUTF16toUTF8
url(mURL
);
208 nsIPrincipal
* urlPrincipal
=
209 nsHostObjectProtocolHandler::GetDataEntryPrincipal(url
);
213 NS_SUCCEEDED(principal
->Subsumes(urlPrincipal
, &subsumes
)) &&
216 doc
->UnregisterHostObjectUri(url
);
219 nsHostObjectProtocolHandler::RemoveDataEntry(url
);
223 mWorkerPrivate
->UnregisterHostObjectURI(url
);
230 URL::CreateObjectURL(const WorkerGlobalObject
& aGlobal
, JSObject
* aBlob
,
231 const mozilla::dom::objectURLOptionsWorkers
& aOptions
,
232 nsString
& aResult
, mozilla::ErrorResult
& aRv
)
234 JSContext
* cx
= aGlobal
.GetContext();
235 WorkerPrivate
* workerPrivate
= GetWorkerPrivateFromContext(cx
);
237 nsCOMPtr
<nsIDOMBlob
> blob
= file::GetDOMBlobFromJSObject(aBlob
);
239 SetDOMStringToNull(aResult
);
241 NS_NAMED_LITERAL_STRING(argStr
, "Argument 1 of URL.createObjectURL");
242 NS_NAMED_LITERAL_STRING(blobStr
, "Blob");
243 aRv
.ThrowTypeError(MSG_DOES_NOT_IMPLEMENT_INTERFACE
, &argStr
, &blobStr
);
247 nsRefPtr
<CreateURLRunnable
> runnable
=
248 new CreateURLRunnable(workerPrivate
, blob
, aOptions
, aResult
);
250 if (!runnable
->Dispatch(cx
)) {
251 JS_ReportPendingException(cx
);
257 URL::CreateObjectURL(const WorkerGlobalObject
& aGlobal
, JSObject
& aBlob
,
258 const mozilla::dom::objectURLOptionsWorkers
& aOptions
,
259 nsString
& aResult
, mozilla::ErrorResult
& aRv
)
261 return CreateObjectURL(aGlobal
, &aBlob
, aOptions
, aResult
, aRv
);
266 URL::RevokeObjectURL(const WorkerGlobalObject
& aGlobal
, const nsAString
& aUrl
)
268 JSContext
* cx
= aGlobal
.GetContext();
269 WorkerPrivate
* workerPrivate
= GetWorkerPrivateFromContext(cx
);
271 nsRefPtr
<RevokeURLRunnable
> runnable
=
272 new RevokeURLRunnable(workerPrivate
, aUrl
);
274 if (!runnable
->Dispatch(cx
)) {
275 JS_ReportPendingException(cx
);