Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / loader / DocumentLoader.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
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 "core/loader/DocumentLoader.h"
32
33 #include "FetchInitiatorTypeNames.h"
34 #include "core/dom/Document.h"
35 #include "core/dom/DocumentParser.h"
36 #include "core/events/Event.h"
37 #include "core/fetch/MemoryCache.h"
38 #include "core/fetch/ResourceFetcher.h"
39 #include "core/fetch/ResourceLoader.h"
40 #include "core/html/HTMLFrameOwnerElement.h"
41 #include "core/html/parser/TextResourceDecoder.h"
42 #include "core/inspector/InspectorInstrumentation.h"
43 #include "core/loader/FrameLoader.h"
44 #include "core/loader/FrameLoaderClient.h"
45 #include "core/loader/UniqueIdentifier.h"
46 #include "core/loader/appcache/ApplicationCacheHost.h"
47 #include "core/frame/ContentSecurityPolicy.h"
48 #include "core/frame/DOMWindow.h"
49 #include "core/frame/Frame.h"
50 #include "core/page/FrameTree.h"
51 #include "core/page/Page.h"
52 #include "core/frame/Settings.h"
53 #include "platform/Logging.h"
54 #include "platform/UserGestureIndicator.h"
55 #include "platform/mhtml/ArchiveResourceCollection.h"
56 #include "platform/mhtml/MHTMLArchive.h"
57 #include "platform/plugins/PluginData.h"
58 #include "platform/weborigin/SchemeRegistry.h"
59 #include "platform/weborigin/SecurityPolicy.h"
60 #include "public/platform/Platform.h"
61 #include "public/platform/WebMimeRegistry.h"
62 #include "wtf/Assertions.h"
63 #include "wtf/text/WTFString.h"
64
65 namespace WebCore {
66
67 static bool isArchiveMIMEType(const String& mimeType)
68 {
69     return mimeType == "multipart/related";
70 }
71
72 DocumentLoader::DocumentLoader(Frame* frame, const ResourceRequest& req, const SubstituteData& substituteData)
73     : m_frame(frame)
74     , m_fetcher(ResourceFetcher::create(this))
75     , m_originalRequest(req)
76     , m_substituteData(substituteData)
77     , m_request(req)
78     , m_committed(false)
79     , m_isClientRedirect(false)
80     , m_replacesCurrentHistoryItem(false)
81     , m_loadingMainResource(false)
82     , m_timeOfLastDataReceived(0.0)
83     , m_applicationCacheHost(adoptPtr(new ApplicationCacheHost(this)))
84 {
85 }
86
87 FrameLoader* DocumentLoader::frameLoader() const
88 {
89     if (!m_frame)
90         return 0;
91     return &m_frame->loader();
92 }
93
94 ResourceLoader* DocumentLoader::mainResourceLoader() const
95 {
96     return m_mainResource ? m_mainResource->loader() : 0;
97 }
98
99 DocumentLoader::~DocumentLoader()
100 {
101     ASSERT(!m_frame || !isLoading());
102     m_fetcher->clearDocumentLoader();
103     clearMainResourceHandle();
104 }
105
106 unsigned long DocumentLoader::mainResourceIdentifier() const
107 {
108     return m_mainResource ? m_mainResource->identifier() : 0;
109 }
110
111 Document* DocumentLoader::document() const
112 {
113     if (m_frame && m_frame->loader().documentLoader() == this)
114         return m_frame->document();
115     return 0;
116 }
117
118 const ResourceRequest& DocumentLoader::originalRequest() const
119 {
120     return m_originalRequest;
121 }
122
123 const ResourceRequest& DocumentLoader::request() const
124 {
125     return m_request;
126 }
127
128 const KURL& DocumentLoader::url() const
129 {
130     return m_request.url();
131 }
132
133 void DocumentLoader::updateForSameDocumentNavigation(const KURL& newURL)
134 {
135     KURL oldURL = m_request.url();
136     m_originalRequest.setURL(newURL);
137     m_request.setURL(newURL);
138     clearRedirectChain();
139     if (m_isClientRedirect)
140         appendRedirect(oldURL);
141     appendRedirect(newURL);
142 }
143
144 bool DocumentLoader::isURLValidForNewHistoryEntry() const
145 {
146     return !originalRequest().url().isEmpty() || !unreachableURL().isEmpty();
147 }
148
149 void DocumentLoader::setMainDocumentError(const ResourceError& error)
150 {
151     m_mainDocumentError = error;
152 }
153
154 void DocumentLoader::mainReceivedError(const ResourceError& error)
155 {
156     ASSERT(!error.isNull());
157     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading() || InspectorInstrumentation::isDebuggerPaused(m_frame));
158     m_applicationCacheHost->failedLoadingMainResource();
159     if (!frameLoader())
160         return;
161     setMainDocumentError(error);
162     clearMainResourceLoader();
163     frameLoader()->receivedMainResourceError(error);
164     clearMainResourceHandle();
165 }
166
167 // Cancels the data source's pending loads.  Conceptually, a data source only loads
168 // one document at a time, but one document may have many related resources.
169 // stopLoading will stop all loads initiated by the data source,
170 // but not loads initiated by child frames' data sources -- that's the WebFrame's job.
171 void DocumentLoader::stopLoading()
172 {
173     RefPtr<Frame> protectFrame(m_frame);
174     RefPtr<DocumentLoader> protectLoader(this);
175
176     // In some rare cases, calling FrameLoader::stopLoading could cause isLoading() to return false.
177     // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it
178     // to stop loading. Because of this, we need to save it so we don't return early.
179     bool loading = isLoading();
180
181     if (m_committed) {
182         // Attempt to stop the frame if the document loader is loading, or if it is done loading but
183         // still  parsing. Failure to do so can cause a world leak.
184         Document* doc = m_frame->document();
185
186         if (loading || doc->parsing())
187             m_frame->loader().stopLoading();
188     }
189
190     clearArchiveResources();
191
192     if (!loading)
193         return;
194
195     if (m_loadingMainResource) {
196         // Stop the main resource loader and let it send the cancelled message.
197         cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
198     } else if (m_fetcher->isFetching()) {
199         // The main resource loader already finished loading. Set the cancelled error on the
200         // document and let the resourceLoaders send individual cancelled messages below.
201         setMainDocumentError(ResourceError::cancelledError(m_request.url()));
202     } else {
203         // If there are no resource loaders, we need to manufacture a cancelled message.
204         // (A back/forward navigation has no resource loaders because its resources are cached.)
205         mainReceivedError(ResourceError::cancelledError(m_request.url()));
206     }
207
208     m_fetcher->stopFetching();
209 }
210
211 void DocumentLoader::commitIfReady()
212 {
213     if (!m_committed) {
214         m_committed = true;
215         frameLoader()->commitProvisionalLoad();
216     }
217 }
218
219 bool DocumentLoader::isLoading() const
220 {
221     if (document() && document()->hasActiveParser())
222         return true;
223
224     return m_loadingMainResource || m_fetcher->isFetching();
225 }
226
227 void DocumentLoader::notifyFinished(Resource* resource)
228 {
229     ASSERT_UNUSED(resource, m_mainResource == resource);
230     ASSERT(m_mainResource);
231
232     RefPtr<DocumentLoader> protect(this);
233
234     if (!m_mainResource->errorOccurred() && !m_mainResource->wasCanceled()) {
235         finishedLoading(m_mainResource->loadFinishTime());
236         return;
237     }
238
239     mainReceivedError(m_mainResource->resourceError());
240 }
241
242 void DocumentLoader::finishedLoading(double finishTime)
243 {
244     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading() || InspectorInstrumentation::isDebuggerPaused(m_frame));
245
246     RefPtr<DocumentLoader> protect(this);
247
248     double responseEndTime = finishTime;
249     if (!responseEndTime)
250         responseEndTime = m_timeOfLastDataReceived;
251     if (!responseEndTime)
252         responseEndTime = monotonicallyIncreasingTime();
253     timing()->setResponseEnd(responseEndTime);
254
255     commitIfReady();
256     if (!frameLoader())
257         return;
258
259     if (!maybeCreateArchive()) {
260         // If this is an empty document, it will not have actually been created yet. Commit dummy data so that
261         // DocumentWriter::begin() gets called and creates the Document.
262         if (!m_writer)
263             commitData(0, 0);
264     }
265
266     endWriting(m_writer.get());
267
268     if (!m_mainDocumentError.isNull())
269         return;
270     clearMainResourceLoader();
271     if (!frameLoader()->stateMachine()->creatingInitialEmptyDocument())
272         frameLoader()->checkLoadComplete();
273
274     // If the document specified an application cache manifest, it violates the author's intent if we store it in the memory cache
275     // and deny the appcache the chance to intercept it in the future, so remove from the memory cache.
276     if (m_frame) {
277         if (m_mainResource && m_frame->document()->hasManifest())
278             memoryCache()->remove(m_mainResource.get());
279     }
280     m_applicationCacheHost->finishedLoadingMainResource();
281     clearMainResourceHandle();
282 }
283
284 bool DocumentLoader::isRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
285 {
286     int status = redirectResponse.httpStatusCode();
287     if (((status >= 301 && status <= 303) || status == 307)
288         && m_originalRequest.httpMethod() == "POST")
289         return true;
290
291     return false;
292 }
293
294 bool DocumentLoader::shouldContinueForNavigationPolicy(const ResourceRequest& request)
295 {
296     // Don't ask if we are loading an empty URL.
297     if (request.url().isEmpty() || m_substituteData.isValid())
298         return true;
299
300     // If we're loading content into a subframe, check against the parent's Content Security Policy
301     // and kill the load if that check fails.
302     if (m_frame->ownerElement() && !m_frame->ownerElement()->document().contentSecurityPolicy()->allowChildFrameFromSource(request.url())) {
303         // Fire a load event, as timing attacks would otherwise reveal that the
304         // frame was blocked. This way, it looks like every other cross-origin
305         // page load.
306         m_frame->document()->enforceSandboxFlags(SandboxOrigin);
307         m_frame->ownerElement()->dispatchEvent(Event::create(EventTypeNames::load));
308         return false;
309     }
310
311     NavigationPolicy policy = m_triggeringAction.policy();
312     policy = frameLoader()->client()->decidePolicyForNavigation(request, this, policy);
313     if (policy == NavigationPolicyCurrentTab)
314         return true;
315     if (policy == NavigationPolicyIgnore)
316         return false;
317     if (!DOMWindow::allowPopUp(m_frame) && !UserGestureIndicator::processingUserGesture())
318         return false;
319     frameLoader()->client()->loadURLExternally(request, policy);
320     return false;
321 }
322
323 void DocumentLoader::redirectReceived(Resource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
324 {
325     ASSERT_UNUSED(resource, resource == m_mainResource);
326     willSendRequest(request, redirectResponse);
327 }
328
329 void DocumentLoader::updateRequest(Resource* resource, const ResourceRequest& request)
330 {
331     ASSERT_UNUSED(resource, resource == m_mainResource);
332     m_request = request;
333 }
334
335 static bool isFormSubmission(NavigationType type)
336 {
337     return type == NavigationTypeFormSubmitted || type == NavigationTypeFormResubmitted;
338 }
339
340 void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
341 {
342     // Note that there are no asserts here as there are for the other callbacks. This is due to the
343     // fact that this "callback" is sent when starting every load, and the state of callback
344     // deferrals plays less of a part in this function in preventing the bad behavior deferring
345     // callbacks is meant to prevent.
346     ASSERT(!newRequest.isNull());
347     if (isFormSubmission(m_triggeringAction.type()) && !m_frame->document()->contentSecurityPolicy()->allowFormAction(newRequest.url())) {
348         cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
349         return;
350     }
351
352     ASSERT(timing()->fetchStart());
353     if (!redirectResponse.isNull()) {
354         // If the redirecting url is not allowed to display content from the target origin,
355         // then block the redirect.
356         RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
357         if (!redirectingOrigin->canDisplay(newRequest.url())) {
358             FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string());
359             cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
360             return;
361         }
362         timing()->addRedirect(redirectResponse.url(), newRequest.url());
363     }
364
365     // Update cookie policy base URL as URL changes, except for subframes, which use the
366     // URL of the main frame which doesn't change when we redirect.
367     if (frameLoader()->isLoadingMainFrame())
368         newRequest.setFirstPartyForCookies(newRequest.url());
369
370     // If we're fielding a redirect in response to a POST, force a load from origin, since
371     // this is a common site technique to return to a page viewing some data that the POST
372     // just modified.
373     if (newRequest.cachePolicy() == UseProtocolCachePolicy && isRedirectAfterPost(newRequest, redirectResponse))
374         newRequest.setCachePolicy(ReloadIgnoringCacheData);
375
376     // If this is a sub-frame, check for mixed content blocking against the top frame.
377     if (m_frame->tree().parent()) {
378         Frame* top = m_frame->tree().top();
379         if (!top->loader().mixedContentChecker()->canRunInsecureContent(top->document()->securityOrigin(), newRequest.url())) {
380             cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
381             return;
382         }
383     }
384
385     m_request = newRequest;
386
387     if (redirectResponse.isNull())
388         return;
389
390     appendRedirect(newRequest.url());
391     frameLoader()->client()->dispatchDidReceiveServerRedirectForProvisionalLoad();
392     if (!shouldContinueForNavigationPolicy(newRequest))
393         cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
394 }
395
396 static bool canShowMIMEType(const String& mimeType, Page* page)
397 {
398     if (blink::Platform::current()->mimeRegistry()->supportsMIMEType(mimeType) == blink::WebMimeRegistry::IsSupported)
399         return true;
400     PluginData* pluginData = page->pluginData();
401     return !mimeType.isEmpty() && pluginData && pluginData->supportsMimeType(mimeType);
402 }
403
404 bool DocumentLoader::shouldContinueForResponse() const
405 {
406     if (m_substituteData.isValid())
407         return true;
408
409     int statusCode = m_response.httpStatusCode();
410     if (statusCode == 204 || statusCode == 205) {
411         // The server does not want us to replace the page contents.
412         return false;
413     }
414
415     if (contentDispositionType(m_response.httpHeaderField("Content-Disposition")) == ContentDispositionAttachment) {
416         // The server wants us to download instead of replacing the page contents.
417         // Downloading is handled by the embedder, but we still get the initial
418         // response so that we can ignore it and clean up properly.
419         return false;
420     }
421
422     if (!canShowMIMEType(m_response.mimeType(), m_frame->page()))
423         return false;
424
425     // Prevent remote web archives from loading because they can claim to be from any domain and thus avoid cross-domain security checks.
426     if (equalIgnoringCase("multipart/related", m_response.mimeType()) && !SchemeRegistry::shouldTreatURLSchemeAsLocal(m_request.url().protocol()))
427         return false;
428
429     return true;
430 }
431
432 void DocumentLoader::responseReceived(Resource* resource, const ResourceResponse& response)
433 {
434     ASSERT_UNUSED(resource, m_mainResource == resource);
435     RefPtr<DocumentLoader> protect(this);
436
437     m_applicationCacheHost->didReceiveResponseForMainResource(response);
438
439     // The memory cache doesn't understand the application cache or its caching rules. So if a main resource is served
440     // from the application cache, ensure we don't save the result for future use. All responses loaded
441     // from appcache will have a non-zero appCacheID().
442     if (response.appCacheID())
443         memoryCache()->remove(m_mainResource.get());
444
445     DEFINE_STATIC_LOCAL(AtomicString, xFrameOptionHeader, ("x-frame-options", AtomicString::ConstructFromLiteral));
446     HTTPHeaderMap::const_iterator it = response.httpHeaderFields().find(xFrameOptionHeader);
447     if (it != response.httpHeaderFields().end()) {
448         String content = it->value;
449         ASSERT(m_mainResource);
450         unsigned long identifier = mainResourceIdentifier();
451         ASSERT(identifier);
452         if (frameLoader()->shouldInterruptLoadForXFrameOptions(content, response.url(), identifier)) {
453             InspectorInstrumentation::continueAfterXFrameOptionsDenied(m_frame, this, identifier, response);
454             String message = "Refused to display '" + response.url().elidedString() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'.";
455             frame()->document()->addConsoleMessageWithRequestIdentifier(SecurityMessageSource, ErrorMessageLevel, message, identifier);
456             frame()->document()->enforceSandboxFlags(SandboxOrigin);
457             if (HTMLFrameOwnerElement* ownerElement = frame()->ownerElement())
458                 ownerElement->dispatchEvent(Event::create(EventTypeNames::load));
459
460             // The load event might have detached this frame. In that case, the load will already have been cancelled during detach.
461             if (frameLoader())
462                 cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
463             return;
464         }
465     }
466
467     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
468
469     m_response = response;
470
471     if (isArchiveMIMEType(m_response.mimeType()) && m_mainResource->dataBufferingPolicy() != BufferData)
472         m_mainResource->setDataBufferingPolicy(BufferData);
473
474     if (!shouldContinueForResponse()) {
475         InspectorInstrumentation::continueWithPolicyIgnore(m_frame, this, m_mainResource->identifier(), m_response);
476         cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
477         return;
478     }
479
480     if (m_response.isHTTP()) {
481         int status = m_response.httpStatusCode();
482         if ((status < 200 || status >= 300) && m_frame->ownerElement() && m_frame->ownerElement()->isObjectElement()) {
483             m_frame->ownerElement()->renderFallbackContent();
484             // object elements are no longer rendered after we fallback, so don't
485             // keep trying to process data from their load
486             cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
487         }
488     }
489 }
490
491 void DocumentLoader::ensureWriter(const AtomicString& mimeType, const KURL& overridingURL)
492 {
493     if (m_writer)
494         return;
495
496     const AtomicString& encoding = overrideEncoding().isNull() ? response().textEncodingName() : overrideEncoding();
497     m_writer = createWriterFor(m_frame, 0, url(), mimeType, encoding, false, false);
498     m_writer->setDocumentWasLoadedAsPartOfNavigation();
499     // This should be set before receivedFirstData().
500     if (!overridingURL.isEmpty())
501         m_frame->document()->setBaseURLOverride(overridingURL);
502
503     // Call receivedFirstData() exactly once per load.
504     frameLoader()->receivedFirstData();
505     m_frame->document()->maybeHandleHttpRefresh(m_response.httpHeaderField("Refresh"), Document::HttpRefreshFromHeader);
506 }
507
508 void DocumentLoader::commitData(const char* bytes, size_t length)
509 {
510     ensureWriter(m_response.mimeType());
511     ASSERT(m_frame->document()->parsing());
512     m_writer->addData(bytes, length);
513 }
514
515 void DocumentLoader::dataReceived(Resource* resource, const char* data, int length)
516 {
517     ASSERT(data);
518     ASSERT(length);
519     ASSERT_UNUSED(resource, resource == m_mainResource);
520     ASSERT(!m_response.isNull());
521     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
522
523     // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource
524     // by starting a new load, so retain temporarily.
525     RefPtr<Frame> protectFrame(m_frame);
526     RefPtr<DocumentLoader> protectLoader(this);
527
528     m_applicationCacheHost->mainResourceDataReceived(data, length);
529     m_timeOfLastDataReceived = monotonicallyIncreasingTime();
530
531     commitIfReady();
532     if (!frameLoader())
533         return;
534     if (isArchiveMIMEType(response().mimeType()))
535         return;
536     commitData(data, length);
537
538     // If we are sending data to MediaDocument, we should stop here
539     // and cancel the request.
540     if (m_frame && m_frame->document()->isMediaDocument())
541         cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
542 }
543
544 void DocumentLoader::checkLoadComplete()
545 {
546     if (!m_frame || isLoading())
547         return;
548     m_frame->domWindow()->finishedLoading();
549 }
550
551 void DocumentLoader::clearRedirectChain()
552 {
553     m_redirectChain.clear();
554 }
555
556 void DocumentLoader::appendRedirect(const KURL& url)
557 {
558     m_redirectChain.append(url);
559 }
560
561 void DocumentLoader::detachFromFrame()
562 {
563     ASSERT(m_frame);
564     RefPtr<Frame> protectFrame(m_frame);
565     RefPtr<DocumentLoader> protectLoader(this);
566
567     // It never makes sense to have a document loader that is detached from its
568     // frame have any loads active, so go ahead and kill all the loads.
569     stopLoading();
570
571     m_applicationCacheHost->setApplicationCache(0);
572     InspectorInstrumentation::loaderDetachedFromFrame(m_frame, this);
573     m_frame = 0;
574 }
575
576 void DocumentLoader::clearMainResourceLoader()
577 {
578     m_loadingMainResource = false;
579     checkLoadComplete();
580 }
581
582 void DocumentLoader::clearMainResourceHandle()
583 {
584     if (!m_mainResource)
585         return;
586     m_mainResource->removeClient(this);
587     m_mainResource = 0;
588 }
589
590 bool DocumentLoader::isLoadingInAPISense() const
591 {
592     // Once a frame has loaded, we no longer need to consider subresources,
593     // but we still need to consider subframes.
594     if (frameLoader()->state() != FrameStateComplete) {
595         Document* doc = m_frame->document();
596         if ((m_loadingMainResource || !m_frame->document()->loadEventFinished()) && isLoading())
597             return true;
598         if (m_fetcher->requestCount())
599             return true;
600         if (doc->isDelayingLoadEvent() && !doc->loadEventFinished())
601             return true;
602         if (doc->processingLoadEvent())
603             return true;
604         if (doc->hasActiveParser())
605             return true;
606     }
607     return frameLoader()->subframeIsLoading();
608 }
609
610 bool DocumentLoader::maybeCreateArchive()
611 {
612     // Give the archive machinery a crack at this document. If the MIME type is not an archive type, it will return 0.
613     if (!isArchiveMIMEType(m_response.mimeType()))
614         return false;
615
616     ASSERT(m_mainResource);
617     m_archive = MHTMLArchive::create(m_response.url(), m_mainResource->resourceBuffer());
618     // Invalid MHTML.
619     if (!m_archive || !m_archive->mainResource()) {
620         m_archive.clear();
621         return false;
622     }
623
624     addAllArchiveResources(m_archive.get());
625     ArchiveResource* mainResource = m_archive->mainResource();
626
627     // The origin is the MHTML file, we need to set the base URL to the document encoded in the MHTML so
628     // relative URLs are resolved properly.
629     ensureWriter(mainResource->mimeType(), m_archive->mainResource()->url());
630
631     commitData(mainResource->data()->data(), mainResource->data()->size());
632     return true;
633 }
634
635 void DocumentLoader::addAllArchiveResources(MHTMLArchive* archive)
636 {
637     ASSERT(archive);
638     if (!m_archiveResourceCollection)
639         m_archiveResourceCollection = adoptPtr(new ArchiveResourceCollection);
640     m_archiveResourceCollection->addAllResources(archive);
641 }
642
643 void DocumentLoader::prepareSubframeArchiveLoadIfNeeded()
644 {
645     if (!m_frame->tree().parent())
646         return;
647
648     ArchiveResourceCollection* parentCollection = m_frame->tree().parent()->loader().documentLoader()->m_archiveResourceCollection.get();
649     if (!parentCollection)
650         return;
651
652     m_archive = parentCollection->popSubframeArchive(m_frame->tree().uniqueName(), m_request.url());
653
654     if (!m_archive)
655         return;
656     addAllArchiveResources(m_archive.get());
657
658     ArchiveResource* mainResource = m_archive->mainResource();
659     m_substituteData = SubstituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
660 }
661
662 void DocumentLoader::clearArchiveResources()
663 {
664     m_archiveResourceCollection.clear();
665 }
666
667 bool DocumentLoader::scheduleArchiveLoad(Resource* cachedResource, const ResourceRequest& request)
668 {
669     if (!m_archive)
670         return false;
671
672     ASSERT(m_archiveResourceCollection);
673     ArchiveResource* archiveResource = m_archiveResourceCollection->archiveResourceForURL(request.url());
674     if (!archiveResource) {
675         cachedResource->error(Resource::LoadError);
676         return true;
677     }
678
679     cachedResource->setLoading(true);
680     cachedResource->responseReceived(archiveResource->response());
681     SharedBuffer* data = archiveResource->data();
682     if (data)
683         cachedResource->appendData(data->data(), data->size());
684     cachedResource->finish();
685     return true;
686 }
687
688 const KURL& DocumentLoader::originalURL() const
689 {
690     return m_originalRequest.url();
691 }
692
693 const AtomicString& DocumentLoader::responseMIMEType() const
694 {
695     return m_response.mimeType();
696 }
697
698 const KURL& DocumentLoader::unreachableURL() const
699 {
700     return m_substituteData.failingURL();
701 }
702
703 void DocumentLoader::setDefersLoading(bool defers)
704 {
705     // Multiple frames may be loading the same main resource simultaneously. If deferral state changes,
706     // each frame's DocumentLoader will try to send a setDefersLoading() to the same underlying ResourceLoader. Ensure only
707     // the "owning" DocumentLoader does so, as setDefersLoading() is not resilient to setting the same value repeatedly.
708     if (mainResourceLoader() && mainResourceLoader()->isLoadedBy(m_fetcher.get()))
709         mainResourceLoader()->setDefersLoading(defers);
710
711     m_fetcher->setDefersLoading(defers);
712 }
713
714 bool DocumentLoader::maybeLoadEmpty()
715 {
716     bool shouldLoadEmpty = !m_substituteData.isValid() && (m_request.url().isEmpty() || SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(m_request.url().protocol()));
717     if (!shouldLoadEmpty)
718         return false;
719
720     if (m_request.url().isEmpty() && !frameLoader()->stateMachine()->creatingInitialEmptyDocument())
721         m_request.setURL(blankURL());
722     m_response = ResourceResponse(m_request.url(), "text/html", 0, nullAtom, String());
723     finishedLoading(monotonicallyIncreasingTime());
724     return true;
725 }
726
727 void DocumentLoader::startLoadingMainResource()
728 {
729     RefPtr<DocumentLoader> protect(this);
730     m_mainDocumentError = ResourceError();
731     timing()->markNavigationStart();
732     ASSERT(!m_mainResource);
733     ASSERT(!m_loadingMainResource);
734     m_loadingMainResource = true;
735
736     if (maybeLoadEmpty())
737         return;
738
739     ASSERT(timing()->navigationStart());
740     ASSERT(!timing()->fetchStart());
741     timing()->markFetchStart();
742     willSendRequest(m_request, ResourceResponse());
743
744     // willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest.
745     if (!m_frame || m_request.isNull())
746         return;
747
748     m_applicationCacheHost->willStartLoadingMainResource(m_request);
749     prepareSubframeArchiveLoadIfNeeded();
750
751     ResourceRequest request(m_request);
752     DEFINE_STATIC_LOCAL(ResourceLoaderOptions, mainResourceLoadOptions,
753         (SniffContent, DoNotBufferData, AllowStoredCredentials, ClientRequestedCredentials, CheckContentSecurityPolicy, DocumentContext));
754     FetchRequest cachedResourceRequest(request, FetchInitiatorTypeNames::document, mainResourceLoadOptions);
755     m_mainResource = m_fetcher->fetchMainResource(cachedResourceRequest, m_substituteData);
756     if (!m_mainResource) {
757         m_request = ResourceRequest();
758         // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost
759         // is now in a state where starting an empty load will be inconsistent. Replace it with
760         // a new ApplicationCacheHost.
761         m_applicationCacheHost = adoptPtr(new ApplicationCacheHost(this));
762         maybeLoadEmpty();
763         return;
764     }
765     m_mainResource->addClient(this);
766
767     // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those.
768     if (mainResourceLoader())
769         request = mainResourceLoader()->originalRequest();
770     // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include
771     // the fragment identifier, so add that back in.
772     if (equalIgnoringFragmentIdentifier(m_request.url(), request.url()))
773         request.setURL(m_request.url());
774     m_request = request;
775 }
776
777 void DocumentLoader::cancelMainResourceLoad(const ResourceError& resourceError)
778 {
779     RefPtr<DocumentLoader> protect(this);
780     ResourceError error = resourceError.isNull() ? ResourceError::cancelledError(m_request.url()) : resourceError;
781
782     if (mainResourceLoader())
783         mainResourceLoader()->cancel(error);
784
785     mainReceivedError(error);
786 }
787
788 void DocumentLoader::endWriting(DocumentWriter* writer)
789 {
790     ASSERT_UNUSED(writer, m_writer == writer);
791     m_writer->end();
792     m_writer.clear();
793 }
794
795 PassRefPtr<DocumentWriter> DocumentLoader::createWriterFor(Frame* frame, const Document* ownerDocument, const KURL& url, const AtomicString& mimeType, const AtomicString& encoding, bool userChosen, bool dispatch)
796 {
797     // Create a new document before clearing the frame, because it may need to
798     // inherit an aliased security context.
799     DocumentInit init(url, frame);
800     init.withNewRegistrationContext();
801
802     // In some rare cases, we'll re-used a DOMWindow for a new Document. For example,
803     // when a script calls window.open("..."), the browser gives JavaScript a window
804     // synchronously but kicks off the load in the window asynchronously. Web sites
805     // expect that modifications that they make to the window object synchronously
806     // won't be blown away when the network load commits. To make that happen, we
807     // "securely transition" the existing DOMWindow to the Document that results from
808     // the network load. See also SecurityContext::isSecureTransitionTo.
809     bool shouldReuseDefaultView = frame->loader().stateMachine()->isDisplayingInitialEmptyDocument() && frame->document()->isSecureTransitionTo(url);
810
811     frame->loader().clear();
812
813     if (frame->document())
814         frame->document()->prepareForDestruction();
815
816     if (!shouldReuseDefaultView)
817         frame->setDOMWindow(DOMWindow::create(frame));
818
819     RefPtr<Document> document = frame->domWindow()->installNewDocument(mimeType, init);
820     if (ownerDocument) {
821         document->setCookieURL(ownerDocument->cookieURL());
822         document->setSecurityOrigin(ownerDocument->securityOrigin());
823     }
824
825     frame->loader().didBeginDocument(dispatch);
826
827     return DocumentWriter::create(document.get(), mimeType, encoding, userChosen);
828 }
829
830 const AtomicString& DocumentLoader::mimeType() const
831 {
832     if (m_writer)
833         return m_writer->mimeType();
834     return m_response.mimeType();
835 }
836
837 void DocumentLoader::setUserChosenEncoding(const String& charset)
838 {
839     if (m_writer)
840         m_writer->setUserChosenEncoding(charset);
841 }
842
843 // This is only called by ScriptController::executeScriptIfJavaScriptURL
844 // and always contains the result of evaluating a javascript: url.
845 // This is the <iframe src="javascript:'html'"> case.
846 void DocumentLoader::replaceDocument(const String& source, Document* ownerDocument)
847 {
848     m_frame->loader().stopAllLoaders();
849     m_writer = createWriterFor(m_frame, ownerDocument, m_frame->document()->url(), mimeType(), m_writer ? m_writer->encoding() : emptyAtom,  m_writer ? m_writer->encodingWasChosenByUser() : false, true);
850     if (!source.isNull())
851         m_writer->appendReplacingData(source);
852     endWriting(m_writer.get());
853 }
854
855 } // namespace WebCore