Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // An implementation of WebURLLoader in terms of ResourceLoaderBridge. | 5 // An implementation of WebURLLoader in terms of ResourceLoaderBridge. |
| 6 | 6 |
| 7 #include "webkit/glue/weburlloader_impl.h" | 7 #include "webkit/glue/weburlloader_impl.h" |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" | 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" |
| 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" | 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" |
| 31 #include "webkit/glue/ftp_directory_listing_response_delegate.h" | 31 #include "webkit/glue/ftp_directory_listing_response_delegate.h" |
| 32 #include "webkit/glue/multipart_response_delegate.h" | 32 #include "webkit/glue/multipart_response_delegate.h" |
| 33 #include "webkit/glue/resource_loader_bridge.h" | 33 #include "webkit/glue/resource_loader_bridge.h" |
| 34 #include "webkit/glue/webkit_glue.h" | 34 #include "webkit/glue/webkit_glue.h" |
| 35 #include "webkit/glue/webkitplatformsupport_impl.h" | 35 #include "webkit/glue/webkitplatformsupport_impl.h" |
| 36 | 36 |
| 37 using base::Time; | 37 using base::Time; |
| 38 using base::TimeDelta; | 38 using base::TimeDelta; |
| 39 using base::TimeTicks; | |
| 39 using WebKit::WebData; | 40 using WebKit::WebData; |
| 40 using WebKit::WebHTTPBody; | 41 using WebKit::WebHTTPBody; |
| 41 using WebKit::WebHTTPHeaderVisitor; | 42 using WebKit::WebHTTPHeaderVisitor; |
| 42 using WebKit::WebHTTPLoadInfo; | 43 using WebKit::WebHTTPLoadInfo; |
| 43 using WebKit::WebSecurityPolicy; | 44 using WebKit::WebSecurityPolicy; |
| 44 using WebKit::WebString; | 45 using WebKit::WebString; |
| 45 using WebKit::WebURL; | 46 using WebKit::WebURL; |
| 46 using WebKit::WebURLError; | 47 using WebKit::WebURLError; |
| 47 using WebKit::WebURLLoadTiming; | 48 using WebKit::WebURLLoadTiming; |
| 48 using WebKit::WebURLLoader; | 49 using WebKit::WebURLLoader; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 private: | 108 private: |
| 108 int load_flags_; | 109 int load_flags_; |
| 109 std::string buffer_; | 110 std::string buffer_; |
| 110 bool has_accept_header_; | 111 bool has_accept_header_; |
| 111 }; | 112 }; |
| 112 | 113 |
| 113 // Extracts the information from a data: url. | 114 // Extracts the information from a data: url. |
| 114 bool GetInfoFromDataURL(const GURL& url, | 115 bool GetInfoFromDataURL(const GURL& url, |
| 115 ResourceResponseInfo* info, | 116 ResourceResponseInfo* info, |
| 116 std::string* data, | 117 std::string* data, |
| 117 net::URLRequestStatus* status) { | 118 net::URLRequestStatus* status, |
| 119 TimeTicks* response_time) { | |
| 118 std::string mime_type; | 120 std::string mime_type; |
| 119 std::string charset; | 121 std::string charset; |
| 120 if (net::DataURL::Parse(url, &mime_type, &charset, data)) { | 122 if (net::DataURL::Parse(url, &mime_type, &charset, data)) { |
| 121 *status = net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0); | 123 *status = net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0); |
| 122 // Assure same time for all time fields of data: URLs. | 124 // Assure same time for all time fields of data: URLs. |
| 123 Time now = Time::Now(); | 125 Time now = Time::Now(); |
| 124 info->load_timing.base_time = now; | 126 info->load_timing.base_time = now; |
| 127 info->load_timing.base_ticks = *response_time = TimeTicks::Now(); | |
| 125 info->request_time = now; | 128 info->request_time = now; |
| 126 info->response_time = now; | 129 info->response_time = now; |
| 127 info->headers = NULL; | 130 info->headers = NULL; |
| 128 info->mime_type.swap(mime_type); | 131 info->mime_type.swap(mime_type); |
| 129 info->charset.swap(charset); | 132 info->charset.swap(charset); |
| 130 info->security_info.clear(); | 133 info->security_info.clear(); |
| 131 info->content_length = -1; | 134 info->content_length = -1; |
| 132 info->encoded_data_length = 0; | 135 info->encoded_data_length = 0; |
| 133 | 136 |
| 134 return true; | 137 return true; |
| 135 } | 138 } |
| 136 | 139 |
| 137 *status = net::URLRequestStatus(net::URLRequestStatus::FAILED, | 140 *status = net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 138 net::ERR_INVALID_URL); | 141 net::ERR_INVALID_URL); |
| 139 return false; | 142 return false; |
| 140 } | 143 } |
| 141 | 144 |
| 142 typedef ResourceDevToolsInfo::HeadersVector HeadersVector; | 145 typedef ResourceDevToolsInfo::HeadersVector HeadersVector; |
| 143 | 146 |
| 144 void PopulateURLResponse( | 147 void PopulateURLResponse( |
| 145 const GURL& url, | 148 const GURL& url, |
| 146 const ResourceResponseInfo& info, | 149 const ResourceResponseInfo& info, |
| 150 const TimeTicks& ipc_request_time, | |
|
darin (slow to review)
2011/12/06 01:06:32
This file should not know anything about IPC. Per
James Simonsen
2011/12/10 00:21:47
Yeah, good point. Thanks. I went with the former.
| |
| 151 const TimeTicks& net_start_time, | |
| 152 const TimeTicks& net_end_time, | |
| 153 const TimeTicks& ipc_response_time, | |
| 147 WebURLResponse* response) { | 154 WebURLResponse* response) { |
| 148 response->setURL(url); | 155 response->setURL(url); |
| 149 response->setResponseTime(info.response_time.ToDoubleT()); | 156 response->setResponseTime(info.response_time.ToDoubleT()); |
| 150 response->setMIMEType(WebString::fromUTF8(info.mime_type)); | 157 response->setMIMEType(WebString::fromUTF8(info.mime_type)); |
| 151 response->setTextEncodingName(WebString::fromUTF8(info.charset)); | 158 response->setTextEncodingName(WebString::fromUTF8(info.charset)); |
| 152 response->setExpectedContentLength(info.content_length); | 159 response->setExpectedContentLength(info.content_length); |
| 153 response->setSecurityInfo(info.security_info); | 160 response->setSecurityInfo(info.security_info); |
| 154 response->setAppCacheID(info.appcache_id); | 161 response->setAppCacheID(info.appcache_id); |
| 155 response->setAppCacheManifestURL(info.appcache_manifest_url); | 162 response->setAppCacheManifestURL(info.appcache_manifest_url); |
| 156 response->setWasCached(!info.load_timing.base_time.is_null() && | 163 response->setWasCached(!info.load_timing.base_time.is_null() && |
| 157 info.response_time < info.load_timing.base_time); | 164 info.response_time < info.load_timing.base_time); |
| 158 response->setWasFetchedViaSPDY(info.was_fetched_via_spdy); | 165 response->setWasFetchedViaSPDY(info.was_fetched_via_spdy); |
| 159 response->setWasNpnNegotiated(info.was_npn_negotiated); | 166 response->setWasNpnNegotiated(info.was_npn_negotiated); |
| 160 response->setWasAlternateProtocolAvailable( | 167 response->setWasAlternateProtocolAvailable( |
| 161 info.was_alternate_protocol_available); | 168 info.was_alternate_protocol_available); |
| 162 response->setWasFetchedViaProxy(info.was_fetched_via_proxy); | 169 response->setWasFetchedViaProxy(info.was_fetched_via_proxy); |
| 163 response->setRemoteIPAddress( | 170 response->setRemoteIPAddress( |
| 164 WebString::fromUTF8(info.socket_address.host())); | 171 WebString::fromUTF8(info.socket_address.host())); |
| 165 response->setRemotePort(info.socket_address.port()); | 172 response->setRemotePort(info.socket_address.port()); |
| 166 response->setConnectionID(info.connection_id); | 173 response->setConnectionID(info.connection_id); |
| 167 response->setConnectionReused(info.connection_reused); | 174 response->setConnectionReused(info.connection_reused); |
| 168 response->setDownloadFilePath(FilePathToWebString(info.download_file_path)); | 175 response->setDownloadFilePath(FilePathToWebString(info.download_file_path)); |
| 169 | 176 |
| 170 const ResourceLoadTimingInfo& timing_info = info.load_timing; | 177 const ResourceLoadTimingInfo& timing_info = info.load_timing; |
| 171 if (!timing_info.base_time.is_null()) { | 178 if (!timing_info.base_time.is_null()) { |
| 172 WebURLLoadTiming timing; | 179 WebURLLoadTiming timing = PopulateWebURLLoadTiming( |
| 173 timing.initialize(); | 180 timing_info, ipc_request_time, net_start_time, net_end_time, |
| 174 timing.setRequestTime(timing_info.base_time.ToDoubleT()); | 181 ipc_response_time); |
| 175 timing.setProxyStart(timing_info.proxy_start); | |
| 176 timing.setProxyEnd(timing_info.proxy_end); | |
| 177 timing.setDNSStart(timing_info.dns_start); | |
| 178 timing.setDNSEnd(timing_info.dns_end); | |
| 179 timing.setConnectStart(timing_info.connect_start); | |
| 180 timing.setConnectEnd(timing_info.connect_end); | |
| 181 timing.setSSLStart(timing_info.ssl_start); | |
| 182 timing.setSSLEnd(timing_info.ssl_end); | |
| 183 timing.setSendStart(timing_info.send_start); | |
| 184 timing.setSendEnd(timing_info.send_end); | |
| 185 timing.setReceiveHeadersEnd(timing_info.receive_headers_end); | |
| 186 response->setLoadTiming(timing); | 182 response->setLoadTiming(timing); |
| 187 } | 183 } |
| 188 | 184 |
| 189 if (info.devtools_info.get()) { | 185 if (info.devtools_info.get()) { |
| 190 WebHTTPLoadInfo load_info; | 186 WebHTTPLoadInfo load_info; |
| 191 | 187 |
| 192 load_info.setHTTPStatusCode(info.devtools_info->http_status_code); | 188 load_info.setHTTPStatusCode(info.devtools_info->http_status_code); |
| 193 load_info.setHTTPStatusText(WebString::fromUTF8( | 189 load_info.setHTTPStatusText(WebString::fromUTF8( |
| 194 info.devtools_info->http_status_text)); | 190 info.devtools_info->http_status_text)); |
| 195 load_info.setEncodedDataLength(info.encoded_data_length); | 191 load_info.setEncodedDataLength(info.encoded_data_length); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 const WebURLRequest& request, | 261 const WebURLRequest& request, |
| 266 ResourceLoaderBridge::SyncLoadResponse* sync_load_response, | 262 ResourceLoaderBridge::SyncLoadResponse* sync_load_response, |
| 267 WebKitPlatformSupportImpl* platform); | 263 WebKitPlatformSupportImpl* platform); |
| 268 void UpdateRoutingId(int new_routing_id); | 264 void UpdateRoutingId(int new_routing_id); |
| 269 | 265 |
| 270 // ResourceLoaderBridge::Peer methods: | 266 // ResourceLoaderBridge::Peer methods: |
| 271 virtual void OnUploadProgress(uint64 position, uint64 size); | 267 virtual void OnUploadProgress(uint64 position, uint64 size); |
| 272 virtual bool OnReceivedRedirect( | 268 virtual bool OnReceivedRedirect( |
| 273 const GURL& new_url, | 269 const GURL& new_url, |
| 274 const ResourceResponseInfo& info, | 270 const ResourceResponseInfo& info, |
| 271 const TimeTicks& net_start_time, | |
| 272 const TimeTicks& net_end_time, | |
| 275 bool* has_new_first_party_for_cookies, | 273 bool* has_new_first_party_for_cookies, |
| 276 GURL* new_first_party_for_cookies); | 274 GURL* new_first_party_for_cookies); |
| 277 virtual void OnReceivedResponse(const ResourceResponseInfo& info); | 275 virtual void OnReceivedResponse(const ResourceResponseInfo& info, |
| 276 const TimeTicks& net_start_time, | |
| 277 const TimeTicks& net_end_time); | |
| 278 virtual void OnDownloadedData(int len); | 278 virtual void OnDownloadedData(int len); |
| 279 virtual void OnReceivedData(const char* data, | 279 virtual void OnReceivedData(const char* data, |
| 280 int data_length, | 280 int data_length, |
| 281 int encoded_data_length); | 281 int encoded_data_length); |
| 282 virtual void OnReceivedCachedMetadata(const char* data, int len); | 282 virtual void OnReceivedCachedMetadata(const char* data, int len); |
| 283 virtual void OnCompletedRequest(const net::URLRequestStatus& status, | 283 virtual void OnCompletedRequest(const net::URLRequestStatus& status, |
| 284 const std::string& security_info, | 284 const std::string& security_info, |
| 285 const base::Time& completion_time); | 285 const TimeTicks& completion_time); |
| 286 | 286 |
| 287 private: | 287 private: |
| 288 friend class base::RefCounted<Context>; | 288 friend class base::RefCounted<Context>; |
| 289 ~Context() {} | 289 ~Context() {} |
| 290 | 290 |
| 291 // We can optimize the handling of data URLs in most cases. | 291 // We can optimize the handling of data URLs in most cases. |
| 292 bool CanHandleDataURL(const GURL& url) const; | 292 bool CanHandleDataURL(const GURL& url) const; |
| 293 void HandleDataURL(); | 293 void HandleDataURL(); |
| 294 | 294 |
| 295 WebURLLoaderImpl* loader_; | 295 WebURLLoaderImpl* loader_; |
| 296 WebURLRequest request_; | 296 WebURLRequest request_; |
| 297 WebURLLoaderClient* client_; | 297 WebURLLoaderClient* client_; |
| 298 TimeTicks initiation_time_; | |
| 298 scoped_ptr<ResourceLoaderBridge> bridge_; | 299 scoped_ptr<ResourceLoaderBridge> bridge_; |
| 299 scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; | 300 scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; |
| 300 scoped_ptr<MultipartResponseDelegate> multipart_delegate_; | 301 scoped_ptr<MultipartResponseDelegate> multipart_delegate_; |
| 301 scoped_ptr<ResourceLoaderBridge> completed_bridge_; | 302 scoped_ptr<ResourceLoaderBridge> completed_bridge_; |
| 302 }; | 303 }; |
| 303 | 304 |
| 304 WebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader) | 305 WebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader) |
| 305 : loader_(loader), | 306 : loader_(loader), |
| 306 client_(NULL) { | 307 client_(NULL) { |
| 307 } | 308 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 DCHECK(!bridge_.get()); | 340 DCHECK(!bridge_.get()); |
| 340 | 341 |
| 341 request_ = request; // Save the request. | 342 request_ = request; // Save the request. |
| 342 | 343 |
| 343 GURL url = request.url(); | 344 GURL url = request.url(); |
| 344 if (url.SchemeIs("data") && CanHandleDataURL(url)) { | 345 if (url.SchemeIs("data") && CanHandleDataURL(url)) { |
| 345 if (sync_load_response) { | 346 if (sync_load_response) { |
| 346 // This is a sync load. Do the work now. | 347 // This is a sync load. Do the work now. |
| 347 sync_load_response->url = url; | 348 sync_load_response->url = url; |
| 348 std::string data; | 349 std::string data; |
| 350 TimeTicks response_time; | |
| 349 GetInfoFromDataURL(sync_load_response->url, sync_load_response, | 351 GetInfoFromDataURL(sync_load_response->url, sync_load_response, |
| 350 &sync_load_response->data, | 352 &sync_load_response->data, |
| 351 &sync_load_response->status); | 353 &sync_load_response->status, &response_time); |
| 354 sync_load_response->net_start_time = response_time; | |
| 355 sync_load_response->net_end_time = response_time; | |
| 352 } else { | 356 } else { |
| 353 AddRef(); // Balanced in OnCompletedRequest | 357 AddRef(); // Balanced in OnCompletedRequest |
| 354 MessageLoop::current()->PostTask(FROM_HERE, | 358 MessageLoop::current()->PostTask(FROM_HERE, |
| 355 base::Bind(&Context::HandleDataURL, this)); | 359 base::Bind(&Context::HandleDataURL, this)); |
| 356 } | 360 } |
| 357 return; | 361 return; |
| 358 } | 362 } |
| 359 | 363 |
| 360 GURL referrer_url( | 364 GURL referrer_url( |
| 361 request.httpHeaderField(WebString::fromUTF8("Referer")).utf8()); | 365 request.httpHeaderField(WebString::fromUTF8("Referer")).utf8()); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 449 case WebHTTPBody::Element::TypeBlob: | 453 case WebHTTPBody::Element::TypeBlob: |
| 450 bridge_->AppendBlobToUpload(GURL(element.blobURL)); | 454 bridge_->AppendBlobToUpload(GURL(element.blobURL)); |
| 451 break; | 455 break; |
| 452 default: | 456 default: |
| 453 NOTREACHED(); | 457 NOTREACHED(); |
| 454 } | 458 } |
| 455 } | 459 } |
| 456 bridge_->SetUploadIdentifier(request.httpBody().identifier()); | 460 bridge_->SetUploadIdentifier(request.httpBody().identifier()); |
| 457 } | 461 } |
| 458 | 462 |
| 463 initiation_time_ = TimeTicks::Now(); | |
| 459 if (sync_load_response) { | 464 if (sync_load_response) { |
| 460 bridge_->SyncLoad(sync_load_response); | 465 bridge_->SyncLoad(sync_load_response); |
| 461 return; | 466 return; |
| 462 } | 467 } |
| 463 | 468 |
| 464 if (bridge_->Start(this)) { | 469 if (bridge_->Start(this)) { |
| 465 AddRef(); // Balanced in OnCompletedRequest | 470 AddRef(); // Balanced in OnCompletedRequest |
| 466 } else { | 471 } else { |
| 467 bridge_.reset(); | 472 bridge_.reset(); |
| 468 } | 473 } |
| 469 } | 474 } |
| 470 | 475 |
| 471 void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) { | 476 void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) { |
| 472 if (client_) | 477 if (client_) |
| 473 client_->didSendData(loader_, position, size); | 478 client_->didSendData(loader_, position, size); |
| 474 } | 479 } |
| 475 | 480 |
| 476 bool WebURLLoaderImpl::Context::OnReceivedRedirect( | 481 bool WebURLLoaderImpl::Context::OnReceivedRedirect( |
| 477 const GURL& new_url, | 482 const GURL& new_url, |
| 478 const ResourceResponseInfo& info, | 483 const ResourceResponseInfo& info, |
| 484 const TimeTicks& net_start_time, | |
| 485 const TimeTicks& net_end_time, | |
| 479 bool* has_new_first_party_for_cookies, | 486 bool* has_new_first_party_for_cookies, |
| 480 GURL* new_first_party_for_cookies) { | 487 GURL* new_first_party_for_cookies) { |
| 481 if (!client_) | 488 if (!client_) |
| 482 return false; | 489 return false; |
| 483 | 490 |
| 491 TimeTicks ipc_response_time = TimeTicks::Now(); | |
| 484 WebURLResponse response; | 492 WebURLResponse response; |
| 485 response.initialize(); | 493 response.initialize(); |
| 486 PopulateURLResponse(request_.url(), info, &response); | 494 PopulateURLResponse(request_.url(), info, initiation_time_, net_start_time, |
| 495 net_end_time, ipc_response_time, &response); | |
| 487 | 496 |
| 488 // TODO(darin): We lack sufficient information to construct the actual | 497 // TODO(darin): We lack sufficient information to construct the actual |
| 489 // request that resulted from the redirect. | 498 // request that resulted from the redirect. |
| 490 WebURLRequest new_request(new_url); | 499 WebURLRequest new_request(new_url); |
| 491 new_request.setFirstPartyForCookies(request_.firstPartyForCookies()); | 500 new_request.setFirstPartyForCookies(request_.firstPartyForCookies()); |
| 492 new_request.setDownloadToFile(request_.downloadToFile()); | 501 new_request.setDownloadToFile(request_.downloadToFile()); |
| 493 | 502 |
| 494 WebString referrer_string = WebString::fromUTF8("Referer"); | 503 WebString referrer_string = WebString::fromUTF8("Referer"); |
| 495 WebString referrer = request_.httpHeaderField(referrer_string); | 504 WebString referrer = request_.httpHeaderField(referrer_string); |
| 496 if (!WebSecurityPolicy::shouldHideReferrer(new_url, referrer)) | 505 if (!WebSecurityPolicy::shouldHideReferrer(new_url, referrer)) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 508 if (new_url == GURL(new_request.url())) | 517 if (new_url == GURL(new_request.url())) |
| 509 return true; | 518 return true; |
| 510 | 519 |
| 511 // We assume that WebKit only changes the URL to suppress a redirect, and we | 520 // We assume that WebKit only changes the URL to suppress a redirect, and we |
| 512 // assume that it does so by setting it to be invalid. | 521 // assume that it does so by setting it to be invalid. |
| 513 DCHECK(!new_request.url().isValid()); | 522 DCHECK(!new_request.url().isValid()); |
| 514 return false; | 523 return false; |
| 515 } | 524 } |
| 516 | 525 |
| 517 void WebURLLoaderImpl::Context::OnReceivedResponse( | 526 void WebURLLoaderImpl::Context::OnReceivedResponse( |
| 518 const ResourceResponseInfo& info) { | 527 const ResourceResponseInfo& info, |
| 528 const TimeTicks& net_start_time, | |
| 529 const TimeTicks& net_end_time) { | |
| 519 if (!client_) | 530 if (!client_) |
| 520 return; | 531 return; |
| 521 | 532 |
| 533 TimeTicks ipc_response_time = TimeTicks::Now(); | |
| 522 WebURLResponse response; | 534 WebURLResponse response; |
| 523 response.initialize(); | 535 response.initialize(); |
| 524 PopulateURLResponse(request_.url(), info, &response); | 536 PopulateURLResponse(request_.url(), info, initiation_time_, net_start_time, |
| 537 net_end_time, ipc_response_time, &response); | |
| 525 | 538 |
| 526 bool show_raw_listing = (GURL(request_.url()).query() == "raw"); | 539 bool show_raw_listing = (GURL(request_.url()).query() == "raw"); |
| 527 | 540 |
| 528 if (info.mime_type == "text/vnd.chromium.ftp-dir") { | 541 if (info.mime_type == "text/vnd.chromium.ftp-dir") { |
| 529 if (show_raw_listing) { | 542 if (show_raw_listing) { |
| 530 // Set the MIME type to plain text to prevent any active content. | 543 // Set the MIME type to plain text to prevent any active content. |
| 531 response.setMIMEType("text/plain"); | 544 response.setMIMEType("text/plain"); |
| 532 } else { | 545 } else { |
| 533 // We're going to produce a parsed listing in HTML. | 546 // We're going to produce a parsed listing in HTML. |
| 534 response.setMIMEType("text/html"); | 547 response.setMIMEType("text/html"); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 591 | 604 |
| 592 void WebURLLoaderImpl::Context::OnReceivedCachedMetadata( | 605 void WebURLLoaderImpl::Context::OnReceivedCachedMetadata( |
| 593 const char* data, int len) { | 606 const char* data, int len) { |
| 594 if (client_) | 607 if (client_) |
| 595 client_->didReceiveCachedMetadata(loader_, data, len); | 608 client_->didReceiveCachedMetadata(loader_, data, len); |
| 596 } | 609 } |
| 597 | 610 |
| 598 void WebURLLoaderImpl::Context::OnCompletedRequest( | 611 void WebURLLoaderImpl::Context::OnCompletedRequest( |
| 599 const net::URLRequestStatus& original_status, | 612 const net::URLRequestStatus& original_status, |
| 600 const std::string& security_info, | 613 const std::string& security_info, |
| 601 const base::Time& completion_time) { | 614 const TimeTicks& completion_time) { |
| 615 TimeTicks monotonic_completion_time = std::min(completion_time, | |
| 616 TimeTicks::Now()); | |
| 602 if (ftp_listing_delegate_.get()) { | 617 if (ftp_listing_delegate_.get()) { |
| 603 ftp_listing_delegate_->OnCompletedRequest(); | 618 ftp_listing_delegate_->OnCompletedRequest(); |
| 604 ftp_listing_delegate_.reset(NULL); | 619 ftp_listing_delegate_.reset(NULL); |
| 605 } else if (multipart_delegate_.get()) { | 620 } else if (multipart_delegate_.get()) { |
| 606 multipart_delegate_->OnCompletedRequest(); | 621 multipart_delegate_->OnCompletedRequest(); |
| 607 multipart_delegate_.reset(NULL); | 622 multipart_delegate_.reset(NULL); |
| 608 } | 623 } |
| 609 | 624 |
| 610 net::URLRequestStatus status = original_status; | 625 net::URLRequestStatus status = original_status; |
| 611 | 626 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 633 error_code = status.error(); | 648 error_code = status.error(); |
| 634 } | 649 } |
| 635 WebURLError error; | 650 WebURLError error; |
| 636 if (error_code == net::ERR_ABORTED) | 651 if (error_code == net::ERR_ABORTED) |
| 637 error.isCancellation = true; | 652 error.isCancellation = true; |
| 638 error.domain = WebString::fromUTF8(net::kErrorDomain); | 653 error.domain = WebString::fromUTF8(net::kErrorDomain); |
| 639 error.reason = error_code; | 654 error.reason = error_code; |
| 640 error.unreachableURL = request_.url(); | 655 error.unreachableURL = request_.url(); |
| 641 client_->didFail(loader_, error); | 656 client_->didFail(loader_, error); |
| 642 } else { | 657 } else { |
| 643 client_->didFinishLoading(loader_, completion_time.ToDoubleT()); | 658 client_->didFinishLoading( |
| 659 loader_, static_cast<double>( | |
|
darin (slow to review)
2011/12/06 01:06:32
Should TimeDelta have a InMicrosecondsF() method?
James Simonsen
2011/12/10 00:21:47
Not sure what I was thinking. This should be in se
| |
| 660 (completion_time - TimeTicks()).InMicroseconds())); | |
| 644 } | 661 } |
| 645 } | 662 } |
| 646 | 663 |
| 647 // We are done with the bridge now, and so we need to release the reference | 664 // We are done with the bridge now, and so we need to release the reference |
| 648 // to ourselves that we took on behalf of the bridge. This may cause our | 665 // to ourselves that we took on behalf of the bridge. This may cause our |
| 649 // destruction. | 666 // destruction. |
| 650 Release(); | 667 Release(); |
| 651 } | 668 } |
| 652 | 669 |
| 653 bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const { | 670 bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 671 return true; | 688 return true; |
| 672 | 689 |
| 673 return false; | 690 return false; |
| 674 } | 691 } |
| 675 | 692 |
| 676 void WebURLLoaderImpl::Context::HandleDataURL() { | 693 void WebURLLoaderImpl::Context::HandleDataURL() { |
| 677 ResourceResponseInfo info; | 694 ResourceResponseInfo info; |
| 678 net::URLRequestStatus status; | 695 net::URLRequestStatus status; |
| 679 std::string data; | 696 std::string data; |
| 680 | 697 |
| 681 if (GetInfoFromDataURL(request_.url(), &info, &data, &status)) { | 698 TimeTicks response_time; |
| 682 OnReceivedResponse(info); | 699 if (GetInfoFromDataURL(request_.url(), &info, &data, &status, |
| 700 &response_time)) { | |
| 701 OnReceivedResponse(info, response_time, response_time); | |
| 683 if (!data.empty()) | 702 if (!data.empty()) |
| 684 OnReceivedData(data.data(), data.size(), 0); | 703 OnReceivedData(data.data(), data.size(), 0); |
| 685 } | 704 } |
| 686 | 705 |
| 687 OnCompletedRequest(status, info.security_info, base::Time::Now()); | 706 OnCompletedRequest(status, info.security_info, TimeTicks::Now()); |
| 688 } | 707 } |
| 689 | 708 |
| 690 // WebURLLoaderImpl ----------------------------------------------------------- | 709 // WebURLLoaderImpl ----------------------------------------------------------- |
| 691 | 710 |
| 692 WebURLLoaderImpl::WebURLLoaderImpl(WebKitPlatformSupportImpl* platform) | 711 WebURLLoaderImpl::WebURLLoaderImpl(WebKitPlatformSupportImpl* platform) |
| 693 : ALLOW_THIS_IN_INITIALIZER_LIST(context_(new Context(this))), | 712 : ALLOW_THIS_IN_INITIALIZER_LIST(context_(new Context(this))), |
| 694 platform_(platform) { | 713 platform_(platform) { |
| 695 } | 714 } |
| 696 | 715 |
| 697 WebURLLoaderImpl::~WebURLLoaderImpl() { | 716 WebURLLoaderImpl::~WebURLLoaderImpl() { |
| 698 cancel(); | 717 cancel(); |
| 699 } | 718 } |
| 700 | 719 |
| 701 void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request, | 720 void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request, |
| 702 WebURLResponse& response, | 721 WebURLResponse& response, |
| 703 WebURLError& error, | 722 WebURLError& error, |
| 704 WebData& data) { | 723 WebData& data) { |
| 724 TimeTicks ipc_request_time = TimeTicks::Now(); | |
| 705 ResourceLoaderBridge::SyncLoadResponse sync_load_response; | 725 ResourceLoaderBridge::SyncLoadResponse sync_load_response; |
| 706 context_->Start(request, &sync_load_response, platform_); | 726 context_->Start(request, &sync_load_response, platform_); |
| 727 TimeTicks completion_time = TimeTicks::Now(); | |
| 707 | 728 |
| 708 const GURL& final_url = sync_load_response.url; | 729 const GURL& final_url = sync_load_response.url; |
| 709 | 730 |
| 710 // TODO(tc): For file loads, we may want to include a more descriptive | 731 // TODO(tc): For file loads, we may want to include a more descriptive |
| 711 // status code or status text. | 732 // status code or status text. |
| 712 const net::URLRequestStatus::Status& status = | 733 const net::URLRequestStatus::Status& status = |
| 713 sync_load_response.status.status(); | 734 sync_load_response.status.status(); |
| 714 if (status != net::URLRequestStatus::SUCCESS && | 735 if (status != net::URLRequestStatus::SUCCESS && |
| 715 status != net::URLRequestStatus::HANDLED_EXTERNALLY) { | 736 status != net::URLRequestStatus::HANDLED_EXTERNALLY) { |
| 716 response.setURL(final_url); | 737 response.setURL(final_url); |
| 717 error.domain = WebString::fromUTF8(net::kErrorDomain); | 738 error.domain = WebString::fromUTF8(net::kErrorDomain); |
| 718 error.reason = sync_load_response.status.error(); | 739 error.reason = sync_load_response.status.error(); |
| 719 error.unreachableURL = final_url; | 740 error.unreachableURL = final_url; |
| 720 return; | 741 return; |
| 721 } | 742 } |
| 722 | 743 |
| 723 PopulateURLResponse(final_url, sync_load_response, &response); | 744 PopulateURLResponse(final_url, sync_load_response, ipc_request_time, |
| 745 sync_load_response.net_start_time, | |
| 746 sync_load_response.net_end_time, completion_time, | |
| 747 &response); | |
| 724 | 748 |
| 725 data.assign(sync_load_response.data.data(), | 749 data.assign(sync_load_response.data.data(), |
| 726 sync_load_response.data.size()); | 750 sync_load_response.data.size()); |
| 727 } | 751 } |
| 728 | 752 |
| 729 void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request, | 753 void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request, |
| 730 WebURLLoaderClient* client) { | 754 WebURLLoaderClient* client) { |
| 731 DCHECK(!context_->client()); | 755 DCHECK(!context_->client()); |
| 732 | 756 |
| 733 context_->set_client(client); | 757 context_->set_client(client); |
| 734 context_->Start(request, NULL, platform_); | 758 context_->Start(request, NULL, platform_); |
| 735 } | 759 } |
| 736 | 760 |
| 737 void WebURLLoaderImpl::cancel() { | 761 void WebURLLoaderImpl::cancel() { |
| 738 context_->Cancel(); | 762 context_->Cancel(); |
| 739 } | 763 } |
| 740 | 764 |
| 741 void WebURLLoaderImpl::setDefersLoading(bool value) { | 765 void WebURLLoaderImpl::setDefersLoading(bool value) { |
| 742 context_->SetDefersLoading(value); | 766 context_->SetDefersLoading(value); |
| 743 } | 767 } |
| 744 | 768 |
| 745 void WebURLLoaderImpl::UpdateRoutingId(int new_routing_id) { | 769 void WebURLLoaderImpl::UpdateRoutingId(int new_routing_id) { |
| 746 context_->UpdateRoutingId(new_routing_id); | 770 context_->UpdateRoutingId(new_routing_id); |
| 747 } | 771 } |
| 748 | 772 |
| 773 // |timing_info| originates in the network layer, which may live in another | |
| 774 // (browser) process. These values are recorded and passed as TimeTicks. On | |
| 775 // Windows, TimeTicks do not tick consistently across processes. So one process | |
| 776 // may be slightly ahead of the other and the delta between them may drift. In | |
| 777 // practice, they usually differ by a few ms or less, and never more than 10 ms. | |
| 778 // | |
| 779 // Our goal is to present monotonically increasing timestamps to WebKit. So we | |
| 780 // must fit the network layer's timestamps into WebKit's timeline. If we don't | |
| 781 // correct for this skew, then we may report anomolies, such as negative page | |
| 782 // load times, to developer tools and analytics scripts. | |
| 783 // | |
| 784 // To correct for this skew, we record 4 times: | |
| 785 // - |ipc_request_time|: when this process passed the request on to the network | |
| 786 // layer. | |
| 787 // - |net_start_time|: when the network layer (other process) started handling | |
| 788 // the request. | |
| 789 // - |net_end_time|: when the network layer finished the request. | |
| 790 // - |ipc_response_time|: when this process received the response from the | |
| 791 // network layer. | |
| 792 // | |
| 793 // Because of the monotonic clock, all members of |timing_info| will occur | |
| 794 // between |net_start_time| and |net_end_time|. If |net_start_time| and/or | |
| 795 // |net_end_time| are out of order wrt |ipc_request_time| and | |
| 796 // |ipc_response_time|, then we adjust the bounds to fit within | |
| 797 // |ipc_request_time| and |ipc_response_time|. When the bounds are adjusted, we | |
| 798 // scale all of the members of |timing_info| so that they are relatively the | |
| 799 // same time delta from |net_start_time| and |net_end_time| as they were before | |
| 800 // adjustment. | |
| 801 // | |
| 802 // In addition to this, we always shift the |net_*| times so that the |net_*| | |
| 803 // range is centered with |ipc_*| range. | |
| 804 namespace { | |
| 805 | |
| 806 class WebKitDelta { | |
|
darin (slow to review)
2011/12/06 01:06:32
It might help to factor out this code into a separ
| |
| 807 public: | |
| 808 int ToWebKitTime() { return value_; } | |
| 809 | |
| 810 private: | |
| 811 friend class TimeConverter; | |
| 812 friend class WebKitMilliseconds; | |
| 813 | |
| 814 WebKitDelta(int value) : value_(value) {} | |
| 815 | |
| 816 int value_; | |
| 817 }; | |
| 818 | |
| 819 class WebKitMilliseconds { | |
| 820 public: | |
| 821 static WebKitMilliseconds FromTimeTicks(const TimeTicks& value) { | |
| 822 return WebKitMilliseconds(value.ToInternalValue()); | |
| 823 } | |
| 824 | |
| 825 double ToWebKitTime() { | |
| 826 return value_ / static_cast<double>(base::Time::kMicrosecondsPerSecond); | |
| 827 } | |
| 828 | |
| 829 WebKitMilliseconds operator+(const WebKitDelta& delta) { | |
| 830 return WebKitMilliseconds(value_ + delta.value_); | |
| 831 } | |
| 832 | |
| 833 private: | |
| 834 friend class TimeConverter; | |
| 835 | |
| 836 WebKitMilliseconds(int64 value) : value_(value) {} | |
| 837 | |
| 838 int64 value_; | |
| 839 }; | |
| 840 | |
| 841 class NetDelta { | |
| 842 public: | |
| 843 static NetDelta FromRawDelta(int delta) { | |
| 844 return NetDelta(delta); | |
| 845 } | |
| 846 | |
| 847 private: | |
| 848 friend class NetMilliseconds; | |
| 849 friend class TimeConverter; | |
| 850 | |
| 851 NetDelta(int value) : value_(value) {} | |
| 852 | |
| 853 int value_; | |
| 854 }; | |
| 855 | |
| 856 class NetMilliseconds { | |
| 857 public: | |
| 858 static NetMilliseconds FromTimeTicks(const TimeTicks& ticks) { | |
| 859 return NetMilliseconds(ticks.ToInternalValue()); | |
| 860 } | |
| 861 | |
| 862 NetDelta operator-(const NetMilliseconds& rhs) const { | |
| 863 return NetDelta(value_ - rhs.value_); | |
| 864 } | |
| 865 | |
| 866 private: | |
| 867 friend class TimeConverter; | |
| 868 | |
| 869 NetMilliseconds(int64 value) : value_(value) {} | |
| 870 | |
| 871 int64 value_; | |
| 872 }; | |
| 873 | |
| 874 class TimeConverter { | |
| 875 public: | |
| 876 TimeConverter(const WebKitMilliseconds& lower_bound, | |
| 877 const WebKitMilliseconds& upper_bound, | |
| 878 const NetMilliseconds& net_start_time, | |
| 879 const NetMilliseconds& net_end_time) | |
| 880 : net_start_time_(net_start_time) { | |
| 881 int64 target_range = upper_bound.value_ - lower_bound.value_; | |
| 882 int64 source_range = net_end_time.value_ - net_start_time.value_; | |
| 883 if (source_range <= target_range) { | |
| 884 // We fit! Just shift the midpoints to match. | |
| 885 numerator_ = 1; | |
| 886 denominator_ = 1; | |
| 887 offset_ = ((upper_bound.value_ + lower_bound.value_) - | |
| 888 (net_end_time.value_ + net_start_time.value_)) / 2; | |
| 889 return; | |
| 890 } | |
| 891 // Set up scaling factors, and then deduce shift. | |
| 892 numerator_ = target_range; | |
| 893 denominator_ = source_range; | |
| 894 // Find out what we need to shift by to make this really work. | |
| 895 offset_ = lower_bound.value_ - Convert(net_start_time.value_); | |
| 896 DCHECK_GE(upper_bound.value_, Convert(net_end_time.value_)); | |
| 897 } | |
| 898 | |
| 899 WebKitMilliseconds ConvertMilliseconds(const NetMilliseconds& net_ms) { | |
| 900 NetDelta net_delta = net_ms - net_start_time_; | |
| 901 return WebKitMilliseconds(net_start_time_.value_ + offset_ + | |
| 902 ConvertDelta(net_delta).value_); | |
| 903 } | |
| 904 | |
| 905 WebKitDelta ConvertDelta(const NetDelta& net_delta) { | |
| 906 return WebKitDelta(Convert(net_delta.value_)); | |
| 907 } | |
| 908 | |
| 909 private: | |
| 910 int64 Convert(int64 value) { | |
| 911 if (value <= 0) { | |
| 912 return value; | |
| 913 } | |
| 914 return numerator_ * value / denominator_; | |
| 915 } | |
| 916 | |
| 917 int64 offset_; | |
| 918 int64 numerator_; | |
| 919 int64 denominator_; | |
| 920 NetMilliseconds net_start_time_; | |
| 921 }; | |
| 922 | |
| 923 } // anonymous namespace | |
| 924 | |
| 925 WebURLLoadTiming PopulateWebURLLoadTiming( | |
| 926 const ResourceLoadTimingInfo& net_timing_info, | |
| 927 const TimeTicks& ipc_request_time, | |
| 928 const TimeTicks& net_start_time, | |
| 929 const TimeTicks& net_end_time, | |
| 930 const TimeTicks& ipc_response_time) { | |
| 931 WebKitMilliseconds lower_bound = WebKitMilliseconds::FromTimeTicks( | |
| 932 ipc_request_time); | |
| 933 WebKitMilliseconds upper_bound = WebKitMilliseconds::FromTimeTicks( | |
| 934 ipc_response_time); | |
| 935 NetMilliseconds net_start_ms = NetMilliseconds::FromTimeTicks(net_start_time); | |
| 936 NetMilliseconds net_end_ms = NetMilliseconds::FromTimeTicks(net_end_time); | |
| 937 | |
| 938 TimeConverter time_converter(lower_bound, upper_bound, | |
| 939 net_start_ms, net_end_ms); | |
| 940 | |
| 941 WebURLLoadTiming timing; | |
| 942 timing.initialize(); | |
| 943 | |
| 944 NetMilliseconds base_ms = NetMilliseconds::FromTimeTicks( | |
| 945 net_timing_info.base_ticks); | |
| 946 WebKitMilliseconds adjusted_base = | |
| 947 time_converter.ConvertMilliseconds(base_ms); | |
| 948 timing.setRequestTime(adjusted_base.ToWebKitTime()); | |
| 949 | |
| 950 #define SET_TIME(setter, value) \ | |
| 951 setter(time_converter.ConvertDelta(NetDelta::FromRawDelta(value)) \ | |
| 952 .ToWebKitTime()) | |
| 953 | |
| 954 SET_TIME(timing.setProxyStart, net_timing_info.proxy_start); | |
| 955 SET_TIME(timing.setProxyEnd, net_timing_info.proxy_end); | |
| 956 SET_TIME(timing.setDNSStart, net_timing_info.dns_start); | |
| 957 SET_TIME(timing.setDNSEnd, net_timing_info.dns_end); | |
| 958 SET_TIME(timing.setConnectStart, net_timing_info.connect_start); | |
| 959 SET_TIME(timing.setConnectEnd, net_timing_info.connect_end); | |
| 960 SET_TIME(timing.setSSLStart, net_timing_info.ssl_start); | |
| 961 SET_TIME(timing.setSSLEnd, net_timing_info.ssl_end); | |
| 962 SET_TIME(timing.setSendStart, net_timing_info.send_start); | |
| 963 SET_TIME(timing.setSendEnd, net_timing_info.send_end); | |
| 964 SET_TIME(timing.setReceiveHeadersEnd, net_timing_info.receive_headers_end); | |
| 965 | |
| 966 #undef SET_TIME | |
| 967 | |
| 968 return timing; | |
| 969 } | |
| 970 | |
| 749 } // namespace webkit_glue | 971 } // namespace webkit_glue |
| OLD | NEW |