Make USB permissions work in the new permission message system
[chromium-blink-merge.git] / content / child / web_url_loader_impl.cc
blob06b60b8c7c509f053cd2ebc90227ad79ce09a56f
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/child/web_url_loader_impl.h"
7 #include <algorithm>
8 #include <string>
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_util.h"
17 #include "base/time/time.h"
18 #include "components/mime_util/mime_util.h"
19 #include "content/child/child_thread_impl.h"
20 #include "content/child/ftp_directory_listing_response_delegate.h"
21 #include "content/child/multipart_response_delegate.h"
22 #include "content/child/request_extra_data.h"
23 #include "content/child/request_info.h"
24 #include "content/child/resource_dispatcher.h"
25 #include "content/child/shared_memory_data_consumer_handle.h"
26 #include "content/child/sync_load_response.h"
27 #include "content/child/web_url_request_util.h"
28 #include "content/child/weburlresponse_extradata_impl.h"
29 #include "content/common/resource_messages.h"
30 #include "content/common/resource_request_body.h"
31 #include "content/common/service_worker/service_worker_types.h"
32 #include "content/common/ssl_status_serialization.h"
33 #include "content/public/child/fixed_received_data.h"
34 #include "content/public/child/request_peer.h"
35 #include "content/public/common/content_switches.h"
36 #include "net/base/data_url.h"
37 #include "net/base/filename_util.h"
38 #include "net/base/net_errors.h"
39 #include "net/http/http_response_headers.h"
40 #include "net/http/http_util.h"
41 #include "net/ssl/ssl_cipher_suite_names.h"
42 #include "net/ssl/ssl_connection_status_flags.h"
43 #include "net/url_request/redirect_info.h"
44 #include "net/url_request/url_request_data_job.h"
45 #include "third_party/WebKit/public/platform/WebHTTPLoadInfo.h"
46 #include "third_party/WebKit/public/platform/WebURL.h"
47 #include "third_party/WebKit/public/platform/WebURLError.h"
48 #include "third_party/WebKit/public/platform/WebURLLoadTiming.h"
49 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
50 #include "third_party/WebKit/public/platform/WebURLRequest.h"
51 #include "third_party/WebKit/public/platform/WebURLResponse.h"
52 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
54 using base::Time;
55 using base::TimeTicks;
56 using blink::WebData;
57 using blink::WebHTTPBody;
58 using blink::WebHTTPHeaderVisitor;
59 using blink::WebHTTPLoadInfo;
60 using blink::WebReferrerPolicy;
61 using blink::WebSecurityPolicy;
62 using blink::WebString;
63 using blink::WebURL;
64 using blink::WebURLError;
65 using blink::WebURLLoadTiming;
66 using blink::WebURLLoader;
67 using blink::WebURLLoaderClient;
68 using blink::WebURLRequest;
69 using blink::WebURLResponse;
71 namespace content {
73 // Utilities ------------------------------------------------------------------
75 namespace {
77 using HeadersVector = ResourceDevToolsInfo::HeadersVector;
79 // Converts timing data from |load_timing| to the format used by WebKit.
80 void PopulateURLLoadTiming(const net::LoadTimingInfo& load_timing,
81 WebURLLoadTiming* url_timing) {
82 DCHECK(!load_timing.request_start.is_null());
84 const TimeTicks kNullTicks;
85 url_timing->initialize();
86 url_timing->setRequestTime(
87 (load_timing.request_start - kNullTicks).InSecondsF());
88 url_timing->setProxyStart(
89 (load_timing.proxy_resolve_start - kNullTicks).InSecondsF());
90 url_timing->setProxyEnd(
91 (load_timing.proxy_resolve_end - kNullTicks).InSecondsF());
92 url_timing->setDNSStart(
93 (load_timing.connect_timing.dns_start - kNullTicks).InSecondsF());
94 url_timing->setDNSEnd(
95 (load_timing.connect_timing.dns_end - kNullTicks).InSecondsF());
96 url_timing->setConnectStart(
97 (load_timing.connect_timing.connect_start - kNullTicks).InSecondsF());
98 url_timing->setConnectEnd(
99 (load_timing.connect_timing.connect_end - kNullTicks).InSecondsF());
100 url_timing->setSSLStart(
101 (load_timing.connect_timing.ssl_start - kNullTicks).InSecondsF());
102 url_timing->setSSLEnd(
103 (load_timing.connect_timing.ssl_end - kNullTicks).InSecondsF());
104 url_timing->setSendStart(
105 (load_timing.send_start - kNullTicks).InSecondsF());
106 url_timing->setSendEnd(
107 (load_timing.send_end - kNullTicks).InSecondsF());
108 url_timing->setReceiveHeadersEnd(
109 (load_timing.receive_headers_end - kNullTicks).InSecondsF());
112 net::RequestPriority ConvertWebKitPriorityToNetPriority(
113 const WebURLRequest::Priority& priority) {
114 switch (priority) {
115 case WebURLRequest::PriorityVeryHigh:
116 return net::HIGHEST;
118 case WebURLRequest::PriorityHigh:
119 return net::MEDIUM;
121 case WebURLRequest::PriorityMedium:
122 return net::LOW;
124 case WebURLRequest::PriorityLow:
125 return net::LOWEST;
127 case WebURLRequest::PriorityVeryLow:
128 return net::IDLE;
130 case WebURLRequest::PriorityUnresolved:
131 default:
132 NOTREACHED();
133 return net::LOW;
137 // Extracts info from a data scheme URL |url| into |info| and |data|. Returns
138 // net::OK if successful. Returns a net error code otherwise.
139 int GetInfoFromDataURL(const GURL& url,
140 ResourceResponseInfo* info,
141 std::string* data) {
142 // Assure same time for all time fields of data: URLs.
143 Time now = Time::Now();
144 info->load_timing.request_start = TimeTicks::Now();
145 info->load_timing.request_start_time = now;
146 info->request_time = now;
147 info->response_time = now;
149 std::string mime_type;
150 std::string charset;
151 scoped_refptr<net::HttpResponseHeaders> headers(
152 new net::HttpResponseHeaders(std::string()));
153 int result = net::URLRequestDataJob::BuildResponse(
154 url, &mime_type, &charset, data, headers.get());
155 if (result != net::OK)
156 return result;
158 info->headers = headers;
159 info->mime_type.swap(mime_type);
160 info->charset.swap(charset);
161 info->security_info.clear();
162 info->content_length = data->length();
163 info->encoded_data_length = 0;
165 return net::OK;
168 #define STATIC_ASSERT_MATCHING_ENUMS(content_name, blink_name) \
169 static_assert( \
170 static_cast<int>(content_name) == static_cast<int>(blink_name), \
171 "mismatching enums: " #content_name)
173 STATIC_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_SAME_ORIGIN,
174 WebURLRequest::FetchRequestModeSameOrigin);
175 STATIC_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_NO_CORS,
176 WebURLRequest::FetchRequestModeNoCORS);
177 STATIC_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_CORS,
178 WebURLRequest::FetchRequestModeCORS);
179 STATIC_ASSERT_MATCHING_ENUMS(
180 FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT,
181 WebURLRequest::FetchRequestModeCORSWithForcedPreflight);
183 FetchRequestMode GetFetchRequestMode(const WebURLRequest& request) {
184 return static_cast<FetchRequestMode>(request.fetchRequestMode());
187 STATIC_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_OMIT,
188 WebURLRequest::FetchCredentialsModeOmit);
189 STATIC_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_SAME_ORIGIN,
190 WebURLRequest::FetchCredentialsModeSameOrigin);
191 STATIC_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_INCLUDE,
192 WebURLRequest::FetchCredentialsModeInclude);
194 FetchCredentialsMode GetFetchCredentialsMode(const WebURLRequest& request) {
195 return static_cast<FetchCredentialsMode>(request.fetchCredentialsMode());
198 STATIC_ASSERT_MATCHING_ENUMS(FetchRedirectMode::FOLLOW_MODE,
199 WebURLRequest::FetchRedirectModeFollow);
200 STATIC_ASSERT_MATCHING_ENUMS(FetchRedirectMode::ERROR_MODE,
201 WebURLRequest::FetchRedirectModeError);
202 STATIC_ASSERT_MATCHING_ENUMS(FetchRedirectMode::MANUAL_MODE,
203 WebURLRequest::FetchRedirectModeManual);
205 FetchRedirectMode GetFetchRedirectMode(const WebURLRequest& request) {
206 return static_cast<FetchRedirectMode>(request.fetchRedirectMode());
209 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY,
210 WebURLRequest::FrameTypeAuxiliary);
211 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_NESTED,
212 WebURLRequest::FrameTypeNested);
213 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_NONE,
214 WebURLRequest::FrameTypeNone);
215 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
216 WebURLRequest::FrameTypeTopLevel);
218 RequestContextFrameType GetRequestContextFrameType(
219 const WebURLRequest& request) {
220 return static_cast<RequestContextFrameType>(request.frameType());
223 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_UNSPECIFIED,
224 WebURLRequest::RequestContextUnspecified);
225 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_AUDIO,
226 WebURLRequest::RequestContextAudio);
227 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_BEACON,
228 WebURLRequest::RequestContextBeacon);
229 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_CSP_REPORT,
230 WebURLRequest::RequestContextCSPReport);
231 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_DOWNLOAD,
232 WebURLRequest::RequestContextDownload);
233 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_EMBED,
234 WebURLRequest::RequestContextEmbed);
235 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_EVENT_SOURCE,
236 WebURLRequest::RequestContextEventSource);
237 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FAVICON,
238 WebURLRequest::RequestContextFavicon);
239 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FETCH,
240 WebURLRequest::RequestContextFetch);
241 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FONT,
242 WebURLRequest::RequestContextFont);
243 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FORM,
244 WebURLRequest::RequestContextForm);
245 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FRAME,
246 WebURLRequest::RequestContextFrame);
247 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_HYPERLINK,
248 WebURLRequest::RequestContextHyperlink);
249 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IFRAME,
250 WebURLRequest::RequestContextIframe);
251 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMAGE,
252 WebURLRequest::RequestContextImage);
253 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMAGE_SET,
254 WebURLRequest::RequestContextImageSet);
255 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMPORT,
256 WebURLRequest::RequestContextImport);
257 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_INTERNAL,
258 WebURLRequest::RequestContextInternal);
259 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_LOCATION,
260 WebURLRequest::RequestContextLocation);
261 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_MANIFEST,
262 WebURLRequest::RequestContextManifest);
263 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_OBJECT,
264 WebURLRequest::RequestContextObject);
265 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PING,
266 WebURLRequest::RequestContextPing);
267 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PLUGIN,
268 WebURLRequest::RequestContextPlugin);
269 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PREFETCH,
270 WebURLRequest::RequestContextPrefetch);
271 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SCRIPT,
272 WebURLRequest::RequestContextScript);
273 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
274 WebURLRequest::RequestContextServiceWorker);
275 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SHARED_WORKER,
276 WebURLRequest::RequestContextSharedWorker);
277 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SUBRESOURCE,
278 WebURLRequest::RequestContextSubresource);
279 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_STYLE,
280 WebURLRequest::RequestContextStyle);
281 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_TRACK,
282 WebURLRequest::RequestContextTrack);
283 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_VIDEO,
284 WebURLRequest::RequestContextVideo);
285 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_WORKER,
286 WebURLRequest::RequestContextWorker);
287 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_XML_HTTP_REQUEST,
288 WebURLRequest::RequestContextXMLHttpRequest);
289 STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_XSLT,
290 WebURLRequest::RequestContextXSLT);
292 RequestContextType GetRequestContextType(const WebURLRequest& request) {
293 return static_cast<RequestContextType>(request.requestContext());
296 void SetSecurityStyleAndDetails(const GURL& url,
297 const std::string& security_info,
298 WebURLResponse* response,
299 bool report_security_info) {
300 if (!report_security_info) {
301 response->setSecurityStyle(WebURLResponse::SecurityStyleUnknown);
302 return;
304 if (!url.SchemeIsCryptographic()) {
305 response->setSecurityStyle(WebURLResponse::SecurityStyleUnauthenticated);
306 return;
309 // There are cases where an HTTPS request can come in without security
310 // info attached (such as a redirect response).
311 if (security_info.empty()) {
312 response->setSecurityStyle(WebURLResponse::SecurityStyleUnknown);
313 return;
316 SSLStatus ssl_status;
317 if (!DeserializeSecurityInfo(security_info, &ssl_status)) {
318 response->setSecurityStyle(WebURLResponse::SecurityStyleUnknown);
319 DLOG(ERROR)
320 << "DeserializeSecurityInfo() failed for an authenticated request.";
321 return;
324 int ssl_version =
325 net::SSLConnectionStatusToVersion(ssl_status.connection_status);
326 const char* protocol;
327 net::SSLVersionToString(&protocol, ssl_version);
329 const char* key_exchange;
330 const char* cipher;
331 const char* mac;
332 bool is_aead;
333 uint16_t cipher_suite =
334 net::SSLConnectionStatusToCipherSuite(ssl_status.connection_status);
335 net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead,
336 cipher_suite);
337 if (mac == NULL) {
338 DCHECK(is_aead);
339 mac = "";
342 blink::WebURLResponse::SecurityStyle securityStyle =
343 WebURLResponse::SecurityStyleUnknown;
344 switch (ssl_status.security_style) {
345 case SECURITY_STYLE_UNKNOWN:
346 securityStyle = WebURLResponse::SecurityStyleUnknown;
347 break;
348 case SECURITY_STYLE_UNAUTHENTICATED:
349 securityStyle = WebURLResponse::SecurityStyleUnauthenticated;
350 break;
351 case SECURITY_STYLE_AUTHENTICATION_BROKEN:
352 securityStyle = WebURLResponse::SecurityStyleAuthenticationBroken;
353 break;
354 case SECURITY_STYLE_WARNING:
355 securityStyle = WebURLResponse::SecurityStyleWarning;
356 break;
357 case SECURITY_STYLE_AUTHENTICATED:
358 securityStyle = WebURLResponse::SecurityStyleAuthenticated;
359 break;
362 response->setSecurityStyle(securityStyle);
364 blink::WebString protocol_string = blink::WebString::fromUTF8(protocol);
365 blink::WebString cipher_string = blink::WebString::fromUTF8(cipher);
366 blink::WebString key_exchange_string =
367 blink::WebString::fromUTF8(key_exchange);
368 blink::WebString mac_string = blink::WebString::fromUTF8(mac);
369 response->setSecurityDetails(protocol_string, cipher_string,
370 key_exchange_string, mac_string,
371 ssl_status.cert_id);
374 } // namespace
376 // WebURLLoaderImpl::Context --------------------------------------------------
378 // This inner class exists since the WebURLLoader may be deleted while inside a
379 // call to WebURLLoaderClient. Refcounting is to keep the context from being
380 // deleted if it may have work to do after calling into the client.
381 class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
382 public RequestPeer {
383 public:
384 Context(WebURLLoaderImpl* loader,
385 ResourceDispatcher* resource_dispatcher,
386 scoped_refptr<base::SingleThreadTaskRunner> task_runner);
388 WebURLLoaderClient* client() const { return client_; }
389 void set_client(WebURLLoaderClient* client) { client_ = client; }
391 void Cancel();
392 void SetDefersLoading(bool value);
393 void DidChangePriority(WebURLRequest::Priority new_priority,
394 int intra_priority_value);
395 bool AttachThreadedDataReceiver(
396 blink::WebThreadedDataReceiver* threaded_data_receiver);
397 void Start(const WebURLRequest& request,
398 SyncLoadResponse* sync_load_response);
400 // RequestPeer methods:
401 void OnUploadProgress(uint64 position, uint64 size) override;
402 bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
403 const ResourceResponseInfo& info) override;
404 void OnReceivedResponse(const ResourceResponseInfo& info) override;
405 void OnDownloadedData(int len, int encoded_data_length) override;
406 void OnReceivedData(scoped_ptr<ReceivedData> data) override;
407 void OnReceivedCachedMetadata(const char* data, int len) override;
408 void OnCompletedRequest(int error_code,
409 bool was_ignored_by_handler,
410 bool stale_copy_in_cache,
411 const std::string& security_info,
412 const base::TimeTicks& completion_time,
413 int64 total_transfer_size) override;
414 void OnReceivedCompletedResponse(const ResourceResponseInfo& info,
415 scoped_ptr<ReceivedData> data,
416 int error_code,
417 bool was_ignored_by_handler,
418 bool stale_copy_in_cache,
419 const std::string& security_info,
420 const base::TimeTicks& completion_time,
421 int64 total_transfer_size) override;
423 private:
424 friend class base::RefCounted<Context>;
425 ~Context() override;
427 // Called when the body data stream is detached from the reader side.
428 void CancelBodyStreaming();
429 // We can optimize the handling of data URLs in most cases.
430 bool CanHandleDataURLRequestLocally() const;
431 void HandleDataURL();
433 WebURLLoaderImpl* loader_;
434 WebURLRequest request_;
435 WebURLLoaderClient* client_;
436 ResourceDispatcher* resource_dispatcher_;
437 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
438 WebReferrerPolicy referrer_policy_;
439 scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
440 scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
441 scoped_ptr<StreamOverrideParameters> stream_override_;
442 scoped_ptr<SharedMemoryDataConsumerHandle::Writer> body_stream_writer_;
443 enum DeferState {NOT_DEFERRING, SHOULD_DEFER, DEFERRED_DATA};
444 DeferState defers_loading_;
445 int request_id_;
448 WebURLLoaderImpl::Context::Context(
449 WebURLLoaderImpl* loader,
450 ResourceDispatcher* resource_dispatcher,
451 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
452 : loader_(loader),
453 client_(NULL),
454 resource_dispatcher_(resource_dispatcher),
455 task_runner_(task_runner),
456 referrer_policy_(blink::WebReferrerPolicyDefault),
457 defers_loading_(NOT_DEFERRING),
458 request_id_(-1) {
461 void WebURLLoaderImpl::Context::Cancel() {
462 if (resource_dispatcher_ && // NULL in unittest.
463 request_id_ != -1) {
464 resource_dispatcher_->Cancel(request_id_);
465 request_id_ = -1;
468 if (body_stream_writer_)
469 body_stream_writer_->Fail();
471 // Ensure that we do not notify the multipart delegate anymore as it has
472 // its own pointer to the client.
473 if (multipart_delegate_)
474 multipart_delegate_->Cancel();
475 // Ditto for the ftp delegate.
476 if (ftp_listing_delegate_)
477 ftp_listing_delegate_->Cancel();
479 // Do not make any further calls to the client.
480 client_ = NULL;
481 loader_ = NULL;
484 void WebURLLoaderImpl::Context::SetDefersLoading(bool value) {
485 if (request_id_ != -1)
486 resource_dispatcher_->SetDefersLoading(request_id_, value);
487 if (value && defers_loading_ == NOT_DEFERRING) {
488 defers_loading_ = SHOULD_DEFER;
489 } else if (!value && defers_loading_ != NOT_DEFERRING) {
490 if (defers_loading_ == DEFERRED_DATA) {
491 task_runner_->PostTask(FROM_HERE,
492 base::Bind(&Context::HandleDataURL, this));
494 defers_loading_ = NOT_DEFERRING;
498 void WebURLLoaderImpl::Context::DidChangePriority(
499 WebURLRequest::Priority new_priority, int intra_priority_value) {
500 if (request_id_ != -1) {
501 resource_dispatcher_->DidChangePriority(
502 request_id_,
503 ConvertWebKitPriorityToNetPriority(new_priority),
504 intra_priority_value);
508 bool WebURLLoaderImpl::Context::AttachThreadedDataReceiver(
509 blink::WebThreadedDataReceiver* threaded_data_receiver) {
510 if (request_id_ != -1) {
511 return resource_dispatcher_->AttachThreadedDataReceiver(
512 request_id_, threaded_data_receiver);
515 return false;
518 void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
519 SyncLoadResponse* sync_load_response) {
520 DCHECK(request_id_ == -1);
521 request_ = request; // Save the request.
522 if (request.extraData()) {
523 RequestExtraData* extra_data =
524 static_cast<RequestExtraData*>(request.extraData());
525 stream_override_ = extra_data->TakeStreamOverrideOwnership();
528 GURL url = request.url();
530 // PlzNavigate: during navigation, the renderer should request a stream which
531 // contains the body of the response. The request has already been made by the
532 // browser.
533 if (stream_override_.get()) {
534 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
535 switches::kEnableBrowserSideNavigation));
536 DCHECK(!sync_load_response);
537 DCHECK_NE(WebURLRequest::FrameTypeNone, request.frameType());
538 DCHECK_EQ("GET", request.httpMethod().latin1());
539 url = stream_override_->stream_url;
542 if (CanHandleDataURLRequestLocally()) {
543 if (sync_load_response) {
544 // This is a sync load. Do the work now.
545 sync_load_response->url = url;
546 sync_load_response->error_code =
547 GetInfoFromDataURL(sync_load_response->url, sync_load_response,
548 &sync_load_response->data);
549 } else {
550 task_runner_->PostTask(FROM_HERE,
551 base::Bind(&Context::HandleDataURL, this));
553 return;
556 // PlzNavigate: outside of tests, the only navigation requests going through
557 // the WebURLLoader are the ones created by CommitNavigation. Several browser
558 // tests load HTML directly through a data url which will be handled by the
559 // block above.
560 DCHECK_IMPLIES(base::CommandLine::ForCurrentProcess()->HasSwitch(
561 switches::kEnableBrowserSideNavigation),
562 stream_override_.get() ||
563 request.frameType() == WebURLRequest::FrameTypeNone);
565 GURL referrer_url(
566 request.httpHeaderField(WebString::fromUTF8("Referer")).latin1());
567 const std::string& method = request.httpMethod().latin1();
569 // TODO(brettw) this should take parameter encoding into account when
570 // creating the GURLs.
572 // TODO(horo): Check credentials flag is unset when credentials mode is omit.
573 // Check credentials flag is set when credentials mode is include.
575 RequestInfo request_info;
576 request_info.method = method;
577 request_info.url = url;
578 request_info.first_party_for_cookies = request.firstPartyForCookies();
579 referrer_policy_ = request.referrerPolicy();
580 request_info.referrer = Referrer(referrer_url, referrer_policy_);
581 request_info.headers = GetWebURLRequestHeaders(request);
582 request_info.load_flags = GetLoadFlagsForWebURLRequest(request);
583 request_info.enable_load_timing = true;
584 request_info.enable_upload_progress = request.reportUploadProgress();
585 if (request.requestContext() == WebURLRequest::RequestContextXMLHttpRequest &&
586 (url.has_username() || url.has_password())) {
587 request_info.do_not_prompt_for_login = true;
589 // requestor_pid only needs to be non-zero if the request originates outside
590 // the render process, so we can use requestorProcessID even for requests
591 // from in-process plugins.
592 request_info.requestor_pid = request.requestorProcessID();
593 request_info.request_type = WebURLRequestToResourceType(request);
594 request_info.priority =
595 ConvertWebKitPriorityToNetPriority(request.priority());
596 request_info.appcache_host_id = request.appCacheHostID();
597 request_info.routing_id = request.requestorID();
598 request_info.download_to_file = request.downloadToFile();
599 request_info.has_user_gesture = request.hasUserGesture();
600 request_info.skip_service_worker = request.skipServiceWorker();
601 request_info.should_reset_appcache = request.shouldResetAppCache();
602 request_info.fetch_request_mode = GetFetchRequestMode(request);
603 request_info.fetch_credentials_mode = GetFetchCredentialsMode(request);
604 request_info.fetch_redirect_mode = GetFetchRedirectMode(request);
605 request_info.fetch_request_context_type = GetRequestContextType(request);
606 request_info.fetch_frame_type = GetRequestContextFrameType(request);
607 request_info.extra_data = request.extraData();
609 scoped_refptr<ResourceRequestBody> request_body =
610 GetRequestBodyForWebURLRequest(request).get();
612 if (sync_load_response) {
613 resource_dispatcher_->StartSync(
614 request_info, request_body.get(), sync_load_response);
615 return;
618 request_id_ = resource_dispatcher_->StartAsync(
619 request_info, request_body.get(), this);
622 void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
623 if (client_)
624 client_->didSendData(loader_, position, size);
627 bool WebURLLoaderImpl::Context::OnReceivedRedirect(
628 const net::RedirectInfo& redirect_info,
629 const ResourceResponseInfo& info) {
630 if (!client_)
631 return false;
633 WebURLResponse response;
634 response.initialize();
635 PopulateURLResponse(request_.url(), info, &response,
636 request_.reportRawHeaders());
638 // TODO(darin): We lack sufficient information to construct the actual
639 // request that resulted from the redirect.
640 WebURLRequest new_request(redirect_info.new_url);
641 new_request.setFirstPartyForCookies(
642 redirect_info.new_first_party_for_cookies);
643 new_request.setDownloadToFile(request_.downloadToFile());
644 new_request.setUseStreamOnResponse(request_.useStreamOnResponse());
645 new_request.setRequestContext(request_.requestContext());
646 new_request.setFrameType(request_.frameType());
647 new_request.setSkipServiceWorker(!info.was_fetched_via_service_worker);
648 new_request.setShouldResetAppCache(request_.shouldResetAppCache());
649 new_request.setFetchRequestMode(request_.fetchRequestMode());
650 new_request.setFetchCredentialsMode(request_.fetchCredentialsMode());
652 new_request.setHTTPReferrer(WebString::fromUTF8(redirect_info.new_referrer),
653 referrer_policy_);
655 std::string old_method = request_.httpMethod().utf8();
656 new_request.setHTTPMethod(WebString::fromUTF8(redirect_info.new_method));
657 if (redirect_info.new_method == old_method)
658 new_request.setHTTPBody(request_.httpBody());
660 // Protect from deletion during call to willSendRequest.
661 scoped_refptr<Context> protect(this);
663 client_->willSendRequest(loader_, new_request, response);
664 request_ = new_request;
666 // Only follow the redirect if WebKit left the URL unmodified.
667 if (redirect_info.new_url == GURL(new_request.url())) {
668 // First-party cookie logic moved from DocumentLoader in Blink to
669 // net::URLRequest in the browser. Assert that Blink didn't try to change it
670 // to something else.
671 DCHECK_EQ(redirect_info.new_first_party_for_cookies.spec(),
672 request_.firstPartyForCookies().string().utf8());
673 return true;
676 // We assume that WebKit only changes the URL to suppress a redirect, and we
677 // assume that it does so by setting it to be invalid.
678 DCHECK(!new_request.url().isValid());
679 return false;
682 void WebURLLoaderImpl::Context::OnReceivedResponse(
683 const ResourceResponseInfo& initial_info) {
684 if (!client_)
685 return;
687 ResourceResponseInfo info = initial_info;
689 // PlzNavigate: during navigations, the ResourceResponse has already been
690 // received on the browser side, and has been passed down to the renderer.
691 if (stream_override_.get()) {
692 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
693 switches::kEnableBrowserSideNavigation));
694 info = stream_override_->response;
697 WebURLResponse response;
698 response.initialize();
699 PopulateURLResponse(request_.url(), info, &response,
700 request_.reportRawHeaders());
702 bool show_raw_listing = (GURL(request_.url()).query() == "raw");
704 if (info.mime_type == "text/vnd.chromium.ftp-dir") {
705 if (show_raw_listing) {
706 // Set the MIME type to plain text to prevent any active content.
707 response.setMIMEType("text/plain");
708 } else {
709 // We're going to produce a parsed listing in HTML.
710 response.setMIMEType("text/html");
714 // Prevent |this| from being destroyed if the client destroys the loader,
715 // ether in didReceiveResponse, or when the multipart/ftp delegate calls into
716 // it.
717 scoped_refptr<Context> protect(this);
719 if (request_.useStreamOnResponse()) {
720 SharedMemoryDataConsumerHandle::BackpressureMode mode =
721 SharedMemoryDataConsumerHandle::kDoNotApplyBackpressure;
722 if (info.headers &&
723 info.headers->HasHeaderValue("Cache-Control", "no-store")) {
724 mode = SharedMemoryDataConsumerHandle::kApplyBackpressure;
727 auto read_handle = make_scoped_ptr(new SharedMemoryDataConsumerHandle(
728 mode, base::Bind(&Context::CancelBodyStreaming, this),
729 &body_stream_writer_));
731 // Here |body_stream_writer_| has an indirect reference to |this| and that
732 // creates a reference cycle, but it is not a problem because the cycle
733 // will break if one of the following happens:
734 // 1) The body data transfer is done (with or without an error).
735 // 2) |read_handle| (and its reader) is detached.
737 // The client takes |read_handle|'s ownership.
738 client_->didReceiveResponse(loader_, response, read_handle.release());
739 // TODO(yhirano): Support ftp listening and multipart
740 return;
741 } else {
742 client_->didReceiveResponse(loader_, response);
745 // We may have been cancelled after didReceiveResponse, which would leave us
746 // without a client and therefore without much need to do further handling.
747 if (!client_)
748 return;
750 DCHECK(!ftp_listing_delegate_.get());
751 DCHECK(!multipart_delegate_.get());
752 if (info.headers.get() && info.mime_type == "multipart/x-mixed-replace") {
753 std::string content_type;
754 info.headers->EnumerateHeader(NULL, "content-type", &content_type);
756 std::string mime_type;
757 std::string charset;
758 bool had_charset = false;
759 std::string boundary;
760 net::HttpUtil::ParseContentType(content_type, &mime_type, &charset,
761 &had_charset, &boundary);
762 base::TrimString(boundary, " \"", &boundary);
764 // If there's no boundary, just handle the request normally. In the gecko
765 // code, nsMultiMixedConv::OnStartRequest throws an exception.
766 if (!boundary.empty()) {
767 multipart_delegate_.reset(
768 new MultipartResponseDelegate(client_, loader_, response, boundary));
770 } else if (info.mime_type == "text/vnd.chromium.ftp-dir" &&
771 !show_raw_listing) {
772 ftp_listing_delegate_.reset(
773 new FtpDirectoryListingResponseDelegate(client_, loader_, response));
777 void WebURLLoaderImpl::Context::OnDownloadedData(int len,
778 int encoded_data_length) {
779 if (client_)
780 client_->didDownloadData(loader_, len, encoded_data_length);
783 void WebURLLoaderImpl::Context::OnReceivedData(scoped_ptr<ReceivedData> data) {
784 const char* payload = data->payload();
785 int data_length = data->length();
786 int encoded_data_length = data->encoded_length();
787 if (!client_)
788 return;
790 if (ftp_listing_delegate_) {
791 // The FTP listing delegate will make the appropriate calls to
792 // client_->didReceiveData and client_->didReceiveResponse. Since the
793 // delegate may want to do work after sending data to the delegate, keep
794 // |this| and the delegate alive until it's finished handling the data.
795 scoped_refptr<Context> protect(this);
796 ftp_listing_delegate_->OnReceivedData(payload, data_length);
797 } else if (multipart_delegate_) {
798 // The multipart delegate will make the appropriate calls to
799 // client_->didReceiveData and client_->didReceiveResponse. Since the
800 // delegate may want to do work after sending data to the delegate, keep
801 // |this| and the delegate alive until it's finished handling the data.
802 scoped_refptr<Context> protect(this);
803 multipart_delegate_->OnReceivedData(payload, data_length,
804 encoded_data_length);
805 } else {
806 scoped_refptr<Context> protect(this);
807 // We dispatch the data even when |useStreamOnResponse()| is set, in order
808 // to make Devtools work.
809 client_->didReceiveData(loader_, payload, data_length, encoded_data_length);
811 if (request_.useStreamOnResponse()) {
812 // We don't support ftp_listening_delegate_ and multipart_delegate_ for
813 // now.
814 // TODO(yhirano): Support ftp listening and multipart.
815 body_stream_writer_->AddData(data.Pass());
820 void WebURLLoaderImpl::Context::OnReceivedCachedMetadata(
821 const char* data, int len) {
822 if (client_)
823 client_->didReceiveCachedMetadata(loader_, data, len);
826 void WebURLLoaderImpl::Context::OnCompletedRequest(
827 int error_code,
828 bool was_ignored_by_handler,
829 bool stale_copy_in_cache,
830 const std::string& security_info,
831 const base::TimeTicks& completion_time,
832 int64 total_transfer_size) {
833 // The WebURLLoaderImpl may be deleted in any of the calls to the client or
834 // the delegates below (As they also may call in to the client). Keep |this|
835 // alive in that case, to avoid a crash. If that happens, the request will be
836 // cancelled and |client_| will be set to NULL.
837 scoped_refptr<Context> protect(this);
839 if (ftp_listing_delegate_) {
840 ftp_listing_delegate_->OnCompletedRequest();
841 ftp_listing_delegate_.reset(NULL);
842 } else if (multipart_delegate_) {
843 multipart_delegate_->OnCompletedRequest();
844 multipart_delegate_.reset(NULL);
847 if (body_stream_writer_ && error_code != net::OK)
848 body_stream_writer_->Fail();
849 body_stream_writer_.reset();
851 if (client_) {
852 if (error_code != net::OK) {
853 client_->didFail(
854 loader_,
855 CreateWebURLError(request_.url(), stale_copy_in_cache, error_code,
856 was_ignored_by_handler));
857 } else {
858 client_->didFinishLoading(loader_,
859 (completion_time - TimeTicks()).InSecondsF(),
860 total_transfer_size);
865 void WebURLLoaderImpl::Context::OnReceivedCompletedResponse(
866 const ResourceResponseInfo& info,
867 scoped_ptr<ReceivedData> data,
868 int error_code,
869 bool was_ignored_by_handler,
870 bool stale_copy_in_cache,
871 const std::string& security_info,
872 const base::TimeTicks& completion_time,
873 int64 total_transfer_size) {
874 scoped_refptr<Context> protect(this);
876 OnReceivedResponse(info);
877 if (data)
878 OnReceivedData(data.Pass());
879 OnCompletedRequest(error_code, was_ignored_by_handler, stale_copy_in_cache,
880 security_info, completion_time, total_transfer_size);
883 WebURLLoaderImpl::Context::~Context() {
884 if (request_id_ >= 0) {
885 resource_dispatcher_->RemovePendingRequest(request_id_);
889 void WebURLLoaderImpl::Context::CancelBodyStreaming() {
890 scoped_refptr<Context> protect(this);
892 // Notify renderer clients that the request is canceled.
893 if (ftp_listing_delegate_) {
894 ftp_listing_delegate_->OnCompletedRequest();
895 ftp_listing_delegate_.reset(NULL);
896 } else if (multipart_delegate_) {
897 multipart_delegate_->OnCompletedRequest();
898 multipart_delegate_.reset(NULL);
901 if (body_stream_writer_) {
902 body_stream_writer_->Fail();
903 body_stream_writer_.reset();
905 if (client_) {
906 // TODO(yhirano): Set |stale_copy_in_cache| appropriately if possible.
907 client_->didFail(
908 loader_, CreateWebURLError(request_.url(), false, net::ERR_ABORTED));
911 // Notify the browser process that the request is canceled.
912 Cancel();
915 bool WebURLLoaderImpl::Context::CanHandleDataURLRequestLocally() const {
916 GURL url = request_.url();
917 if (!url.SchemeIs(url::kDataScheme))
918 return false;
920 // The fast paths for data URL, Start() and HandleDataURL(), don't support
921 // the downloadToFile option.
922 if (request_.downloadToFile())
923 return false;
925 // Data url requests from object tags may need to be intercepted as streams
926 // and so need to be sent to the browser.
927 if (request_.requestContext() == WebURLRequest::RequestContextObject)
928 return false;
930 // Optimize for the case where we can handle a data URL locally. We must
931 // skip this for data URLs targetted at frames since those could trigger a
932 // download.
934 // NOTE: We special case MIME types we can render both for performance
935 // reasons as well as to support unit tests.
937 #if defined(OS_ANDROID)
938 // For compatibility reasons on Android we need to expose top-level data://
939 // to the browser.
940 if (request_.frameType() == WebURLRequest::FrameTypeTopLevel)
941 return false;
942 #endif
944 if (request_.frameType() != WebURLRequest::FrameTypeTopLevel &&
945 request_.frameType() != WebURLRequest::FrameTypeNested)
946 return true;
948 std::string mime_type, unused_charset;
949 if (net::DataURL::Parse(request_.url(), &mime_type, &unused_charset, NULL) &&
950 mime_util::IsSupportedMimeType(mime_type))
951 return true;
953 return false;
956 void WebURLLoaderImpl::Context::HandleDataURL() {
957 DCHECK_NE(defers_loading_, DEFERRED_DATA);
958 if (defers_loading_ == SHOULD_DEFER) {
959 defers_loading_ = DEFERRED_DATA;
960 return;
963 ResourceResponseInfo info;
964 std::string data;
966 int error_code = GetInfoFromDataURL(request_.url(), &info, &data);
968 if (error_code == net::OK) {
969 OnReceivedResponse(info);
970 if (!data.empty())
971 OnReceivedData(
972 make_scoped_ptr(new FixedReceivedData(data.data(), data.size(), 0)));
975 OnCompletedRequest(error_code, false, false, info.security_info,
976 base::TimeTicks::Now(), 0);
979 // WebURLLoaderImpl -----------------------------------------------------------
981 WebURLLoaderImpl::WebURLLoaderImpl(
982 ResourceDispatcher* resource_dispatcher,
983 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
984 : context_(new Context(this, resource_dispatcher, task_runner)) {
987 WebURLLoaderImpl::~WebURLLoaderImpl() {
988 cancel();
991 void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
992 const ResourceResponseInfo& info,
993 WebURLResponse* response,
994 bool report_security_info) {
995 response->setURL(url);
996 response->setResponseTime(info.response_time.ToInternalValue());
997 response->setMIMEType(WebString::fromUTF8(info.mime_type));
998 response->setTextEncodingName(WebString::fromUTF8(info.charset));
999 response->setExpectedContentLength(info.content_length);
1000 response->setSecurityInfo(info.security_info);
1001 response->setAppCacheID(info.appcache_id);
1002 response->setAppCacheManifestURL(info.appcache_manifest_url);
1003 response->setWasCached(!info.load_timing.request_start_time.is_null() &&
1004 info.response_time < info.load_timing.request_start_time);
1005 response->setRemoteIPAddress(
1006 WebString::fromUTF8(info.socket_address.host()));
1007 response->setRemotePort(info.socket_address.port());
1008 response->setConnectionID(info.load_timing.socket_log_id);
1009 response->setConnectionReused(info.load_timing.socket_reused);
1010 response->setDownloadFilePath(info.download_file_path.AsUTF16Unsafe());
1011 response->setWasFetchedViaSPDY(info.was_fetched_via_spdy);
1012 response->setWasFetchedViaServiceWorker(info.was_fetched_via_service_worker);
1013 response->setWasFallbackRequiredByServiceWorker(
1014 info.was_fallback_required_by_service_worker);
1015 response->setServiceWorkerResponseType(info.response_type_via_service_worker);
1016 response->setOriginalURLViaServiceWorker(
1017 info.original_url_via_service_worker);
1019 SetSecurityStyleAndDetails(url, info.security_info, response,
1020 report_security_info);
1022 WebURLResponseExtraDataImpl* extra_data =
1023 new WebURLResponseExtraDataImpl(info.npn_negotiated_protocol);
1024 response->setExtraData(extra_data);
1025 extra_data->set_was_fetched_via_spdy(info.was_fetched_via_spdy);
1026 extra_data->set_was_npn_negotiated(info.was_npn_negotiated);
1027 extra_data->set_was_alternate_protocol_available(
1028 info.was_alternate_protocol_available);
1029 extra_data->set_connection_info(info.connection_info);
1030 extra_data->set_was_fetched_via_proxy(info.was_fetched_via_proxy);
1031 extra_data->set_proxy_server(info.proxy_server);
1033 // If there's no received headers end time, don't set load timing. This is
1034 // the case for non-HTTP requests, requests that don't go over the wire, and
1035 // certain error cases.
1036 if (!info.load_timing.receive_headers_end.is_null()) {
1037 WebURLLoadTiming timing;
1038 PopulateURLLoadTiming(info.load_timing, &timing);
1039 const TimeTicks kNullTicks;
1040 timing.setWorkerStart(
1041 (info.service_worker_start_time - kNullTicks).InSecondsF());
1042 timing.setWorkerReady(
1043 (info.service_worker_ready_time - kNullTicks).InSecondsF());
1044 response->setLoadTiming(timing);
1047 if (info.devtools_info.get()) {
1048 WebHTTPLoadInfo load_info;
1050 load_info.setHTTPStatusCode(info.devtools_info->http_status_code);
1051 load_info.setHTTPStatusText(WebString::fromLatin1(
1052 info.devtools_info->http_status_text));
1053 load_info.setEncodedDataLength(info.encoded_data_length);
1055 load_info.setRequestHeadersText(WebString::fromLatin1(
1056 info.devtools_info->request_headers_text));
1057 load_info.setResponseHeadersText(WebString::fromLatin1(
1058 info.devtools_info->response_headers_text));
1059 const HeadersVector& request_headers = info.devtools_info->request_headers;
1060 for (HeadersVector::const_iterator it = request_headers.begin();
1061 it != request_headers.end(); ++it) {
1062 load_info.addRequestHeader(WebString::fromLatin1(it->first),
1063 WebString::fromLatin1(it->second));
1065 const HeadersVector& response_headers =
1066 info.devtools_info->response_headers;
1067 for (HeadersVector::const_iterator it = response_headers.begin();
1068 it != response_headers.end(); ++it) {
1069 load_info.addResponseHeader(WebString::fromLatin1(it->first),
1070 WebString::fromLatin1(it->second));
1072 load_info.setNPNNegotiatedProtocol(WebString::fromLatin1(
1073 info.npn_negotiated_protocol));
1074 response->setHTTPLoadInfo(load_info);
1077 const net::HttpResponseHeaders* headers = info.headers.get();
1078 if (!headers)
1079 return;
1081 WebURLResponse::HTTPVersion version = WebURLResponse::Unknown;
1082 if (headers->GetHttpVersion() == net::HttpVersion(0, 9))
1083 version = WebURLResponse::HTTP_0_9;
1084 else if (headers->GetHttpVersion() == net::HttpVersion(1, 0))
1085 version = WebURLResponse::HTTP_1_0;
1086 else if (headers->GetHttpVersion() == net::HttpVersion(1, 1))
1087 version = WebURLResponse::HTTP_1_1;
1088 response->setHTTPVersion(version);
1089 response->setHTTPStatusCode(headers->response_code());
1090 response->setHTTPStatusText(WebString::fromLatin1(headers->GetStatusText()));
1092 // TODO(darin): We should leverage HttpResponseHeaders for this, and this
1093 // should be using the same code as ResourceDispatcherHost.
1094 // TODO(jungshik): Figure out the actual value of the referrer charset and
1095 // pass it to GetSuggestedFilename.
1096 std::string value;
1097 headers->EnumerateHeader(NULL, "content-disposition", &value);
1098 response->setSuggestedFileName(
1099 net::GetSuggestedFilename(url,
1100 value,
1101 std::string(), // referrer_charset
1102 std::string(), // suggested_name
1103 std::string(), // mime_type
1104 std::string())); // default_name
1106 Time time_val;
1107 if (headers->GetLastModifiedValue(&time_val))
1108 response->setLastModifiedDate(time_val.ToDoubleT());
1110 // Build up the header map.
1111 void* iter = NULL;
1112 std::string name;
1113 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
1114 response->addHTTPHeaderField(WebString::fromLatin1(name),
1115 WebString::fromLatin1(value));
1119 void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request,
1120 WebURLResponse& response,
1121 WebURLError& error,
1122 WebData& data) {
1123 SyncLoadResponse sync_load_response;
1124 context_->Start(request, &sync_load_response);
1126 const GURL& final_url = sync_load_response.url;
1128 // TODO(tc): For file loads, we may want to include a more descriptive
1129 // status code or status text.
1130 int error_code = sync_load_response.error_code;
1131 if (error_code != net::OK) {
1132 response.setURL(final_url);
1133 error.domain = WebString::fromUTF8(net::kErrorDomain);
1134 error.reason = error_code;
1135 error.unreachableURL = final_url;
1136 return;
1139 PopulateURLResponse(final_url, sync_load_response, &response,
1140 request.reportRawHeaders());
1142 data.assign(sync_load_response.data.data(),
1143 sync_load_response.data.size());
1146 void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request,
1147 WebURLLoaderClient* client) {
1148 DCHECK(!context_->client());
1150 context_->set_client(client);
1151 context_->Start(request, NULL);
1154 void WebURLLoaderImpl::cancel() {
1155 context_->Cancel();
1158 void WebURLLoaderImpl::setDefersLoading(bool value) {
1159 context_->SetDefersLoading(value);
1162 void WebURLLoaderImpl::didChangePriority(WebURLRequest::Priority new_priority,
1163 int intra_priority_value) {
1164 context_->DidChangePriority(new_priority, intra_priority_value);
1167 bool WebURLLoaderImpl::attachThreadedDataReceiver(
1168 blink::WebThreadedDataReceiver* threaded_data_receiver) {
1169 return context_->AttachThreadedDataReceiver(threaded_data_receiver);
1172 } // namespace content