ImageCacheKey.cpp (3936B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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/. */ 5 6 #include "ImageCacheKey.h" 7 8 #include "mozilla/AntiTrackingUtils.h" 9 #include "mozilla/HashFunctions.h" 10 #include "mozilla/StorageAccess.h" 11 #include "mozilla/StoragePrincipalHelper.h" 12 #include "mozilla/dom/Document.h" 13 #include "mozilla/dom/ServiceWorkerManager.h" 14 #include "mozilla/StaticPrefs_privacy.h" 15 #include "mozilla/StorageAccess.h" 16 #include "nsContentUtils.h" 17 #include "nsHashKeys.h" 18 #include "nsLayoutUtils.h" 19 20 namespace mozilla { 21 22 using namespace dom; 23 24 namespace image { 25 26 static nsIPrincipal* GetLoaderPrincipal(Document* aDocument) { 27 return aDocument ? aDocument->NodePrincipal() 28 : nsContentUtils::GetSystemPrincipal(); 29 } 30 31 static nsIPrincipal* GetPartitionPrincipal(Document* aDocument) { 32 return aDocument ? aDocument->PartitionedPrincipal() 33 : nsContentUtils::GetSystemPrincipal(); 34 } 35 36 ImageCacheKey::ImageCacheKey(nsIURI* aURI, CORSMode aCORSMode, 37 Document* aDocument) 38 : mURI(aURI), 39 mControlledDocument(GetSpecialCaseDocumentToken(aDocument)), 40 mLoaderPrincipal(GetLoaderPrincipal(aDocument)), 41 mPartitionPrincipal(GetPartitionPrincipal(aDocument)), 42 mCORSMode(aCORSMode), 43 mAppType(GetAppType(aDocument)) { 44 MOZ_ASSERT(mLoaderPrincipal); 45 MOZ_ASSERT(mPartitionPrincipal); 46 } 47 48 ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther) = default; 49 ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther) = default; 50 51 bool ImageCacheKey::operator==(const ImageCacheKey& aOther) const { 52 // Don't share the image cache between a controlled document and anything 53 // else. 54 if (mControlledDocument != aOther.mControlledDocument) { 55 return false; 56 } 57 58 if (!mPartitionPrincipal->Equals(aOther.mPartitionPrincipal)) { 59 return false; 60 } 61 62 if (mCORSMode != aOther.mCORSMode) { 63 return false; 64 } 65 // Don't share the image cache between two different appTypes 66 if (mAppType != aOther.mAppType) { 67 return false; 68 } 69 70 // For non-blob URIs, compare the URIs. 71 bool equals = false; 72 nsresult rv = mURI->Equals(aOther.mURI, &equals); 73 return NS_SUCCEEDED(rv) && equals; 74 } 75 76 void ImageCacheKey::EnsureHash() const { 77 MOZ_ASSERT(mHash.isNothing()); 78 79 // NOTE(emilio): Not adding the partition principal to the hash, since it 80 // can mutate (see bug 1955775). 81 nsAutoCString spec; 82 (void)mURI->GetSpec(spec); 83 mHash.emplace( 84 AddToHash(HashString(spec), mControlledDocument, mAppType, mCORSMode)); 85 } 86 87 /* static */ 88 void* ImageCacheKey::GetSpecialCaseDocumentToken(Document* aDocument) { 89 // Cookie-averse documents can never have storage granted to them. Since they 90 // may not have inner windows, they would require special handling below, so 91 // just bail out early here. 92 if (!aDocument || aDocument->IsCookieAverse()) { 93 return nullptr; 94 } 95 96 // For controlled documents, we cast the pointer into a void* to avoid 97 // dereferencing it (since we only use it for comparisons). 98 RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); 99 if (swm && aDocument->GetController().isSome()) { 100 return aDocument; 101 } 102 103 return nullptr; 104 } 105 106 /* static */ 107 nsIDocShell::AppType ImageCacheKey::GetAppType(Document* aDocument) { 108 if (!aDocument) { 109 return nsIDocShell::APP_TYPE_UNKNOWN; 110 } 111 112 nsCOMPtr<nsIDocShellTreeItem> dsti = aDocument->GetDocShell(); 113 if (!dsti) { 114 return nsIDocShell::APP_TYPE_UNKNOWN; 115 } 116 117 nsCOMPtr<nsIDocShellTreeItem> root; 118 dsti->GetInProcessRootTreeItem(getter_AddRefs(root)); 119 if (nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(root)) { 120 return docShell->GetAppType(); 121 } 122 return nsIDocShell::APP_TYPE_UNKNOWN; 123 } 124 125 } // namespace image 126 } // namespace mozilla