/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
using mozilla::ErrorResult; using mozilla::ipc::BackgroundChild; using mozilla::ipc::PBackgroundChild; using mozilla::ipc::PrincipalInfo; using mozilla::ipc::PrincipalToPrincipalInfo;
// We cannot reference IPC types in a webidl binding implementation header. So // define this in the .cpp. struct CacheStorage::Entry final {
RefPtr<Promise> mPromise;
CacheOpArgs mArgs; // We cannot add the requests until after the actor is present. So store // the request data separately for now.
SafeRefPtr<InternalRequest> mRequest;
};
namespace {
bool IsTrusted(const PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled) { // Can happen on main thread or worker thread
if (aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) { returntrue;
}
// Require a ContentPrincipal to avoid null principal, etc.
QM_TRY(OkIf(aPrincipalInfo.type() == PrincipalInfo::TContentPrincipalInfo), false);
// If we're in testing mode, then don't do any more work to determine if // the origin is trusted. We have to run some tests as http. if (aTestingPrefEnabled) { returntrue;
}
// Now parse the scheme of the principal's origin. This is a short term // method for determining "trust". In the long term we need to implement // the full algorithm here: // // https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-secure // // TODO: Implement full secure setting algorithm. (bug 1177856)
if (!IsTrusted(principalInfo, testingEnabled)) {
NS_WARNING("CacheStorage not supported on untrusted origins.");
RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR); return ref.forget();
}
if (aWorkerPrivate->GetOriginAttributes().IsPrivateBrowsing() &&
!StaticPrefs::dom_cache_privateBrowsing_enabled()) {
NS_WARNING("CacheStorage not supported during private browsing.");
RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR); return ref.forget();
}
SafeRefPtr<CacheWorkerRef> workerRef =
CacheWorkerRef::Create(aWorkerPrivate, CacheWorkerRef::eIPCWorkerRef); if (!workerRef) {
NS_WARNING("Worker thread is shutting down.");
aRv.Throw(NS_ERROR_FAILURE); return nullptr;
}
// We have a number of cases where we want to skip the https scheme // validation: // // 1) Any worker when dom.caches.testing.enabled pref is true. // 2) Any worker when dom.serviceWorkers.testing.enabled pref is true. This // is mainly because most sites using SWs will expect Cache to work if // SWs are enabled. // 3) If the window that created this worker has the devtools SW testing // option enabled. Same reasoning as (2). // 4) If the worker itself is a ServiceWorker, then we always skip the // origin checks. The ServiceWorker has its own trusted origin checks // that are better than ours. In addition, we don't have information // about the window any more, so we can't do our own checks. bool testingEnabled = StaticPrefs::dom_caches_testing_enabled() ||
StaticPrefs::dom_serviceWorkers_testing_enabled() ||
aWorkerPrivate->ServiceWorkersTestingInWindow() ||
aWorkerPrivate->IsServiceWorker();
if (!IsTrusted(principalInfo, testingEnabled)) {
NS_WARNING("CacheStorage not supported on untrusted origins.");
RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR); return ref.forget();
}
// If the PBackground actor is already initialized then we can // immediately use it
PBackgroundChild* actor = BackgroundChild::GetOrCreateForCurrentThread(); if (NS_WARN_IF(!actor)) {
mStatus = NS_ERROR_UNEXPECTED; return;
}
// WorkerRef ownership is passed to the CacheStorageChild actor and any // actors it may create. The WorkerRef will keep the worker thread alive // until the actors can gracefully shutdown.
CacheStorageChild* newActor = new CacheStorageChild(this, std::move(aWorkerRef));
PCacheStorageChild* constructedActor = actor->SendPCacheStorageConstructor(
newActor, mNamespace, *mPrincipalInfo);
if (NS_WARN_IF(!constructedActor)) {
mStatus = NS_ERROR_UNEXPECTED; return;
}
// TODO: remove Namespace in favor of CacheStorageNamespace
static_assert(DEFAULT_NAMESPACE == (uint32_t)CacheStorageNamespace::Content, "Default namespace should match webidl Content enum");
static_assert(
CHROME_ONLY_NAMESPACE == (uint32_t)CacheStorageNamespace::Chrome, "Chrome namespace should match webidl Chrome enum");
static_assert(
NUMBER_OF_NAMESPACES == ContiguousEnumSize<CacheStorageNamespace>::value, "Number of namespace should match webidl count");
Namespace ns = static_cast<Namespace>(aNamespace);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
if (privateBrowsing && !StaticPrefs::dom_cache_privateBrowsing_enabled()) {
RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR); return ref.forget();
}
// Create a CacheStorage object bypassing the trusted origin checks // since this is a chrome-only constructor. return CreateOnMainThread(ns, global, aPrincipal, true/* force trusted origin */, aRv);
}
PBackgroundChild* CacheStorage::GetIPCManager() { // This is true because CacheStorage always uses IgnoreBody for requests. // So we should never need to get the IPC manager during Request or // Response serialization.
MOZ_CRASH("CacheStorage does not implement TypeUtils::GetIPCManager()");
}
CacheStorage::~CacheStorage() {
NS_ASSERT_OWNINGTHREAD(CacheStorage); if (mActor) {
mActor->StartDestroyFromListener(); // DestroyInternal() is called synchronously by StartDestroyFromListener(). // So we should have already cleared the mActor.
MOZ_DIAGNOSTIC_ASSERT(!mActor);
}
}
StorageAccess access = mGlobal->GetStorageAccess(); if (access == StorageAccess::ePrivateBrowsing) { if (NS_IsMainThread()) {
SetUseCounter(mGlobal->GetGlobalJSObject(), aLabel);
} else {
SetUseCounter(aLabelWorker);
}
}
// Deny storage access for private browsing unless pref is toggled on. if (nsIPrincipal* principal = mGlobal->PrincipalOrNull()) { if (!principal->IsSystemPrincipal() &&
principal->GetPrivateBrowsingId() !=
nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID &&
!StaticPrefs::dom_cache_privateBrowsing_enabled()) { returnfalse;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.