2011-05-24 Jay Civelli <jcivelli@chromium.org>
[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 "DocumentLoader.h"
35 #include "FileStreamProxy.h"
36 #include "Frame.h"
37 #include "FrameLoader.h"
38 #include "FrameLoaderClient.h"
39 #include "InspectorInstrumentation.h"
40 #include "Page.h"
41 #include "ProgressTracker.h"
42 #include "ResourceError.h"
43 #include "ResourceHandle.h"
44 #include "ResourceLoadScheduler.h"
45 #include "Settings.h"
46 #include "SharedBuffer.h"
47
48 namespace WebCore {
49
50 PassRefPtr<SharedBuffer> ResourceLoader::resourceData()
51 {
52     if (m_resourceData)
53         return m_resourceData;
54
55     if (ResourceHandle::supportsBufferedData() && m_handle)
56         return m_handle->bufferedData();
57     
58     return 0;
59 }
60
61 ResourceLoader::ResourceLoader(Frame* frame, bool sendResourceLoadCallbacks, bool shouldContentSniff)
62     : m_frame(frame)
63     , m_documentLoader(frame->loader()->activeDocumentLoader())
64     , m_identifier(0)
65     , m_reachedTerminalState(false)
66     , m_calledWillCancel(false)
67     , m_cancelled(false)
68     , m_calledDidFinishLoad(false)
69     , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks)
70     , m_shouldContentSniff(shouldContentSniff)
71     , m_shouldBufferData(true)
72     , m_defersLoading(frame->page()->defersLoading())
73 {
74 }
75
76 ResourceLoader::~ResourceLoader()
77 {
78     ASSERT(m_reachedTerminalState);
79 }
80
81 void ResourceLoader::releaseResources()
82 {
83     ASSERT(!m_reachedTerminalState);
84     
85     // It's possible that when we release the handle, it will be
86     // deallocated and release the last reference to this object.
87     // We need to retain to avoid accessing the object after it
88     // has been deallocated and also to avoid reentering this method.
89     RefPtr<ResourceLoader> protector(this);
90
91     m_frame = 0;
92     m_documentLoader = 0;
93     
94     // We need to set reachedTerminalState to true before we release
95     // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
96     m_reachedTerminalState = true;
97
98     m_identifier = 0;
99
100     resourceLoadScheduler()->remove(this);
101
102     if (m_handle) {
103         // Clear out the ResourceHandle's client so that it doesn't try to call
104         // us back after we release it, unless it has been replaced by someone else.
105         if (m_handle->client() == this)
106             m_handle->setClient(0);
107         m_handle = 0;
108     }
109
110     m_resourceData = 0;
111     m_deferredRequest = ResourceRequest();
112 }
113
114 bool ResourceLoader::init(const ResourceRequest& r)
115 {
116     ASSERT(!m_handle);
117     ASSERT(m_request.isNull());
118     ASSERT(m_deferredRequest.isNull());
119     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
120     
121     ResourceRequest clientRequest(r);
122     
123     // https://bugs.webkit.org/show_bug.cgi?id=26391
124     // The various plug-in implementations call directly to ResourceLoader::load() instead of piping requests
125     // through FrameLoader. As a result, they miss the FrameLoader::addExtraFieldsToRequest() step which sets
126     // up the 1st party for cookies URL. Until plug-in implementations can be reigned in to pipe through that
127     // method, we need to make sure there is always a 1st party for cookies set.
128     if (clientRequest.firstPartyForCookies().isNull()) {
129         if (Document* document = m_frame->document())
130             clientRequest.setFirstPartyForCookies(document->firstPartyForCookies());
131     }
132
133     willSendRequest(clientRequest, ResourceResponse());
134     if (clientRequest.isNull()) {
135         didFail(frameLoader()->cancelledError(m_request));
136         return false;
137     }
138
139     m_request = clientRequest;
140     return true;
141 }
142
143 void ResourceLoader::start()
144 {
145     ASSERT(!m_handle);
146     ASSERT(!m_request.isNull());
147     ASSERT(m_deferredRequest.isNull());
148
149 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
150     if (m_documentLoader->scheduleArchiveLoad(this, m_request, m_request.url()))
151         return;
152 #endif
153     
154 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
155     if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, m_request, m_request.url()))
156         return;
157 #endif
158
159     if (m_defersLoading) {
160         m_deferredRequest = m_request;
161         return;
162     }
163
164     if (!m_reachedTerminalState)
165         m_handle = ResourceHandle::create(m_frame->loader()->networkingContext(), m_request, this, m_defersLoading, m_shouldContentSniff);
166 }
167
168 void ResourceLoader::setDefersLoading(bool defers)
169 {
170     m_defersLoading = defers;
171     if (m_handle)
172         m_handle->setDefersLoading(defers);
173     if (!defers && !m_deferredRequest.isNull()) {
174         m_request = m_deferredRequest;
175         m_deferredRequest = ResourceRequest();
176         start();
177     }
178 }
179
180 FrameLoader* ResourceLoader::frameLoader() const
181 {
182     if (!m_frame)
183         return 0;
184     return m_frame->loader();
185 }
186
187 void ResourceLoader::setShouldBufferData(bool shouldBufferData)
188
189     m_shouldBufferData = shouldBufferData; 
190
191     // Reset any already buffered data
192     if (!m_shouldBufferData)
193         m_resourceData = 0;
194 }
195     
196
197 void ResourceLoader::addData(const char* data, int length, bool allAtOnce)
198 {
199     if (!m_shouldBufferData)
200         return;
201
202     if (allAtOnce) {
203         m_resourceData = SharedBuffer::create(data, length);
204         return;
205     }
206         
207     if (ResourceHandle::supportsBufferedData()) {
208         // Buffer data only if the connection has handed us the data because is has stopped buffering it.
209         if (m_resourceData)
210             m_resourceData->append(data, length);
211     } else {
212         if (!m_resourceData)
213             m_resourceData = SharedBuffer::create(data, length);
214         else
215             m_resourceData->append(data, length);
216     }
217 }
218
219 void ResourceLoader::clearResourceData()
220 {
221     if (m_resourceData)
222         m_resourceData->clear();
223 }
224
225 void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
226 {
227     // Protect this in this delegate method since the additional processing can do
228     // anything including possibly derefing this; one example of this is Radar 3266216.
229     RefPtr<ResourceLoader> protector(this);
230
231     ASSERT(!m_reachedTerminalState);
232
233     if (m_sendResourceLoadCallbacks) {
234         if (!m_identifier) {
235             m_identifier = m_frame->page()->progress()->createUniqueIdentifier();
236             frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifier, documentLoader(), request);
237         }
238
239         frameLoader()->notifier()->willSendRequest(this, request, redirectResponse);
240     }
241
242     if (!redirectResponse.isNull())
243         resourceLoadScheduler()->crossOriginRedirectReceived(this, request.url());
244     m_request = request;
245 }
246
247 void ResourceLoader::didSendData(unsigned long long, unsigned long long)
248 {
249 }
250
251 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
252 {
253     ASSERT(!m_reachedTerminalState);
254
255     // Protect this in this delegate method since the additional processing can do
256     // anything including possibly derefing this; one example of this is Radar 3266216.
257     RefPtr<ResourceLoader> protector(this);
258
259     m_response = r;
260
261     if (FormData* data = m_request.httpBody())
262         data->removeGeneratedFilesIfNeeded();
263         
264     if (m_sendResourceLoadCallbacks)
265         frameLoader()->notifier()->didReceiveResponse(this, m_response);
266 }
267
268 void ResourceLoader::didReceiveData(const char* data, int length, long long encodedDataLength, bool allAtOnce)
269 {
270     // The following assertions are not quite valid here, since a subclass
271     // might override didReceiveData in a way that invalidates them. This
272     // happens with the steps listed in 3266216
273     // ASSERT(con == connection);
274     // ASSERT(!m_reachedTerminalState);
275
276     // Protect this in this delegate method since the additional processing can do
277     // anything including possibly derefing this; one example of this is Radar 3266216.
278     RefPtr<ResourceLoader> protector(this);
279
280     addData(data, length, allAtOnce);
281     // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
282     // However, with today's computers and networking speeds, this won't happen in practice.
283     // Could be an issue with a giant local file.
284     if (m_sendResourceLoadCallbacks && m_frame)
285         frameLoader()->notifier()->didReceiveData(this, data, length, static_cast<int>(encodedDataLength));
286 }
287
288 void ResourceLoader::willStopBufferingData(const char* data, int length)
289 {
290     if (!m_shouldBufferData)
291         return;
292
293     ASSERT(!m_resourceData);
294     m_resourceData = SharedBuffer::create(data, length);
295 }
296
297 void ResourceLoader::didFinishLoading(double finishTime)
298 {
299     // If load has been cancelled after finishing (which could happen with a 
300     // JavaScript that changes the window location), do nothing.
301     if (m_cancelled)
302         return;
303     ASSERT(!m_reachedTerminalState);
304
305     didFinishLoadingOnePart(finishTime);
306     releaseResources();
307 }
308
309 void ResourceLoader::didFinishLoadingOnePart(double finishTime)
310 {
311     if (m_cancelled)
312         return;
313     ASSERT(!m_reachedTerminalState);
314
315     if (m_calledDidFinishLoad)
316         return;
317     m_calledDidFinishLoad = true;
318     if (m_sendResourceLoadCallbacks)
319         frameLoader()->notifier()->didFinishLoad(this, finishTime);
320 }
321
322 void ResourceLoader::didFail(const ResourceError& error)
323 {
324     if (m_cancelled)
325         return;
326     ASSERT(!m_reachedTerminalState);
327
328     // Protect this in this delegate method since the additional processing can do
329     // anything including possibly derefing this; one example of this is Radar 3266216.
330     RefPtr<ResourceLoader> protector(this);
331
332     if (FormData* data = m_request.httpBody())
333         data->removeGeneratedFilesIfNeeded();
334
335     if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad)
336         frameLoader()->notifier()->didFailToLoad(this, error);
337
338     releaseResources();
339 }
340
341 void ResourceLoader::cancel()
342 {
343     cancel(ResourceError());
344 }
345
346 void ResourceLoader::cancel(const ResourceError& error)
347 {
348     // If the load has already completed - succeeded, failed, or previously cancelled - do nothing.
349     if (m_reachedTerminalState)
350         return;
351        
352     ResourceError nonNullError = error.isNull() ? cancelledError() : error;
353     
354     // willCancel() and didFailToLoad() both call out to clients that might do 
355     // something causing the last reference to this object to go away.
356     RefPtr<ResourceLoader> protector(this);
357     
358     // If we re-enter cancel() from inside willCancel(), we want to pick up from where we left 
359     // off without re-running willCancel()
360     if (!m_calledWillCancel) {
361         m_calledWillCancel = true;
362         
363         willCancel(nonNullError);
364     }
365
366     // If we re-enter cancel() from inside didFailToLoad(), we want to pick up from where we 
367     // left off without redoing any of this work.
368     if (!m_cancelled) {
369         m_cancelled = true;
370         
371         if (FormData* data = m_request.httpBody())
372             data->removeGeneratedFilesIfNeeded();
373
374         if (m_handle)
375             m_handle->clearAuthentication();
376
377         m_documentLoader->cancelPendingSubstituteLoad(this);
378         if (m_handle) {
379             m_handle->cancel();
380             m_handle = 0;
381         }
382
383         if (m_sendResourceLoadCallbacks && m_identifier && !m_calledDidFinishLoad)
384             frameLoader()->notifier()->didFailToLoad(this, nonNullError);
385     }
386
387     // If cancel() completed from within the call to willCancel() or didFailToLoad(),
388     // we don't want to redo didCancel() or releasesResources().
389     if (m_reachedTerminalState)
390         return;
391
392     didCancel(nonNullError);
393             
394     releaseResources();
395 }
396
397 const ResourceResponse& ResourceLoader::response() const
398 {
399     return m_response;
400 }
401
402 ResourceError ResourceLoader::cancelledError()
403 {
404     return frameLoader()->cancelledError(m_request);
405 }
406
407 ResourceError ResourceLoader::blockedError()
408 {
409     return frameLoader()->blockedError(m_request);
410 }
411
412 ResourceError ResourceLoader::cannotShowURLError()
413 {
414     return frameLoader()->cannotShowURLError(m_request);
415 }
416
417 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
418 {
419 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
420     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
421         return;
422 #endif
423     willSendRequest(request, redirectResponse);
424 }
425
426 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
427 {
428     didSendData(bytesSent, totalBytesToBeSent);
429 }
430
431 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
432 {
433 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
434     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
435         return;
436 #endif
437     didReceiveResponse(response);
438 }
439
440 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int encodedDataLength)
441 {
442     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceData(m_frame.get(), identifier());
443     didReceiveData(data, length, encodedDataLength, false);
444     InspectorInstrumentation::didReceiveResourceData(cookie);
445 }
446
447 void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
448 {
449     didFinishLoading(finishTime);
450 }
451
452 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
453 {
454 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
455     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
456         return;
457 #endif
458     didFail(error);
459 }
460
461 void ResourceLoader::wasBlocked(ResourceHandle*)
462 {
463     didFail(blockedError());
464 }
465
466 void ResourceLoader::cannotShowURL(ResourceHandle*)
467 {
468     didFail(cannotShowURLError());
469 }
470
471 bool ResourceLoader::shouldUseCredentialStorage()
472 {
473     RefPtr<ResourceLoader> protector(this);
474     return frameLoader()->shouldUseCredentialStorage(this);
475 }
476
477 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
478 {
479     // Protect this in this delegate method since the additional processing can do
480     // anything including possibly derefing this; one example of this is Radar 3266216.
481     RefPtr<ResourceLoader> protector(this);
482     frameLoader()->notifier()->didReceiveAuthenticationChallenge(this, challenge);
483 }
484
485 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
486 {
487     // Protect this in this delegate method since the additional processing can do
488     // anything including possibly derefing this; one example of this is Radar 3266216.
489     RefPtr<ResourceLoader> protector(this);
490     frameLoader()->notifier()->didCancelAuthenticationChallenge(this, challenge);
491 }
492
493 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
494 bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
495 {
496     RefPtr<ResourceLoader> protector(this);
497     return frameLoader()->canAuthenticateAgainstProtectionSpace(this, protectionSpace);
498 }
499 #endif
500
501 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
502 {
503     cancel();
504 }
505
506 void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy)
507 {
508     // <rdar://problem/7249553> - There are reports of crashes with this method being called
509     // with a null m_frame->settings(), which can only happen if the frame doesn't have a page.
510     // Sadly we have no reproducible cases of this.
511     // We think that any frame without a page shouldn't have any loads happening in it, yet
512     // there is at least one code path where that is not true.
513     ASSERT(m_frame->settings());
514     
515     // When in private browsing mode, prevent caching to disk
516     if (policy == StorageAllowed && m_frame->settings() && m_frame->settings()->privateBrowsingEnabled())
517         policy = StorageAllowedInMemoryOnly;    
518 }
519
520 #if ENABLE(BLOB)
521 AsyncFileStream* ResourceLoader::createAsyncFileStream(FileStreamClient* client)
522 {
523     // It is OK to simply return a pointer since FileStreamProxy::create adds an extra ref.
524     return FileStreamProxy::create(m_frame->document()->scriptExecutionContext(), client).get();
525 }
526 #endif
527
528 }