Line data Source code
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/Move.h"
9 : #include "ImageURL.h"
10 : #include "nsHostObjectProtocolHandler.h"
11 : #include "nsString.h"
12 : #include "mozilla/dom/File.h"
13 : #include "mozilla/dom/workers/ServiceWorkerManager.h"
14 : #include "nsIDocument.h"
15 : #include "nsPrintfCString.h"
16 :
17 : namespace mozilla {
18 :
19 : using namespace dom;
20 :
21 : namespace image {
22 :
23 : bool
24 90 : URISchemeIs(ImageURL* aURI, const char* aScheme)
25 : {
26 90 : bool schemeMatches = false;
27 90 : if (NS_WARN_IF(NS_FAILED(aURI->SchemeIs(aScheme, &schemeMatches)))) {
28 0 : return false;
29 : }
30 90 : return schemeMatches;
31 : }
32 :
33 : static Maybe<uint64_t>
34 0 : BlobSerial(ImageURL* aURI)
35 : {
36 0 : nsAutoCString spec;
37 0 : aURI->GetSpec(spec);
38 :
39 0 : RefPtr<BlobImpl> blob;
40 0 : if (NS_SUCCEEDED(NS_GetBlobForBlobURISpec(spec, getter_AddRefs(blob))) &&
41 0 : blob) {
42 0 : return Some(blob->GetSerialNumber());
43 : }
44 :
45 0 : return Nothing();
46 : }
47 :
48 45 : ImageCacheKey::ImageCacheKey(nsIURI* aURI,
49 : const OriginAttributes& aAttrs,
50 : nsIDocument* aDocument,
51 45 : nsresult& aRv)
52 45 : : mURI(new ImageURL(aURI, aRv))
53 : , mOriginAttributes(aAttrs)
54 45 : , mControlledDocument(GetControlledDocumentToken(aDocument))
55 90 : , mIsChrome(URISchemeIs(mURI, "chrome"))
56 : {
57 45 : NS_ENSURE_SUCCESS_VOID(aRv);
58 :
59 45 : MOZ_ASSERT(NS_IsMainThread());
60 :
61 45 : if (URISchemeIs(mURI, "blob")) {
62 0 : mBlobSerial = BlobSerial(mURI);
63 : }
64 :
65 45 : mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument);
66 : }
67 :
68 0 : ImageCacheKey::ImageCacheKey(ImageURL* aURI,
69 : const OriginAttributes& aAttrs,
70 0 : nsIDocument* aDocument)
71 : : mURI(aURI)
72 : , mOriginAttributes(aAttrs)
73 0 : , mControlledDocument(GetControlledDocumentToken(aDocument))
74 0 : , mIsChrome(URISchemeIs(mURI, "chrome"))
75 : {
76 0 : MOZ_ASSERT(aURI);
77 :
78 0 : if (URISchemeIs(mURI, "blob")) {
79 0 : mBlobSerial = BlobSerial(mURI);
80 : }
81 :
82 0 : mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument);
83 0 : }
84 :
85 82 : ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
86 : : mURI(aOther.mURI)
87 : , mBlobSerial(aOther.mBlobSerial)
88 : , mOriginAttributes(aOther.mOriginAttributes)
89 82 : , mControlledDocument(aOther.mControlledDocument)
90 82 : , mHash(aOther.mHash)
91 246 : , mIsChrome(aOther.mIsChrome)
92 82 : { }
93 :
94 0 : ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
95 0 : : mURI(Move(aOther.mURI))
96 0 : , mBlobSerial(Move(aOther.mBlobSerial))
97 : , mOriginAttributes(aOther.mOriginAttributes)
98 0 : , mControlledDocument(aOther.mControlledDocument)
99 0 : , mHash(aOther.mHash)
100 0 : , mIsChrome(aOther.mIsChrome)
101 0 : { }
102 :
103 : bool
104 46 : ImageCacheKey::operator==(const ImageCacheKey& aOther) const
105 : {
106 : // Don't share the image cache between a controlled document and anything else.
107 46 : if (mControlledDocument != aOther.mControlledDocument) {
108 0 : return false;
109 : }
110 : // The origin attributes always have to match.
111 46 : if (mOriginAttributes != aOther.mOriginAttributes) {
112 0 : return false;
113 : }
114 46 : if (mBlobSerial || aOther.mBlobSerial) {
115 : // If at least one of us has a blob serial, just compare the blob serial and
116 : // the ref portion of the URIs.
117 0 : return mBlobSerial == aOther.mBlobSerial &&
118 0 : mURI->HasSameRef(*aOther.mURI);
119 : }
120 :
121 : // For non-blob URIs, compare the URIs.
122 46 : return *mURI == *aOther.mURI;
123 : }
124 :
125 : const char*
126 83 : ImageCacheKey::Spec() const
127 : {
128 83 : return mURI->Spec();
129 : }
130 :
131 : /* static */ PLDHashNumber
132 45 : ImageCacheKey::ComputeHash(ImageURL* aURI,
133 : const Maybe<uint64_t>& aBlobSerial,
134 : const OriginAttributes& aAttrs,
135 : void* aControlledDocument)
136 : {
137 : // Since we frequently call Hash() several times in a row on the same
138 : // ImageCacheKey, as an optimization we compute our hash once and store it.
139 :
140 90 : nsPrintfCString ptr("%p", aControlledDocument);
141 90 : nsAutoCString suffix;
142 45 : aAttrs.CreateSuffix(suffix);
143 :
144 45 : return AddToHash(0, aURI->ComputeHash(aBlobSerial),
145 90 : HashString(suffix), HashString(ptr));
146 : }
147 :
148 : /* static */ void*
149 45 : ImageCacheKey::GetControlledDocumentToken(nsIDocument* aDocument)
150 : {
151 : // For non-controlled documents, we just return null. For controlled
152 : // documents, we cast the pointer into a void* to avoid dereferencing
153 : // it (since we only use it for comparisons), and return it.
154 45 : void* pointer = nullptr;
155 : using dom::workers::ServiceWorkerManager;
156 90 : RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
157 45 : if (aDocument && swm) {
158 90 : ErrorResult rv;
159 45 : if (swm->IsControlled(aDocument, rv)) {
160 0 : pointer = aDocument;
161 : }
162 : }
163 90 : return pointer;
164 : }
165 :
166 : } // namespace image
167 : } // namespace mozilla
|