[chromium] Lower priority of preloaded images
[WebKit-https.git] / Source / WebCore / loader / ResourceLoader.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved.
3  *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer. 
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution. 
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "ResourceLoader.h"
32
33 #include "ApplicationCacheHost.h"
34 #include "AsyncFileStream.h"
35 #include "AuthenticationChallenge.h"
36 #include "DocumentLoader.h"
37 #include "Frame.h"
38 #include "FrameLoader.h"
39 #include "FrameLoaderClient.h"
40 #include "InspectorInstrumentation.h"
41 #include "LoaderStrategy.h"
42 #include "Page.h"
43 #include "PlatformStrategies.h"
44 #include "ProgressTracker.h"
45 #include "ResourceBuffer.h"
46 #include "ResourceError.h"
47 #include "ResourceHandle.h"
48 #include "ResourceLoadScheduler.h"
49 #include "SecurityOrigin.h"
50 #include "Settings.h"
51 #include "SharedBuffer.h"
52
53 namespace WebCore {
54
55 PassRefPtr<ResourceBuffer> ResourceLoader::resourceData()
56 {
57     return m_resourceData;
58 }
59
60 ResourceLoader::ResourceLoader(Frame* frame, ResourceLoaderOptions options)
61     : m_frame(frame)
62     , m_documentLoader(frame->loader()->activeDocumentLoader())
63     , m_identifier(0)
64     , m_reachedTerminalState(false)
65     , m_calledWillCancel(false)
66     , m_cancelled(false)
67     , m_notifiedLoadComplete(false)
68     , m_defersLoading(frame->page()->defersLoading())
69     , m_options(options)
70 {
71 }
72
73 ResourceLoader::~ResourceLoader()
74 {
75     ASSERT(m_reachedTerminalState);
76 }
77
78 void ResourceLoader::releaseResources()
79 {
80     ASSERT(!m_reachedTerminalState);
81     
82     // It's possible that when we release the handle, it will be
83     // deallocated and release the last reference to this object.
84     // We need to retain to avoid accessing the object after it
85     // has been deallocated and also to avoid reentering this method.
86     RefPtr<ResourceLoader> protector(this);
87
88     m_frame = 0;
89     m_documentLoader = 0;
90     
91     // We need to set reachedTerminalState to true before we release
92     // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
93     m_reachedTerminalState = true;
94
95 #if USE(PLATFORM_STRATEGIES)
96     platformStrategies()->loaderStrategy()->resourceLoadScheduler()->remove(this);
97 #endif
98     m_identifier = 0;
99 #if !USE(PLATFORM_STRATEGIES)
100     resourceLoadScheduler()->remove(this);
101 #endif
102
103     if (m_handle) {
104         // Clear out the ResourceHandle's client so that it doesn't try to call
105         // us back after we release it, unless it has been replaced by someone else.
106         if (m_handle->client() == this)
107             m_handle->setClient(0);
108         m_handle = 0;
109     }
110
111     m_resourceData = 0;
112     m_deferredRequest = ResourceRequest();
113 }
114
115 bool ResourceLoader::init(const ResourceRequest& r)
116 {
117     ASSERT(!m_handle);
118     ASSERT(m_request.isNull());
119     ASSERT(m_deferredRequest.isNull());
120     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
121     
122     ResourceRequest clientRequest(r);
123     
124     m_defersLoading = m_frame->page()->defersLoading();
125     if (m_options.securityCheck == DoSecurityCheck && !m_frame->document()->securityOrigin()->canDisplay(clientRequest.url())) {
126         FrameLoader::reportLocalLoadFailed(m_frame.get(), clientRequest.url().string());
127         releaseResources();
128         return false;
129     }
130     
131     // https://bugs.webkit.org/show_bug.cgi?id=26391
132     // The various plug-in implementations call directly to ResourceLoader::load() instead of piping requests
133     // through FrameLoader. As a result, they miss the FrameLoader::addExtraFieldsToRequest() step which sets
134     // up the 1st party for cookies URL. Until plug-in implementations can be reigned in to pipe through that
135     // method, we need to make sure there is always a 1st party for cookies set.
136     if (clientRequest.firstPartyForCookies().isNull()) {
137         if (Document* document = m_frame->document())
138             clientRequest.setFirstPartyForCookies(document->firstPartyForCookies());
139     }
140
141     willSendRequest(clientRequest, ResourceResponse());
142     if (clientRequest.isNull()) {
143         cancel();
144         return false;
145     }
146
147     m_originalRequest = m_request = clientRequest;
148     return true;
149 }
150
151 void ResourceLoader::start()
152 {
153     ASSERT(!m_handle);
154     ASSERT(!m_request.isNull());
155     ASSERT(m_deferredRequest.isNull());
156
157 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
158     if (m_documentLoader->scheduleArchiveLoad(this, m_request))
159         return;
160 #endif
161
162     if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, m_request, m_request.url()))
163         return;
164
165     if (m_defersLoading) {
166         m_deferredRequest = m_request;
167         return;
168     }
169
170     if (!m_reachedTerminalState)
171         m_handle = ResourceHandle::create(m_frame->loader()->networkingContext(), m_request, this, m_defersLoading, m_options.sniffContent == SniffContent);
172 }
173
174 void ResourceLoader::setDefersLoading(bool defers)
175 {
176     m_defersLoading = defers;
177     if (m_handle)
178         m_handle->setDefersLoading(defers);
179     if (!defers && !m_deferredRequest.isNull()) {
180         m_request = m_deferredRequest;
181         m_deferredRequest = ResourceRequest();
182         start();
183     }
184 }
185
186 FrameLoader* ResourceLoader::frameLoader() const
187 {
188     if (!m_frame)
189         return 0;
190     return m_frame->loader();
191 }
192
193 void ResourceLoader::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
194
195     m_options.dataBufferingPolicy = dataBufferingPolicy; 
196
197     // Reset any already buffered data
198     if (dataBufferingPolicy == DoNotBufferData)
199         m_resourceData = 0;
200 }
201     
202
203 void ResourceLoader::addData(const char* data, int length, bool allAtOnce)
204 {
205     if (m_options.dataBufferingPolicy == DoNotBufferData)
206         return;
207
208     if (allAtOnce) {
209         m_resourceData = ResourceBuffer::create(data, length);
210         return;
211     }
212         
213     if (!m_resourceData)
214         m_resourceData = ResourceBuffer::create(data, length);
215     else
216         m_resourceData->append(data, length);
217 }
218
219 void ResourceLoader::clearResourceData()
220 {
221     if (m_resourceData)
222         m_resourceData->clear();
223 }
224
225 bool ResourceLoader::isSubresourceLoader()
226 {
227     return false;
228 }
229
230 void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
231 {
232     // Protect this in this delegate method since the additional processing can do
233     // anything including possibly derefing this; one example of this is Radar 3266216.
234     RefPtr<ResourceLoader> protector(this);
235
236     ASSERT(!m_reachedTerminalState);
237
238     // We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests).
239     bool createdResourceIdentifier = false;
240     if (!m_identifier) {
241         m_identifier = m_frame->page()->progress()->createUniqueIdentifier();
242         createdResourceIdentifier = true;
243     }
244
245     if (m_options.sendLoadCallbacks == SendCallbacks) {
246         if (createdResourceIdentifier)
247             frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifier, documentLoader(), request);
248
249         frameLoader()->notifier()->willSendRequest(this, request, redirectResponse);
250     }
251 #if ENABLE(INSPECTOR)
252     else
253         InspectorInstrumentation::willSendRequest(m_frame.get(), m_identifier, m_frame->loader()->documentLoader(), request, redirectResponse);
254 #endif
255
256     if (!redirectResponse.isNull()) {
257 #if USE(PLATFORM_STRATEGIES)
258         platformStrategies()->loaderStrategy()->resourceLoadScheduler()->crossOriginRedirectReceived(this, request.url());
259 #else
260         resourceLoadScheduler()->crossOriginRedirectReceived(this, request.url());
261 #endif
262     }
263     m_request = request;
264
265     if (!redirectResponse.isNull() && !m_documentLoader->isCommitted())
266         frameLoader()->client()->dispatchDidReceiveServerRedirectForProvisionalLoad();
267 }
268
269 void ResourceLoader::didSendData(unsigned long long, unsigned long long)
270 {
271 }
272
273 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
274 {
275     ASSERT(!m_reachedTerminalState);
276
277     // Protect this in this delegate method since the additional processing can do
278     // anything including possibly derefing this; one example of this is Radar 3266216.
279     RefPtr<ResourceLoader> protector(this);
280
281     m_response = r;
282
283     if (FormData* data = m_request.httpBody())
284         data->removeGeneratedFilesIfNeeded();
285         
286     if (m_options.sendLoadCallbacks == SendCallbacks)
287         frameLoader()->notifier()->didReceiveResponse(this, m_response);
288 }
289
290 void ResourceLoader::didReceiveData(const char* data, int length, long long encodedDataLength, bool allAtOnce)
291 {
292     // The following assertions are not quite valid here, since a subclass
293     // might override didReceiveData in a way that invalidates them. This
294     // happens with the steps listed in 3266216
295     // ASSERT(con == connection);
296     // ASSERT(!m_reachedTerminalState);
297
298     // Protect this in this delegate method since the additional processing can do
299     // anything including possibly derefing this; one example of this is Radar 3266216.
300     RefPtr<ResourceLoader> protector(this);
301
302     addData(data, length, allAtOnce);
303     // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
304     // However, with today's computers and networking speeds, this won't happen in practice.
305     // Could be an issue with a giant local file.
306     if (m_options.sendLoadCallbacks == SendCallbacks && m_frame)
307         frameLoader()->notifier()->didReceiveData(this, data, length, static_cast<int>(encodedDataLength));
308 }
309
310 void ResourceLoader::willStopBufferingData(const char* data, int length)
311 {
312     if (m_options.dataBufferingPolicy == DoNotBufferData)
313         return;
314
315     ASSERT(!m_resourceData);
316     m_resourceData = ResourceBuffer::create(data, length);
317 }
318
319 void ResourceLoader::didFinishLoading(double finishTime)
320 {
321     didFinishLoadingOnePart(finishTime);
322
323     // If the load has been cancelled by a delegate in response to didFinishLoad(), do not release
324     // the resources a second time, they have been released by cancel.
325     if (m_cancelled)
326         return;
327     releaseResources();
328 }
329
330 void ResourceLoader::didFinishLoadingOnePart(double finishTime)
331 {
332     // If load has been cancelled after finishing (which could happen with a
333     // JavaScript that changes the window location), do nothing.
334     if (m_cancelled)
335         return;
336     ASSERT(!m_reachedTerminalState);
337
338     if (m_notifiedLoadComplete)
339         return;
340     m_notifiedLoadComplete = true;
341     if (m_options.sendLoadCallbacks == SendCallbacks)
342         frameLoader()->notifier()->didFinishLoad(this, finishTime);
343 }
344
345 void ResourceLoader::didFail(const ResourceError& error)
346 {
347     if (m_cancelled)
348         return;
349     ASSERT(!m_reachedTerminalState);
350
351     // Protect this in this delegate method since the additional processing can do
352     // anything including possibly derefing this; one example of this is Radar 3266216.
353     RefPtr<ResourceLoader> protector(this);
354
355     if (FormData* data = m_request.httpBody())
356         data->removeGeneratedFilesIfNeeded();
357
358     if (!m_notifiedLoadComplete) {
359         m_notifiedLoadComplete = true;
360         if (m_options.sendLoadCallbacks == SendCallbacks)
361             frameLoader()->notifier()->didFailToLoad(this, error);
362     }
363
364     releaseResources();
365 }
366
367 void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority)
368 {
369     if (handle()) {
370         frameLoader()->client()->dispatchDidChangeResourcePriority(identifier(), loadPriority);
371         handle()->didChangePriority(loadPriority);
372     }
373 }
374
375 void ResourceLoader::cancel()
376 {
377     cancel(ResourceError());
378 }
379
380 void ResourceLoader::cancel(const ResourceError& error)
381 {
382     // If the load has already completed - succeeded, failed, or previously cancelled - do nothing.
383     if (m_reachedTerminalState)
384         return;
385        
386     ResourceError nonNullError = error.isNull() ? cancelledError() : error;
387     
388     // willCancel() and didFailToLoad() both call out to clients that might do 
389     // something causing the last reference to this object to go away.
390     RefPtr<ResourceLoader> protector(this);
391     
392     // If we re-enter cancel() from inside willCancel(), we want to pick up from where we left 
393     // off without re-running willCancel()
394     if (!m_calledWillCancel) {
395         m_calledWillCancel = true;
396         
397         willCancel(nonNullError);
398     }
399
400     // If we re-enter cancel() from inside didFailToLoad(), we want to pick up from where we 
401     // left off without redoing any of this work.
402     if (!m_cancelled) {
403         m_cancelled = true;
404         
405         if (FormData* data = m_request.httpBody())
406             data->removeGeneratedFilesIfNeeded();
407
408         if (m_handle)
409             m_handle->clearAuthentication();
410
411         m_documentLoader->cancelPendingSubstituteLoad(this);
412         if (m_handle) {
413             m_handle->cancel();
414             m_handle = 0;
415         }
416
417         if (m_options.sendLoadCallbacks == SendCallbacks && m_identifier && !m_notifiedLoadComplete)
418             frameLoader()->notifier()->didFailToLoad(this, nonNullError);
419     }
420
421     // If cancel() completed from within the call to willCancel() or didFailToLoad(),
422     // we don't want to redo didCancel() or releasesResources().
423     if (m_reachedTerminalState)
424         return;
425
426     didCancel(nonNullError);
427             
428     releaseResources();
429 }
430
431 ResourceError ResourceLoader::cancelledError()
432 {
433     return frameLoader()->cancelledError(m_request);
434 }
435
436 ResourceError ResourceLoader::blockedError()
437 {
438     return frameLoader()->client()->blockedError(m_request);
439 }
440
441 ResourceError ResourceLoader::cannotShowURLError()
442 {
443     return frameLoader()->client()->cannotShowURLError(m_request);
444 }
445
446 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
447 {
448     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
449         return;
450     willSendRequest(request, redirectResponse);
451 }
452
453 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
454 {
455     didSendData(bytesSent, totalBytesToBeSent);
456 }
457
458 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
459 {
460     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
461         return;
462     didReceiveResponse(response);
463 }
464
465 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int encodedDataLength)
466 {
467     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceData(m_frame.get(), identifier(), encodedDataLength);
468     didReceiveData(data, length, encodedDataLength, false);
469     InspectorInstrumentation::didReceiveResourceData(cookie);
470 }
471
472 void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
473 {
474     didFinishLoading(finishTime);
475 }
476
477 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
478 {
479     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
480         return;
481     didFail(error);
482 }
483
484 void ResourceLoader::wasBlocked(ResourceHandle*)
485 {
486     didFail(blockedError());
487 }
488
489 void ResourceLoader::cannotShowURL(ResourceHandle*)
490 {
491     didFail(cannotShowURLError());
492 }
493
494 bool ResourceLoader::shouldUseCredentialStorage()
495 {
496     if (m_options.allowCredentials == DoNotAllowStoredCredentials)
497         return false;
498     
499     RefPtr<ResourceLoader> protector(this);
500     return frameLoader()->client()->shouldUseCredentialStorage(documentLoader(), identifier());
501 }
502
503 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
504 {
505     ASSERT(handle()->hasAuthenticationChallenge());
506
507     // Protect this in this delegate method since the additional processing can do
508     // anything including possibly derefing this; one example of this is Radar 3266216.
509     RefPtr<ResourceLoader> protector(this);
510
511     if (m_options.allowCredentials == AllowStoredCredentials) {
512         if (m_options.crossOriginCredentialPolicy == AskClientForCrossOriginCredentials || m_frame->document()->securityOrigin()->canRequest(originalRequest().url())) {
513             frameLoader()->notifier()->didReceiveAuthenticationChallenge(this, challenge);
514             return;
515         }
516     }
517     // Only these platforms provide a way to continue without credentials.
518     // If we can't continue with credentials, we need to cancel the load altogether.
519 #if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL) || PLATFORM(GTK) || PLATFORM(EFL)
520     challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
521     ASSERT(!handle() || !handle()->hasAuthenticationChallenge());
522 #else
523     didFail(blockedError());
524 #endif
525 }
526
527 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
528 {
529     // Protect this in this delegate method since the additional processing can do
530     // anything including possibly derefing this; one example of this is Radar 3266216.
531     RefPtr<ResourceLoader> protector(this);
532     frameLoader()->notifier()->didCancelAuthenticationChallenge(this, challenge);
533 }
534
535 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
536 bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
537 {
538     RefPtr<ResourceLoader> protector(this);
539     return frameLoader()->client()->canAuthenticateAgainstProtectionSpace(documentLoader(), identifier(), protectionSpace);
540 }
541 #endif
542
543 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
544 {
545     cancel();
546 }
547
548 #if ENABLE(BLOB)
549 AsyncFileStream* ResourceLoader::createAsyncFileStream(FileStreamClient* client)
550 {
551     // It is OK to simply return a pointer since AsyncFileStream::create adds an extra ref.
552     return AsyncFileStream::create(m_frame->document()->scriptExecutionContext(), client).get();
553 }
554 #endif
555
556 void ResourceLoader::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
557 {
558     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Loader);
559     info.addMember(m_handle, "handle");
560     info.addMember(m_frame, "frame");
561     info.addMember(m_documentLoader, "documentLoader");
562     info.addMember(m_request, "request");
563     info.addMember(m_originalRequest, "originalRequest");
564     info.addMember(m_resourceData, "resourceData");
565     info.addMember(m_deferredRequest, "deferredRequest");
566     info.addMember(m_options, "options");
567 }
568
569 }