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