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 |