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