URLWorker.cpp (5139B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "URLWorker.h" 8 9 #include "mozilla/dom/Blob.h" 10 #include "mozilla/dom/BlobImpl.h" 11 #include "mozilla/dom/BlobURLProtocolHandler.h" 12 #include "mozilla/dom/WorkerRunnable.h" 13 #include "mozilla/dom/WorkerScope.h" 14 15 namespace mozilla::dom { 16 17 // This class creates an URL from a DOM Blob on the main thread. 18 class CreateURLRunnable : public WorkerMainThreadRunnable { 19 private: 20 BlobImpl* mBlobImpl; 21 nsACString& mURL; 22 23 public: 24 CreateURLRunnable(WorkerPrivate* aWorkerPrivate, BlobImpl* aBlobImpl, 25 nsACString& aURL) 26 : WorkerMainThreadRunnable(aWorkerPrivate, "URL :: CreateURL"_ns), 27 mBlobImpl(aBlobImpl), 28 mURL(aURL) { 29 MOZ_ASSERT(aBlobImpl); 30 } 31 32 bool MainThreadRun() override { 33 using namespace mozilla::ipc; 34 35 MOZ_ASSERT(mWorkerRef); 36 WorkerPrivate* workerPrivate = mWorkerRef->Private(); 37 38 AssertIsOnMainThread(); 39 40 nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal(); 41 42 nsCOMPtr<nsICookieJarSettings> cookieJarSettings = 43 workerPrivate->CookieJarSettings(); 44 45 nsAutoString partKey; 46 cookieJarSettings->GetPartitionKey(partKey); 47 48 nsresult rv = BlobURLProtocolHandler::AddDataEntry( 49 mBlobImpl, principal, NS_ConvertUTF16toUTF8(partKey), mURL); 50 if (NS_FAILED(rv)) { 51 NS_WARNING("Failed to add data entry for the blob!"); 52 mURL.SetIsVoid(true); 53 return false; 54 } 55 return true; 56 } 57 }; 58 59 // This class revokes an URL on the main thread. 60 class RevokeURLRunnable : public WorkerMainThreadRunnable { 61 private: 62 const nsCString mURL; 63 64 public: 65 RevokeURLRunnable(WorkerPrivate* aWorkerPrivate, const nsACString& aURL) 66 : WorkerMainThreadRunnable(aWorkerPrivate, "URL :: RevokeURL"_ns), 67 mURL(aURL) {} 68 69 bool MainThreadRun() override { 70 AssertIsOnMainThread(); 71 72 MOZ_ASSERT(mWorkerRef); 73 WorkerPrivate* workerPrivate = mWorkerRef->Private(); 74 75 nsCOMPtr<nsICookieJarSettings> cookieJarSettings = 76 workerPrivate->CookieJarSettings(); 77 78 nsAutoString partKey; 79 cookieJarSettings->GetPartitionKey(partKey); 80 81 BlobURLProtocolHandler::RemoveDataEntry(mURL, workerPrivate->GetPrincipal(), 82 NS_ConvertUTF16toUTF8(partKey)); 83 return true; 84 } 85 }; 86 87 // This class checks if an URL is valid and belongs to a Blob on the main 88 // thread. 89 class IsBoundToBlobRunnable : public WorkerMainThreadRunnable { 90 private: 91 const nsCString mURL; 92 bool mResult; 93 94 public: 95 IsBoundToBlobRunnable(WorkerPrivate* aWorkerPrivate, const nsACString& aURL) 96 : WorkerMainThreadRunnable(aWorkerPrivate, "URL :: IsValidURL"_ns), 97 mURL(aURL), 98 mResult(false) {} 99 100 bool MainThreadRun() override { 101 AssertIsOnMainThread(); 102 103 mResult = BlobURLProtocolHandler::HasDataEntryTypeBlob(mURL); 104 105 return true; 106 } 107 108 bool Result() const { return mResult; } 109 }; 110 111 /* static */ 112 void URLWorker::CreateObjectURL(const GlobalObject& aGlobal, 113 const BlobOrMediaSource& aObj, 114 nsACString& aResult, 115 mozilla::ErrorResult& aRv) { 116 if (!aObj.IsBlob()) { 117 MOZ_CRASH("MediaSource is not supported in workers"); 118 return; 119 } 120 121 JSContext* cx = aGlobal.Context(); 122 WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); 123 124 RefPtr<BlobImpl> blobImpl = aObj.GetAsBlob().Impl(); 125 MOZ_ASSERT(blobImpl); 126 127 RefPtr<CreateURLRunnable> runnable = 128 new CreateURLRunnable(workerPrivate, blobImpl, aResult); 129 130 runnable->Dispatch(workerPrivate, Canceling, aRv); 131 if (NS_WARN_IF(aRv.Failed())) { 132 return; 133 } 134 135 WorkerGlobalScope* scope = workerPrivate->GlobalScope(); 136 MOZ_ASSERT(scope); 137 138 scope->RegisterHostObjectURI(aResult); 139 } 140 141 /* static */ 142 void URLWorker::RevokeObjectURL(const GlobalObject& aGlobal, 143 const nsACString& aUrl, ErrorResult& aRv) { 144 JSContext* cx = aGlobal.Context(); 145 WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); 146 147 RefPtr<RevokeURLRunnable> runnable = 148 new RevokeURLRunnable(workerPrivate, aUrl); 149 150 runnable->Dispatch(workerPrivate, Canceling, aRv); 151 if (NS_WARN_IF(aRv.Failed())) { 152 return; 153 } 154 155 WorkerGlobalScope* scope = workerPrivate->GlobalScope(); 156 MOZ_ASSERT(scope); 157 158 scope->UnregisterHostObjectURI(aUrl); 159 } 160 161 /* static */ 162 bool URLWorker::IsBoundToBlob(const GlobalObject& aGlobal, 163 const nsACString& aUrl, ErrorResult& aRv) { 164 JSContext* cx = aGlobal.Context(); 165 WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); 166 167 RefPtr<IsBoundToBlobRunnable> runnable = 168 new IsBoundToBlobRunnable(workerPrivate, aUrl); 169 170 runnable->Dispatch(workerPrivate, Canceling, aRv); 171 if (NS_WARN_IF(aRv.Failed())) { 172 return false; 173 } 174 175 return runnable->Result(); 176 } 177 178 } // namespace mozilla::dom