172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// An implementation of WebURLLoader in terms of ResourceLoaderBridge.
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/weburlloader_impl.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/process_util.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/data_url.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/load_flags.h"
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/mime_util.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_response_headers.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPLoadInfo.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoadTiming.h"
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/ftp_directory_listing_response_delegate.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/multipart_response_delegate.h"
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/resource_loader_bridge.h"
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/site_isolation_metrics.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/webkit_glue.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time;
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta;
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebData;
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebHTTPBody;
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebHTTPHeaderVisitor;
41201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochusing WebKit::WebHTTPLoadInfo;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebSecurityPolicy;
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebString;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURL;
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLError;
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLLoadTiming;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLLoader;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLLoaderClient;
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLRequest;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLResponse;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace webkit_glue {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Utilities ------------------------------------------------------------------
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HeaderFlattener : public WebHTTPHeaderVisitor {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit HeaderFlattener(int load_flags)
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : load_flags_(load_flags),
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        has_accept_header_(false) {
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void visitHeader(const WebString& name, const WebString& value) {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(darin): is UTF-8 really correct here?  It is if the strings are
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // already ASCII (i.e., if they are already escaped properly).
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& name_utf8 = name.utf8();
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& value_utf8 = value.utf8();
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Skip over referrer headers found in the header map because we already
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // pulled it out as a separate parameter.
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (LowerCaseEqualsASCII(name_utf8, "referer"))
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Skip over "Cache-Control: max-age=0" header if the corresponding
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // load flag is already specified. FrameLoader sets both the flag and
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the extra header -- the extra header is redundant since our network
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // implementation will add the necessary headers based on load flags.
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // See http://code.google.com/p/chromium/issues/detail?id=3434.
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((load_flags_ & net::LOAD_VALIDATE_CACHE) &&
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LowerCaseEqualsASCII(name_utf8, "cache-control") &&
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LowerCaseEqualsASCII(value_utf8, "max-age=0"))
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (LowerCaseEqualsASCII(name_utf8, "accept"))
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      has_accept_header_ = true;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!buffer_.empty())
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buffer_.append("\r\n");
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    buffer_.append(name_utf8 + ": " + value_utf8);
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& GetBuffer() {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // In some cases, WebKit doesn't add an Accept header, but not having the
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // header confuses some web servers.  See bug 808613.
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!has_accept_header_) {
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!buffer_.empty())
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        buffer_.append("\r\n");
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buffer_.append("Accept: */*");
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      has_accept_header_ = true;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return buffer_;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int load_flags_;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string buffer_;
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool has_accept_header_;
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochResourceType::Type FromTargetType(WebURLRequest::TargetType type) {
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type) {
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsMainFrame:
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::MAIN_FRAME;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsSubframe:
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SUB_FRAME;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsSubresource:
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SUB_RESOURCE;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsStyleSheet:
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::STYLESHEET;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsScript:
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SCRIPT;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsFontResource:
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::FONT_RESOURCE;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsImage:
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::IMAGE;
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsObject:
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::OBJECT;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsMedia:
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::MEDIA;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsWorker:
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::WORKER;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsSharedWorker:
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SHARED_WORKER;
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case WebURLRequest::TargetIsPrefetch:
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ResourceType::PREFETCH;
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case WebURLRequest::TargetIsFavicon:
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return ResourceType::FAVICON;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SUB_RESOURCE;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Extracts the information from a data: url.
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetInfoFromDataURL(const GURL& url,
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                        ResourceResponseInfo* info,
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        std::string* data,
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        net::URLRequestStatus* status) {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string mime_type;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string charset;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    *status = net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->request_time = Time::Now();
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->response_time = Time::Now();
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->headers = NULL;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->mime_type.swap(mime_type);
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->charset.swap(charset);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->security_info.clear();
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->content_length = -1;
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    info->encoded_data_length = 0;
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    info->load_timing.base_time = Time::Now();
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  *status = net::URLRequestStatus(net::URLRequestStatus::FAILED,
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  net::ERR_INVALID_URL);
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173731df977c0511bca2206b5f333555b1205ff1f43Iain Merricktypedef ResourceDevToolsInfo::HeadersVector HeadersVector;
174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PopulateURLResponse(
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& url,
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const ResourceResponseInfo& info,
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WebURLResponse* response) {
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setURL(url);
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setResponseTime(info.response_time.ToDoubleT());
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setMIMEType(WebString::fromUTF8(info.mime_type));
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setTextEncodingName(WebString::fromUTF8(info.charset));
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setExpectedContentLength(info.content_length);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setSecurityInfo(info.security_info);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setAppCacheID(info.appcache_id);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setAppCacheManifestURL(info.appcache_manifest_url);
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasCached(!info.load_timing.base_time.is_null() &&
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info.response_time < info.load_timing.base_time);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasFetchedViaSPDY(info.was_fetched_via_spdy);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasNpnNegotiated(info.was_npn_negotiated);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasAlternateProtocolAvailable(
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info.was_alternate_protocol_available);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasFetchedViaProxy(info.was_fetched_via_proxy);
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  response->setRemoteIPAddress(
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      WebString::fromUTF8(info.socket_address.host()));
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  response->setRemotePort(info.socket_address.port());
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setConnectionID(info.connection_id);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setConnectionReused(info.connection_reused);
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  response->setDownloadFilePath(FilePathToWebString(info.download_file_path));
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const ResourceLoadTimingInfo& timing_info = info.load_timing;
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!timing_info.base_time.is_null()) {
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WebURLLoadTiming timing;
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.initialize();
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setRequestTime(timing_info.base_time.ToDoubleT());
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setProxyStart(timing_info.proxy_start);
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setProxyEnd(timing_info.proxy_end);
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setDNSStart(timing_info.dns_start);
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setDNSEnd(timing_info.dns_end);
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setConnectStart(timing_info.connect_start);
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setConnectEnd(timing_info.connect_end);
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setSSLStart(timing_info.ssl_start);
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setSSLEnd(timing_info.ssl_end);
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setSendStart(timing_info.send_start);
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setSendEnd(timing_info.send_end);
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    timing.setReceiveHeadersEnd(timing_info.receive_headers_end);
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    response->setLoadTiming(timing);
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (info.devtools_info.get()) {
221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    WebHTTPLoadInfo load_info;
222201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
223201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    load_info.setHTTPStatusCode(info.devtools_info->http_status_code);
224201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    load_info.setHTTPStatusText(WebString::fromUTF8(
225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        info.devtools_info->http_status_text));
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    load_info.setEncodedDataLength(info.encoded_data_length);
227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
228731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const HeadersVector& request_headers = info.devtools_info->request_headers;
229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    for (HeadersVector::const_iterator it = request_headers.begin();
230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         it != request_headers.end(); ++it) {
231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      load_info.addRequestHeader(WebString::fromUTF8(it->first),
232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          WebString::fromUTF8(it->second));
233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const HeadersVector& response_headers =
235731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        info.devtools_info->response_headers;
236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    for (HeadersVector::const_iterator it = response_headers.begin();
237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         it != response_headers.end(); ++it) {
238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      load_info.addResponseHeader(WebString::fromUTF8(it->first),
239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          WebString::fromUTF8(it->second));
240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    response->setHTTPLoadInfo(load_info);
242731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
243731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const net::HttpResponseHeaders* headers = info.headers;
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!headers)
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setHTTPStatusCode(headers->response_code());
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setHTTPStatusText(WebString::fromUTF8(headers->GetStatusText()));
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(darin): We should leverage HttpResponseHeaders for this, and this
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should be using the same code as ResourceDispatcherHost.
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(jungshik): Figure out the actual value of the referrer charset and
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pass it to GetSuggestedFilename.
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string value;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (headers->EnumerateHeader(NULL, "content-disposition", &value)) {
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    response->setSuggestedFileName(
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        net::GetSuggestedFilename(url, value, "", string16()));
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time time_val;
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (headers->GetLastModifiedValue(&time_val))
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    response->setLastModifiedDate(time_val.ToDoubleT());
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Build up the header map.
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void* iter = NULL;
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string name;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    response->addHTTPHeaderField(WebString::fromUTF8(name),
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 WebString::fromUTF8(value));
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WebURLLoaderImpl::Context --------------------------------------------------
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This inner class exists since the WebURLLoader may be deleted while inside a
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// call to WebURLLoaderClient.  The bridge requires its Peer to stay alive
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// until it receives OnCompletedRequest.
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebURLLoaderImpl::Context : public base::RefCounted<Context>,
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  public ResourceLoaderBridge::Peer {
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit Context(WebURLLoaderImpl* loader);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLLoaderClient* client() const { return client_; }
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void set_client(WebURLLoaderClient* client) { client_ = client; }
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Cancel();
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetDefersLoading(bool value);
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Start(
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const WebURLRequest& request,
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ResourceLoaderBridge::SyncLoadResponse* sync_load_response);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ResourceLoaderBridge::Peer methods:
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnUploadProgress(uint64 position, uint64 size);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool OnReceivedRedirect(
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& new_url,
299731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      const ResourceResponseInfo& info,
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool* has_new_first_party_for_cookies,
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GURL* new_first_party_for_cookies);
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void OnReceivedResponse(const ResourceResponseInfo& info);
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnDownloadedData(int len);
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnReceivedData(const char* data,
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              int data_length,
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              int encoded_data_length);
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnReceivedCachedMetadata(const char* data, int len);
30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void OnCompletedRequest(const net::URLRequestStatus& status,
30972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  const std::string& security_info,
31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  const base::Time& completion_time);
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class base::RefCounted<Context>;
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~Context() {}
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We can optimize the handling of data URLs in most cases.
31721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool CanHandleDataURL(const GURL& url) const;
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void HandleDataURL();
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLLoaderImpl* loader_;
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLRequest request_;
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLLoaderClient* client_;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<ResourceLoaderBridge> bridge_;
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<ResourceLoaderBridge> completed_bridge_;
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(japhet): Storing this is a temporary hack for site isolation logging.
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURL response_url_;
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader)
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : loader_(loader),
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_(NULL) {
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::Cancel() {
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The bridge will still send OnCompletedRequest, which will Release() us, so
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we don't do that here.
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bridge_.get())
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->Cancel();
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ensure that we do not notify the multipart delegate anymore as it has
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // its own pointer to the client.
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (multipart_delegate_.get())
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    multipart_delegate_->Cancel();
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do not make any further calls to the client.
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_ = NULL;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  loader_ = NULL;
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::SetDefersLoading(bool value) {
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bridge_.get())
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->SetDefersLoading(value);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::Start(
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const WebURLRequest& request,
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ResourceLoaderBridge::SyncLoadResponse* sync_load_response) {
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!bridge_.get());
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_ = request;  // Save the request.
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url = request.url();
36621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (url.SchemeIs("data") && CanHandleDataURL(url)) {
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (sync_load_response) {
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This is a sync load. Do the work now.
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      sync_load_response->url = url;
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::string data;
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetInfoFromDataURL(sync_load_response->url, sync_load_response,
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &sync_load_response->data,
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &sync_load_response->status);
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AddRef();  // Balanced in OnCompletedRequest
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MessageLoop::current()->PostTask(FROM_HERE,
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NewRunnableMethod(this, &Context::HandleDataURL));
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL referrer_url(
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      request.httpHeaderField(WebString::fromUTF8("Referer")).utf8());
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& method = request.httpMethod().utf8();
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int load_flags = net::LOAD_NORMAL;
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (request.cachePolicy()) {
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::ReloadIgnoringCacheData:
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Required by LayoutTests/http/tests/misc/refresh-headers.php
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      load_flags |= net::LOAD_VALIDATE_CACHE;
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::ReturnCacheDataElseLoad:
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      load_flags |= net::LOAD_PREFERRING_CACHE;
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::ReturnCacheDataDontLoad:
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      load_flags |= net::LOAD_ONLY_FROM_CACHE;
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::UseProtocolCachePolicy:
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (request.reportUploadProgress())
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS;
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (request.reportLoadTiming())
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_ENABLE_LOAD_TIMING;
406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (request.reportRawHeaders())
407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    load_flags |= net::LOAD_REPORT_RAW_HEADERS;
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!request.allowCookies() || !request.allowStoredCredentials()) {
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!request.allowStoredCredentials())
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HeaderFlattener flattener(load_flags);
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.visitHTTPHeaderFields(&flattener);
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(abarth): These are wrong!  I need to figure out how to get the right
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //               strings here.  See: http://crbug.com/8706
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string frame_origin = request.firstPartyForCookies().spec();
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string main_frame_origin = request.firstPartyForCookies().spec();
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(brettw) this should take parameter encoding into account when
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // creating the GURLs.
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ResourceLoaderBridge::RequestInfo request_info;
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.method = method;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.url = url;
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.first_party_for_cookies = request.firstPartyForCookies();
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.referrer = referrer_url;
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.frame_origin = frame_origin;
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.main_frame_origin = main_frame_origin;
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.headers = flattener.GetBuffer();
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.load_flags = load_flags;
43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // requestor_pid only needs to be non-zero if the request originates outside
43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // the render process, so we can use requestorProcessID even for requests
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // from in-process plugins.
44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info.requestor_pid = request.requestorProcessID();
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.request_type = FromTargetType(request.targetType());
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.appcache_host_id = request.appCacheHostID();
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.routing_id = request.requestorID();
4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_info.download_to_file = request.downloadToFile();
44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  request_info.has_user_gesture = request.hasUserGesture();
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bridge_.reset(ResourceLoaderBridge::Create(request_info));
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!request.httpBody().isNull()) {
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // GET and HEAD requests shouldn't have http bodies.
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(method != "GET" && method != "HEAD");
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const WebHTTPBody& httpBody = request.httpBody();
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t i = 0;
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WebHTTPBody::Element element;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (httpBody.elementAt(i++, element)) {
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      switch (element.type) {
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case WebHTTPBody::Element::TypeData:
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (!element.data.isEmpty()) {
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // WebKit sometimes gives up empty data to append. These aren't
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // necessary so we just optimize those out here.
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            bridge_->AppendDataToUpload(
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                element.data.data(), static_cast<int>(element.data.size()));
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case WebHTTPBody::Element::TypeFile:
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (element.fileLength == -1) {
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            bridge_->AppendFileToUpload(
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                WebStringToFilePath(element.filePath));
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          } else {
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            bridge_->AppendFileRangeToUpload(
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                WebStringToFilePath(element.filePath),
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                static_cast<uint64>(element.fileStart),
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                static_cast<uint64>(element.fileLength),
4733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                base::Time::FromDoubleT(element.modificationTime));
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
4763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case WebHTTPBody::Element::TypeBlob:
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          bridge_->AppendBlobToUpload(GURL(element.blobURL));
4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        default:
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NOTREACHED();
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->SetUploadIdentifier(request.httpBody().identifier());
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_load_response) {
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->SyncLoad(sync_load_response);
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bridge_->Start(this)) {
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddRef();  // Balanced in OnCompletedRequest
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_.reset();
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_)
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    client_->didSendData(loader_, position, size);
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebURLLoaderImpl::Context::OnReceivedRedirect(
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& new_url,
505731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const ResourceResponseInfo& info,
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool* has_new_first_party_for_cookies,
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL* new_first_party_for_cookies) {
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLResponse response;
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response.initialize();
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopulateURLResponse(request_.url(), info, &response);
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(darin): We lack sufficient information to construct the actual
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // request that resulted from the redirect.
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLRequest new_request(new_url);
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new_request.setFirstPartyForCookies(request_.firstPartyForCookies());
519731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  new_request.setDownloadToFile(request_.downloadToFile());
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebString referrer_string = WebString::fromUTF8("Referer");
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebString referrer = request_.httpHeaderField(referrer_string);
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!WebSecurityPolicy::shouldHideReferrer(new_url, referrer))
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_request.setHTTPHeaderField(referrer_string, referrer);
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response.httpStatusCode() == 307)
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_request.setHTTPMethod(request_.httpMethod());
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_->willSendRequest(loader_, new_request, response);
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_ = new_request;
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *has_new_first_party_for_cookies = true;
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *new_first_party_for_cookies = request_.firstPartyForCookies();
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Only follow the redirect if WebKit left the URL unmodified.
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_url == GURL(new_request.url()))
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We assume that WebKit only changes the URL to suppress a redirect, and we
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // assume that it does so by setting it to be invalid.
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!new_request.url().isValid());
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnReceivedResponse(
545dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const ResourceResponseInfo& info) {
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLResponse response;
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response.initialize();
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopulateURLResponse(request_.url(), info, &response);
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool show_raw_listing = (GURL(request_.url()).query() == "raw");
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info.mime_type == "text/vnd.chromium.ftp-dir") {
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (show_raw_listing) {
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Set the MIME type to plain text to prevent any active content.
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      response.setMIMEType("text/plain");
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We're going to produce a parsed listing in HTML.
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      response.setMIMEType("text/html");
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_->didReceiveResponse(loader_, response);
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We may have been cancelled after didReceiveResponse, which would leave us
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // without a client and therefore without much need to do further handling.
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!ftp_listing_delegate_.get());
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!multipart_delegate_.get());
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info.headers && info.mime_type == "multipart/x-mixed-replace") {
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string content_type;
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info.headers->EnumerateHeader(NULL, "content-type", &content_type);
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
578513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    std::string boundary = net::GetHeaderParamValue(
579513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        content_type, "boundary", net::QuoteRule::REMOVE_OUTER_QUOTES);
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TrimString(boundary, " \"", &boundary);
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If there's no boundary, just handle the request normally.  In the gecko
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // code, nsMultiMixedConv::OnStartRequest throws an exception.
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!boundary.empty()) {
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      multipart_delegate_.reset(
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          new MultipartResponseDelegate(client_, loader_, response, boundary));
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (info.mime_type == "text/vnd.chromium.ftp-dir" &&
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             !show_raw_listing) {
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ftp_listing_delegate_.reset(
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new FtpDirectoryListingResponseDelegate(client_, loader_, response));
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response_url_ = response.url();
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebURLLoaderImpl::Context::OnDownloadedData(int len) {
5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (client_)
5993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    client_->didDownloadData(loader_, len);
6003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid WebURLLoaderImpl::Context::OnReceivedData(const char* data,
603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                               int data_length,
604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                               int encoded_data_length) {
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Temporary logging, see site_isolation_metrics.h/cc.
609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SiteIsolationMetrics::SniffCrossOriginHTML(response_url_, data, data_length);
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ftp_listing_delegate_.get()) {
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The FTP listing delegate will make the appropriate calls to
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // client_->didReceiveData and client_->didReceiveResponse.
614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ftp_listing_delegate_->OnReceivedData(data, data_length);
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (multipart_delegate_.get()) {
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The multipart delegate will make the appropriate calls to
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // client_->didReceiveData and client_->didReceiveResponse.
618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    multipart_delegate_->OnReceivedData(data, data_length, encoded_data_length);
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    client_->didReceiveData(loader_, data, data_length, encoded_data_length);
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnReceivedCachedMetadata(
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* data, int len) {
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_)
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    client_->didReceiveCachedMetadata(loader_, data, len);
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnCompletedRequest(
63172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const net::URLRequestStatus& status,
6323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::string& security_info,
6333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const base::Time& completion_time) {
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ftp_listing_delegate_.get()) {
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ftp_listing_delegate_->OnCompletedRequest();
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ftp_listing_delegate_.reset(NULL);
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (multipart_delegate_.get()) {
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    multipart_delegate_->OnCompletedRequest();
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    multipart_delegate_.reset(NULL);
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Prevent any further IPC to the browser now that we're complete, but
6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // don't delete it to keep any downloaded temp files alive.
6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(!completed_bridge_.get());
6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  completed_bridge_.swap(bridge_);
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_) {
64872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (status.status() != net::URLRequestStatus::SUCCESS) {
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int error_code;
65072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (status.status() == net::URLRequestStatus::HANDLED_EXTERNALLY) {
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // By marking this request as aborted we insure that we don't navigate
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // to an error page.
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        error_code = net::ERR_ABORTED;
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        error_code = status.os_error();
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WebURLError error;
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      error.domain = WebString::fromUTF8(net::kErrorDomain);
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      error.reason = error_code;
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      error.unreachableURL = request_.url();
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_->didFail(loader_, error);
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
6633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      client_->didFinishLoading(loader_, completion_time.ToDoubleT());
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Temporary logging, see site_isolation_metrics.h/cc
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SiteIsolationMetrics::RemoveCompletedResponse(response_url_);
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We are done with the bridge now, and so we need to release the reference
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to ourselves that we took on behalf of the bridge.  This may cause our
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // destruction.
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Release();
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const {
67721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(url.SchemeIs("data"));
67821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
67921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Optimize for the case where we can handle a data URL locally.  We must
68021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // skip this for data URLs targetted at frames since those could trigger a
68121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // download.
68221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  //
68321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // NOTE: We special case MIME types we can render both for performance
68421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // reasons as well as to support unit tests, which do not have an underlying
68521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // ResourceLoaderBridge implementation.
68621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
68721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (request_.targetType() != WebURLRequest::TargetIsMainFrame &&
68821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      request_.targetType() != WebURLRequest::TargetIsSubframe)
68921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return true;
69021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
69121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string mime_type, unused_charset;
69221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (net::DataURL::Parse(url, &mime_type, &unused_charset, NULL) &&
69321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      net::IsSupportedMimeType(mime_type))
69421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return true;
69521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
69621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return false;
69721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
69821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::HandleDataURL() {
700731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ResourceResponseInfo info;
70172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net::URLRequestStatus status;
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string data;
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GetInfoFromDataURL(request_.url(), &info, &data, &status)) {
705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OnReceivedResponse(info);
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!data.empty())
707ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      OnReceivedData(data.data(), data.size(), 0);
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OnCompletedRequest(status, info.security_info, base::Time::Now());
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WebURLLoaderImpl -----------------------------------------------------------
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebURLLoaderImpl::WebURLLoaderImpl()
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : ALLOW_THIS_IN_INITIALIZER_LIST(context_(new Context(this))) {
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebURLLoaderImpl::~WebURLLoaderImpl() {
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cancel();
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request,
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         WebURLResponse& response,
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         WebURLError& error,
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         WebData& data) {
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceLoaderBridge::SyncLoadResponse sync_load_response;
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->Start(request, &sync_load_response);
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const GURL& final_url = sync_load_response.url;
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(tc): For file loads, we may want to include a more descriptive
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // status code or status text.
73472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const net::URLRequestStatus::Status& status =
73572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      sync_load_response.status.status();
73672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (status != net::URLRequestStatus::SUCCESS &&
73772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      status != net::URLRequestStatus::HANDLED_EXTERNALLY) {
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    response.setURL(final_url);
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    error.domain = WebString::fromUTF8(net::kErrorDomain);
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    error.reason = sync_load_response.status.os_error();
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    error.unreachableURL = final_url;
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopulateURLResponse(final_url, sync_load_response, &response);
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data.assign(sync_load_response.data.data(),
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              sync_load_response.data.size());
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request,
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          WebURLLoaderClient* client) {
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!context_->client());
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->set_client(client);
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->Start(request, NULL);
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::cancel() {
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->Cancel();
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::setDefersLoading(bool value) {
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->SetDefersLoading(value);
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace webkit_glue
768