Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: webkit/glue/weburlloader_impl.cc

Issue 7602023: Use a monotonic clock (TimeTicks) to report network times to WebCore. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add random test Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698