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