weburlloader_impl.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Copyright (c) 2010 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"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/process_util.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/scoped_ptr.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"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
22201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebHTTPLoadInfo.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebSecurityPolicy.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebURLLoadTiming.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/WebKit/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
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // pulled it out as a separate parameter.  We likewise prune the UA since
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // that will be added back by the network layer.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (LowerCaseEqualsASCII(name_utf8, "referer") ||
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LowerCaseEqualsASCII(name_utf8, "user-agent"))
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Skip over "Cache-Control: max-age=0" header if the corresponding
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // load flag is already specified. FrameLoader sets both the flag and
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the extra header -- the extra header is redundant since our network
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // implementation will add the necessary headers based on load flags.
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // See http://code.google.com/p/chromium/issues/detail?id=3434.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((load_flags_ & net::LOAD_VALIDATE_CACHE) &&
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LowerCaseEqualsASCII(name_utf8, "cache-control") &&
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LowerCaseEqualsASCII(value_utf8, "max-age=0"))
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (LowerCaseEqualsASCII(name_utf8, "accept"))
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      has_accept_header_ = true;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!buffer_.empty())
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buffer_.append("\r\n");
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    buffer_.append(name_utf8 + ": " + value_utf8);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& GetBuffer() {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // In some cases, WebKit doesn't add an Accept header, but not having the
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // header confuses some web servers.  See bug 808613.
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!has_accept_header_) {
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!buffer_.empty())
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        buffer_.append("\r\n");
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buffer_.append("Accept: */*");
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      has_accept_header_ = true;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return buffer_;
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int load_flags_;
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string buffer_;
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool has_accept_header_;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochResourceType::Type FromTargetType(WebURLRequest::TargetType type) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type) {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsMainFrame:
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::MAIN_FRAME;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsSubframe:
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SUB_FRAME;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsSubresource:
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SUB_RESOURCE;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsStyleSheet:
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::STYLESHEET;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsScript:
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SCRIPT;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsFontResource:
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::FONT_RESOURCE;
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsImage:
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::IMAGE;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsObject:
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::OBJECT;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsMedia:
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::MEDIA;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsWorker:
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::WORKER;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::TargetIsSharedWorker:
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResourceType::SHARED_WORKER;
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case WebURLRequest::TargetIsPrefetch:
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ResourceType::PREFETCH;
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,
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        std::string* data, URLRequestStatus* status) {
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string mime_type;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string charset;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *status = URLRequestStatus(URLRequestStatus::SUCCESS, 0);
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->request_time = Time::Now();
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->response_time = Time::Now();
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->headers = NULL;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->mime_type.swap(mime_type);
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->charset.swap(charset);
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->security_info.clear();
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->content_length = -1;
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *status = URLRequestStatus(URLRequestStatus::FAILED, net::ERR_INVALID_URL);
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merricktypedef ResourceDevToolsInfo::HeadersVector HeadersVector;
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PopulateURLResponse(
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& url,
173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const ResourceResponseInfo& info,
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WebURLResponse* response) {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setURL(url);
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setResponseTime(info.response_time.ToDoubleT());
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setMIMEType(WebString::fromUTF8(info.mime_type));
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setTextEncodingName(WebString::fromUTF8(info.charset));
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setExpectedContentLength(info.content_length);
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setSecurityInfo(info.security_info);
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setAppCacheID(info.appcache_id);
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setAppCacheManifestURL(info.appcache_manifest_url);
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasCached(!info.load_timing.base_time.is_null() &&
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info.response_time < info.load_timing.base_time);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasFetchedViaSPDY(info.was_fetched_via_spdy);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasNpnNegotiated(info.was_npn_negotiated);
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasAlternateProtocolAvailable(
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info.was_alternate_protocol_available);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setWasFetchedViaProxy(info.was_fetched_via_proxy);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setConnectionID(info.connection_id);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setConnectionReused(info.connection_reused);
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  response->setDownloadFilePath(FilePathToWebString(info.download_file_path));
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLLoadTiming timing;
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.initialize();
196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const ResourceLoadTimingInfo& timing_info = info.load_timing;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setRequestTime(timing_info.base_time.ToDoubleT());
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setProxyStart(timing_info.proxy_start);
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setProxyEnd(timing_info.proxy_end);
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setDNSStart(timing_info.dns_start);
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setDNSEnd(timing_info.dns_end);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setConnectStart(timing_info.connect_start);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setConnectEnd(timing_info.connect_end);
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setSSLStart(timing_info.ssl_start);
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setSSLEnd(timing_info.ssl_end);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setSendStart(timing_info.send_start);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setSendEnd(timing_info.send_end);
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  timing.setReceiveHeadersEnd(timing_info.receive_headers_end);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setLoadTiming(timing);
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (info.devtools_info.get()) {
212201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    WebHTTPLoadInfo load_info;
213201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
214201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    load_info.setHTTPStatusCode(info.devtools_info->http_status_code);
215201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    load_info.setHTTPStatusText(WebString::fromUTF8(
216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        info.devtools_info->http_status_text));
217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const HeadersVector& request_headers = info.devtools_info->request_headers;
219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    for (HeadersVector::const_iterator it = request_headers.begin();
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         it != request_headers.end(); ++it) {
221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      load_info.addRequestHeader(WebString::fromUTF8(it->first),
222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          WebString::fromUTF8(it->second));
223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const HeadersVector& response_headers =
225731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        info.devtools_info->response_headers;
226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    for (HeadersVector::const_iterator it = response_headers.begin();
227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         it != response_headers.end(); ++it) {
228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      load_info.addResponseHeader(WebString::fromUTF8(it->first),
229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          WebString::fromUTF8(it->second));
230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    response->setHTTPLoadInfo(load_info);
232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const net::HttpResponseHeaders* headers = info.headers;
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!headers)
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setHTTPStatusCode(headers->response_code());
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response->setHTTPStatusText(WebString::fromUTF8(headers->GetStatusText()));
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(darin): We should leverage HttpResponseHeaders for this, and this
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should be using the same code as ResourceDispatcherHost.
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(jungshik): Figure out the actual value of the referrer charset and
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pass it to GetSuggestedFilename.
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string value;
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (headers->EnumerateHeader(NULL, "content-disposition", &value)) {
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    response->setSuggestedFileName(FilePathToWebString(
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net::GetSuggestedFilename(url, value, "", FilePath())));
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time time_val;
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (headers->GetLastModifiedValue(&time_val))
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    response->setLastModifiedDate(time_val.ToDoubleT());
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Build up the header map.
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void* iter = NULL;
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string name;
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    response->addHTTPHeaderField(WebString::fromUTF8(name),
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 WebString::fromUTF8(value));
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WebURLLoaderImpl::Context --------------------------------------------------
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This inner class exists since the WebURLLoader may be deleted while inside a
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// call to WebURLLoaderClient.  The bridge requires its Peer to stay alive
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// until it receives OnCompletedRequest.
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebURLLoaderImpl::Context : public base::RefCounted<Context>,
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  public ResourceLoaderBridge::Peer {
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit Context(WebURLLoaderImpl* loader);
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLLoaderClient* client() const { return client_; }
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void set_client(WebURLLoaderClient* client) { client_ = client; }
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Cancel();
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetDefersLoading(bool value);
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Start(
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const WebURLRequest& request,
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ResourceLoaderBridge::SyncLoadResponse* sync_load_response);
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ResourceLoaderBridge::Peer methods:
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnUploadProgress(uint64 position, uint64 size);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool OnReceivedRedirect(
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& new_url,
289731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      const ResourceResponseInfo& info,
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool* has_new_first_party_for_cookies,
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GURL* new_first_party_for_cookies);
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnReceivedResponse(
293731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      const ResourceResponseInfo& info, bool content_filtered);
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnDownloadedData(int len);
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnReceivedData(const char* data, int len);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnReceivedCachedMetadata(const char* data, int len);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnCompletedRequest(
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const URLRequestStatus& status,
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const std::string& security_info,
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const base::Time& completion_time);
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class base::RefCounted<Context>;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~Context() {}
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We can optimize the handling of data URLs in most cases.
30721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool CanHandleDataURL(const GURL& url) const;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void HandleDataURL();
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLLoaderImpl* loader_;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLRequest request_;
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLLoaderClient* client_;
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<ResourceLoaderBridge> bridge_;
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<ResourceLoaderBridge> completed_bridge_;
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(japhet): Storing this is a temporary hack for site isolation logging.
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURL response_url_;
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader)
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : loader_(loader),
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_(NULL) {
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::Cancel() {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The bridge will still send OnCompletedRequest, which will Release() us, so
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we don't do that here.
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bridge_.get())
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->Cancel();
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ensure that we do not notify the multipart delegate anymore as it has
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // its own pointer to the client.
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (multipart_delegate_.get())
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    multipart_delegate_->Cancel();
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do not make any further calls to the client.
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_ = NULL;
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  loader_ = NULL;
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::SetDefersLoading(bool value) {
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bridge_.get())
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->SetDefersLoading(value);
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::Start(
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const WebURLRequest& request,
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ResourceLoaderBridge::SyncLoadResponse* sync_load_response) {
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!bridge_.get());
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_ = request;  // Save the request.
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url = request.url();
35621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (url.SchemeIs("data") && CanHandleDataURL(url)) {
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (sync_load_response) {
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This is a sync load. Do the work now.
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      sync_load_response->url = url;
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::string data;
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetInfoFromDataURL(sync_load_response->url, sync_load_response,
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &sync_load_response->data,
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &sync_load_response->status);
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AddRef();  // Balanced in OnCompletedRequest
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MessageLoop::current()->PostTask(FROM_HERE,
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NewRunnableMethod(this, &Context::HandleDataURL));
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL referrer_url(
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      request.httpHeaderField(WebString::fromUTF8("Referer")).utf8());
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& method = request.httpMethod().utf8();
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int load_flags = net::LOAD_NORMAL;
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (request.cachePolicy()) {
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::ReloadIgnoringCacheData:
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Required by LayoutTests/http/tests/misc/refresh-headers.php
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      load_flags |= net::LOAD_VALIDATE_CACHE;
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::ReturnCacheDataElseLoad:
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      load_flags |= net::LOAD_PREFERRING_CACHE;
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::ReturnCacheDataDontLoad:
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      load_flags |= net::LOAD_ONLY_FROM_CACHE;
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WebURLRequest::UseProtocolCachePolicy:
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (request.reportUploadProgress())
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS;
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (request.reportLoadTiming())
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_ENABLE_LOAD_TIMING;
396731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (request.reportRawHeaders())
397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    load_flags |= net::LOAD_REPORT_RAW_HEADERS;
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!request.allowCookies() || !request.allowStoredCredentials()) {
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!request.allowStoredCredentials())
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(jcampan): in the non out-of-process plugin case the request does not
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // have a requestor_pid. Find a better place to set this.
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int requestor_pid = request.requestorProcessID();
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (requestor_pid == 0)
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    requestor_pid = base::GetCurrentProcId();
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HeaderFlattener flattener(load_flags);
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.visitHTTPHeaderFields(&flattener);
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(abarth): These are wrong!  I need to figure out how to get the right
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //               strings here.  See: http://crbug.com/8706
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string frame_origin = request.firstPartyForCookies().spec();
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string main_frame_origin = request.firstPartyForCookies().spec();
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(brettw) this should take parameter encoding into account when
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // creating the GURLs.
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ResourceLoaderBridge::RequestInfo request_info;
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.method = method;
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.url = url;
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.first_party_for_cookies = request.firstPartyForCookies();
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.referrer = referrer_url;
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.frame_origin = frame_origin;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.main_frame_origin = main_frame_origin;
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.headers = flattener.GetBuffer();
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.load_flags = load_flags;
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.requestor_pid = requestor_pid;
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.request_type = FromTargetType(request.targetType());
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.appcache_host_id = request.appCacheHostID();
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_info.routing_id = request.requestorID();
4373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_info.download_to_file = request.downloadToFile();
43821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  request_info.has_user_gesture = request.hasUserGesture();
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bridge_.reset(ResourceLoaderBridge::Create(request_info));
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!request.httpBody().isNull()) {
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // GET and HEAD requests shouldn't have http bodies.
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(method != "GET" && method != "HEAD");
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const WebHTTPBody& httpBody = request.httpBody();
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t i = 0;
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WebHTTPBody::Element element;
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (httpBody.elementAt(i++, element)) {
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      switch (element.type) {
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case WebHTTPBody::Element::TypeData:
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (!element.data.isEmpty()) {
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // WebKit sometimes gives up empty data to append. These aren't
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // necessary so we just optimize those out here.
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            bridge_->AppendDataToUpload(
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                element.data.data(), static_cast<int>(element.data.size()));
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case WebHTTPBody::Element::TypeFile:
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (element.fileLength == -1) {
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            bridge_->AppendFileToUpload(
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                WebStringToFilePath(element.filePath));
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          } else {
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            bridge_->AppendFileRangeToUpload(
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                WebStringToFilePath(element.filePath),
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                static_cast<uint64>(element.fileStart),
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                static_cast<uint64>(element.fileLength),
4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                base::Time::FromDoubleT(element.modificationTime));
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case WebHTTPBody::Element::TypeBlob:
4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          bridge_->AppendBlobToUpload(GURL(element.blobURL));
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        default:
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NOTREACHED();
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->SetUploadIdentifier(request.httpBody().identifier());
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_load_response) {
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->SyncLoad(sync_load_response);
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bridge_->Start(this)) {
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddRef();  // Balanced in OnCompletedRequest
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_.reset();
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_)
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    client_->didSendData(loader_, position, size);
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebURLLoaderImpl::Context::OnReceivedRedirect(
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& new_url,
498731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const ResourceResponseInfo& info,
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool* has_new_first_party_for_cookies,
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL* new_first_party_for_cookies) {
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLResponse response;
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response.initialize();
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopulateURLResponse(request_.url(), info, &response);
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(darin): We lack sufficient information to construct the actual
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // request that resulted from the redirect.
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLRequest new_request(new_url);
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new_request.setFirstPartyForCookies(request_.firstPartyForCookies());
512731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  new_request.setDownloadToFile(request_.downloadToFile());
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebString referrer_string = WebString::fromUTF8("Referer");
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebString referrer = request_.httpHeaderField(referrer_string);
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!WebSecurityPolicy::shouldHideReferrer(new_url, referrer))
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_request.setHTTPHeaderField(referrer_string, referrer);
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response.httpStatusCode() == 307)
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_request.setHTTPMethod(request_.httpMethod());
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_->willSendRequest(loader_, new_request, response);
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_ = new_request;
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *has_new_first_party_for_cookies = true;
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *new_first_party_for_cookies = request_.firstPartyForCookies();
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Only follow the redirect if WebKit left the URL unmodified.
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_url == GURL(new_request.url()))
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We assume that WebKit only changes the URL to suppress a redirect, and we
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // assume that it does so by setting it to be invalid.
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!new_request.url().isValid());
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnReceivedResponse(
538731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const ResourceResponseInfo& info,
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool content_filtered) {
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebURLResponse response;
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response.initialize();
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopulateURLResponse(request_.url(), info, &response);
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response.setIsContentFiltered(content_filtered);
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool show_raw_listing = (GURL(request_.url()).query() == "raw");
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info.mime_type == "text/vnd.chromium.ftp-dir") {
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (show_raw_listing) {
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Set the MIME type to plain text to prevent any active content.
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      response.setMIMEType("text/plain");
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We're going to produce a parsed listing in HTML.
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      response.setMIMEType("text/html");
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_->didReceiveResponse(loader_, response);
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We may have been cancelled after didReceiveResponse, which would leave us
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // without a client and therefore without much need to do further handling.
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!ftp_listing_delegate_.get());
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!multipart_delegate_.get());
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info.headers && info.mime_type == "multipart/x-mixed-replace") {
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string content_type;
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info.headers->EnumerateHeader(NULL, "content-type", &content_type);
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
573513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    std::string boundary = net::GetHeaderParamValue(
574513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        content_type, "boundary", net::QuoteRule::REMOVE_OUTER_QUOTES);
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TrimString(boundary, " \"", &boundary);
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If there's no boundary, just handle the request normally.  In the gecko
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // code, nsMultiMixedConv::OnStartRequest throws an exception.
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!boundary.empty()) {
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      multipart_delegate_.reset(
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          new MultipartResponseDelegate(client_, loader_, response, boundary));
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (info.mime_type == "text/vnd.chromium.ftp-dir" &&
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             !show_raw_listing) {
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ftp_listing_delegate_.reset(
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new FtpDirectoryListingResponseDelegate(client_, loader_, response));
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response_url_ = response.url();
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebURLLoaderImpl::Context::OnDownloadedData(int len) {
5933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (client_)
5943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    client_->didDownloadData(loader_, len);
5953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
5963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnReceivedData(const char* data, int len) {
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!client_)
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Temporary logging, see site_isolation_metrics.h/cc.
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SiteIsolationMetrics::SniffCrossOriginHTML(response_url_, data, len);
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ftp_listing_delegate_.get()) {
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The FTP listing delegate will make the appropriate calls to
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // client_->didReceiveData and client_->didReceiveResponse.
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ftp_listing_delegate_->OnReceivedData(data, len);
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (multipart_delegate_.get()) {
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The multipart delegate will make the appropriate calls to
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // client_->didReceiveData and client_->didReceiveResponse.
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    multipart_delegate_->OnReceivedData(data, len);
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    client_->didReceiveData(loader_, data, len);
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnReceivedCachedMetadata(
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* data, int len) {
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_)
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    client_->didReceiveCachedMetadata(loader_, data, len);
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::OnCompletedRequest(
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const URLRequestStatus& status,
6253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::string& security_info,
6263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const base::Time& completion_time) {
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ftp_listing_delegate_.get()) {
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ftp_listing_delegate_->OnCompletedRequest();
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ftp_listing_delegate_.reset(NULL);
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (multipart_delegate_.get()) {
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    multipart_delegate_->OnCompletedRequest();
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    multipart_delegate_.reset(NULL);
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Prevent any further IPC to the browser now that we're complete, but
6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // don't delete it to keep any downloaded temp files alive.
6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(!completed_bridge_.get());
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  completed_bridge_.swap(bridge_);
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_) {
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (status.status() != URLRequestStatus::SUCCESS) {
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int error_code;
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) {
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // By marking this request as aborted we insure that we don't navigate
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // to an error page.
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        error_code = net::ERR_ABORTED;
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        error_code = status.os_error();
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WebURLError error;
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      error.domain = WebString::fromUTF8(net::kErrorDomain);
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      error.reason = error_code;
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      error.unreachableURL = request_.url();
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_->didFail(loader_, error);
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      client_->didFinishLoading(loader_, completion_time.ToDoubleT());
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Temporary logging, see site_isolation_metrics.h/cc
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SiteIsolationMetrics::RemoveCompletedResponse(response_url_);
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We are done with the bridge now, and so we need to release the reference
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to ourselves that we took on behalf of the bridge.  This may cause our
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // destruction.
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Release();
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const {
67021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(url.SchemeIs("data"));
67121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
67221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Optimize for the case where we can handle a data URL locally.  We must
67321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // skip this for data URLs targetted at frames since those could trigger a
67421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // download.
67521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  //
67621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // NOTE: We special case MIME types we can render both for performance
67721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // reasons as well as to support unit tests, which do not have an underlying
67821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // ResourceLoaderBridge implementation.
67921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
68021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (request_.targetType() != WebURLRequest::TargetIsMainFrame &&
68121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      request_.targetType() != WebURLRequest::TargetIsSubframe)
68221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return true;
68321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
68421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string mime_type, unused_charset;
68521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (net::DataURL::Parse(url, &mime_type, &unused_charset, NULL) &&
68621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      net::IsSupportedMimeType(mime_type))
68721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return true;
68821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
68921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return false;
69021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
69121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::Context::HandleDataURL() {
693731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ResourceResponseInfo info;
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLRequestStatus status;
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string data;
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GetInfoFromDataURL(request_.url(), &info, &data, &status)) {
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OnReceivedResponse(info, false);
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!data.empty())
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      OnReceivedData(data.data(), data.size());
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OnCompletedRequest(status, info.security_info, base::Time::Now());
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WebURLLoaderImpl -----------------------------------------------------------
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebURLLoaderImpl::WebURLLoaderImpl()
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : ALLOW_THIS_IN_INITIALIZER_LIST(context_(new Context(this))) {
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebURLLoaderImpl::~WebURLLoaderImpl() {
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cancel();
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request,
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         WebURLResponse& response,
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         WebURLError& error,
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         WebData& data) {
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceLoaderBridge::SyncLoadResponse sync_load_response;
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->Start(request, &sync_load_response);
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const GURL& final_url = sync_load_response.url;
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(tc): For file loads, we may want to include a more descriptive
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // status code or status text.
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const URLRequestStatus::Status& status = sync_load_response.status.status();
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (status != URLRequestStatus::SUCCESS &&
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      status != URLRequestStatus::HANDLED_EXTERNALLY) {
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    response.setURL(final_url);
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    error.domain = WebString::fromUTF8(net::kErrorDomain);
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    error.reason = sync_load_response.status.os_error();
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    error.unreachableURL = final_url;
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopulateURLResponse(final_url, sync_load_response, &response);
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data.assign(sync_load_response.data.data(),
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              sync_load_response.data.size());
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request,
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          WebURLLoaderClient* client) {
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!context_->client());
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->set_client(client);
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->Start(request, NULL);
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::cancel() {
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->Cancel();
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebURLLoaderImpl::setDefersLoading(bool value) {
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  context_->SetDefersLoading(value);
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace webkit_glue
760