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& initiation_time, | |
149 const TimeTicks& start_time, | |
150 const TimeTicks& end_time, | |
151 const TimeTicks& callback_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, initiation_time, start_time, end_time, callback_time); |
172 timing.setRequestTime(timing_info.base_time.ToDoubleT()); | |
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); | 179 response->setLoadTiming(timing); |
185 } | 180 } |
186 | 181 |
187 if (info.devtools_info.get()) { | 182 if (info.devtools_info.get()) { |
188 WebHTTPLoadInfo load_info; | 183 WebHTTPLoadInfo load_info; |
189 | 184 |
190 load_info.setHTTPStatusCode(info.devtools_info->http_status_code); | 185 load_info.setHTTPStatusCode(info.devtools_info->http_status_code); |
191 load_info.setHTTPStatusText(WebString::fromUTF8( | 186 load_info.setHTTPStatusText(WebString::fromUTF8( |
192 info.devtools_info->http_status_text)); | 187 info.devtools_info->http_status_text)); |
193 load_info.setEncodedDataLength(info.encoded_data_length); | 188 load_info.setEncodedDataLength(info.encoded_data_length); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 void Start( | 257 void Start( |
263 const WebURLRequest& request, | 258 const WebURLRequest& request, |
264 ResourceLoaderBridge::SyncLoadResponse* sync_load_response); | 259 ResourceLoaderBridge::SyncLoadResponse* sync_load_response); |
265 void UpdateRoutingId(int new_routing_id); | 260 void UpdateRoutingId(int new_routing_id); |
266 | 261 |
267 // ResourceLoaderBridge::Peer methods: | 262 // ResourceLoaderBridge::Peer methods: |
268 virtual void OnUploadProgress(uint64 position, uint64 size); | 263 virtual void OnUploadProgress(uint64 position, uint64 size); |
269 virtual bool OnReceivedRedirect( | 264 virtual bool OnReceivedRedirect( |
270 const GURL& new_url, | 265 const GURL& new_url, |
271 const ResourceResponseInfo& info, | 266 const ResourceResponseInfo& info, |
267 const TimeTicks& start_time, | |
268 const TimeTicks& end_time, | |
272 bool* has_new_first_party_for_cookies, | 269 bool* has_new_first_party_for_cookies, |
273 GURL* new_first_party_for_cookies); | 270 GURL* new_first_party_for_cookies); |
274 virtual void OnReceivedResponse(const ResourceResponseInfo& info); | 271 virtual void OnReceivedResponse(const ResourceResponseInfo& info, |
272 const TimeTicks& start_time, | |
273 const TimeTicks& end_time); | |
275 virtual void OnDownloadedData(int len); | 274 virtual void OnDownloadedData(int len); |
276 virtual void OnReceivedData(const char* data, | 275 virtual void OnReceivedData(const char* data, |
277 int data_length, | 276 int data_length, |
278 int encoded_data_length); | 277 int encoded_data_length); |
279 virtual void OnReceivedCachedMetadata(const char* data, int len); | 278 virtual void OnReceivedCachedMetadata(const char* data, int len); |
280 virtual void OnCompletedRequest(const net::URLRequestStatus& status, | 279 virtual void OnCompletedRequest(const net::URLRequestStatus& status, |
281 const std::string& security_info, | 280 const std::string& security_info, |
282 const base::Time& completion_time); | 281 const TimeTicks& completion_time); |
283 | 282 |
284 private: | 283 private: |
285 friend class base::RefCounted<Context>; | 284 friend class base::RefCounted<Context>; |
286 ~Context() {} | 285 ~Context() {} |
287 | 286 |
288 // We can optimize the handling of data URLs in most cases. | 287 // We can optimize the handling of data URLs in most cases. |
289 bool CanHandleDataURL(const GURL& url) const; | 288 bool CanHandleDataURL(const GURL& url) const; |
290 void HandleDataURL(); | 289 void HandleDataURL(); |
291 | 290 |
292 WebURLLoaderImpl* loader_; | 291 WebURLLoaderImpl* loader_; |
293 WebURLRequest request_; | 292 WebURLRequest request_; |
294 WebURLLoaderClient* client_; | 293 WebURLLoaderClient* client_; |
294 TimeTicks initiation_time_; | |
295 scoped_ptr<ResourceLoaderBridge> bridge_; | 295 scoped_ptr<ResourceLoaderBridge> bridge_; |
296 scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; | 296 scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; |
297 scoped_ptr<MultipartResponseDelegate> multipart_delegate_; | 297 scoped_ptr<MultipartResponseDelegate> multipart_delegate_; |
298 scoped_ptr<ResourceLoaderBridge> completed_bridge_; | 298 scoped_ptr<ResourceLoaderBridge> completed_bridge_; |
299 }; | 299 }; |
300 | 300 |
301 WebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader) | 301 WebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader) |
302 : loader_(loader), | 302 : loader_(loader), |
303 client_(NULL) { | 303 client_(NULL) { |
304 } | 304 } |
(...skipping 30 matching lines...) Expand all Loading... | |
335 DCHECK(!bridge_.get()); | 335 DCHECK(!bridge_.get()); |
336 | 336 |
337 request_ = request; // Save the request. | 337 request_ = request; // Save the request. |
338 | 338 |
339 GURL url = request.url(); | 339 GURL url = request.url(); |
340 if (url.SchemeIs("data") && CanHandleDataURL(url)) { | 340 if (url.SchemeIs("data") && CanHandleDataURL(url)) { |
341 if (sync_load_response) { | 341 if (sync_load_response) { |
342 // This is a sync load. Do the work now. | 342 // This is a sync load. Do the work now. |
343 sync_load_response->url = url; | 343 sync_load_response->url = url; |
344 std::string data; | 344 std::string data; |
345 TimeTicks response_time; | |
345 GetInfoFromDataURL(sync_load_response->url, sync_load_response, | 346 GetInfoFromDataURL(sync_load_response->url, sync_load_response, |
346 &sync_load_response->data, | 347 &sync_load_response->data, |
347 &sync_load_response->status); | 348 &sync_load_response->status, &response_time); |
349 sync_load_response->start_time = response_time; | |
350 sync_load_response->end_time = response_time; | |
348 } else { | 351 } else { |
349 AddRef(); // Balanced in OnCompletedRequest | 352 AddRef(); // Balanced in OnCompletedRequest |
350 MessageLoop::current()->PostTask(FROM_HERE, | 353 MessageLoop::current()->PostTask(FROM_HERE, |
351 NewRunnableMethod(this, &Context::HandleDataURL)); | 354 NewRunnableMethod(this, &Context::HandleDataURL)); |
352 } | 355 } |
353 return; | 356 return; |
354 } | 357 } |
355 | 358 |
356 GURL referrer_url( | 359 GURL referrer_url( |
357 request.httpHeaderField(WebString::fromUTF8("Referer")).utf8()); | 360 request.httpHeaderField(WebString::fromUTF8("Referer")).utf8()); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
445 case WebHTTPBody::Element::TypeBlob: | 448 case WebHTTPBody::Element::TypeBlob: |
446 bridge_->AppendBlobToUpload(GURL(element.blobURL)); | 449 bridge_->AppendBlobToUpload(GURL(element.blobURL)); |
447 break; | 450 break; |
448 default: | 451 default: |
449 NOTREACHED(); | 452 NOTREACHED(); |
450 } | 453 } |
451 } | 454 } |
452 bridge_->SetUploadIdentifier(request.httpBody().identifier()); | 455 bridge_->SetUploadIdentifier(request.httpBody().identifier()); |
453 } | 456 } |
454 | 457 |
458 initiation_time_ = TimeTicks::Now(); | |
455 if (sync_load_response) { | 459 if (sync_load_response) { |
456 bridge_->SyncLoad(sync_load_response); | 460 bridge_->SyncLoad(sync_load_response); |
457 return; | 461 return; |
458 } | 462 } |
459 | 463 |
460 if (bridge_->Start(this)) { | 464 if (bridge_->Start(this)) { |
461 AddRef(); // Balanced in OnCompletedRequest | 465 AddRef(); // Balanced in OnCompletedRequest |
462 } else { | 466 } else { |
463 bridge_.reset(); | 467 bridge_.reset(); |
464 } | 468 } |
465 } | 469 } |
466 | 470 |
467 void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) { | 471 void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) { |
468 if (client_) | 472 if (client_) |
469 client_->didSendData(loader_, position, size); | 473 client_->didSendData(loader_, position, size); |
470 } | 474 } |
471 | 475 |
472 bool WebURLLoaderImpl::Context::OnReceivedRedirect( | 476 bool WebURLLoaderImpl::Context::OnReceivedRedirect( |
473 const GURL& new_url, | 477 const GURL& new_url, |
474 const ResourceResponseInfo& info, | 478 const ResourceResponseInfo& info, |
479 const TimeTicks& start_time, | |
480 const TimeTicks& end_time, | |
475 bool* has_new_first_party_for_cookies, | 481 bool* has_new_first_party_for_cookies, |
476 GURL* new_first_party_for_cookies) { | 482 GURL* new_first_party_for_cookies) { |
477 if (!client_) | 483 if (!client_) |
478 return false; | 484 return false; |
479 | 485 |
486 TimeTicks callback_time = TimeTicks::Now(); | |
480 WebURLResponse response; | 487 WebURLResponse response; |
481 response.initialize(); | 488 response.initialize(); |
482 PopulateURLResponse(request_.url(), info, &response); | 489 PopulateURLResponse(request_.url(), info, initiation_time_, start_time, |
490 end_time, callback_time, &response); | |
483 | 491 |
484 // TODO(darin): We lack sufficient information to construct the actual | 492 // TODO(darin): We lack sufficient information to construct the actual |
485 // request that resulted from the redirect. | 493 // request that resulted from the redirect. |
486 WebURLRequest new_request(new_url); | 494 WebURLRequest new_request(new_url); |
487 new_request.setFirstPartyForCookies(request_.firstPartyForCookies()); | 495 new_request.setFirstPartyForCookies(request_.firstPartyForCookies()); |
488 new_request.setDownloadToFile(request_.downloadToFile()); | 496 new_request.setDownloadToFile(request_.downloadToFile()); |
489 | 497 |
490 WebString referrer_string = WebString::fromUTF8("Referer"); | 498 WebString referrer_string = WebString::fromUTF8("Referer"); |
491 WebString referrer = request_.httpHeaderField(referrer_string); | 499 WebString referrer = request_.httpHeaderField(referrer_string); |
492 if (!WebSecurityPolicy::shouldHideReferrer(new_url, referrer)) | 500 if (!WebSecurityPolicy::shouldHideReferrer(new_url, referrer)) |
(...skipping 11 matching lines...) Expand all Loading... | |
504 if (new_url == GURL(new_request.url())) | 512 if (new_url == GURL(new_request.url())) |
505 return true; | 513 return true; |
506 | 514 |
507 // We assume that WebKit only changes the URL to suppress a redirect, and we | 515 // 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. | 516 // assume that it does so by setting it to be invalid. |
509 DCHECK(!new_request.url().isValid()); | 517 DCHECK(!new_request.url().isValid()); |
510 return false; | 518 return false; |
511 } | 519 } |
512 | 520 |
513 void WebURLLoaderImpl::Context::OnReceivedResponse( | 521 void WebURLLoaderImpl::Context::OnReceivedResponse( |
514 const ResourceResponseInfo& info) { | 522 const ResourceResponseInfo& info, |
523 const TimeTicks& start_time, | |
524 const TimeTicks& end_time) { | |
515 if (!client_) | 525 if (!client_) |
516 return; | 526 return; |
517 | 527 |
528 TimeTicks callback_time = TimeTicks::Now(); | |
518 WebURLResponse response; | 529 WebURLResponse response; |
519 response.initialize(); | 530 response.initialize(); |
520 PopulateURLResponse(request_.url(), info, &response); | 531 PopulateURLResponse(request_.url(), info, initiation_time_, start_time, |
532 end_time, callback_time, &response); | |
521 | 533 |
522 bool show_raw_listing = (GURL(request_.url()).query() == "raw"); | 534 bool show_raw_listing = (GURL(request_.url()).query() == "raw"); |
523 | 535 |
524 if (info.mime_type == "text/vnd.chromium.ftp-dir") { | 536 if (info.mime_type == "text/vnd.chromium.ftp-dir") { |
525 if (show_raw_listing) { | 537 if (show_raw_listing) { |
526 // Set the MIME type to plain text to prevent any active content. | 538 // Set the MIME type to plain text to prevent any active content. |
527 response.setMIMEType("text/plain"); | 539 response.setMIMEType("text/plain"); |
528 } else { | 540 } else { |
529 // We're going to produce a parsed listing in HTML. | 541 // We're going to produce a parsed listing in HTML. |
530 response.setMIMEType("text/html"); | 542 response.setMIMEType("text/html"); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
587 | 599 |
588 void WebURLLoaderImpl::Context::OnReceivedCachedMetadata( | 600 void WebURLLoaderImpl::Context::OnReceivedCachedMetadata( |
589 const char* data, int len) { | 601 const char* data, int len) { |
590 if (client_) | 602 if (client_) |
591 client_->didReceiveCachedMetadata(loader_, data, len); | 603 client_->didReceiveCachedMetadata(loader_, data, len); |
592 } | 604 } |
593 | 605 |
594 void WebURLLoaderImpl::Context::OnCompletedRequest( | 606 void WebURLLoaderImpl::Context::OnCompletedRequest( |
595 const net::URLRequestStatus& status, | 607 const net::URLRequestStatus& status, |
596 const std::string& security_info, | 608 const std::string& security_info, |
597 const base::Time& completion_time) { | 609 const TimeTicks& completion_time) { |
610 TimeTicks monotonic_completion_time = std::min(completion_time, | |
611 TimeTicks::Now()); | |
598 if (ftp_listing_delegate_.get()) { | 612 if (ftp_listing_delegate_.get()) { |
599 ftp_listing_delegate_->OnCompletedRequest(); | 613 ftp_listing_delegate_->OnCompletedRequest(); |
600 ftp_listing_delegate_.reset(NULL); | 614 ftp_listing_delegate_.reset(NULL); |
601 } else if (multipart_delegate_.get()) { | 615 } else if (multipart_delegate_.get()) { |
602 multipart_delegate_->OnCompletedRequest(); | 616 multipart_delegate_->OnCompletedRequest(); |
603 multipart_delegate_.reset(NULL); | 617 multipart_delegate_.reset(NULL); |
604 } | 618 } |
605 | 619 |
606 // Prevent any further IPC to the browser now that we're complete, but | 620 // 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. | 621 // don't delete it to keep any downloaded temp files alive. |
(...skipping 11 matching lines...) Expand all Loading... | |
619 error_code = status.error(); | 633 error_code = status.error(); |
620 } | 634 } |
621 WebURLError error; | 635 WebURLError error; |
622 if (error_code == net::ERR_ABORTED) | 636 if (error_code == net::ERR_ABORTED) |
623 error.isCancellation = true; | 637 error.isCancellation = true; |
624 error.domain = WebString::fromUTF8(net::kErrorDomain); | 638 error.domain = WebString::fromUTF8(net::kErrorDomain); |
625 error.reason = error_code; | 639 error.reason = error_code; |
626 error.unreachableURL = request_.url(); | 640 error.unreachableURL = request_.url(); |
627 client_->didFail(loader_, error); | 641 client_->didFail(loader_, error); |
628 } else { | 642 } else { |
629 client_->didFinishLoading(loader_, completion_time.ToDoubleT()); | 643 client_->didFinishLoading( |
644 loader_, completion_time.ToInternalValue() / | |
645 static_cast<double>(base::Time::kMicrosecondsPerSecond)); | |
630 } | 646 } |
631 } | 647 } |
632 | 648 |
633 // We are done with the bridge now, and so we need to release the reference | 649 // 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 | 650 // to ourselves that we took on behalf of the bridge. This may cause our |
635 // destruction. | 651 // destruction. |
636 Release(); | 652 Release(); |
637 } | 653 } |
638 | 654 |
639 bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const { | 655 bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const { |
(...skipping 17 matching lines...) Expand all Loading... | |
657 return true; | 673 return true; |
658 | 674 |
659 return false; | 675 return false; |
660 } | 676 } |
661 | 677 |
662 void WebURLLoaderImpl::Context::HandleDataURL() { | 678 void WebURLLoaderImpl::Context::HandleDataURL() { |
663 ResourceResponseInfo info; | 679 ResourceResponseInfo info; |
664 net::URLRequestStatus status; | 680 net::URLRequestStatus status; |
665 std::string data; | 681 std::string data; |
666 | 682 |
667 if (GetInfoFromDataURL(request_.url(), &info, &data, &status)) { | 683 TimeTicks response_time; |
668 OnReceivedResponse(info); | 684 if (GetInfoFromDataURL(request_.url(), &info, &data, &status, |
685 &response_time)) { | |
686 OnReceivedResponse(info, response_time, response_time); | |
669 if (!data.empty()) | 687 if (!data.empty()) |
670 OnReceivedData(data.data(), data.size(), 0); | 688 OnReceivedData(data.data(), data.size(), 0); |
671 } | 689 } |
672 | 690 |
673 OnCompletedRequest(status, info.security_info, base::Time::Now()); | 691 OnCompletedRequest(status, info.security_info, TimeTicks::Now()); |
674 } | 692 } |
675 | 693 |
676 // WebURLLoaderImpl ----------------------------------------------------------- | 694 // WebURLLoaderImpl ----------------------------------------------------------- |
677 | 695 |
678 WebURLLoaderImpl::WebURLLoaderImpl() | 696 WebURLLoaderImpl::WebURLLoaderImpl() |
679 : ALLOW_THIS_IN_INITIALIZER_LIST(context_(new Context(this))) { | 697 : ALLOW_THIS_IN_INITIALIZER_LIST(context_(new Context(this))) { |
680 } | 698 } |
681 | 699 |
682 WebURLLoaderImpl::~WebURLLoaderImpl() { | 700 WebURLLoaderImpl::~WebURLLoaderImpl() { |
683 cancel(); | 701 cancel(); |
684 } | 702 } |
685 | 703 |
686 void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request, | 704 void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request, |
687 WebURLResponse& response, | 705 WebURLResponse& response, |
688 WebURLError& error, | 706 WebURLError& error, |
689 WebData& data) { | 707 WebData& data) { |
708 TimeTicks initiation_time = TimeTicks::Now(); | |
690 ResourceLoaderBridge::SyncLoadResponse sync_load_response; | 709 ResourceLoaderBridge::SyncLoadResponse sync_load_response; |
691 context_->Start(request, &sync_load_response); | 710 context_->Start(request, &sync_load_response); |
711 TimeTicks completion_time = TimeTicks::Now(); | |
692 | 712 |
693 const GURL& final_url = sync_load_response.url; | 713 const GURL& final_url = sync_load_response.url; |
694 | 714 |
695 // TODO(tc): For file loads, we may want to include a more descriptive | 715 // TODO(tc): For file loads, we may want to include a more descriptive |
696 // status code or status text. | 716 // status code or status text. |
697 const net::URLRequestStatus::Status& status = | 717 const net::URLRequestStatus::Status& status = |
698 sync_load_response.status.status(); | 718 sync_load_response.status.status(); |
699 if (status != net::URLRequestStatus::SUCCESS && | 719 if (status != net::URLRequestStatus::SUCCESS && |
700 status != net::URLRequestStatus::HANDLED_EXTERNALLY) { | 720 status != net::URLRequestStatus::HANDLED_EXTERNALLY) { |
701 response.setURL(final_url); | 721 response.setURL(final_url); |
702 error.domain = WebString::fromUTF8(net::kErrorDomain); | 722 error.domain = WebString::fromUTF8(net::kErrorDomain); |
703 error.reason = sync_load_response.status.error(); | 723 error.reason = sync_load_response.status.error(); |
704 error.unreachableURL = final_url; | 724 error.unreachableURL = final_url; |
705 return; | 725 return; |
706 } | 726 } |
707 | 727 |
708 PopulateURLResponse(final_url, sync_load_response, &response); | 728 PopulateURLResponse(final_url, sync_load_response, initiation_time, |
729 sync_load_response.start_time, | |
730 sync_load_response.end_time, completion_time, &response); | |
709 | 731 |
710 data.assign(sync_load_response.data.data(), | 732 data.assign(sync_load_response.data.data(), |
711 sync_load_response.data.size()); | 733 sync_load_response.data.size()); |
712 } | 734 } |
713 | 735 |
714 void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request, | 736 void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request, |
715 WebURLLoaderClient* client) { | 737 WebURLLoaderClient* client) { |
716 DCHECK(!context_->client()); | 738 DCHECK(!context_->client()); |
717 | 739 |
718 context_->set_client(client); | 740 context_->set_client(client); |
719 context_->Start(request, NULL); | 741 context_->Start(request, NULL); |
720 } | 742 } |
721 | 743 |
722 void WebURLLoaderImpl::cancel() { | 744 void WebURLLoaderImpl::cancel() { |
723 context_->Cancel(); | 745 context_->Cancel(); |
724 } | 746 } |
725 | 747 |
726 void WebURLLoaderImpl::setDefersLoading(bool value) { | 748 void WebURLLoaderImpl::setDefersLoading(bool value) { |
727 context_->SetDefersLoading(value); | 749 context_->SetDefersLoading(value); |
728 } | 750 } |
729 | 751 |
730 void WebURLLoaderImpl::UpdateRoutingId(int new_routing_id) { | 752 void WebURLLoaderImpl::UpdateRoutingId(int new_routing_id) { |
731 context_->UpdateRoutingId(new_routing_id); | 753 context_->UpdateRoutingId(new_routing_id); |
732 } | 754 } |
733 | 755 |
756 int64 CorrectTime(int64 raw_time, int64 numerator, int64 denominator) { | |
757 if (raw_time <= 0) { | |
758 return raw_time; | |
759 } | |
760 return numerator * raw_time / denominator; | |
761 } | |
762 | |
763 // |timing_info| originates in the network layer, which may live in another | |
764 // (browser) process. These values are recorded and passed as TimeTicks. On | |
765 // Windows, TimeTicks do not tick consistently across processes. So one process | |
766 // may be slightly ahead of the other and the delta between them may drift. In | |
767 // practice, they usually differ by a few ms or less, and never more than 10 ms. | |
jar (doing other things)
2011/10/15 02:42:13
Since a common resolution is 15ms. The drift at an
James Simonsen
2011/10/18 23:15:47
We use timeGetTime() on Windows, which attempts to
jar (doing other things)
2011/11/08 03:42:49
timeGetTime() returns a DWORD, which is in units o
| |
768 // | |
769 // To make things consistent for WebKit, we must correct for this cross-process | |
770 // skew. To do this, we record 4 times: | |
771 // - |initiation_time|: when this process started handling the request. | |
jar (doing other things)
2011/10/15 02:42:13
Is this when you *tried* to contact the browser pr
James Simonsen
2011/10/18 23:15:47
The former. I've updated the comment.
| |
772 // - |start_time|: when the network layer (other process) started handling it. | |
773 // - |end_time|: when the network layer finished the request. | |
774 // - |callback_time|: when this process received the response from the network | |
775 // layer. | |
776 // Because of the monotonic clock, all members of |timing_info| will occur | |
777 // between start_time and end_time. If |start_time| and/or |end_time| are out of | |
778 // order wrt |initiation_time| and |callback_time|, then we adjust the bounds to | |
779 // fit within |initiation_time| and |callback_time|. When the bounds are | |
780 // adjusted, we scale all of the members of |timing_info| so that they are | |
781 // relatively the same time delta from |start_time| and |end_time| as they were | |
782 // before adjustment. | |
jar (doing other things)
2011/10/15 02:42:13
I'm still trying to understand the goal. Is the g
James Simonsen
2011/10/18 23:15:47
I think we're talking about the same thing, but I'
| |
783 WebURLLoadTiming PopulateWebURLLoadTiming( | |
784 const ResourceLoadTimingInfo& timing_info, | |
785 const TimeTicks& initiation_time, | |
786 const TimeTicks& start_time, | |
787 const TimeTicks& end_time, | |
788 const TimeTicks& callback_time) { | |
789 int64 lower_bound = start_time.ToInternalValue(); | |
jar (doing other things)
2011/10/15 02:42:13
nit: better might be
int64 lower_bound =
std
James Simonsen
2011/10/18 23:15:47
That has a slightly different meaning.
The curren
| |
790 if (start_time < initiation_time) { | |
791 lower_bound = initiation_time.ToInternalValue(); | |
792 } | |
793 int64 upper_bound = end_time.ToInternalValue(); | |
794 if (end_time > callback_time) { | |
795 upper_bound = callback_time.ToInternalValue(); | |
796 } | |
797 if (lower_bound > upper_bound) { | |
798 lower_bound = upper_bound; | |
799 } | |
800 | |
801 int64 numerator = upper_bound - lower_bound; | |
802 int64 denominator = (end_time - start_time).ToInternalValue(); | |
jar (doing other things)
2011/10/15 02:42:13
Hmm... with a common 15ms granularity, I would ass
James Simonsen
2011/10/18 23:15:47
As above, we do get higher resolution numbers.
Al
| |
803 if (denominator == 0) { | |
804 numerator = 0; | |
805 denominator = 1; | |
806 } | |
807 | |
808 int64 adjusted_base = | |
809 lower_bound + | |
810 numerator * | |
811 (timing_info.base_ticks - start_time).ToInternalValue() / | |
812 denominator; | |
813 | |
814 WebURLLoadTiming timing; | |
815 timing.initialize(); | |
816 timing.setRequestTime( | |
817 adjusted_base / | |
818 static_cast<double>(base::Time::kMicrosecondsPerSecond)); | |
819 timing.setProxyStart( | |
820 CorrectTime(timing_info.proxy_start, numerator, denominator)); | |
821 timing.setProxyEnd( | |
822 CorrectTime(timing_info.proxy_end, numerator, denominator)); | |
823 timing.setDNSStart( | |
824 CorrectTime(timing_info.dns_start, numerator, denominator)); | |
825 timing.setDNSEnd( | |
826 CorrectTime(timing_info.dns_end, numerator, denominator)); | |
827 timing.setConnectStart( | |
828 CorrectTime(timing_info.connect_start, numerator, denominator)); | |
829 timing.setConnectEnd( | |
830 CorrectTime(timing_info.connect_end, numerator, denominator)); | |
831 timing.setSSLStart( | |
832 CorrectTime(timing_info.ssl_start, numerator, denominator)); | |
833 timing.setSSLEnd( | |
834 CorrectTime(timing_info.ssl_end, numerator, denominator)); | |
835 timing.setSendStart( | |
836 CorrectTime(timing_info.send_start, numerator, denominator)); | |
837 timing.setSendEnd( | |
838 CorrectTime(timing_info.send_end, numerator, denominator)); | |
839 timing.setReceiveHeadersEnd( | |
840 CorrectTime(timing_info.receive_headers_end, numerator, denominator)); | |
841 | |
842 return timing; | |
843 } | |
844 | |
734 } // namespace webkit_glue | 845 } // namespace webkit_glue |
OLD | NEW |