1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
|
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/events/ApplicationCacheErrorEvent.h"
#include "core/events/ProgressEvent.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/inspector/InspectorApplicationCacheAgent.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/appcache/ApplicationCache.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "platform/exported/WrappedResourceRequest.h"
#include "platform/exported/WrappedResourceResponse.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebURLError.h"
#include "public/platform/WebURLResponse.h"
#include "public/platform/WebVector.h"
using namespace blink;
namespace WebCore {
// We provide a custom implementation of this class that calls out to the
// embedding application instead of using WebCore's built in appcache system.
// This file replaces webcore/appcache/ApplicationCacheHost.cpp in our build.
ApplicationCacheHost::ApplicationCacheHost(DocumentLoader* documentLoader)
: m_domApplicationCache(0)
, m_documentLoader(documentLoader)
, m_defersEvents(true)
{
ASSERT(m_documentLoader);
}
ApplicationCacheHost::~ApplicationCacheHost()
{
}
void ApplicationCacheHost::willStartLoadingMainResource(ResourceRequest& request)
{
// We defer creating the outer host object to avoid spurious creation/destruction
// around creating empty documents. At this point, we're initiating a main resource
// load for the document, so its for real.
if (!isApplicationCacheEnabled())
return;
ASSERT(m_documentLoader->frame());
LocalFrame& frame = *m_documentLoader->frame();
m_host = frame.loader().client()->createApplicationCacheHost(this);
if (m_host) {
WrappedResourceRequest wrapped(request);
const WebApplicationCacheHost* spawningHost = 0;
Frame* spawningFrame = frame.tree().parent();
if (!spawningFrame || !spawningFrame->isLocalFrame())
spawningFrame = frame.loader().opener();
if (!spawningFrame || !spawningFrame->isLocalFrame())
spawningFrame = &frame;
if (DocumentLoader* spawningDocLoader = toLocalFrame(spawningFrame)->loader().documentLoader())
spawningHost = spawningDocLoader->applicationCacheHost() ? spawningDocLoader->applicationCacheHost()->m_host.get() : 0;
m_host->willStartMainResourceRequest(wrapped, spawningHost);
}
// NOTE: The semantics of this method, and others in this interface, are subtly different
// than the method names would suggest. For example, in this method never returns an appcached
// response in the SubstituteData out argument, instead we return the appcached response thru
// the usual resource loading pipeline.
}
void ApplicationCacheHost::selectCacheWithoutManifest()
{
if (m_host)
m_host->selectCacheWithoutManifest();
}
void ApplicationCacheHost::selectCacheWithManifest(const KURL& manifestURL)
{
if (m_host && !m_host->selectCacheWithManifest(manifestURL)) {
// It's a foreign entry, restart the current navigation from the top
// of the navigation algorithm. The navigation will not result in the
// same resource being loaded, because "foreign" entries are never picked
// during navigation.
// see WebCore::ApplicationCacheGroup::selectCache()
LocalFrame* frame = m_documentLoader->frame();
frame->navigationScheduler().scheduleLocationChange(frame->document(), frame->document()->url(), Referrer(frame->document()->referrer(), frame->document()->referrerPolicy()));
}
}
void ApplicationCacheHost::didReceiveResponseForMainResource(const ResourceResponse& response)
{
if (m_host) {
WrappedResourceResponse wrapped(response);
m_host->didReceiveResponseForMainResource(wrapped);
}
}
void ApplicationCacheHost::mainResourceDataReceived(const char* data, int length)
{
if (m_host)
m_host->didReceiveDataForMainResource(data, length);
}
void ApplicationCacheHost::failedLoadingMainResource()
{
if (m_host)
m_host->didFinishLoadingMainResource(false);
}
void ApplicationCacheHost::finishedLoadingMainResource()
{
if (m_host)
m_host->didFinishLoadingMainResource(true);
}
void ApplicationCacheHost::willStartLoadingResource(ResourceRequest& request)
{
if (m_host) {
WrappedResourceRequest wrapped(request);
m_host->willStartSubResourceRequest(wrapped);
}
}
void ApplicationCacheHost::setApplicationCache(ApplicationCache* domApplicationCache)
{
ASSERT(!m_domApplicationCache || !domApplicationCache);
m_domApplicationCache = domApplicationCache;
}
void ApplicationCacheHost::notifyApplicationCache(EventID id, int progressTotal, int progressDone, blink::WebApplicationCacheHost::ErrorReason errorReason, const String& errorURL, int errorStatus, const String& errorMessage)
{
if (id != PROGRESS_EVENT)
InspectorInstrumentation::updateApplicationCacheStatus(m_documentLoader->frame());
if (m_defersEvents) {
// Event dispatching is deferred until document.onload has fired.
m_deferredEvents.append(DeferredEvent(id, progressTotal, progressDone, errorReason, errorURL, errorStatus, errorMessage));
return;
}
dispatchDOMEvent(id, progressTotal, progressDone, errorReason, errorURL, errorStatus, errorMessage);
}
ApplicationCacheHost::CacheInfo ApplicationCacheHost::applicationCacheInfo()
{
if (!m_host)
return CacheInfo(KURL(), 0, 0, 0);
blink::WebApplicationCacheHost::CacheInfo webInfo;
m_host->getAssociatedCacheInfo(&webInfo);
return CacheInfo(webInfo.manifestURL, webInfo.creationTime, webInfo.updateTime, webInfo.totalSize);
}
void ApplicationCacheHost::fillResourceList(ResourceInfoList* resources)
{
if (!m_host)
return;
blink::WebVector<blink::WebApplicationCacheHost::ResourceInfo> webResources;
m_host->getResourceList(&webResources);
for (size_t i = 0; i < webResources.size(); ++i) {
resources->append(ResourceInfo(
webResources[i].url, webResources[i].isMaster, webResources[i].isManifest, webResources[i].isFallback,
webResources[i].isForeign, webResources[i].isExplicit, webResources[i].size));
}
}
void ApplicationCacheHost::stopDeferringEvents()
{
RefPtr<DocumentLoader> protect(documentLoader());
for (unsigned i = 0; i < m_deferredEvents.size(); ++i) {
const DeferredEvent& deferred = m_deferredEvents[i];
dispatchDOMEvent(deferred.eventID, deferred.progressTotal, deferred.progressDone, deferred.errorReason, deferred.errorURL, deferred.errorStatus, deferred.errorMessage);
}
m_deferredEvents.clear();
m_defersEvents = false;
}
void ApplicationCacheHost::dispatchDOMEvent(EventID id, int progressTotal, int progressDone, blink::WebApplicationCacheHost::ErrorReason errorReason, const String& errorURL, int errorStatus, const String& errorMessage)
{
if (m_domApplicationCache) {
const AtomicString& eventType = ApplicationCache::toEventType(id);
RefPtrWillBeRawPtr<Event> event = nullptr;
if (id == PROGRESS_EVENT)
event = ProgressEvent::create(eventType, true, progressDone, progressTotal);
else if (id == ERROR_EVENT)
event = ApplicationCacheErrorEvent::create(errorReason, errorURL, errorStatus, errorMessage);
else
event = Event::create(eventType);
m_domApplicationCache->dispatchEvent(event, ASSERT_NO_EXCEPTION);
}
}
ApplicationCacheHost::Status ApplicationCacheHost::status() const
{
return m_host ? static_cast<Status>(m_host->status()) : UNCACHED;
}
bool ApplicationCacheHost::update()
{
return m_host ? m_host->startUpdate() : false;
}
bool ApplicationCacheHost::swapCache()
{
bool success = m_host ? m_host->swapCache() : false;
if (success)
InspectorInstrumentation::updateApplicationCacheStatus(m_documentLoader->frame());
return success;
}
void ApplicationCacheHost::abort()
{
if (m_host)
m_host->abort();
}
bool ApplicationCacheHost::isApplicationCacheEnabled()
{
ASSERT(m_documentLoader->frame());
return m_documentLoader->frame()->settings() && m_documentLoader->frame()->settings()->offlineWebApplicationCacheEnabled();
}
void ApplicationCacheHost::didChangeCacheAssociation()
{
// FIXME: Prod the inspector to update its notion of what cache the page is using.
}
void ApplicationCacheHost::notifyEventListener(blink::WebApplicationCacheHost::EventID eventID)
{
notifyApplicationCache(static_cast<ApplicationCacheHost::EventID>(eventID), 0, 0, blink::WebApplicationCacheHost::UnknownError, String(), 0, String());
}
void ApplicationCacheHost::notifyProgressEventListener(const blink::WebURL&, int progressTotal, int progressDone)
{
notifyApplicationCache(PROGRESS_EVENT, progressTotal, progressDone, blink::WebApplicationCacheHost::UnknownError, String(), 0, String());
}
void ApplicationCacheHost::notifyErrorEventListener(blink::WebApplicationCacheHost::ErrorReason reason, const blink::WebURL& url, int status, const blink::WebString& message)
{
notifyApplicationCache(ERROR_EVENT, 0, 0, reason, url.string(), status, message);
}
} // namespace WebCore
|