SharedSubResourceCache.cpp (5327B)
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 "SharedSubResourceCache.h" 8 9 #include "mozilla/RefPtr.h" 10 #include "mozilla/UniquePtr.h" 11 #include "mozilla/dom/CacheablePerformanceTimingData.h" 12 #include "mozilla/dom/Document.h" 13 #include "mozilla/dom/Performance.h" 14 #include "mozilla/dom/PerformanceResourceTimingBinding.h" 15 #include "mozilla/dom/PerformanceStorage.h" 16 #include "mozilla/dom/PerformanceTiming.h" 17 #include "mozilla/net/HttpBaseChannel.h" 18 #include "nsCOMPtr.h" 19 #include "nsDOMNavigationTiming.h" 20 #include "nsHttpResponseHead.h" 21 #include "nsIHttpChannel.h" 22 #include "nsIRequest.h" 23 #include "nsITimedChannel.h" 24 #include "nsPIDOMWindow.h" 25 #include "nsQueryObject.h" 26 27 namespace mozilla { 28 29 namespace SharedSubResourceCacheUtils { 30 31 void AddPerformanceEntryForCache( 32 const nsString& aEntryName, const nsString& aInitiatorType, 33 const SubResourceNetworkMetadataHolder* aNetworkMetadata, 34 TimeStamp aStartTime, TimeStamp aEndTime, dom::Document* aDocument) { 35 MOZ_ASSERT(aDocument); 36 37 if (!aNetworkMetadata || !aNetworkMetadata->GetPerfData()) { 38 return; 39 } 40 41 nsPIDOMWindowInner* win = aDocument->GetInnerWindow(); 42 if (!win) { 43 return; 44 } 45 RefPtr<dom::Performance> performance = win->GetPerformance(); 46 if (!performance) { 47 return; 48 } 49 50 // TODO: Bug 1751383. 51 auto renderBlocking = dom::RenderBlockingStatusType::Non_blocking; 52 53 UniquePtr<dom::PerformanceTimingData> data( 54 dom::PerformanceTimingData::Create(*aNetworkMetadata->GetPerfData(), 0, 55 aStartTime, aEndTime, renderBlocking)); 56 if (!data) { 57 return; 58 } 59 60 dom::PerformanceStorage* storage = performance->AsPerformanceStorage(); 61 MOZ_ASSERT(storage); 62 storage->AddEntry(aEntryName, aInitiatorType, std::move(data)); 63 } 64 65 bool ShouldClearEntry(nsIURI* aEntryURI, nsIPrincipal* aEntryLoaderPrincipal, 66 nsIPrincipal* aEntryPartitionPrincipal, 67 const Maybe<bool>& aChrome, 68 const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal, 69 const Maybe<nsCString>& aSchemelessSite, 70 const Maybe<OriginAttributesPattern>& aPattern, 71 const Maybe<nsCString>& aURL) { 72 if (aChrome.isSome()) { 73 RefPtr<nsIURI> uri = aEntryURI; 74 if (!uri) { 75 // If there's no uri (inline resource) try to use the principal URI. 76 uri = aEntryLoaderPrincipal->GetURI(); 77 } 78 const bool isChrome = [&] { 79 if (uri && (uri->SchemeIs("chrome") || uri->SchemeIs("resource"))) { 80 return true; 81 } 82 if (!aEntryURI && aEntryLoaderPrincipal->IsSystemPrincipal()) { 83 return true; 84 } 85 return false; 86 }(); 87 88 if (*aChrome != isChrome) { 89 return false; 90 } 91 92 if (!aPrincipal && !aSchemelessSite && !aURL) { 93 return true; 94 } 95 } 96 97 if (aURL) { 98 if (!aEntryURI) { 99 // Inline resources have no URL. 100 return false; 101 } 102 nsAutoCString spec; 103 nsresult rv = aEntryURI->GetSpec(spec); 104 if (NS_FAILED(rv)) { 105 return false; 106 } 107 return spec == *aURL; 108 } 109 110 if (aPrincipal && aEntryPartitionPrincipal->Equals(aPrincipal.ref())) { 111 return true; 112 } 113 if (!aSchemelessSite) { 114 return false; 115 } 116 // Clear by site. 117 // Clear entries with site. This includes entries which are partitioned 118 // under other top level sites (= have a partitionKey set). 119 nsAutoCString principalBaseDomain; 120 nsresult rv = aEntryPartitionPrincipal->GetBaseDomain(principalBaseDomain); 121 if (NS_WARN_IF(NS_FAILED(rv))) { 122 return false; 123 } 124 if (principalBaseDomain.Equals(aSchemelessSite.ref()) && 125 aPattern.ref().Matches(aEntryPartitionPrincipal->OriginAttributesRef())) { 126 return true; 127 } 128 129 // Clear entries partitioned under aSchemelessSite. We need to add the 130 // partition key filter to aPattern so that we include any OA filtering 131 // specified by the caller. For example the caller may pass aPattern = { 132 // privateBrowsingId: 1 } which means we may only clear partitioned 133 // private browsing data. 134 OriginAttributesPattern patternWithPartitionKey(aPattern.ref()); 135 patternWithPartitionKey.mPartitionKeyPattern.Construct(); 136 patternWithPartitionKey.mPartitionKeyPattern.Value().mBaseDomain.Construct( 137 NS_ConvertUTF8toUTF16(aSchemelessSite.ref())); 138 139 return patternWithPartitionKey.Matches( 140 aEntryPartitionPrincipal->OriginAttributesRef()); 141 } 142 143 } // namespace SharedSubResourceCacheUtils 144 145 SubResourceNetworkMetadataHolder::~SubResourceNetworkMetadataHolder() = default; 146 147 SubResourceNetworkMetadataHolder::SubResourceNetworkMetadataHolder( 148 nsIRequest* aRequest) { 149 nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(aRequest); 150 if (timedChannel) { 151 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest); 152 mPerfData.emplace(timedChannel, httpChannel); 153 } 154 155 RefPtr<net::HttpBaseChannel> httpBaseChannel = do_QueryObject(aRequest); 156 if (httpBaseChannel) { 157 mResponseHead = httpBaseChannel->MaybeCloneResponseHeadForCachedResource(); 158 } 159 } 160 161 } // namespace mozilla