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