OfflineCacheUpdateGlue.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  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 "OfflineCacheUpdateGlue.h"
  6. #include "nsOfflineCacheUpdate.h"
  7. #include "mozilla/Services.h"
  8. #include "nsIApplicationCache.h"
  9. #include "nsIApplicationCacheChannel.h"
  10. #include "nsIApplicationCacheContainer.h"
  11. #include "nsIChannel.h"
  12. #include "nsIDocument.h"
  13. #include "mozilla/Logging.h"
  14. //
  15. // To enable logging (see mozilla/Logging.h for full details):
  16. //
  17. // set MOZ_LOG=nsOfflineCacheUpdate:5
  18. // set MOZ_LOG_FILE=offlineupdate.log
  19. //
  20. // this enables LogLevel::Info level information and places all output in
  21. // the file offlineupdate.log
  22. //
  23. extern mozilla::LazyLogModule gOfflineCacheUpdateLog;
  24. #undef LOG
  25. #define LOG(args) MOZ_LOG(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug, args)
  26. #undef LOG_ENABLED
  27. #define LOG_ENABLED() MOZ_LOG_TEST(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug)
  28. namespace mozilla {
  29. namespace docshell {
  30. //-----------------------------------------------------------------------------
  31. // OfflineCacheUpdateGlue::nsISupports
  32. //-----------------------------------------------------------------------------
  33. NS_IMPL_ISUPPORTS(OfflineCacheUpdateGlue,
  34. nsIOfflineCacheUpdate,
  35. nsIOfflineCacheUpdateObserver,
  36. nsISupportsWeakReference)
  37. //-----------------------------------------------------------------------------
  38. // OfflineCacheUpdateGlue <public>
  39. //-----------------------------------------------------------------------------
  40. OfflineCacheUpdateGlue::OfflineCacheUpdateGlue()
  41. : mCoalesced(false)
  42. {
  43. LOG(("OfflineCacheUpdateGlue::OfflineCacheUpdateGlue [%p]", this));
  44. }
  45. OfflineCacheUpdateGlue::~OfflineCacheUpdateGlue()
  46. {
  47. LOG(("OfflineCacheUpdateGlue::~OfflineCacheUpdateGlue [%p]", this));
  48. }
  49. nsIOfflineCacheUpdate*
  50. OfflineCacheUpdateGlue::EnsureUpdate()
  51. {
  52. if (!mUpdate) {
  53. mUpdate = new nsOfflineCacheUpdate();
  54. LOG(("OfflineCacheUpdateGlue [%p] is using update [%p]", this, mUpdate.get()));
  55. }
  56. return mUpdate;
  57. }
  58. NS_IMETHODIMP
  59. OfflineCacheUpdateGlue::Schedule()
  60. {
  61. nsCOMPtr<nsIObserverService> observerService =
  62. mozilla::services::GetObserverService();
  63. if (observerService) {
  64. LOG(("Calling offline-cache-update-added"));
  65. observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
  66. "offline-cache-update-added",
  67. nullptr);
  68. LOG(("Done offline-cache-update-added"));
  69. }
  70. if (!EnsureUpdate())
  71. return NS_ERROR_NULL_POINTER;
  72. // Do not use weak reference, we must survive!
  73. mUpdate->AddObserver(this, false);
  74. if (mCoalesced) // already scheduled
  75. return NS_OK;
  76. return mUpdate->Schedule();
  77. }
  78. NS_IMETHODIMP
  79. OfflineCacheUpdateGlue::Init(nsIURI *aManifestURI,
  80. nsIURI *aDocumentURI,
  81. nsIPrincipal* aLoadingPrincipal,
  82. nsIDOMDocument *aDocument,
  83. nsIFile *aCustomProfileDir)
  84. {
  85. nsresult rv;
  86. nsAutoCString originSuffix;
  87. rv = aLoadingPrincipal->GetOriginSuffix(originSuffix);
  88. NS_ENSURE_SUCCESS(rv, rv);
  89. nsOfflineCacheUpdateService* service =
  90. nsOfflineCacheUpdateService::EnsureService();
  91. if (service) {
  92. service->FindUpdate(aManifestURI, originSuffix, aCustomProfileDir,
  93. getter_AddRefs(mUpdate));
  94. mCoalesced = !!mUpdate;
  95. }
  96. if (!EnsureUpdate())
  97. return NS_ERROR_NULL_POINTER;
  98. mDocumentURI = aDocumentURI;
  99. mLoadingPrincipal = aLoadingPrincipal;
  100. if (aDocument)
  101. SetDocument(aDocument);
  102. if (mCoalesced) { // already initialized
  103. LOG(("OfflineCacheUpdateGlue %p coalesced with update %p", this, mUpdate.get()));
  104. return NS_OK;
  105. }
  106. return mUpdate->Init(aManifestURI, aDocumentURI, aLoadingPrincipal, nullptr,
  107. aCustomProfileDir);
  108. }
  109. void
  110. OfflineCacheUpdateGlue::SetDocument(nsIDOMDocument *aDocument)
  111. {
  112. // The design is one document for one cache update on the content process.
  113. NS_ASSERTION(!mDocument,
  114. "Setting more then a single document on an instance of OfflineCacheUpdateGlue");
  115. LOG(("Document %p added to update glue %p", aDocument, this));
  116. // Add document only if it was not loaded from an offline cache.
  117. // If it were loaded from an offline cache then it has already
  118. // been associated with it and must not be again cached as
  119. // implicit (which are the reasons we collect documents here).
  120. nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
  121. if (!document)
  122. return;
  123. nsIChannel* channel = document->GetChannel();
  124. nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
  125. do_QueryInterface(channel);
  126. if (!appCacheChannel)
  127. return;
  128. bool loadedFromAppCache;
  129. appCacheChannel->GetLoadedFromApplicationCache(&loadedFromAppCache);
  130. if (loadedFromAppCache)
  131. return;
  132. if (EnsureUpdate()) {
  133. mUpdate->StickDocument(mDocumentURI);
  134. }
  135. mDocument = aDocument;
  136. }
  137. NS_IMETHODIMP
  138. OfflineCacheUpdateGlue::UpdateStateChanged(nsIOfflineCacheUpdate *aUpdate, uint32_t state)
  139. {
  140. if (state == nsIOfflineCacheUpdateObserver::STATE_FINISHED) {
  141. LOG(("OfflineCacheUpdateGlue got STATE_FINISHED [%p]", this));
  142. nsCOMPtr<nsIObserverService> observerService =
  143. mozilla::services::GetObserverService();
  144. if (observerService) {
  145. LOG(("Calling offline-cache-update-completed"));
  146. observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
  147. "offline-cache-update-completed",
  148. nullptr);
  149. LOG(("Done offline-cache-update-completed"));
  150. }
  151. aUpdate->RemoveObserver(this);
  152. }
  153. return NS_OK;
  154. }
  155. NS_IMETHODIMP
  156. OfflineCacheUpdateGlue::ApplicationCacheAvailable(nsIApplicationCache *aApplicationCache)
  157. {
  158. NS_ENSURE_ARG(aApplicationCache);
  159. // Check that the document that requested this update was
  160. // previously associated with an application cache. If not, it
  161. // should be associated with the new one.
  162. nsCOMPtr<nsIApplicationCacheContainer> container =
  163. do_QueryInterface(mDocument);
  164. if (!container)
  165. return NS_OK;
  166. nsCOMPtr<nsIApplicationCache> existingCache;
  167. nsresult rv = container->GetApplicationCache(getter_AddRefs(existingCache));
  168. NS_ENSURE_SUCCESS(rv, rv);
  169. if (!existingCache) {
  170. if (LOG_ENABLED()) {
  171. nsAutoCString clientID;
  172. if (aApplicationCache) {
  173. aApplicationCache->GetClientID(clientID);
  174. }
  175. LOG(("Update %p: associating app cache %s to document %p",
  176. this, clientID.get(), mDocument.get()));
  177. }
  178. rv = container->SetApplicationCache(aApplicationCache);
  179. NS_ENSURE_SUCCESS(rv, rv);
  180. }
  181. return NS_OK;
  182. }
  183. } // namespace docshell
  184. } // namespace mozilla