Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1176)

Unified Diff: Source/core/loader/DocumentThreadableLoader.cpp

Issue 1262593004: Prevent ThreadableLoaderClient methods from being called after failure notification (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/loader/DocumentThreadableLoader.cpp
diff --git a/Source/core/loader/DocumentThreadableLoader.cpp b/Source/core/loader/DocumentThreadableLoader.cpp
index 74bf523ccfafd5dd70bdf8d83fee6171c90a7c4e..fd200356acbd5ff3f971bdcdd06654072ba7a22a 100644
--- a/Source/core/loader/DocumentThreadableLoader.cpp
+++ b/Source/core/loader/DocumentThreadableLoader.cpp
@@ -100,7 +100,10 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl
ASSERT(m_async || request.httpReferrer().isEmpty());
if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) {
- m_client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are not supported."));
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are not supported."));
+ // |this| may be dead here.
return;
}
@@ -158,13 +161,17 @@ void DocumentThreadableLoader::dispatchInitialRequest(const ResourceRequest& req
void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceRequest& request)
{
ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
+ ASSERT(!resource());
// Cross-origin requests are only allowed certain registered schemes.
// We would catch this when checking response headers later, but there
// is no reason to send a request, preflighted or not, that's guaranteed
// to be denied.
if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) {
- m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are only supported for protocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + "."));
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are only supported for protocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + "."));
+ // |this| may be dead here.
return;
}
@@ -232,8 +239,6 @@ void DocumentThreadableLoader::cancel()
void DocumentThreadableLoader::cancelWithError(const ResourceError& error)
{
- RefPtr<DocumentThreadableLoader> protect(this);
-
// Cancel can re-enter and m_resource might be null here as a result.
if (m_client && resource()) {
ResourceError errorForCallback = error;
@@ -242,11 +247,14 @@ void DocumentThreadableLoader::cancelWithError(const ResourceError& error)
errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resource()->url().string(), "Load cancelled");
errorForCallback.setIsCancellation(true);
}
- m_client->didFail(errorForCallback);
+
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFail(errorForCallback);
+ // |this| may be dead here.
+ } else {
+ clear();
}
- clearResource();
- m_client = 0;
- m_requestStartedSeconds = 0.0;
}
void DocumentThreadableLoader::setDefersLoading(bool value)
@@ -255,6 +263,18 @@ void DocumentThreadableLoader::setDefersLoading(bool value)
resource()->setDefersLoading(value);
}
+void DocumentThreadableLoader::clear()
+{
+ m_client = 0;
+
+ if (!m_async)
+ return;
+
+ clearResource();
+ m_timeoutTimer.stop();
+ m_requestStartedSeconds = 0.0;
+}
+
// In this method, we can clear |request| to tell content::WebURLLoaderImpl of
// Chromium not to follow the redirect. This works only when this method is
// called by RawResource::willSendRequest(). If called by
@@ -270,12 +290,13 @@ void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
RefPtr<DocumentThreadableLoader> protect(this);
hiroshige 2015/08/06 05:25:03 Can we remove |protect| here as well? (I'm not so
tyoshino (SeeGerritForStatus) 2015/08/26 12:57:32 Agreed. Removed.
if (!isAllowedByContentSecurityPolicy(request.url(), ContentSecurityPolicy::DidRedirect)) {
- m_client->didFailRedirectCheck();
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFailRedirectCheck();
+ // |this| may be dead here.
- clearResource();
request = ResourceRequest();
- m_requestStartedSeconds = 0.0;
return;
}
@@ -287,7 +308,10 @@ void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
}
if (m_corsRedirectLimit <= 0) {
- m_client->didFailRedirectCheck();
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFailRedirectCheck();
+ // |this| may be dead here.
} else if (m_options.crossOriginRequestPolicy == UseAccessControl) {
--m_corsRedirectLimit;
@@ -338,16 +362,18 @@ void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
return;
}
- ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url().string(), accessControlErrorDescription);
- m_client->didFailAccessControlCheck(error);
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, redirectResponse.url().string(), accessControlErrorDescription));
+ // |this| may be dead here.
} else {
- m_client->didFailRedirectCheck();
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFailRedirectCheck();
+ // |this| may be dead here.
}
- clearResource();
request = ResourceRequest();
-
- m_requestStartedSeconds = 0.0;
}
void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
@@ -468,7 +494,11 @@ void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re
String accessControlErrorDescription;
if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription)) {
reportResponseReceived(identifier, response);
- m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, response.url().string(), accessControlErrorDescription));
+
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, response.url().string(), accessControlErrorDescription));
+ // |this| may be dead here.
return;
}
}
@@ -513,12 +543,15 @@ void DocumentThreadableLoader::notifyFinished(Resource* resource)
ASSERT(resource == this->resource());
ASSERT(m_async);
- m_timeoutTimer.stop();
-
- if (resource->errorOccurred())
- m_client->didFail(resource->resourceError());
- else
+ if (resource->errorOccurred()) {
+ ThreadableLoaderClient* client = m_client;
+ ResourceError error = resource->resourceError();
+ clear();
+ client->didFail(error);
+ // |this| may be dead here.
+ } else {
handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime());
+ }
}
void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, double finishTime)
@@ -530,9 +563,14 @@ void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier,
ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
loadActualRequest();
} else {
- // FIXME: Should prevent timeout from being overridden after finished loading, without
- // resetting m_requestStartedSeconds to 0.0
- m_client->didFinishLoading(identifier, finishTime);
+ ThreadableLoaderClient* client = m_client;
+ m_client = 0;
+ if (m_async) {
+ m_timeoutTimer.stop();
+ m_requestStartedSeconds = 0.0;
+ }
hiroshige 2015/08/04 10:20:16 nit: please add a comment that the code sequence a
+ client->didFinishLoading(identifier, finishTime);
+ // |this| may be dead here.
}
}
@@ -576,9 +614,10 @@ void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S
// Prevent handleSuccessfulFinish() from bypassing access check.
m_actualRequest = nullptr;
- // FIXME: Should prevent timeout from being overridden after preflight failure, without
- // resetting m_requestStartedSeconds to 0.0
- m_client->didFailAccessControlCheck(error);
+ ThreadableLoaderClient* client = m_client;
+ clear();
+ client->didFailAccessControlCheck(error);
+ // |this| may be dead here.
}
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, ResourceLoaderOptions resourceLoaderOptions)
@@ -646,6 +685,14 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou
handleResponse(identifier, response, nullptr);
+ // handleResponse() may detect an error. In such a case (check |m_client|
+ // as it gets reset by clear() call), skip the rest.
+ //
+ // |this| is alive here since loadResourceSynchronously() keeps it alive
+ // until the end of the function.
+ if (!m_client)
+ return;
+
SharedBuffer* data = resource->resourceBuffer();
if (data)
handleReceivedData(data->data(), data->size());

Powered by Google App Engine
This is Rietveld 408576698