| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2013, Intel Corporation | 3 * Copyright (C) 2013, Intel Corporation |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document&
document, ThreadableLoaderClient* client, const ResourceRequest& request, const
ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOpt
ions) | 120 PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document&
document, ThreadableLoaderClient* client, const ResourceRequest& request, const
ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOpt
ions) |
| 121 { | 121 { |
| 122 RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoa
der(document, client, LoadAsynchronously, request, options, resourceLoaderOption
s)); | 122 RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoa
der(document, client, LoadAsynchronously, request, options, resourceLoaderOption
s)); |
| 123 if (!loader->resource()) | 123 if (!loader->resource()) |
| 124 loader = nullptr; | 124 loader = nullptr; |
| 125 return loader.release(); | 125 return loader.release(); |
| 126 } | 126 } |
| 127 | 127 |
| 128 DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl
eLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest&
request, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& r
esourceLoaderOptions) | 128 DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl
eLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest&
request, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& r
esourceLoaderOptions) |
| 129 : m_client(client) | 129 : m_client(client) |
| 130 , m_document(document) | 130 , m_document(&document) |
| 131 , m_options(options) | 131 , m_options(options) |
| 132 , m_resourceLoaderOptions(resourceLoaderOptions) | 132 , m_resourceLoaderOptions(resourceLoaderOptions) |
| 133 , m_forceDoNotAllowStoredCredentials(false) | 133 , m_forceDoNotAllowStoredCredentials(false) |
| 134 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) | 134 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) |
| 135 , m_sameOriginRequest(securityOrigin()->canRequestNoSuborigin(request.url())
) | 135 , m_sameOriginRequest(securityOrigin()->canRequestNoSuborigin(request.url())
) |
| 136 , m_crossOriginNonSimpleRequest(false) | 136 , m_crossOriginNonSimpleRequest(false) |
| 137 , m_isUsingDataConsumerHandle(false) | 137 , m_isUsingDataConsumerHandle(false) |
| 138 , m_async(blockingBehavior == LoadAsynchronously) | 138 , m_async(blockingBehavior == LoadAsynchronously) |
| 139 , m_requestContext(request.requestContext()) | 139 , m_requestContext(request.requestContext()) |
| 140 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) | 140 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 // - ThreadableLoader is used as backend for all javascript initiated networ
k | 176 // - ThreadableLoader is used as backend for all javascript initiated networ
k |
| 177 // fetches. | 177 // fetches. |
| 178 // - Note that ThreadableLoader is also used for non-network fetch such as | 178 // - Note that ThreadableLoader is also used for non-network fetch such as |
| 179 // FileReaderLoader. However it emulates GET method so signal is not | 179 // FileReaderLoader. However it emulates GET method so signal is not |
| 180 // recorded here. | 180 // recorded here. |
| 181 // - ThreadableLoader w/ non-GET request is only created from javascript | 181 // - ThreadableLoader w/ non-GET request is only created from javascript |
| 182 // initiated fetch. | 182 // initiated fetch. |
| 183 // - Some non-script initiated fetches such as WorkerScriptLoader also use | 183 // - Some non-script initiated fetches such as WorkerScriptLoader also use |
| 184 // ThreadableLoader, but they are guaranteed to use GET method. | 184 // ThreadableLoader, but they are guaranteed to use GET method. |
| 185 if (request.httpMethod() != "GET") { | 185 if (request.httpMethod() != "GET") { |
| 186 if (Page* page = m_document.page()) | 186 if (Page* page = document.page()) |
| 187 page->chromeClient().didObserveNonGetFetchFromScript(); | 187 page->chromeClient().didObserveNonGetFetchFromScript(); |
| 188 } | 188 } |
| 189 | 189 |
| 190 // If the fetch request will be handled by the ServiceWorker, the | 190 // If the fetch request will be handled by the ServiceWorker, the |
| 191 // FetchRequestMode of the request must be FetchRequestModeCORS or | 191 // FetchRequestMode of the request must be FetchRequestModeCORS or |
| 192 // FetchRequestModeCORSWithForcedPreflight. Otherwise the ServiceWorker can | 192 // FetchRequestModeCORSWithForcedPreflight. Otherwise the ServiceWorker can |
| 193 // return a opaque response which is from the other origin site and the | 193 // return a opaque response which is from the other origin site and the |
| 194 // script in the page can read the content. | 194 // script in the page can read the content. |
| 195 // | 195 // |
| 196 // We assume that ServiceWorker is skipped for sync requests and non-HTTP | 196 // We assume that ServiceWorker is skipped for sync requests and non-HTTP |
| 197 // familiy requests by content/ code. | 197 // familiy requests by content/ code. |
| 198 if (m_async && !request.skipServiceWorker() && request.url().protocolIsInHTT
PFamily() && m_document.fetcher()->isControlledByServiceWorker()) { | 198 if (m_async && !request.skipServiceWorker() && request.url().protocolIsInHTT
PFamily() && document.fetcher()->isControlledByServiceWorker()) { |
| 199 ResourceRequest newRequest(request); | 199 ResourceRequest newRequest(request); |
| 200 // FetchRequestMode should be set by the caller. But the expected value | 200 // FetchRequestMode should be set by the caller. But the expected value |
| 201 // of FetchRequestMode is not speced yet except for XHR. So we set here. | 201 // of FetchRequestMode is not speced yet except for XHR. So we set here. |
| 202 // FIXME: When we support fetch API in document, this value should not | 202 // FIXME: When we support fetch API in document, this value should not |
| 203 // be overridden here. | 203 // be overridden here. |
| 204 if (options.preflightPolicy == ForcePreflight) | 204 if (options.preflightPolicy == ForcePreflight) |
| 205 newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORSWi
thForcedPreflight); | 205 newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORSWi
thForcedPreflight); |
| 206 else | 206 else |
| 207 newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS); | 207 newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS); |
| 208 | 208 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 } else { | 260 } else { |
| 261 m_crossOriginNonSimpleRequest = true; | 261 m_crossOriginNonSimpleRequest = true; |
| 262 | 262 |
| 263 OwnPtr<ResourceRequest> crossOriginRequest = adoptPtr(new ResourceReques
t(request)); | 263 OwnPtr<ResourceRequest> crossOriginRequest = adoptPtr(new ResourceReques
t(request)); |
| 264 OwnPtr<ResourceLoaderOptions> crossOriginOptions = adoptPtr(new Resource
LoaderOptions(m_resourceLoaderOptions)); | 264 OwnPtr<ResourceLoaderOptions> crossOriginOptions = adoptPtr(new Resource
LoaderOptions(m_resourceLoaderOptions)); |
| 265 // Do not set the Origin header for preflight requests. | 265 // Do not set the Origin header for preflight requests. |
| 266 updateRequestForAccessControl(*crossOriginRequest, 0, effectiveAllowCred
entials()); | 266 updateRequestForAccessControl(*crossOriginRequest, 0, effectiveAllowCred
entials()); |
| 267 m_actualRequest = crossOriginRequest.release(); | 267 m_actualRequest = crossOriginRequest.release(); |
| 268 m_actualOptions = crossOriginOptions.release(); | 268 m_actualOptions = crossOriginOptions.release(); |
| 269 | 269 |
| 270 bool shouldForcePreflight = InspectorInstrumentation::shouldForceCORSPre
flight(&m_document); | 270 bool shouldForcePreflight = InspectorInstrumentation::shouldForceCORSPre
flight(m_document); |
| 271 bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSki
pPreflight(securityOrigin()->toString(), m_actualRequest->url(), effectiveAllowC
redentials(), m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields()
); | 271 bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSki
pPreflight(securityOrigin()->toString(), m_actualRequest->url(), effectiveAllowC
redentials(), m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields()
); |
| 272 if (canSkipPreflight && !shouldForcePreflight) { | 272 if (canSkipPreflight && !shouldForcePreflight) { |
| 273 loadActualRequest(); | 273 loadActualRequest(); |
| 274 } else { | 274 } else { |
| 275 ResourceRequest preflightRequest = createAccessControlPreflightReque
st(*m_actualRequest, securityOrigin()); | 275 ResourceRequest preflightRequest = createAccessControlPreflightReque
st(*m_actualRequest, securityOrigin()); |
| 276 // Create a ResourceLoaderOptions for preflight. | 276 // Create a ResourceLoaderOptions for preflight. |
| 277 ResourceLoaderOptions preflightOptions = *m_actualOptions; | 277 ResourceLoaderOptions preflightOptions = *m_actualOptions; |
| 278 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; | 278 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; |
| 279 loadRequest(preflightRequest, preflightOptions); | 279 loadRequest(preflightRequest, preflightOptions); |
| 280 } | 280 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 } | 419 } |
| 420 | 420 |
| 421 if (m_corsRedirectLimit <= 0) { | 421 if (m_corsRedirectLimit <= 0) { |
| 422 ThreadableLoaderClient* client = m_client; | 422 ThreadableLoaderClient* client = m_client; |
| 423 clear(); | 423 clear(); |
| 424 client->didFailRedirectCheck(); | 424 client->didFailRedirectCheck(); |
| 425 // |this| may be dead here. | 425 // |this| may be dead here. |
| 426 } else if (m_options.crossOriginRequestPolicy == UseAccessControl) { | 426 } else if (m_options.crossOriginRequestPolicy == UseAccessControl) { |
| 427 --m_corsRedirectLimit; | 427 --m_corsRedirectLimit; |
| 428 | 428 |
| 429 InspectorInstrumentation::didReceiveCORSRedirectResponse(m_document.fram
e(), resource->identifier(), m_document.frame()->loader().documentLoader(), redi
rectResponse, 0); | 429 InspectorInstrumentation::didReceiveCORSRedirectResponse(document().fram
e(), resource->identifier(), document().frame()->loader().documentLoader(), redi
rectResponse, 0); |
| 430 | 430 |
| 431 bool allowRedirect = false; | 431 bool allowRedirect = false; |
| 432 String accessControlErrorDescription; | 432 String accessControlErrorDescription; |
| 433 | 433 |
| 434 // Non-simple cross origin requests (both preflight and actual one) are | 434 // Non-simple cross origin requests (both preflight and actual one) are |
| 435 // not allowed to follow redirect. | 435 // not allowed to follow redirect. |
| 436 if (m_crossOriginNonSimpleRequest) { | 436 if (m_crossOriginNonSimpleRequest) { |
| 437 accessControlErrorDescription = "The request was redirected to '"+ r
equest.url().string() + "', which is disallowed for cross-origin requests that r
equire preflight."; | 437 accessControlErrorDescription = "The request was redirected to '"+ r
equest.url().string() + "', which is disallowed for cross-origin requests that r
equire preflight."; |
| 438 } else { | 438 } else { |
| 439 // The redirect response must pass the access control check if the | 439 // The redirect response must pass the access control check if the |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 handlePreflightFailure(response.url().string(), accessControlErrorDescri
ption); | 554 handlePreflightFailure(response.url().string(), accessControlErrorDescri
ption); |
| 555 // |this| may be dead here in async mode. | 555 // |this| may be dead here in async mode. |
| 556 return; | 556 return; |
| 557 } | 557 } |
| 558 | 558 |
| 559 CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toSt
ring(), m_actualRequest->url(), preflightResult.release()); | 559 CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toSt
ring(), m_actualRequest->url(), preflightResult.release()); |
| 560 } | 560 } |
| 561 | 561 |
| 562 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier,
const ResourceResponse& response) | 562 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier,
const ResourceResponse& response) |
| 563 { | 563 { |
| 564 DocumentLoader* loader = m_document.frame()->loader().documentLoader(); | 564 LocalFrame* frame = document().frame(); |
| 565 TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceReceiveResponse", TRACE_E
VENT_SCOPE_THREAD, "data", InspectorReceiveResponseEvent::data(identifier, m_doc
ument.frame(), response)); | 565 DocumentLoader* loader = frame->loader().documentLoader(); |
| 566 LocalFrame* frame = m_document.frame(); | 566 TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceReceiveResponse", TRACE_E
VENT_SCOPE_THREAD, "data", InspectorReceiveResponseEvent::data(identifier, frame
, response)); |
| 567 InspectorInstrumentation::didReceiveResourceResponse(frame, identifier, load
er, response, resource() ? resource()->loader() : 0); | 567 InspectorInstrumentation::didReceiveResourceResponse(frame, identifier, load
er, response, resource() ? resource()->loader() : 0); |
| 568 frame->console().reportResourceResponseReceived(loader, identifier, response
); | 568 frame->console().reportResourceResponseReceived(loader, identifier, response
); |
| 569 } | 569 } |
| 570 | 570 |
| 571 void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re
sourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) | 571 void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re
sourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) |
| 572 { | 572 { |
| 573 ASSERT(m_client); | 573 ASSERT(m_client); |
| 574 | 574 |
| 575 if (m_actualRequest) { | 575 if (m_actualRequest) { |
| 576 reportResponseReceived(identifier, response); | 576 reportResponseReceived(identifier, response); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 resourceLoaderOptions.dataBufferingPolicy = BufferData; | 780 resourceLoaderOptions.dataBufferingPolicy = BufferData; |
| 781 | 781 |
| 782 if (m_options.timeoutMilliseconds > 0) | 782 if (m_options.timeoutMilliseconds > 0) |
| 783 m_timeoutTimer.startOneShot(m_options.timeoutMilliseconds / 1000.0,
BLINK_FROM_HERE); | 783 m_timeoutTimer.startOneShot(m_options.timeoutMilliseconds / 1000.0,
BLINK_FROM_HERE); |
| 784 | 784 |
| 785 FetchRequest newRequest(request, m_options.initiator, resourceLoaderOpti
ons); | 785 FetchRequest newRequest(request, m_options.initiator, resourceLoaderOpti
ons); |
| 786 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) | 786 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) |
| 787 newRequest.setOriginRestriction(FetchRequest::NoOriginRestriction); | 787 newRequest.setOriginRestriction(FetchRequest::NoOriginRestriction); |
| 788 ASSERT(!resource()); | 788 ASSERT(!resource()); |
| 789 if (request.requestContext() == WebURLRequest::RequestContextVideo || re
quest.requestContext() == WebURLRequest::RequestContextAudio) | 789 if (request.requestContext() == WebURLRequest::RequestContextVideo || re
quest.requestContext() == WebURLRequest::RequestContextAudio) |
| 790 setResource(RawResource::fetchMedia(newRequest, m_document.fetcher()
)); | 790 setResource(RawResource::fetchMedia(newRequest, document().fetcher()
)); |
| 791 else | 791 else |
| 792 setResource(RawResource::fetch(newRequest, m_document.fetcher())); | 792 setResource(RawResource::fetch(newRequest, document().fetcher())); |
| 793 if (resource() && resource()->loader()) { | 793 if (resource() && resource()->loader()) { |
| 794 unsigned long identifier = resource()->identifier(); | 794 unsigned long identifier = resource()->identifier(); |
| 795 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForC
lient(&m_document, identifier, m_client); | 795 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForC
lient(m_document, identifier, m_client); |
| 796 } | 796 } |
| 797 return; | 797 return; |
| 798 } | 798 } |
| 799 | 799 |
| 800 FetchRequest fetchRequest(request, m_options.initiator, resourceLoaderOption
s); | 800 FetchRequest fetchRequest(request, m_options.initiator, resourceLoaderOption
s); |
| 801 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) | 801 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) |
| 802 fetchRequest.setOriginRestriction(FetchRequest::NoOriginRestriction); | 802 fetchRequest.setOriginRestriction(FetchRequest::NoOriginRestriction); |
| 803 ResourcePtr<Resource> resource = RawResource::fetchSynchronously(fetchReques
t, m_document.fetcher()); | 803 ResourcePtr<Resource> resource = RawResource::fetchSynchronously(fetchReques
t, document().fetcher()); |
| 804 ResourceResponse response = resource ? resource->response() : ResourceRespon
se(); | 804 ResourceResponse response = resource ? resource->response() : ResourceRespon
se(); |
| 805 unsigned long identifier = resource ? resource->identifier() : std::numeric_
limits<unsigned long>::max(); | 805 unsigned long identifier = resource ? resource->identifier() : std::numeric_
limits<unsigned long>::max(); |
| 806 ResourceError error = resource ? resource->resourceError() : ResourceError()
; | 806 ResourceError error = resource ? resource->resourceError() : ResourceError()
; |
| 807 | 807 |
| 808 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(&m
_document, identifier, m_client); | 808 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(m_
document, identifier, m_client); |
| 809 | 809 |
| 810 if (!resource) { | 810 if (!resource) { |
| 811 m_client->didFail(error); | 811 m_client->didFail(error); |
| 812 return; | 812 return; |
| 813 } | 813 } |
| 814 | 814 |
| 815 // No exception for file:/// resources, see <rdar://problem/4962298>. | 815 // No exception for file:/// resources, see <rdar://problem/4962298>. |
| 816 // Also, if we have an HTTP response, then it wasn't a network error in fact
. | 816 // Also, if we have an HTTP response, then it wasn't a network error in fact
. |
| 817 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode(
) <= 0) { | 817 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode(
) <= 0) { |
| 818 m_client->didFail(error); | 818 m_client->didFail(error); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) | 854 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) |
| 855 return true; | 855 return true; |
| 856 | 856 |
| 857 return m_sameOriginRequest && securityOrigin()->canRequest(url); | 857 return m_sameOriginRequest && securityOrigin()->canRequest(url); |
| 858 } | 858 } |
| 859 | 859 |
| 860 bool DocumentThreadableLoader::isAllowedByContentSecurityPolicy(const KURL& url,
ContentSecurityPolicy::RedirectStatus redirectStatus) const | 860 bool DocumentThreadableLoader::isAllowedByContentSecurityPolicy(const KURL& url,
ContentSecurityPolicy::RedirectStatus redirectStatus) const |
| 861 { | 861 { |
| 862 if (m_options.contentSecurityPolicyEnforcement != EnforceConnectSrcDirective
) | 862 if (m_options.contentSecurityPolicyEnforcement != EnforceConnectSrcDirective
) |
| 863 return true; | 863 return true; |
| 864 return m_document.contentSecurityPolicy()->allowConnectToSource(url, redirec
tStatus); | 864 return document().contentSecurityPolicy()->allowConnectToSource(url, redirec
tStatus); |
| 865 } | 865 } |
| 866 | 866 |
| 867 StoredCredentials DocumentThreadableLoader::effectiveAllowCredentials() const | 867 StoredCredentials DocumentThreadableLoader::effectiveAllowCredentials() const |
| 868 { | 868 { |
| 869 if (m_forceDoNotAllowStoredCredentials) | 869 if (m_forceDoNotAllowStoredCredentials) |
| 870 return DoNotAllowStoredCredentials; | 870 return DoNotAllowStoredCredentials; |
| 871 return m_resourceLoaderOptions.allowCredentials; | 871 return m_resourceLoaderOptions.allowCredentials; |
| 872 } | 872 } |
| 873 | 873 |
| 874 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const | 874 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const |
| 875 { | 875 { |
| 876 return m_securityOrigin ? m_securityOrigin.get() : m_document.securityOrigin
(); | 876 return m_securityOrigin ? m_securityOrigin.get() : document().securityOrigin
(); |
| 877 } |
| 878 |
| 879 Document& DocumentThreadableLoader::document() const |
| 880 { |
| 881 ASSERT(m_document); |
| 882 return *m_document; |
| 877 } | 883 } |
| 878 | 884 |
| 879 } // namespace blink | 885 } // namespace blink |
| OLD | NEW |