ImageCacheKey.cpp 4.7 KB

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