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