void DOMStorageManager::ClearCaches(uint32_t aUnloadFlags, const OriginAttributesPattern& aPattern, const nsACString& aOriginScope) { for (auto iter1 = mCaches.Iter(); !iter1.Done(); iter1.Next()) { PrincipalOriginAttributes oa; DebugOnly<bool> rv = oa.PopulateFromSuffix(iter1.Key()); MOZ_ASSERT(rv); if (!aPattern.Matches(oa)) { // This table doesn't match the given origin attributes pattern continue; } CacheOriginHashtable* table = iter1.Data(); for (auto iter2 = table->Iter(); !iter2.Done(); iter2.Next()) { DOMStorageCache* cache = iter2.Get()->cache(); if (aOriginScope.IsEmpty() || StringBeginsWith(cache->OriginNoSuffix(), aOriginScope)) { cache->UnloadItems(aUnloadFlags); } } } }
NS_IMETHODIMP LoadInfo::ResetPrincipalsToNullPrincipal() { // take the originAttributes from the LoadInfo and create // a new NullPrincipal using those origin attributes. PrincipalOriginAttributes pAttrs; pAttrs.InheritFromNecko(mOriginAttributes); nsCOMPtr<nsIPrincipal> newNullPrincipal = nsNullPrincipal::Create(pAttrs); MOZ_ASSERT(mInternalContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT || !mLoadingPrincipal, "LoadingPrincipal should be null for toplevel loads"); // the loadingPrincipal for toplevel loads is always a nullptr; if (mInternalContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) { mLoadingPrincipal = newNullPrincipal; } mTriggeringPrincipal = newNullPrincipal; mPrincipalToInherit = newNullPrincipal; // setting SEC_FORCE_INHERIT_PRINCIPAL_OVERRULE_OWNER will overrule // any non null owner set on the channel and will return the principal // form the loadinfo instead. mSecurityFlags |= SEC_FORCE_INHERIT_PRINCIPAL_OVERRULE_OWNER; return NS_OK; }
/* static */ already_AddRefed<nsNullPrincipal> nsNullPrincipal::CreateWithInheritedAttributes(nsIDocShell* aDocShell) { PrincipalOriginAttributes attrs; attrs.InheritFromDocShellToDoc(nsDocShell::Cast(aDocShell)->GetOriginAttributes(), nullptr); RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal(); nsresult rv = nullPrin->Init(attrs); MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); return nullPrin.forget(); }
NS_IMETHODIMP nsPrincipal::Read(nsIObjectInputStream* aStream) { nsCOMPtr<nsISupports> supports; nsCOMPtr<nsIURI> codebase; nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); if (NS_FAILED(rv)) { return rv; } codebase = do_QueryInterface(supports); nsCOMPtr<nsIURI> domain; rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); if (NS_FAILED(rv)) { return rv; } domain = do_QueryInterface(supports); nsAutoCString suffix; rv = aStream->ReadCString(suffix); NS_ENSURE_SUCCESS(rv, rv); PrincipalOriginAttributes attrs; bool ok = attrs.PopulateFromSuffix(suffix); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); NS_ENSURE_SUCCESS(rv, rv); // This may be null. nsCOMPtr<nsIContentSecurityPolicy> csp = do_QueryInterface(supports, &rv); rv = Init(codebase, attrs); NS_ENSURE_SUCCESS(rv, rv); rv = SetCsp(csp); NS_ENSURE_SUCCESS(rv, rv); // need to link in the CSP context here (link in the URI of the protected // resource). if (csp) { csp->SetRequestContext(nullptr, this); } SetDomain(domain); return NS_OK; }
static bool ReadSuffixAndSpec(JSStructuredCloneReader* aReader, PrincipalOriginAttributes& aAttrs, nsACString& aSpec) { uint32_t suffixLength, specLength; if (!JS_ReadUint32Pair(aReader, &suffixLength, &specLength)) { return false; } nsAutoCString suffix; suffix.SetLength(suffixLength); if (!JS_ReadBytes(aReader, suffix.BeginWriting(), suffixLength)) { return false; } if (!aAttrs.PopulateFromSuffix(suffix)) { return false; } aSpec.SetLength(specLength); if (!JS_ReadBytes(aReader, aSpec.BeginWriting(), specLength)) { return false; } return true; }
/* static */ uint32_t ImageCacheKey::ComputeHash(ImageURL* aURI, const Maybe<uint64_t>& aBlobSerial, const PrincipalOriginAttributes& aAttrs, void* aControlledDocument) { // Since we frequently call Hash() several times in a row on the same // ImageCacheKey, as an optimization we compute our hash once and store it. nsPrintfCString ptr("%p", aControlledDocument); nsAutoCString suffix; aAttrs.CreateSuffix(suffix); if (aBlobSerial) { // For blob URIs, we hash the serial number of the underlying blob, so that // different blob URIs which point to the same blob share a cache entry. We // also include the ref portion of the URI to support media fragments which // requires us to create different Image objects even if the source data is // the same. nsAutoCString ref; aURI->GetRef(ref); return HashGeneric(*aBlobSerial, HashString(ref + suffix + ptr)); } // For non-blob URIs, we hash the URI spec. nsAutoCString spec; aURI->GetSpec(spec); return HashString(spec + suffix + ptr); }
NS_IMETHODIMP nsPrincipal::Read(nsIObjectInputStream* aStream) { nsCOMPtr<nsISupports> supports; nsCOMPtr<nsIURI> codebase; nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); if (NS_FAILED(rv)) { return rv; } codebase = do_QueryInterface(supports); nsCOMPtr<nsIURI> domain; rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); if (NS_FAILED(rv)) { return rv; } domain = do_QueryInterface(supports); nsAutoCString suffix; rv = aStream->ReadCString(suffix); NS_ENSURE_SUCCESS(rv, rv); PrincipalOriginAttributes attrs; bool ok = attrs.PopulateFromSuffix(suffix); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); NS_ENSURE_SUCCESS(rv, rv); rv = Init(codebase, attrs); NS_ENSURE_SUCCESS(rv, rv); mCSP = do_QueryInterface(supports, &rv); // make sure setRequestContext is called after Init(), // to make sure the principals URI been initalized. if (mCSP) { mCSP->SetRequestContext(nullptr, this); } SetDomain(domain); return NS_OK; }
static bool WriteSuffixAndSpec(JSStructuredCloneWriter* aWriter, const PrincipalOriginAttributes& aAttrs, const nsCString& aSpec) { nsAutoCString suffix; aAttrs.CreateSuffix(suffix); return JS_WriteUint32Pair(aWriter, suffix.Length(), aSpec.Length()) && JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) && JS_WriteBytes(aWriter, aSpec.get(), aSpec.Length()); }
nsresult ServiceWorkerRegistrar::ReadData() { // We cannot assert about the correct thread because normally this method // runs on a IO thread, but in gTests we call it from the main-thread. MOZ_ASSERT(mProfileDir); nsCOMPtr<nsIFile> file; nsresult rv = mProfileDir->Clone(getter_AddRefs(file)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } rv = file->Append(NS_LITERAL_STRING(SERVICEWORKERREGISTRAR_FILE)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool exists; rv = file->Exists(&exists); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (!exists) { return NS_OK; } nsCOMPtr<nsIInputStream> stream; rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsILineInputStream> lineInputStream = do_QueryInterface(stream); MOZ_ASSERT(lineInputStream); nsAutoCString version; bool hasMoreLines; rv = lineInputStream->ReadLine(version, &hasMoreLines); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (!IsSupportedVersion(version)) { nsContentUtils::LogMessageToConsole(nsPrintfCString( "Unsupported service worker registrar version: %s", version.get()).get()); return NS_ERROR_FAILURE; } nsTArray<ServiceWorkerRegistrationData> tmpData; bool overwrite = false; bool dedupe = false; while (hasMoreLines) { ServiceWorkerRegistrationData* entry = tmpData.AppendElement(); #define GET_LINE(x) \ rv = lineInputStream->ReadLine(x, &hasMoreLines); \ if (NS_WARN_IF(NS_FAILED(rv))) { \ return rv; \ } \ if (NS_WARN_IF(!hasMoreLines)) { \ return NS_ERROR_FAILURE; \ } nsAutoCString line; nsAutoCString unused; if (version.EqualsLiteral(SERVICEWORKERREGISTRAR_VERSION)) { nsAutoCString suffix; GET_LINE(suffix); PrincipalOriginAttributes attrs; if (!attrs.PopulateFromSuffix(suffix)) { return NS_ERROR_INVALID_ARG; } GET_LINE(entry->scope()); entry->principal() = mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope()); GET_LINE(entry->currentWorkerURL()); nsAutoCString cacheName; GET_LINE(cacheName); CopyUTF8toUTF16(cacheName, entry->cacheName()); } else if (version.EqualsLiteral("3")) { overwrite = true; dedupe = true; nsAutoCString suffix; GET_LINE(suffix); PrincipalOriginAttributes attrs; if (!attrs.PopulateFromSuffix(suffix)) { return NS_ERROR_INVALID_ARG; } // principal spec is no longer used; we use scope directly instead GET_LINE(unused); GET_LINE(entry->scope()); entry->principal() = mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope()); GET_LINE(entry->currentWorkerURL()); nsAutoCString cacheName; GET_LINE(cacheName); CopyUTF8toUTF16(cacheName, entry->cacheName()); } else if (version.EqualsLiteral("2")) { overwrite = true; dedupe = true; nsAutoCString suffix; GET_LINE(suffix); PrincipalOriginAttributes attrs; if (!attrs.PopulateFromSuffix(suffix)) { return NS_ERROR_INVALID_ARG; } // principal spec is no longer used; we use scope directly instead GET_LINE(unused); GET_LINE(entry->scope()); entry->principal() = mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope()); // scriptSpec is no more used in latest version. GET_LINE(unused); GET_LINE(entry->currentWorkerURL()); nsAutoCString cacheName; GET_LINE(cacheName); CopyUTF8toUTF16(cacheName, entry->cacheName()); // waitingCacheName is no more used in latest version. GET_LINE(unused); } else { MOZ_ASSERT_UNREACHABLE("Should never get here!"); } #undef GET_LINE rv = lineInputStream->ReadLine(line, &hasMoreLines); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (!line.EqualsLiteral(SERVICEWORKERREGISTRAR_TERMINATOR)) { return NS_ERROR_FAILURE; } } stream->Close(); // Copy data over to mData. for (uint32_t i = 0; i < tmpData.Length(); ++i) { bool match = false; if (dedupe) { MOZ_ASSERT(overwrite); // If this is an old profile, then we might need to deduplicate. In // theory this can be removed in the future (Bug 1248449) for (uint32_t j = 0; j < mData.Length(); ++j) { // Use same comparison as RegisterServiceWorker. Scope contains // basic origin information. Combine with any principal attributes. if (Equivalent(tmpData[i], mData[j])) { // Last match wins, just like legacy loading used to do in // the ServiceWorkerManager. mData[j] = tmpData[i]; // Dupe found, so overwrite file with reduced list. match = true; break; } } } else { #ifdef DEBUG // Otherwise assert no duplications in debug builds. for (uint32_t j = 0; j < mData.Length(); ++j) { MOZ_ASSERT(!Equivalent(tmpData[i], mData[j])); } #endif } if (!match) { mData.AppendElement(tmpData[i]); } } // Overwrite previous version. // Cannot call SaveData directly because gtest uses main-thread. if (overwrite && NS_FAILED(WriteData())) { NS_WARNING("Failed to write data for the ServiceWorker Registations."); DeleteData(); } return NS_OK; }