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

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: Use strong typing 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/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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698