1/*
2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "ResourceLoadNotifier.h"
33
34#include "DocumentLoader.h"
35#include "Frame.h"
36#include "FrameLoader.h"
37#include "FrameLoaderClient.h"
38#include "InspectorInstrumentation.h"
39#include "Page.h"
40#include "ProgressTracker.h"
41#include "ResourceLoader.h"
42#include "RuntimeEnabledFeatures.h"
43
44#if USE(QUICK_LOOK)
45#include "QuickLook.h"
46#endif
47
48namespace WebCore {
49
50ResourceLoadNotifier::ResourceLoadNotifier(Frame& frame)
51 : m_frame(frame)
52{
53}
54
55void ResourceLoadNotifier::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge)
56{
57 didReceiveAuthenticationChallenge(loader->identifier(), loader->documentLoader(), currentWebChallenge);
58}
59
60void ResourceLoadNotifier::didReceiveAuthenticationChallenge(unsigned long identifier, DocumentLoader* loader, const AuthenticationChallenge& currentWebChallenge)
61{
62 m_frame.loader().client().dispatchDidReceiveAuthenticationChallenge(loader, identifier, currentWebChallenge);
63}
64
65void ResourceLoadNotifier::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
66{
67 m_frame.loader().applyUserAgentIfNeeded(clientRequest);
68
69 dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
70}
71
72void ResourceLoadNotifier::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
73{
74 loader->documentLoader()->addResponse(r);
75
76 if (Page* page = m_frame.page())
77 page->progress().incrementProgress(loader->identifier(), r);
78
79 dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r, loader);
80}
81
82void ResourceLoadNotifier::didReceiveData(ResourceLoader* loader, const char* data, int dataLength, int encodedDataLength)
83{
84 if (Page* page = m_frame.page())
85 page->progress().incrementProgress(loader->identifier(), dataLength);
86
87 dispatchDidReceiveData(loader->documentLoader(), loader->identifier(), data, dataLength, encodedDataLength);
88}
89
90void ResourceLoadNotifier::didFinishLoad(ResourceLoader* loader, const NetworkLoadMetrics& networkLoadMetrics)
91{
92 if (Page* page = m_frame.page())
93 page->progress().completeProgress(loader->identifier());
94
95 dispatchDidFinishLoading(loader->documentLoader(), loader->identifier(), networkLoadMetrics, loader);
96}
97
98void ResourceLoadNotifier::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
99{
100 if (Page* page = m_frame.page())
101 page->progress().completeProgress(loader->identifier());
102
103 // Notifying the FrameLoaderClient may cause the frame to be destroyed.
104 Ref<Frame> protect(m_frame);
105 if (!error.isNull())
106 m_frame.loader().client().dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
107
108 InspectorInstrumentation::didFailLoading(&m_frame, loader->documentLoader(), loader->identifier(), error);
109}
110
111void ResourceLoadNotifier::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
112{
113 m_frame.loader().client().assignIdentifierToInitialRequest(identifier, loader, request);
114}
115
116void ResourceLoadNotifier::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
117{
118#if USE(QUICK_LOOK)
119 // Always allow QuickLook-generated URLs based on the protocol scheme.
120 if (!request.isNull() && isQuickLookPreviewURL(request.url()))
121 return;
122#endif
123
124 String oldRequestURL = request.url().string();
125 m_frame.loader().documentLoader()->didTellClientAboutLoad(request.url());
126
127 // Notifying the FrameLoaderClient may cause the frame to be destroyed.
128 Ref<Frame> protect(m_frame);
129 m_frame.loader().client().dispatchWillSendRequest(loader, identifier, request, redirectResponse);
130
131 // If the URL changed, then we want to put that new URL in the "did tell client" set too.
132 if (!request.isNull() && oldRequestURL != request.url().string())
133 m_frame.loader().documentLoader()->didTellClientAboutLoad(request.url());
134
135 InspectorInstrumentation::willSendRequest(&m_frame, identifier, loader, request, redirectResponse);
136}
137
138void ResourceLoadNotifier::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r, ResourceLoader* resourceLoader)
139{
140 // Notifying the FrameLoaderClient may cause the frame to be destroyed.
141 Ref<Frame> protect(m_frame);
142 m_frame.loader().client().dispatchDidReceiveResponse(loader, identifier, r);
143
144 InspectorInstrumentation::didReceiveResourceResponse(m_frame, identifier, loader, r, resourceLoader);
145}
146
147void ResourceLoadNotifier::dispatchDidReceiveData(DocumentLoader* loader, unsigned long identifier, const char* data, int dataLength, int encodedDataLength)
148{
149 // Notifying the FrameLoaderClient may cause the frame to be destroyed.
150 Ref<Frame> protect(m_frame);
151 m_frame.loader().client().dispatchDidReceiveContentLength(loader, identifier, dataLength);
152
153 InspectorInstrumentation::didReceiveData(&m_frame, identifier, data, dataLength, encodedDataLength);
154}
155
156void ResourceLoadNotifier::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier, const NetworkLoadMetrics& networkLoadMetrics, ResourceLoader* resourceLoader)
157{
158 // Notifying the FrameLoaderClient may cause the frame to be destroyed.
159 Ref<Frame> protect(m_frame);
160 m_frame.loader().client().dispatchDidFinishLoading(loader, identifier);
161
162 InspectorInstrumentation::didFinishLoading(&m_frame, loader, identifier, networkLoadMetrics, resourceLoader);
163}
164
165void ResourceLoadNotifier::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
166{
167 // Notifying the FrameLoaderClient may cause the frame to be destroyed.
168 Ref<Frame> protect(m_frame);
169 m_frame.loader().client().dispatchDidFailLoading(loader, identifier, error);
170
171 InspectorInstrumentation::didFailLoading(&m_frame, loader, identifier, error);
172}
173
174void ResourceLoadNotifier::sendRemainingDelegateMessages(DocumentLoader* loader, unsigned long identifier, const ResourceRequest& request, const ResourceResponse& response, const char* data, int dataLength, int encodedDataLength, const ResourceError& error)
175{
176 // If the request is null, willSendRequest cancelled the load. We should
177 // only dispatch didFailLoading in this case.
178 if (request.isNull()) {
179 ASSERT(error.isCancellation());
180 dispatchDidFailLoading(loader, identifier, error);
181 return;
182 }
183
184 if (!response.isNull())
185 dispatchDidReceiveResponse(loader, identifier, response);
186
187 if (dataLength > 0)
188 dispatchDidReceiveData(loader, identifier, data, dataLength, encodedDataLength);
189
190 if (error.isNull()) {
191 NetworkLoadMetrics emptyMetrics;
192 dispatchDidFinishLoading(loader, identifier, emptyMetrics, nullptr);
193 } else
194 dispatchDidFailLoading(loader, identifier, error);
195}
196
197} // namespace WebCore
198