|
1 /* |
|
2 * Copyright (C) 2009 Google Inc. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions are |
|
6 * met: |
|
7 * |
|
8 * * Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * * Redistributions in binary form must reproduce the above |
|
11 * copyright notice, this list of conditions and the following disclaimer |
|
12 * in the documentation and/or other materials provided with the |
|
13 * distribution. |
|
14 * * Neither the name of Google Inc. nor the names of its |
|
15 * contributors may be used to endorse or promote products derived from |
|
16 * this software without specific prior written permission. |
|
17 * |
|
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
29 */ |
|
30 |
|
31 #include "config.h" |
|
32 #include "ApplicationCacheHost.h" |
|
33 |
|
34 #if ENABLE(OFFLINE_WEB_APPLICATIONS) |
|
35 |
|
36 #include "ApplicationCacheHostInternal.h" |
|
37 #include "DocumentLoader.h" |
|
38 #include "DOMApplicationCache.h" |
|
39 #include "Frame.h" |
|
40 #include "ProgressEvent.h" |
|
41 #include "Settings.h" |
|
42 #include "WebURL.h" |
|
43 #include "WebURLError.h" |
|
44 #include "WebURLResponse.h" |
|
45 #include "WrappedResourceRequest.h" |
|
46 #include "WrappedResourceResponse.h" |
|
47 |
|
48 using namespace WebKit; |
|
49 |
|
50 namespace WebCore { |
|
51 |
|
52 // We provide a custom implementation of this class that calls out to the |
|
53 // embedding application instead of using WebCore's built in appcache system. |
|
54 // This file replaces webcore/appcache/ApplicationCacheHost.cpp in our build. |
|
55 |
|
56 ApplicationCacheHost::ApplicationCacheHost(DocumentLoader* documentLoader) |
|
57 : m_domApplicationCache(0) |
|
58 , m_documentLoader(documentLoader) |
|
59 , m_defersEvents(true) |
|
60 { |
|
61 ASSERT(m_documentLoader); |
|
62 } |
|
63 |
|
64 ApplicationCacheHost::~ApplicationCacheHost() |
|
65 { |
|
66 } |
|
67 |
|
68 void ApplicationCacheHost::maybeLoadMainResource(ResourceRequest& request, SubstituteData&) |
|
69 { |
|
70 // We defer creating the outer host object to avoid spurious creation/destruction |
|
71 // around creating empty documents. At this point, we're initiating a main resource |
|
72 // load for the document, so its for real. |
|
73 |
|
74 if (!isApplicationCacheEnabled()) |
|
75 return; |
|
76 |
|
77 m_internal.set(new ApplicationCacheHostInternal(this)); |
|
78 if (m_internal->m_outerHost) { |
|
79 WrappedResourceRequest wrapped(request); |
|
80 m_internal->m_outerHost->willStartMainResourceRequest(wrapped); |
|
81 } else |
|
82 m_internal.clear(); |
|
83 |
|
84 // NOTE: The semantics of this method, and others in this interface, are subtly different |
|
85 // than the method names would suggest. For example, in this method never returns an appcached |
|
86 // response in the SubstituteData out argument, instead we return the appcached response thru |
|
87 // the usual resource loading pipeline. |
|
88 } |
|
89 |
|
90 void ApplicationCacheHost::selectCacheWithoutManifest() |
|
91 { |
|
92 if (m_internal) |
|
93 m_internal->m_outerHost->selectCacheWithoutManifest(); |
|
94 } |
|
95 |
|
96 void ApplicationCacheHost::selectCacheWithManifest(const KURL& manifestURL) |
|
97 { |
|
98 if (m_internal) { |
|
99 if (!m_internal->m_outerHost->selectCacheWithManifest(manifestURL)) { |
|
100 // It's a foreign entry, restart the current navigation from the top |
|
101 // of the navigation algorithm. The navigation will not result in the |
|
102 // same resource being loaded, because "foreign" entries are never picked |
|
103 // during navigation. |
|
104 // see WebCore::ApplicationCacheGroup::selectCache() |
|
105 const KURL& docURL = m_documentLoader->frame()->document()->url(); |
|
106 String referrer = m_documentLoader->frameLoader()->referrer(); |
|
107 m_documentLoader->frame()->redirectScheduler()->scheduleLocationChange(docURL, referrer); |
|
108 } |
|
109 } |
|
110 } |
|
111 |
|
112 bool ApplicationCacheHost::maybeLoadFallbackForMainResponse(const ResourceRequest&, const ResourceResponse& response) |
|
113 { |
|
114 if (m_internal) { |
|
115 WrappedResourceResponse wrapped(response); |
|
116 m_internal->m_outerHost->didReceiveResponseForMainResource(wrapped); |
|
117 } |
|
118 return false; |
|
119 } |
|
120 |
|
121 bool ApplicationCacheHost::maybeLoadFallbackForMainError(const ResourceRequest&, const ResourceError& error) |
|
122 { |
|
123 // N/A to the chromium port |
|
124 return false; |
|
125 } |
|
126 |
|
127 void ApplicationCacheHost::mainResourceDataReceived(const char* data, int length, long long, bool) |
|
128 { |
|
129 if (m_internal) |
|
130 m_internal->m_outerHost->didReceiveDataForMainResource(data, length); |
|
131 } |
|
132 |
|
133 void ApplicationCacheHost::failedLoadingMainResource() |
|
134 { |
|
135 if (m_internal) |
|
136 m_internal->m_outerHost->didFinishLoadingMainResource(false); |
|
137 } |
|
138 |
|
139 void ApplicationCacheHost::finishedLoadingMainResource() |
|
140 { |
|
141 if (m_internal) |
|
142 m_internal->m_outerHost->didFinishLoadingMainResource(true); |
|
143 } |
|
144 |
|
145 bool ApplicationCacheHost::maybeLoadResource(ResourceLoader*, ResourceRequest& request, const KURL&) |
|
146 { |
|
147 // FIXME: look into the purpose of the unused KURL& originalURL parameter |
|
148 if (m_internal) { |
|
149 WrappedResourceRequest wrapped(request); |
|
150 m_internal->m_outerHost->willStartSubResourceRequest(wrapped); |
|
151 } |
|
152 return false; |
|
153 } |
|
154 |
|
155 bool ApplicationCacheHost::maybeLoadFallbackForRedirect(ResourceLoader*, ResourceRequest&, const ResourceResponse&) |
|
156 { |
|
157 // N/A to the chromium port |
|
158 return false; |
|
159 } |
|
160 |
|
161 bool ApplicationCacheHost::maybeLoadFallbackForResponse(ResourceLoader*, const ResourceResponse&) |
|
162 { |
|
163 // N/A to the chromium port |
|
164 return false; |
|
165 } |
|
166 |
|
167 bool ApplicationCacheHost::maybeLoadFallbackForError(ResourceLoader*, const ResourceError&) |
|
168 { |
|
169 // N/A to the chromium port |
|
170 return false; |
|
171 } |
|
172 |
|
173 bool ApplicationCacheHost::maybeLoadSynchronously(ResourceRequest& request, ResourceError&, ResourceResponse&, Vector<char>&) |
|
174 { |
|
175 if (m_internal) { |
|
176 WrappedResourceRequest wrapped(request); |
|
177 m_internal->m_outerHost->willStartSubResourceRequest(wrapped); |
|
178 } |
|
179 return false; |
|
180 } |
|
181 |
|
182 void ApplicationCacheHost::maybeLoadFallbackSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>&) |
|
183 { |
|
184 // N/A to the chromium port |
|
185 } |
|
186 |
|
187 bool ApplicationCacheHost::canCacheInPageCache() const |
|
188 { |
|
189 // N/A to the chromium port which doesn't use the page cache. |
|
190 return false; |
|
191 } |
|
192 |
|
193 void ApplicationCacheHost::setDOMApplicationCache(DOMApplicationCache* domApplicationCache) |
|
194 { |
|
195 ASSERT(!m_domApplicationCache || !domApplicationCache); |
|
196 m_domApplicationCache = domApplicationCache; |
|
197 } |
|
198 |
|
199 void ApplicationCacheHost::notifyDOMApplicationCache(EventID id, int total, int done) |
|
200 { |
|
201 if (m_defersEvents) { |
|
202 // Event dispatching is deferred until document.onload has fired. |
|
203 m_deferredEvents.append(DeferredEvent(id, total, done)); |
|
204 return; |
|
205 } |
|
206 dispatchDOMEvent(id, total, done); |
|
207 } |
|
208 |
|
209 void ApplicationCacheHost::stopDeferringEvents() |
|
210 { |
|
211 RefPtr<DocumentLoader> protect(documentLoader()); |
|
212 for (unsigned i = 0; i < m_deferredEvents.size(); ++i) { |
|
213 const DeferredEvent& deferred = m_deferredEvents[i]; |
|
214 dispatchDOMEvent(deferred.eventID, deferred.progressTotal, deferred.progressDone); |
|
215 } |
|
216 m_deferredEvents.clear(); |
|
217 m_defersEvents = false; |
|
218 } |
|
219 |
|
220 void ApplicationCacheHost::dispatchDOMEvent(EventID id, int total, int done) |
|
221 { |
|
222 if (m_domApplicationCache) { |
|
223 const AtomicString& eventType = DOMApplicationCache::toEventType(id); |
|
224 ExceptionCode ec = 0; |
|
225 RefPtr<Event> event; |
|
226 if (id == PROGRESS_EVENT) |
|
227 event = ProgressEvent::create(eventType, true, done, total); |
|
228 else |
|
229 event = Event::create(eventType, false, false); |
|
230 m_domApplicationCache->dispatchEvent(event, ec); |
|
231 ASSERT(!ec); |
|
232 } |
|
233 } |
|
234 |
|
235 ApplicationCacheHost::Status ApplicationCacheHost::status() const |
|
236 { |
|
237 return m_internal ? static_cast<Status>(m_internal->m_outerHost->status()) : UNCACHED; |
|
238 } |
|
239 |
|
240 bool ApplicationCacheHost::update() |
|
241 { |
|
242 return m_internal ? m_internal->m_outerHost->startUpdate() : false; |
|
243 } |
|
244 |
|
245 bool ApplicationCacheHost::swapCache() |
|
246 { |
|
247 return m_internal ? m_internal->m_outerHost->swapCache() : false; |
|
248 } |
|
249 |
|
250 bool ApplicationCacheHost::isApplicationCacheEnabled() |
|
251 { |
|
252 ASSERT(m_documentLoader->frame()); |
|
253 return m_documentLoader->frame()->settings() |
|
254 && m_documentLoader->frame()->settings()->offlineWebApplicationCacheEnabled(); |
|
255 } |
|
256 |
|
257 } // namespace WebCore |
|
258 |
|
259 #endif // ENABLE(OFFLINE_WEB_APPLICATIONS) |