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