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 "Settings.h" 41 #include "WebURL.h" 42 #include "WebURLError.h" 43 #include "WebURLResponse.h" 44 #include "WrappedResourceRequest.h" 45 #include "WrappedResourceResponse.h" 46 47 using namespace WebKit; 48 49 namespace WebCore { 50 51 // We provide a custom implementation of this class that calls out to the 52 // embedding application instead of using WebCore's built in appcache system. 53 // This file replaces webcore/appcache/ApplicationCacheHost.cpp in our build. 54 55 ApplicationCacheHost::ApplicationCacheHost(DocumentLoader* documentLoader) 56 : m_domApplicationCache(0) 57 , m_documentLoader(documentLoader) 58 , m_defersEvents(true) 59 { 60 ASSERT(m_documentLoader); 61 } 62 63 ApplicationCacheHost::~ApplicationCacheHost() 64 { 65 } 66 67 void ApplicationCacheHost::maybeLoadMainResource(ResourceRequest& request, SubstituteData&) 68 { 69 // We defer creating the outer host object to avoid spurious creation/destruction 70 // around creating empty documents. At this point, we're initiating a main resource 71 // load for the document, so its for real. 72 73 if (!isApplicationCacheEnabled()) 74 return; 75 76 m_internal.set(new ApplicationCacheHostInternal(this)); 77 if (m_internal->m_outerHost) { 78 WrappedResourceRequest wrapped(request); 79 m_internal->m_outerHost->willStartMainResourceRequest(wrapped); 80 } else 81 m_internal.clear(); 82 83 // NOTE: The semantics of this method, and others in this interface, are subtly different 84 // than the method names would suggest. For example, in this method never returns an appcached 85 // response in the SubstituteData out argument, instead we return the appcached response thru 86 // the usual resource loading pipeline. 87 } 88 89 void ApplicationCacheHost::selectCacheWithoutManifest() 90 { 91 if (m_internal) 92 m_internal->m_outerHost->selectCacheWithoutManifest(); 93 } 94 95 void ApplicationCacheHost::selectCacheWithManifest(const KURL& manifestURL) 96 { 97 if (m_internal) { 98 if (!m_internal->m_outerHost->selectCacheWithManifest(manifestURL)) { 99 // It's a foreign entry, restart the current navigation from the top 100 // of the navigation algorithm. The navigation will not result in the 101 // same resource being loaded, because "foreign" entries are never picked 102 // during navigation. 103 // see WebCore::ApplicationCacheGroup::selectCache() 104 const KURL& docURL = m_documentLoader->frame()->document()->url(); 105 String referrer = m_documentLoader->frameLoader()->referrer(); 106 m_documentLoader->frame()->redirectScheduler()->scheduleLocationChange(docURL, referrer); 107 } 108 } 109 } 110 111 bool ApplicationCacheHost::maybeLoadFallbackForMainResponse(const ResourceRequest&, const ResourceResponse& response) 112 { 113 if (m_internal) { 114 WrappedResourceResponse wrapped(response); 115 m_internal->m_outerHost->didReceiveResponseForMainResource(wrapped); 116 } 117 return false; 118 } 119 120 bool ApplicationCacheHost::maybeLoadFallbackForMainError(const ResourceRequest&, const ResourceError& error) 121 { 122 // N/A to the chromium port 123 return false; 124 } 125 126 void ApplicationCacheHost::mainResourceDataReceived(const char* data, int length, long long, bool) 127 { 128 if (m_internal) 129 m_internal->m_outerHost->didReceiveDataForMainResource(data, length); 130 } 131 132 void ApplicationCacheHost::failedLoadingMainResource() 133 { 134 if (m_internal) 135 m_internal->m_outerHost->didFinishLoadingMainResource(false); 136 } 137 138 void ApplicationCacheHost::finishedLoadingMainResource() 139 { 140 if (m_internal) 141 m_internal->m_outerHost->didFinishLoadingMainResource(true); 142 } 143 144 bool ApplicationCacheHost::maybeLoadResource(ResourceLoader*, ResourceRequest& request, const KURL&) 145 { 146 // FIXME: look into the purpose of the unused KURL& originalURL parameter 147 if (m_internal) { 148 WrappedResourceRequest wrapped(request); 149 m_internal->m_outerHost->willStartSubResourceRequest(wrapped); 150 } 151 return false; 152 } 153 154 bool ApplicationCacheHost::maybeLoadFallbackForRedirect(ResourceLoader*, ResourceRequest&, const ResourceResponse&) 155 { 156 // N/A to the chromium port 157 return false; 158 } 159 160 bool ApplicationCacheHost::maybeLoadFallbackForResponse(ResourceLoader*, const ResourceResponse&) 161 { 162 // N/A to the chromium port 163 return false; 164 } 165 166 bool ApplicationCacheHost::maybeLoadFallbackForError(ResourceLoader*, const ResourceError&) 167 { 168 // N/A to the chromium port 169 return false; 170 } 171 172 bool ApplicationCacheHost::maybeLoadSynchronously(ResourceRequest& request, ResourceError&, ResourceResponse&, Vector<char>&) 173 { 174 if (m_internal) { 175 WrappedResourceRequest wrapped(request); 176 m_internal->m_outerHost->willStartSubResourceRequest(wrapped); 177 } 178 return false; 179 } 180 181 void ApplicationCacheHost::maybeLoadFallbackSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>&) 182 { 183 // N/A to the chromium port 184 } 185 186 bool ApplicationCacheHost::canCacheInPageCache() const 187 { 188 // N/A to the chromium port which doesn't use the page cache. 189 return false; 190 } 191 192 void ApplicationCacheHost::setDOMApplicationCache(DOMApplicationCache* domApplicationCache) 193 { 194 ASSERT(!m_domApplicationCache || !domApplicationCache); 195 m_domApplicationCache = domApplicationCache; 196 } 197 198 void ApplicationCacheHost::notifyDOMApplicationCache(EventID id) 199 { 200 if (m_defersEvents) { 201 m_deferredEvents.append(id); 202 return; 203 } 204 if (m_domApplicationCache) { 205 ExceptionCode ec = 0; 206 m_domApplicationCache->dispatchEvent(Event::create(DOMApplicationCache::toEventType(id), false, false), ec); 207 ASSERT(!ec); 208 } 209 } 210 211 void ApplicationCacheHost::stopDeferringEvents() 212 { 213 RefPtr<DocumentLoader> protect(documentLoader()); 214 for (unsigned i = 0; i < m_deferredEvents.size(); ++i) { 215 EventID id = m_deferredEvents[i]; 216 if (m_domApplicationCache) { 217 ExceptionCode ec = 0; 218 m_domApplicationCache->dispatchEvent(Event::create(DOMApplicationCache::toEventType(id), false, false), ec); 219 ASSERT(!ec); 220 } 221 } 222 m_deferredEvents.clear(); 223 m_defersEvents = false; 224 } 225 226 ApplicationCacheHost::Status ApplicationCacheHost::status() const 227 { 228 return m_internal ? static_cast<Status>(m_internal->m_outerHost->status()) : UNCACHED; 229 } 230 231 bool ApplicationCacheHost::update() 232 { 233 return m_internal ? m_internal->m_outerHost->startUpdate() : false; 234 } 235 236 bool ApplicationCacheHost::swapCache() 237 { 238 return m_internal ? m_internal->m_outerHost->swapCache() : false; 239 } 240 241 bool ApplicationCacheHost::isApplicationCacheEnabled() 242 { 243 ASSERT(m_documentLoader->frame()); 244 return m_documentLoader->frame()->settings() 245 && m_documentLoader->frame()->settings()->offlineWebApplicationCacheEnabled(); 246 } 247 248 } // namespace WebCore 249 250 #endif // ENABLE(OFFLINE_WEB_APPLICATIONS) 251