| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "chrome/browser/renderer_host/async_resource_handler.h" | 5 #include "chrome/browser/renderer_host/async_resource_handler.h" |
| 6 | 6 |
| 7 #include "base/hash_tables.h" |
| 7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 8 #include "base/process.h" | 9 #include "base/process.h" |
| 9 #include "base/shared_memory.h" | 10 #include "base/shared_memory.h" |
| 10 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
| 11 #include "chrome/browser/net/chrome_net_log.h" | 12 #include "chrome/browser/net/chrome_net_log.h" |
| 12 #include "chrome/browser/net/chrome_url_request_context.h" | 13 #include "chrome/browser/net/chrome_url_request_context.h" |
| 13 #include "chrome/browser/net/passive_log_collector.h" | 14 #include "chrome/browser/net/load_timing_observer.h" |
| 14 #include "chrome/browser/renderer_host/global_request_id.h" | 15 #include "chrome/browser/renderer_host/global_request_id.h" |
| 15 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" | 16 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" |
| 16 #include "chrome/common/render_messages.h" | 17 #include "chrome/common/render_messages.h" |
| 17 #include "net/base/io_buffer.h" | 18 #include "net/base/io_buffer.h" |
| 18 #include "net/base/load_flags.h" | 19 #include "net/base/load_flags.h" |
| 19 #include "net/base/net_log.h" | 20 #include "net/base/net_log.h" |
| 20 #include "webkit/glue/resource_loader_bridge.h" | 21 #include "webkit/glue/resource_loader_bridge.h" |
| 21 | 22 |
| 22 using base::Time; | 23 using base::Time; |
| 23 using base::TimeTicks; | 24 using base::TimeTicks; |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 // When reading, we don't know if we are going to get EOF (0 bytes read), so | 28 // When reading, we don't know if we are going to get EOF (0 bytes read), so |
| 28 // we typically have a buffer that we allocated but did not use. We keep | 29 // we typically have a buffer that we allocated but did not use. We keep |
| 29 // this buffer around for the next read as a small optimization. | 30 // this buffer around for the next read as a small optimization. |
| 30 SharedIOBuffer* g_spare_read_buffer = NULL; | 31 SharedIOBuffer* g_spare_read_buffer = NULL; |
| 31 | 32 |
| 32 // The initial size of the shared memory buffer. (32 kilobytes). | 33 // The initial size of the shared memory buffer. (32 kilobytes). |
| 33 const int kInitialReadBufSize = 32768; | 34 const int kInitialReadBufSize = 32768; |
| 34 | 35 |
| 35 // The maximum size of the shared memory buffer. (512 kilobytes). | 36 // The maximum size of the shared memory buffer. (512 kilobytes). |
| 36 const int kMaxReadBufSize = 524288; | 37 const int kMaxReadBufSize = 524288; |
| 37 | 38 |
| 38 // We know that this conversion is not solid and suffers from world clock | |
| 39 // changes, but it should be good enough for the load timing info. | |
| 40 static Time TimeTicksToTime(const TimeTicks& time_ticks) { | |
| 41 static int64 tick_to_time_offset; | |
| 42 static bool tick_to_time_offset_available = false; | |
| 43 if (!tick_to_time_offset_available) { | |
| 44 int64 cur_time = (Time::Now() - Time()).InMicroseconds(); | |
| 45 int64 cur_time_ticks = (TimeTicks::Now() - TimeTicks()).InMicroseconds(); | |
| 46 // If we add this number to a time tick value, it gives the timestamp. | |
| 47 tick_to_time_offset = cur_time - cur_time_ticks; | |
| 48 tick_to_time_offset_available = true; | |
| 49 } | |
| 50 return Time::FromInternalValue(time_ticks.ToInternalValue() + | |
| 51 tick_to_time_offset); | |
| 52 } | |
| 53 | |
| 54 } // namespace | 39 } // namespace |
| 55 | 40 |
| 56 // Our version of IOBuffer that uses shared memory. | 41 // Our version of IOBuffer that uses shared memory. |
| 57 class SharedIOBuffer : public net::IOBuffer { | 42 class SharedIOBuffer : public net::IOBuffer { |
| 58 public: | 43 public: |
| 59 explicit SharedIOBuffer(int buffer_size) | 44 explicit SharedIOBuffer(int buffer_size) |
| 60 : net::IOBuffer(), | 45 : net::IOBuffer(), |
| 61 ok_(false), | 46 ok_(false), |
| 62 buffer_size_(buffer_size) {} | 47 buffer_size_(buffer_size) {} |
| 63 | 48 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 process_handle_(process_handle), | 86 process_handle_(process_handle), |
| 102 rdh_(resource_dispatcher_host), | 87 rdh_(resource_dispatcher_host), |
| 103 next_buffer_size_(kInitialReadBufSize) { | 88 next_buffer_size_(kInitialReadBufSize) { |
| 104 } | 89 } |
| 105 | 90 |
| 106 AsyncResourceHandler::~AsyncResourceHandler() { | 91 AsyncResourceHandler::~AsyncResourceHandler() { |
| 107 } | 92 } |
| 108 | 93 |
| 109 void AsyncResourceHandler::PopulateTimingInfo(URLRequest* request, | 94 void AsyncResourceHandler::PopulateTimingInfo(URLRequest* request, |
| 110 ResourceResponse* response) { | 95 ResourceResponse* response) { |
| 111 uint32 source_id = request->net_log().source().id; | 96 if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)) |
| 97 return; |
| 98 |
| 112 ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>( | 99 ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>( |
| 113 request->net_log().net_log()); | 100 request->net_log().net_log()); |
| 114 | 101 if (chrome_net_log == NULL) |
| 115 PassiveLogCollector* collector = chrome_net_log->passive_collector(); | |
| 116 PassiveLogCollector::SourceTracker* url_tracker = | |
| 117 static_cast<PassiveLogCollector::SourceTracker*>(collector-> | |
| 118 GetTrackerForSourceType(net::NetLog::SOURCE_URL_REQUEST)); | |
| 119 | |
| 120 PassiveLogCollector::SourceInfo* url_request = | |
| 121 url_tracker->GetSourceInfo(source_id); | |
| 122 | |
| 123 if (!url_request) | |
| 124 return; | 102 return; |
| 125 | 103 |
| 126 ResourceResponseHead& response_head = response->response_head; | 104 uint32 source_id = request->net_log().source().id; |
| 127 webkit_glue::ResourceLoaderBridge::LoadTimingInfo& timing = | 105 LoadTimingObserver* observer = chrome_net_log->load_timing_observer(); |
| 128 response_head.load_timing; | 106 LoadTimingObserver::URLRequestRecord* record = |
| 129 | 107 observer->GetURLRequestRecord(source_id); |
| 130 uint32 connect_job_id = net::NetLog::Source::kInvalidId; | 108 if (record) { |
| 131 | 109 response->response_head.connection_id = record->socket_log_id; |
| 132 base::TimeTicks base_time; | 110 response->response_head.connection_reused = record->socket_reused; |
| 133 | 111 response->response_head.load_timing = record->timing; |
| 134 for (PassiveLogCollector::EntryList::const_iterator it = | |
| 135 url_request->entries.begin(); | |
| 136 it != url_request->entries.end(); ++it) { | |
| 137 const PassiveLogCollector::Entry& entry = *it; | |
| 138 | |
| 139 bool is_begin = entry.phase == net::NetLog::PHASE_BEGIN; | |
| 140 bool is_end = entry.phase == net::NetLog::PHASE_END; | |
| 141 | |
| 142 switch (entry.type) { | |
| 143 case net::NetLog::TYPE_URL_REQUEST_START_JOB: | |
| 144 if (is_begin) { | |
| 145 // Reset state so that we captured last redirect only. | |
| 146 timing.base_time = TimeTicksToTime(entry.time); | |
| 147 base_time = entry.time; | |
| 148 connect_job_id = net::NetLog::Source::kInvalidId; | |
| 149 } | |
| 150 break; | |
| 151 case net::NetLog::TYPE_PROXY_SERVICE: | |
| 152 if (is_begin) { | |
| 153 timing.proxy_start = static_cast<int32>( | |
| 154 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 155 } else if (is_end) { | |
| 156 timing.proxy_end = static_cast<int32>( | |
| 157 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 158 } | |
| 159 break; | |
| 160 case net::NetLog::TYPE_SOCKET_POOL: | |
| 161 if (is_begin) { | |
| 162 timing.connect_start = static_cast<int32>( | |
| 163 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 164 } else if (is_end && | |
| 165 connect_job_id != net::NetLog::Source::kInvalidId) { | |
| 166 timing.connect_end = static_cast<int32>( | |
| 167 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 168 } | |
| 169 break; | |
| 170 case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB: | |
| 171 connect_job_id = static_cast<net::NetLogSourceParameter*>( | |
| 172 entry.params.get())->value().id; | |
| 173 break; | |
| 174 case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET: | |
| 175 { | |
| 176 uint32 log_id = static_cast<net::NetLogSourceParameter*>( | |
| 177 entry.params.get())->value().id; | |
| 178 response->response_head.connection_id = | |
| 179 log_id != net::NetLog::Source::kInvalidId ? log_id : 0; | |
| 180 } | |
| 181 break; | |
| 182 case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST: | |
| 183 case net::NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST: | |
| 184 if (is_begin) { | |
| 185 timing.send_start = static_cast<int32>( | |
| 186 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 187 } else if (is_end) { | |
| 188 timing.send_end = static_cast<int32>( | |
| 189 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 190 } | |
| 191 break; | |
| 192 case net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS: | |
| 193 case net::NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS: | |
| 194 if (is_begin) { | |
| 195 timing.receive_headers_start = static_cast<int32>( | |
| 196 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 197 } else if (is_end) { | |
| 198 timing.receive_headers_end = static_cast<int32>( | |
| 199 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 200 } | |
| 201 break; | |
| 202 default: | |
| 203 break; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 // For DNS time, get the ID of the "connect job" from the | |
| 208 // BOUND_TO_CONNECT_JOB entry, in its source info look at the | |
| 209 // HOST_RESOLVER_IMPL times. | |
| 210 if (connect_job_id == net::NetLog::Source::kInvalidId) { | |
| 211 // Clean up connection time to match contract. | |
| 212 timing.connect_start = -1; | |
| 213 timing.connect_end = -1; | |
| 214 return; | |
| 215 } | |
| 216 | |
| 217 PassiveLogCollector::SourceTracker* connect_job_tracker = | |
| 218 static_cast<PassiveLogCollector::SourceTracker*>( | |
| 219 collector->GetTrackerForSourceType(net::NetLog::SOURCE_CONNECT_JOB)); | |
| 220 PassiveLogCollector::SourceInfo* connect_job = | |
| 221 connect_job_tracker->GetSourceInfo(connect_job_id); | |
| 222 if (!connect_job) | |
| 223 return; | |
| 224 | |
| 225 for (PassiveLogCollector::EntryList::const_iterator it = | |
| 226 connect_job->entries.begin(); | |
| 227 it != connect_job->entries.end(); ++it) { | |
| 228 const PassiveLogCollector::Entry& entry = *it; | |
| 229 if (entry.phase == net::NetLog::PHASE_BEGIN && | |
| 230 entry.type == net::NetLog::TYPE_HOST_RESOLVER_IMPL) { | |
| 231 timing.dns_start = static_cast<int32>( | |
| 232 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 233 } else if (entry.phase == net::NetLog::PHASE_END && | |
| 234 entry.type == net::NetLog::TYPE_HOST_RESOLVER_IMPL) { | |
| 235 timing.dns_end = static_cast<int32>( | |
| 236 (entry.time - base_time).InMillisecondsRoundedUp()); | |
| 237 // Connect time already includes dns time, subtract it here. | |
| 238 break; | |
| 239 } | |
| 240 } | 112 } |
| 241 } | 113 } |
| 242 | 114 |
| 243 bool AsyncResourceHandler::OnUploadProgress(int request_id, | 115 bool AsyncResourceHandler::OnUploadProgress(int request_id, |
| 244 uint64 position, | 116 uint64 position, |
| 245 uint64 size) { | 117 uint64 size) { |
| 246 return receiver_->Send(new ViewMsg_Resource_UploadProgress(routing_id_, | 118 return receiver_->Send(new ViewMsg_Resource_UploadProgress(routing_id_, |
| 247 request_id, | 119 request_id, |
| 248 position, size)); | 120 position, size)); |
| 249 } | 121 } |
| 250 | 122 |
| 251 bool AsyncResourceHandler::OnRequestRedirected(int request_id, | 123 bool AsyncResourceHandler::OnRequestRedirected(int request_id, |
| 252 const GURL& new_url, | 124 const GURL& new_url, |
| 253 ResourceResponse* response, | 125 ResourceResponse* response, |
| 254 bool* defer) { | 126 bool* defer) { |
| 255 *defer = true; | 127 *defer = true; |
| 256 URLRequest* request = rdh_->GetURLRequest( | 128 URLRequest* request = rdh_->GetURLRequest( |
| 257 GlobalRequestID(process_id_, request_id)); | 129 GlobalRequestID(process_id_, request_id)); |
| 258 // TODO(pfeldman): enable once migrated to LoadTimingObserver. | 130 PopulateTimingInfo(request, response); |
| 259 if (false && request && (request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)
) | |
| 260 PopulateTimingInfo(request, response); | |
| 261 return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect( | 131 return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect( |
| 262 routing_id_, request_id, new_url, response->response_head)); | 132 routing_id_, request_id, new_url, response->response_head)); |
| 263 } | 133 } |
| 264 | 134 |
| 265 bool AsyncResourceHandler::OnResponseStarted(int request_id, | 135 bool AsyncResourceHandler::OnResponseStarted(int request_id, |
| 266 ResourceResponse* response) { | 136 ResourceResponse* response) { |
| 267 // For changes to the main frame, inform the renderer of the new URL's | 137 // For changes to the main frame, inform the renderer of the new URL's |
| 268 // per-host settings before the request actually commits. This way the | 138 // per-host settings before the request actually commits. This way the |
| 269 // renderer will be able to set these precisely at the time the | 139 // renderer will be able to set these precisely at the time the |
| 270 // request commits, avoiding the possibility of e.g. zooming the old content | 140 // request commits, avoiding the possibility of e.g. zooming the old content |
| 271 // or of having to layout the new content twice. | 141 // or of having to layout the new content twice. |
| 272 URLRequest* request = rdh_->GetURLRequest( | 142 URLRequest* request = rdh_->GetURLRequest( |
| 273 GlobalRequestID(process_id_, request_id)); | 143 GlobalRequestID(process_id_, request_id)); |
| 274 | 144 |
| 275 // TODO(pfeldman): enable once migrated to LoadTimingObserver. | 145 PopulateTimingInfo(request, response); |
| 276 if (false && request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING) | |
| 277 PopulateTimingInfo(request, response); | |
| 278 | 146 |
| 279 ResourceDispatcherHostRequestInfo* info = rdh_->InfoForRequest(request); | 147 ResourceDispatcherHostRequestInfo* info = rdh_->InfoForRequest(request); |
| 280 if (info->resource_type() == ResourceType::MAIN_FRAME) { | 148 if (info->resource_type() == ResourceType::MAIN_FRAME) { |
| 281 GURL request_url(request->url()); | 149 GURL request_url(request->url()); |
| 282 ChromeURLRequestContext* context = | 150 ChromeURLRequestContext* context = |
| 283 static_cast<ChromeURLRequestContext*>(request->context()); | 151 static_cast<ChromeURLRequestContext*>(request->context()); |
| 284 if (context) { | 152 if (context) { |
| 285 receiver_->Send(new ViewMsg_SetContentSettingsForLoadingURL( | 153 receiver_->Send(new ViewMsg_SetContentSettingsForLoadingURL( |
| 286 info->route_id(), request_url, | 154 info->route_id(), request_url, |
| 287 context->host_content_settings_map()->GetContentSettings( | 155 context->host_content_settings_map()->GetContentSettings( |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 | 269 |
| 402 // static | 270 // static |
| 403 void AsyncResourceHandler::GlobalCleanup() { | 271 void AsyncResourceHandler::GlobalCleanup() { |
| 404 if (g_spare_read_buffer) { | 272 if (g_spare_read_buffer) { |
| 405 // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer(). | 273 // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer(). |
| 406 SharedIOBuffer* tmp = g_spare_read_buffer; | 274 SharedIOBuffer* tmp = g_spare_read_buffer; |
| 407 g_spare_read_buffer = NULL; | 275 g_spare_read_buffer = NULL; |
| 408 tmp->Release(); | 276 tmp->Release(); |
| 409 } | 277 } |
| 410 } | 278 } |
| OLD | NEW |