CacheLoadHandler.cpp (20886B)
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 "CacheLoadHandler.h" 8 9 #include "ScriptResponseHeaderProcessor.h" // ScriptResponseHeaderProcessor 10 #include "WorkerLoadContext.h" // WorkerLoadContext 11 #include "jsapi.h" 12 #include "mozilla/Assertions.h" 13 #include "mozilla/Encoding.h" 14 #include "mozilla/TaskQueue.h" 15 #include "mozilla/UniquePtr.h" 16 #include "mozilla/dom/CacheBinding.h" 17 #include "mozilla/dom/Document.h" 18 #include "mozilla/dom/PolicyContainer.h" 19 #include "mozilla/dom/Response.h" 20 #include "mozilla/dom/ServiceWorkerBinding.h" // ServiceWorkerState 21 #include "mozilla/dom/WorkerScope.h" 22 #include "mozilla/dom/cache/CacheTypes.h" 23 #include "mozilla/dom/workerinternals/ScriptLoader.h" // WorkerScriptLoader 24 #include "nsIPrincipal.h" 25 #include "nsIThreadRetargetableRequest.h" 26 #include "nsIXPConnect.h" 27 #include "nsNetUtil.h" 28 29 namespace mozilla { 30 namespace dom { 31 32 namespace workerinternals::loader { 33 34 NS_IMPL_ISUPPORTS0(CacheCreator) 35 36 NS_IMPL_ISUPPORTS(CacheLoadHandler, nsIStreamLoaderObserver) 37 38 NS_IMPL_ISUPPORTS0(CachePromiseHandler) 39 40 CachePromiseHandler::CachePromiseHandler( 41 WorkerScriptLoader* aLoader, ThreadSafeRequestHandle* aRequestHandle) 42 : mLoader(aLoader), mRequestHandle(aRequestHandle) { 43 AssertIsOnMainThread(); 44 MOZ_ASSERT(mLoader); 45 } 46 47 void CachePromiseHandler::ResolvedCallback(JSContext* aCx, 48 JS::Handle<JS::Value> aValue, 49 ErrorResult& aRv) { 50 AssertIsOnMainThread(); 51 if (mRequestHandle->IsEmpty()) { 52 return; 53 } 54 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 55 56 // May already have been canceled by CacheLoadHandler::Fail from 57 // CancelMainThread. 58 MOZ_ASSERT(loadContext->mCacheStatus == WorkerLoadContext::WritingToCache || 59 loadContext->mCacheStatus == WorkerLoadContext::Cancel); 60 MOZ_ASSERT_IF(loadContext->mCacheStatus == WorkerLoadContext::Cancel, 61 !loadContext->mCachePromise); 62 63 if (loadContext->mCachePromise) { 64 loadContext->mCacheStatus = WorkerLoadContext::Cached; 65 loadContext->mCachePromise = nullptr; 66 mRequestHandle->MaybeExecuteFinishedScripts(); 67 } 68 } 69 70 void CachePromiseHandler::RejectedCallback(JSContext* aCx, 71 JS::Handle<JS::Value> aValue, 72 ErrorResult& aRv) { 73 AssertIsOnMainThread(); 74 if (mRequestHandle->IsEmpty()) { 75 return; 76 } 77 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 78 79 // May already have been canceled by CacheLoadHandler::Fail from 80 // CancelMainThread. 81 MOZ_ASSERT(loadContext->mCacheStatus == WorkerLoadContext::WritingToCache || 82 loadContext->mCacheStatus == WorkerLoadContext::Cancel); 83 loadContext->mCacheStatus = WorkerLoadContext::Cancel; 84 85 loadContext->mCachePromise = nullptr; 86 87 // This will delete the cache object and will call LoadingFinished() with an 88 // error for each ongoing operation. 89 auto* cacheCreator = mRequestHandle->GetCacheCreator(); 90 if (cacheCreator) { 91 cacheCreator->DeleteCache(NS_ERROR_FAILURE); 92 } 93 } 94 95 CacheCreator::CacheCreator(WorkerPrivate* aWorkerPrivate) 96 : mCacheName(aWorkerPrivate->ServiceWorkerCacheName()), 97 mOriginAttributes(aWorkerPrivate->GetOriginAttributes()) { 98 MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); 99 } 100 101 nsresult CacheCreator::CreateCacheStorage(nsIPrincipal* aPrincipal) { 102 AssertIsOnMainThread(); 103 MOZ_ASSERT(!mCacheStorage); 104 MOZ_ASSERT(aPrincipal); 105 106 nsIXPConnect* xpc = nsContentUtils::XPConnect(); 107 MOZ_ASSERT(xpc, "This should never be null!"); 108 109 AutoJSAPI jsapi; 110 jsapi.Init(); 111 JSContext* cx = jsapi.cx(); 112 JS::Rooted<JSObject*> sandbox(cx); 113 nsresult rv = xpc->CreateSandbox(cx, aPrincipal, sandbox.address()); 114 if (NS_WARN_IF(NS_FAILED(rv))) { 115 return rv; 116 } 117 118 // The JSContext is not in a realm, so CreateSandbox returned an unwrapped 119 // global. 120 MOZ_ASSERT(JS_IsGlobalObject(sandbox)); 121 122 mSandboxGlobalObject = xpc::NativeGlobal(sandbox); 123 if (NS_WARN_IF(!mSandboxGlobalObject)) { 124 return NS_ERROR_FAILURE; 125 } 126 127 // Create a CacheStorage bypassing its trusted origin checks. The 128 // ServiceWorker has already performed its own checks before getting 129 // to this point. 130 ErrorResult error; 131 mCacheStorage = CacheStorage::CreateOnMainThread( 132 mozilla::dom::cache::CHROME_ONLY_NAMESPACE, mSandboxGlobalObject, 133 aPrincipal, true /* force trusted origin */, error); 134 if (NS_WARN_IF(error.Failed())) { 135 return error.StealNSResult(); 136 } 137 138 return NS_OK; 139 } 140 141 nsresult CacheCreator::Load(nsIPrincipal* aPrincipal) { 142 AssertIsOnMainThread(); 143 MOZ_ASSERT(!mLoaders.IsEmpty()); 144 145 nsresult rv = CreateCacheStorage(aPrincipal); 146 if (NS_WARN_IF(NS_FAILED(rv))) { 147 return rv; 148 } 149 150 ErrorResult error; 151 MOZ_ASSERT(!mCacheName.IsEmpty()); 152 RefPtr<Promise> promise = mCacheStorage->Open(mCacheName, error); 153 if (NS_WARN_IF(error.Failed())) { 154 return error.StealNSResult(); 155 } 156 157 promise->AppendNativeHandler(this); 158 return NS_OK; 159 } 160 161 void CacheCreator::FailLoaders(nsresult aRv) { 162 AssertIsOnMainThread(); 163 164 // Fail() can call LoadingFinished() which may call ExecuteFinishedScripts() 165 // which sets mCacheCreator to null, so hold a ref. 166 RefPtr<CacheCreator> kungfuDeathGrip = this; 167 168 for (uint32_t i = 0, len = mLoaders.Length(); i < len; ++i) { 169 mLoaders[i]->Fail(aRv); 170 } 171 172 mLoaders.Clear(); 173 } 174 175 void CacheCreator::RejectedCallback(JSContext* aCx, 176 JS::Handle<JS::Value> aValue, 177 ErrorResult& aRv) { 178 AssertIsOnMainThread(); 179 FailLoaders(NS_ERROR_FAILURE); 180 } 181 182 void CacheCreator::ResolvedCallback(JSContext* aCx, 183 JS::Handle<JS::Value> aValue, 184 ErrorResult& aRv) { 185 AssertIsOnMainThread(); 186 if (!aValue.isObject()) { 187 FailLoaders(NS_ERROR_FAILURE); 188 return; 189 } 190 191 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); 192 Cache* cache = nullptr; 193 nsresult rv = UNWRAP_OBJECT(Cache, &obj, cache); 194 if (NS_WARN_IF(NS_FAILED(rv))) { 195 FailLoaders(NS_ERROR_FAILURE); 196 return; 197 } 198 199 mCache = cache; 200 MOZ_DIAGNOSTIC_ASSERT(mCache); 201 202 // If the worker is canceled, CancelMainThread() will have cleared the 203 // loaders via DeleteCache(). 204 for (uint32_t i = 0, len = mLoaders.Length(); i < len; ++i) { 205 mLoaders[i]->Load(cache); 206 } 207 } 208 209 void CacheCreator::DeleteCache(nsresult aReason) { 210 AssertIsOnMainThread(); 211 212 // This is called when the load is canceled which can occur before 213 // mCacheStorage is initialized. 214 if (mCacheStorage) { 215 // It's safe to do this while Cache::Match() and Cache::Put() calls are 216 // running. 217 RefPtr<Promise> promise = mCacheStorage->Delete(mCacheName, IgnoreErrors()); 218 219 // We don't care to know the result of the promise object. 220 } 221 222 // Always call this here to ensure the loaders array is cleared. 223 FailLoaders(NS_ERROR_FAILURE); 224 } 225 226 CacheLoadHandler::CacheLoadHandler(ThreadSafeWorkerRef* aWorkerRef, 227 ThreadSafeRequestHandle* aRequestHandle, 228 bool aIsWorkerScript, 229 bool aOnlyExistingCachedResourcesAllowed, 230 WorkerScriptLoader* aLoader) 231 : mRequestHandle(aRequestHandle), 232 mLoader(aLoader), 233 mWorkerRef(aWorkerRef), 234 mIsWorkerScript(aIsWorkerScript), 235 mFailed(false), 236 mOnlyExistingCachedResourcesAllowed(aOnlyExistingCachedResourcesAllowed) { 237 MOZ_ASSERT(aWorkerRef); 238 MOZ_ASSERT(aWorkerRef->Private()->IsServiceWorker()); 239 mMainThreadEventTarget = aWorkerRef->Private()->MainThreadEventTarget(); 240 MOZ_ASSERT(mMainThreadEventTarget); 241 mBaseURI = mLoader->GetBaseURI(); 242 AssertIsOnMainThread(); 243 244 // Worker scripts are always decoded as UTF-8 per spec. 245 mDecoder = MakeUnique<ScriptDecoder>(UTF_8_ENCODING, 246 ScriptDecoder::BOMHandling::Remove); 247 } 248 249 void CacheLoadHandler::Fail(nsresult aRv) { 250 AssertIsOnMainThread(); 251 MOZ_ASSERT(NS_FAILED(aRv)); 252 253 if (mFailed) { 254 return; 255 } 256 257 mFailed = true; 258 259 if (mPump) { 260 MOZ_ASSERT_IF(!mRequestHandle->IsEmpty(), 261 mRequestHandle->GetContext()->mCacheStatus == 262 WorkerLoadContext::ReadingFromCache); 263 mPump->Cancel(aRv); 264 mPump = nullptr; 265 } 266 if (mRequestHandle->IsEmpty()) { 267 return; 268 } 269 270 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 271 272 loadContext->mCacheStatus = WorkerLoadContext::Cancel; 273 274 if (loadContext->mCachePromise) { 275 loadContext->mCachePromise->MaybeReject(aRv); 276 } 277 278 loadContext->mCachePromise = nullptr; 279 280 mRequestHandle->LoadingFinished(aRv); 281 } 282 283 void CacheLoadHandler::Load(Cache* aCache) { 284 AssertIsOnMainThread(); 285 MOZ_ASSERT(aCache); 286 MOZ_ASSERT(!mRequestHandle->IsEmpty()); 287 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 288 289 nsCOMPtr<nsIURI> uri; 290 nsresult rv = NS_NewURI(getter_AddRefs(uri), loadContext->mRequest->mURL, 291 nullptr, mBaseURI); 292 if (NS_WARN_IF(NS_FAILED(rv))) { 293 Fail(rv); 294 return; 295 } 296 297 MOZ_ASSERT(loadContext->mFullURL.IsEmpty()); 298 rv = uri->GetSpec(loadContext->mFullURL); 299 if (NS_WARN_IF(NS_FAILED(rv))) { 300 Fail(rv); 301 return; 302 } 303 304 mozilla::dom::RequestOrUTF8String request; 305 request.SetAsUTF8String().ShareOrDependUpon(loadContext->mFullURL); 306 307 mozilla::dom::CacheQueryOptions params; 308 309 // This JSContext will not end up executing JS code because here there are 310 // no ReadableStreams involved. 311 AutoJSAPI jsapi; 312 jsapi.Init(); 313 314 ErrorResult error; 315 RefPtr<Promise> promise = aCache->Match(jsapi.cx(), request, params, error); 316 if (NS_WARN_IF(error.Failed())) { 317 Fail(error.StealNSResult()); 318 return; 319 } 320 321 promise->AppendNativeHandler(this); 322 } 323 324 void CacheLoadHandler::RejectedCallback(JSContext* aCx, 325 JS::Handle<JS::Value> aValue, 326 ErrorResult& aRv) { 327 AssertIsOnMainThread(); 328 MOZ_ASSERT(!mRequestHandle->IsEmpty()); 329 330 MOZ_ASSERT(mRequestHandle->GetContext()->mCacheStatus == 331 WorkerLoadContext::Uncached); 332 Fail(NS_ERROR_FAILURE); 333 } 334 335 void CacheLoadHandler::ResolvedCallback(JSContext* aCx, 336 JS::Handle<JS::Value> aValue, 337 ErrorResult& aRv) { 338 AssertIsOnMainThread(); 339 MOZ_ASSERT(!mRequestHandle->IsEmpty()); 340 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 341 342 // If we have already called 'Fail', we should not proceed. If we cancelled, 343 // we should similarily not proceed. 344 if (mFailed) { 345 return; 346 } 347 348 MOZ_ASSERT(loadContext->mCacheStatus == WorkerLoadContext::Uncached); 349 350 nsresult rv; 351 352 // The ServiceWorkerScriptCache will store data for any scripts it 353 // it knows about. This is always at least the top level script. 354 // Depending on if a previous version of the service worker has 355 // been installed or not it may also know about importScripts(). We 356 // must handle loading and offlining new importScripts() here, however. 357 if (aValue.isUndefined()) { 358 // If this is the main script or we're not loading a new service worker 359 // then this is an error. This can happen for internal reasons, like 360 // storage was probably wiped without removing the service worker 361 // registration. It can also happen for exposed reasons like the 362 // service worker script calling importScripts() after install. 363 if (NS_WARN_IF(mIsWorkerScript || mOnlyExistingCachedResourcesAllowed)) { 364 Fail(NS_ERROR_DOM_INVALID_STATE_ERR); 365 return; 366 } 367 368 loadContext->mCacheStatus = WorkerLoadContext::ToBeCached; 369 rv = mLoader->LoadScript(mRequestHandle); 370 if (NS_WARN_IF(NS_FAILED(rv))) { 371 Fail(rv); 372 } 373 return; 374 } 375 376 MOZ_ASSERT(aValue.isObject()); 377 378 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); 379 mozilla::dom::Response* response = nullptr; 380 rv = UNWRAP_OBJECT(Response, &obj, response); 381 if (NS_WARN_IF(NS_FAILED(rv))) { 382 Fail(rv); 383 return; 384 } 385 386 InternalHeaders* headers = response->GetInternalHeaders(); 387 388 headers->Get("content-security-policy"_ns, mCSPHeaderValue, IgnoreErrors()); 389 headers->Get("content-security-policy-report-only"_ns, 390 mCSPReportOnlyHeaderValue, IgnoreErrors()); 391 headers->Get("referrer-policy"_ns, mReferrerPolicyHeaderValue, 392 IgnoreErrors()); 393 394 nsAutoCString coepHeader; 395 headers->Get("cross-origin-embedder-policy"_ns, coepHeader, IgnoreErrors()); 396 397 nsILoadInfo::CrossOriginEmbedderPolicy coep = 398 NS_GetCrossOriginEmbedderPolicyFromHeader( 399 coepHeader, mWorkerRef->Private()->Trials().IsEnabled( 400 OriginTrial::CoepCredentialless)); 401 402 rv = ScriptResponseHeaderProcessor::ProcessCrossOriginEmbedderPolicyHeader( 403 mWorkerRef->Private(), coep, loadContext->IsTopLevel()); 404 405 if (NS_WARN_IF(NS_FAILED(rv))) { 406 Fail(rv); 407 return; 408 } 409 410 nsCOMPtr<nsIInputStream> inputStream; 411 response->GetBody(getter_AddRefs(inputStream)); 412 mChannelInfo = response->GetChannelInfo(); 413 const UniquePtr<PrincipalInfo>& pInfo = response->GetPrincipalInfo(); 414 if (pInfo) { 415 mPrincipalInfo = mozilla::MakeUnique<PrincipalInfo>(*pInfo); 416 } 417 418 if (!inputStream) { 419 loadContext->mCacheStatus = WorkerLoadContext::Cached; 420 421 if (mRequestHandle->IsCancelled()) { 422 auto* cacheCreator = mRequestHandle->GetCacheCreator(); 423 if (cacheCreator) { 424 cacheCreator->DeleteCache(mRequestHandle->GetCancelResult()); 425 } 426 return; 427 } 428 429 nsresult rv = DataReceivedFromCache( 430 (uint8_t*)"", 0, mChannelInfo, std::move(mPrincipalInfo), 431 mCSPHeaderValue, mCSPReportOnlyHeaderValue, mReferrerPolicyHeaderValue); 432 433 mRequestHandle->OnStreamComplete(rv); 434 return; 435 } 436 437 MOZ_ASSERT(!mPump); 438 rv = NS_NewInputStreamPump(getter_AddRefs(mPump), inputStream.forget(), 439 0, /* default segsize */ 440 0, /* default segcount */ 441 false, /* default closeWhenDone */ 442 mMainThreadEventTarget); 443 if (NS_WARN_IF(NS_FAILED(rv))) { 444 Fail(rv); 445 return; 446 } 447 448 nsCOMPtr<nsIStreamLoader> loader; 449 rv = NS_NewStreamLoader(getter_AddRefs(loader), this); 450 if (NS_WARN_IF(NS_FAILED(rv))) { 451 Fail(rv); 452 return; 453 } 454 455 rv = mPump->AsyncRead(loader); 456 if (NS_WARN_IF(NS_FAILED(rv))) { 457 mPump = nullptr; 458 Fail(rv); 459 return; 460 } 461 462 nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(mPump); 463 if (rr) { 464 nsCOMPtr<nsIEventTarget> sts = 465 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); 466 RefPtr<TaskQueue> queue = 467 TaskQueue::Create(sts.forget(), "CacheLoadHandler STS Delivery Queue"); 468 rv = rr->RetargetDeliveryTo(queue); 469 if (NS_FAILED(rv)) { 470 NS_WARNING("Failed to dispatch the nsIInputStreamPump to a IO thread."); 471 } 472 } 473 474 loadContext->mCacheStatus = WorkerLoadContext::ReadingFromCache; 475 } 476 477 NS_IMETHODIMP 478 CacheLoadHandler::OnStreamComplete(nsIStreamLoader* aLoader, 479 nsISupports* aContext, nsresult aStatus, 480 uint32_t aStringLen, 481 const uint8_t* aString) { 482 AssertIsOnMainThread(); 483 if (mRequestHandle->IsEmpty()) { 484 return NS_OK; 485 } 486 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 487 488 mPump = nullptr; 489 490 if (NS_FAILED(aStatus)) { 491 MOZ_ASSERT(loadContext->mCacheStatus == 492 WorkerLoadContext::ReadingFromCache || 493 loadContext->mCacheStatus == WorkerLoadContext::Cancel); 494 Fail(aStatus); 495 return NS_OK; 496 } 497 498 MOZ_ASSERT(loadContext->mCacheStatus == WorkerLoadContext::ReadingFromCache); 499 loadContext->mCacheStatus = WorkerLoadContext::Cached; 500 501 MOZ_ASSERT(mPrincipalInfo); 502 503 nsresult rv = DataReceivedFromCache( 504 aString, aStringLen, mChannelInfo, std::move(mPrincipalInfo), 505 mCSPHeaderValue, mCSPReportOnlyHeaderValue, mReferrerPolicyHeaderValue); 506 return mRequestHandle->OnStreamComplete(rv); 507 } 508 509 nsresult CacheLoadHandler::DataReceivedFromCache( 510 const uint8_t* aString, uint32_t aStringLen, 511 const mozilla::dom::ChannelInfo& aChannelInfo, 512 UniquePtr<PrincipalInfo> aPrincipalInfo, const nsACString& aCSPHeaderValue, 513 const nsACString& aCSPReportOnlyHeaderValue, 514 const nsACString& aReferrerPolicyHeaderValue) { 515 AssertIsOnMainThread(); 516 if (mRequestHandle->IsEmpty()) { 517 return NS_OK; 518 } 519 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 520 521 MOZ_ASSERT(loadContext->mCacheStatus == WorkerLoadContext::Cached); 522 MOZ_ASSERT(loadContext->mRequest); 523 524 auto responsePrincipalOrErr = PrincipalInfoToPrincipal(*aPrincipalInfo); 525 MOZ_DIAGNOSTIC_ASSERT(responsePrincipalOrErr.isOk()); 526 527 nsIPrincipal* principal = mWorkerRef->Private()->GetPrincipal(); 528 if (!principal) { 529 WorkerPrivate* parentWorker = mWorkerRef->Private()->GetParent(); 530 MOZ_ASSERT(parentWorker, "Must have a parent!"); 531 principal = parentWorker->GetPrincipal(); 532 } 533 534 nsCOMPtr<nsIPrincipal> responsePrincipal = responsePrincipalOrErr.unwrap(); 535 536 loadContext->mMutedErrorFlag.emplace(!principal->Subsumes(responsePrincipal)); 537 538 // May be null. 539 Document* parentDoc = mWorkerRef->Private()->GetDocument(); 540 541 // Use the regular ScriptDecoder Decoder for this grunt work! Should be just 542 // fine because we're running on the main thread. 543 nsresult rv; 544 545 // Set the Source type to "text" for decoding. 546 loadContext->mRequest->SetTextSource(loadContext); 547 548 rv = mDecoder->DecodeRawData(loadContext->mRequest, aString, aStringLen, 549 /* aEndOfStream = */ true); 550 NS_ENSURE_SUCCESS(rv, rv); 551 552 if (!loadContext->mRequest->ScriptTextLength()) { 553 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, 554 parentDoc, nsContentUtils::eDOM_PROPERTIES, 555 "EmptyWorkerSourceWarning"); 556 } 557 558 nsCOMPtr<nsIURI> finalURI; 559 rv = NS_NewURI(getter_AddRefs(finalURI), loadContext->mFullURL); 560 if (!loadContext->mRequest->BaseURL()) { 561 loadContext->mRequest->SetBaseURL(finalURI); 562 } 563 if (loadContext->IsTopLevel()) { 564 if (NS_SUCCEEDED(rv)) { 565 mWorkerRef->Private()->SetBaseURI(finalURI); 566 } 567 568 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED 569 nsIPrincipal* principal = mWorkerRef->Private()->GetPrincipal(); 570 MOZ_DIAGNOSTIC_ASSERT(principal); 571 572 bool equal = false; 573 MOZ_ALWAYS_SUCCEEDS(responsePrincipal->Equals(principal, &equal)); 574 MOZ_DIAGNOSTIC_ASSERT(equal); 575 576 nsCOMPtr<nsIContentSecurityPolicy> csp; 577 if (parentDoc) { 578 csp = PolicyContainer::GetCSP(parentDoc->GetPolicyContainer()); 579 } 580 MOZ_DIAGNOSTIC_ASSERT(!csp); 581 #endif 582 583 mWorkerRef->Private()->InitChannelInfo(aChannelInfo); 584 585 nsILoadGroup* loadGroup = mWorkerRef->Private()->GetLoadGroup(); 586 MOZ_DIAGNOSTIC_ASSERT(loadGroup); 587 588 // Override the principal on the WorkerPrivate. This is only necessary 589 // in order to get a principal with exactly the correct URL. The fetch 590 // referrer logic depends on the WorkerPrivate principal having a URL 591 // that matches the worker script URL. If bug 1340694 is ever fixed 592 // this can be removed. 593 // XXX: force the partitionedPrincipal to be equal to the response one. 594 // This is OK for now because we don't want to expose partitionedPrincipal 595 // functionality in ServiceWorkers yet. 596 rv = mWorkerRef->Private()->SetPrincipalsAndCSPOnMainThread( 597 responsePrincipal, responsePrincipal, loadGroup, nullptr); 598 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 599 600 rv = mWorkerRef->Private()->SetCSPFromHeaderValues( 601 aCSPHeaderValue, aCSPReportOnlyHeaderValue); 602 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 603 604 mWorkerRef->Private()->UpdateReferrerInfoFromHeader( 605 aReferrerPolicyHeaderValue); 606 } 607 608 if (NS_SUCCEEDED(rv)) { 609 return DataReceived(); 610 } 611 612 return rv; 613 } 614 615 nsresult CacheLoadHandler::DataReceived() { 616 MOZ_ASSERT(!mRequestHandle->IsEmpty()); 617 WorkerLoadContext* loadContext = mRequestHandle->GetContext(); 618 619 if (loadContext->IsTopLevel()) { 620 WorkerPrivate* parent = mWorkerRef->Private()->GetParent(); 621 622 if (parent) { 623 // XHR Params Allowed 624 mWorkerRef->Private()->SetXHRParamsAllowed(parent->XHRParamsAllowed()); 625 626 // Set ContentSecurityPolicy 627 nsresult rv = mWorkerRef->Private()->SetCsp(parent->GetCsp()); 628 NS_ENSURE_SUCCESS(rv, rv); 629 } 630 } 631 632 return NS_OK; 633 } 634 635 } // namespace workerinternals::loader 636 637 } // namespace dom 638 } // namespace mozilla