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