| Index: third_party/WebKit/Source/core/loader/DocumentLoader.cpp
|
| diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
|
| index 2c84b0d65a9e036b1930a676de24699d396ab9b7..01b2985374a573954d9734b5cebfd7aaeac18ec3 100644
|
| --- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
|
| +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
|
| @@ -95,11 +95,10 @@
|
| , m_documentLoadTiming(*this)
|
| , m_timeOfLastDataReceived(0.0)
|
| , m_applicationCacheHost(ApplicationCacheHost::create(this))
|
| - , m_state(Provisional)
|
| + , m_state(NotStarted)
|
| , m_inDataReceived(false)
|
| , m_dataBuffer(SharedBuffer::create())
|
| {
|
| - timing().markNavigationStart();
|
| }
|
|
|
| FrameLoader* DocumentLoader::frameLoader() const
|
| @@ -251,7 +250,7 @@
|
| if (document() && document()->hasActiveParser())
|
| return true;
|
|
|
| - return m_state < MainResourceDone || m_fetcher->isFetching();
|
| + return (m_state > NotStarted && m_state < MainResourceDone) || m_fetcher->isFetching();
|
| }
|
|
|
| void DocumentLoader::notifyFinished(Resource* resource)
|
| @@ -313,38 +312,60 @@
|
| void DocumentLoader::redirectReceived(Resource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
|
| {
|
| ASSERT_UNUSED(resource, resource == m_mainResource);
|
| + willSendRequest(request, redirectResponse);
|
| +}
|
| +
|
| +void DocumentLoader::updateRequest(Resource* resource, const ResourceRequest& request)
|
| +{
|
| + ASSERT_UNUSED(resource, resource == m_mainResource);
|
| + m_request = request;
|
| +}
|
| +
|
| +static bool isFormSubmission(NavigationType type)
|
| +{
|
| + return type == NavigationTypeFormSubmitted || type == NavigationTypeFormResubmitted;
|
| +}
|
| +
|
| +void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
|
| +{
|
| + // Note that there are no asserts here as there are for the other callbacks. This is due to the
|
| + // fact that this "callback" is sent when starting every load, and the state of callback
|
| + // deferrals plays less of a part in this function in preventing the bad behavior deferring
|
| + // callbacks is meant to prevent.
|
| + ASSERT(!newRequest.isNull());
|
| + if (isFormSubmission(m_navigationType) && !m_frame->document()->contentSecurityPolicy()->allowFormAction(newRequest.url())) {
|
| + cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
|
| + return;
|
| + }
|
| +
|
| + ASSERT(timing().fetchStart());
|
| + if (!redirectResponse.isNull()) {
|
| + // If the redirecting url is not allowed to display content from the target origin,
|
| + // then block the redirect.
|
| + RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
|
| + if (!redirectingOrigin->canDisplay(newRequest.url())) {
|
| + FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string());
|
| + cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
|
| + return;
|
| + }
|
| + timing().addRedirect(redirectResponse.url(), newRequest.url());
|
| + }
|
|
|
| // If we're fielding a redirect in response to a POST, force a load from origin, since
|
| // this is a common site technique to return to a page viewing some data that the POST
|
| // just modified.
|
| - if (request.cachePolicy() == UseProtocolCachePolicy && isRedirectAfterPost(request, redirectResponse))
|
| - request.setCachePolicy(ReloadBypassingCache);
|
| -
|
| - m_request = request;
|
| -
|
| - // Add the fragment to the new request url. Note that this is only done on m_request,
|
| - // not on the request that will be passed back out of blink. The network stack doesn't care
|
| - // about the fragment, and doesn't expect the URL to change unless it is invalidated.
|
| - KURL url = request.url();
|
| - if (m_originalRequest.url().hasFragmentIdentifier()) {
|
| - url.setFragmentIdentifier(m_originalRequest.url().fragmentIdentifier());
|
| - m_request.setURL(url);
|
| - }
|
| -
|
| - // If the redirecting url is not allowed to display content from the target origin,
|
| - // then block the redirect.
|
| - RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
|
| - if (!redirectingOrigin->canDisplay(url)) {
|
| - FrameLoader::reportLocalLoadFailed(m_frame, url.string());
|
| - cancelMainResourceLoad(ResourceError::cancelledError(url));
|
| - return;
|
| - }
|
| -
|
| - timing().addRedirect(redirectResponse.url(), url);
|
| - appendRedirect(url);
|
| + if (newRequest.cachePolicy() == UseProtocolCachePolicy && isRedirectAfterPost(newRequest, redirectResponse))
|
| + newRequest.setCachePolicy(ReloadBypassingCache);
|
| +
|
| + m_request = newRequest;
|
| +
|
| + if (redirectResponse.isNull())
|
| + return;
|
| +
|
| + appendRedirect(newRequest.url());
|
| frameLoader()->receivedMainResourceRedirect(m_request.url());
|
| - if (!frameLoader()->shouldContinueForNavigationPolicy(request, SubstituteData(), this, CheckContentSecurityPolicy, m_navigationType, NavigationPolicyCurrentTab, replacesCurrentHistoryItem()))
|
| - cancelMainResourceLoad(ResourceError::cancelledError(url));
|
| + if (!frameLoader()->shouldContinueForNavigationPolicy(newRequest, SubstituteData(), this, CheckContentSecurityPolicy, m_navigationType, NavigationPolicyCurrentTab, replacesCurrentHistoryItem()))
|
| + cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
|
| }
|
|
|
| static bool canShowMIMEType(const String& mimeType, Page* page)
|
| @@ -701,35 +722,53 @@
|
| void DocumentLoader::startLoadingMainResource()
|
| {
|
| RefPtrWillBeRawPtr<DocumentLoader> protect(this);
|
| - ASSERT(m_state == Provisional);
|
| + m_mainDocumentError = ResourceError();
|
| + timing().markNavigationStart();
|
| + ASSERT(!m_mainResource);
|
| + ASSERT(m_state == NotStarted);
|
| + m_state = Provisional;
|
|
|
| if (maybeLoadEmpty())
|
| return;
|
|
|
| + ASSERT(timing().navigationStart());
|
| ASSERT(!timing().fetchStart());
|
| timing().markFetchStart();
|
| + willSendRequest(m_request, ResourceResponse());
|
| +
|
| + // willSendRequest() may lead to our LocalFrame being detached or cancelling the load via nulling the ResourceRequest.
|
| + if (!m_frame || m_request.isNull())
|
| + return;
|
| +
|
| + m_applicationCacheHost->willStartLoadingMainResource(m_request);
|
| prepareSubframeArchiveLoadIfNeeded();
|
|
|
| + ResourceRequest request(m_request);
|
| DEFINE_STATIC_LOCAL(ResourceLoaderOptions, mainResourceLoadOptions,
|
| (DoNotBufferData, AllowStoredCredentials, ClientRequestedCredentials, CheckContentSecurityPolicy, DocumentContext));
|
| - FetchRequest fetchRequest(m_request, FetchInitiatorTypeNames::document, mainResourceLoadOptions);
|
| -
|
| - m_mainResource = RawResource::fetchMainResource(fetchRequest, fetcher(), m_substituteData);
|
| + FetchRequest cachedResourceRequest(request, FetchInitiatorTypeNames::document, mainResourceLoadOptions);
|
| + m_mainResource = RawResource::fetchMainResource(cachedResourceRequest, fetcher(), m_substituteData);
|
| if (!m_mainResource) {
|
| m_request = ResourceRequest();
|
| + // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost
|
| + // is now in a state where starting an empty load will be inconsistent. Replace it with
|
| + // a new ApplicationCacheHost.
|
| + if (m_applicationCacheHost)
|
| + m_applicationCacheHost->detachFromDocumentLoader();
|
| + m_applicationCacheHost = ApplicationCacheHost::create(this);
|
| maybeLoadEmpty();
|
| return;
|
| }
|
| -
|
| m_mainResource->addClient(this);
|
| - if (!m_mainResource)
|
| - return;
|
|
|
| // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those.
|
| - // However, if there was a fragment identifier on m_request, the cache will have stripped it. m_request should include
|
| - // the fragment identifier, so reset the url.
|
| - m_request = m_mainResource->resourceRequest();
|
| - m_request.setURL(m_originalRequest.url());
|
| + if (mainResourceLoader())
|
| + request = mainResourceLoader()->originalRequest();
|
| + // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include
|
| + // the fragment identifier, so add that back in.
|
| + if (equalIgnoringFragmentIdentifier(m_request.url(), request.url()))
|
| + request.setURL(m_request.url());
|
| + m_request = request;
|
| }
|
|
|
| void DocumentLoader::cancelMainResourceLoad(const ResourceError& resourceError)
|
|
|