| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading |
| 6 | 6 |
| 7 #include "content/child/resource_dispatcher.h" | 7 #include "content/child/resource_dispatcher.h" |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/debug/alias.h" | 12 #include "base/debug/alias.h" |
| 13 #include "base/debug/dump_without_crashing.h" | 13 #include "base/debug/dump_without_crashing.h" |
| 14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
| 15 #include "base/memory/shared_memory.h" | 15 #include "base/memory/shared_memory.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "content/child/request_extra_data.h" | 19 #include "content/child/request_extra_data.h" |
| 20 #include "content/child/request_info.h" | 20 #include "content/child/request_info.h" |
| 21 #include "content/child/shared_memory_received_data_factory.h" |
| 21 #include "content/child/site_isolation_policy.h" | 22 #include "content/child/site_isolation_policy.h" |
| 22 #include "content/child/sync_load_response.h" | 23 #include "content/child/sync_load_response.h" |
| 23 #include "content/child/threaded_data_provider.h" | 24 #include "content/child/threaded_data_provider.h" |
| 24 #include "content/common/inter_process_time_ticks_converter.h" | 25 #include "content/common/inter_process_time_ticks_converter.h" |
| 25 #include "content/common/resource_messages.h" | 26 #include "content/common/resource_messages.h" |
| 27 #include "content/public/child/fixed_received_data.h" |
| 26 #include "content/public/child/request_peer.h" | 28 #include "content/public/child/request_peer.h" |
| 27 #include "content/public/child/resource_dispatcher_delegate.h" | 29 #include "content/public/child/resource_dispatcher_delegate.h" |
| 28 #include "content/public/common/resource_response.h" | 30 #include "content/public/common/resource_response.h" |
| 29 #include "content/public/common/resource_type.h" | 31 #include "content/public/common/resource_type.h" |
| 30 #include "net/base/net_errors.h" | 32 #include "net/base/net_errors.h" |
| 31 #include "net/base/net_util.h" | 33 #include "net/base/net_util.h" |
| 32 #include "net/base/request_priority.h" | 34 #include "net/base/request_priority.h" |
| 33 #include "net/http/http_response_headers.h" | 35 #include "net/http/http_response_headers.h" |
| 34 | 36 |
| 35 namespace content { | 37 namespace content { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer"); | 186 TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer"); |
| 185 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 187 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 186 if (!request_info) | 188 if (!request_info) |
| 187 return; | 189 return; |
| 188 | 190 |
| 189 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); | 191 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); |
| 190 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); | 192 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); |
| 191 | 193 |
| 192 request_info->buffer.reset( | 194 request_info->buffer.reset( |
| 193 new base::SharedMemory(shm_handle, true)); // read only | 195 new base::SharedMemory(shm_handle, true)); // read only |
| 196 request_info->received_data_factory = |
| 197 make_scoped_refptr(new SharedMemoryReceivedDataFactory( |
| 198 message_sender_, request_id, request_info->buffer)); |
| 194 | 199 |
| 195 bool ok = request_info->buffer->Map(shm_size); | 200 bool ok = request_info->buffer->Map(shm_size); |
| 196 if (!ok) { | 201 if (!ok) { |
| 197 // Added to help debug crbug/160401. | 202 // Added to help debug crbug/160401. |
| 198 base::ProcessId renderer_pid_copy = renderer_pid; | 203 base::ProcessId renderer_pid_copy = renderer_pid; |
| 199 base::debug::Alias(&renderer_pid_copy); | 204 base::debug::Alias(&renderer_pid_copy); |
| 200 | 205 |
| 201 base::SharedMemoryHandle shm_handle_copy = shm_handle; | 206 base::SharedMemoryHandle shm_handle_copy = shm_handle; |
| 202 base::debug::Alias(&shm_handle_copy); | 207 base::debug::Alias(&shm_handle_copy); |
| 203 | 208 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 215 TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData"); | 220 TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData"); |
| 216 DCHECK_GT(data_length, 0); | 221 DCHECK_GT(data_length, 0); |
| 217 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 222 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 218 bool send_ack = true; | 223 bool send_ack = true; |
| 219 if (request_info && data_length > 0) { | 224 if (request_info && data_length > 0) { |
| 220 CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); | 225 CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); |
| 221 CHECK_GE(request_info->buffer_size, data_offset + data_length); | 226 CHECK_GE(request_info->buffer_size, data_offset + data_length); |
| 222 | 227 |
| 223 // Ensure that the SHM buffer remains valid for the duration of this scope. | 228 // Ensure that the SHM buffer remains valid for the duration of this scope. |
| 224 // It is possible for Cancel() to be called before we exit this scope. | 229 // It is possible for Cancel() to be called before we exit this scope. |
| 225 linked_ptr<base::SharedMemory> retain_buffer(request_info->buffer); | 230 // SharedMemoryReceivedDataFactory stores the SHM buffer inside it. |
| 231 scoped_refptr<SharedMemoryReceivedDataFactory> factory( |
| 232 request_info->received_data_factory); |
| 226 | 233 |
| 227 base::TimeTicks time_start = base::TimeTicks::Now(); | 234 base::TimeTicks time_start = base::TimeTicks::Now(); |
| 228 | 235 |
| 229 const char* data_start = static_cast<char*>(request_info->buffer->memory()); | 236 const char* data_start = static_cast<char*>(request_info->buffer->memory()); |
| 230 CHECK(data_start); | 237 CHECK(data_start); |
| 231 CHECK(data_start + data_offset); | 238 CHECK(data_start + data_offset); |
| 232 const char* data_ptr = data_start + data_offset; | 239 const char* data_ptr = data_start + data_offset; |
| 233 | 240 |
| 234 // Check whether this response data is compliant with our cross-site | 241 // Check whether this response data is compliant with our cross-site |
| 235 // document blocking policy. We only do this for the first packet. | 242 // document blocking policy. We only do this for the first packet. |
| 236 std::string alternative_data; | 243 std::string alternative_data; |
| 237 if (request_info->site_isolation_metadata.get()) { | 244 if (request_info->site_isolation_metadata.get()) { |
| 238 request_info->blocked_response = | 245 request_info->blocked_response = SiteIsolationPolicy::ShouldBlockResponse( |
| 239 SiteIsolationPolicy::ShouldBlockResponse( | 246 request_info->site_isolation_metadata, data_ptr, data_length, |
| 240 request_info->site_isolation_metadata, data_ptr, data_length, | 247 &alternative_data); |
| 241 &alternative_data); | |
| 242 request_info->site_isolation_metadata.reset(); | 248 request_info->site_isolation_metadata.reset(); |
| 249 } |
| 243 | 250 |
| 244 // When the response is blocked we may have any alternative data to | 251 // When the response is blocked we may have any alternative data to |
| 245 // send to the renderer. When |alternative_data| is zero-sized, we do not | 252 // send to the renderer. |
| 246 // call peer's callback. | 253 // When |alternative_data| is zero-sized, we do not call peer's callback. |
| 247 if (request_info->blocked_response && !alternative_data.empty()) { | 254 if (!request_info->blocked_response || !alternative_data.empty()) { |
| 248 data_ptr = alternative_data.data(); | 255 if (request_info->threaded_data_provider) { |
| 249 data_length = alternative_data.size(); | 256 // TODO(yhirano): Use |alternative_data| when it is not null. |
| 250 encoded_data_length = alternative_data.size(); | 257 // A threaded data provider will take care of its own ACKing, as the |
| 258 // data may be processed later on another thread. |
| 259 send_ack = false; |
| 260 request_info->threaded_data_provider->OnReceivedDataOnForegroundThread( |
| 261 data_ptr, data_length, encoded_data_length); |
| 262 } else { |
| 263 scoped_ptr<RequestPeer::ReceivedData> data; |
| 264 if (!alternative_data.empty()) { |
| 265 data = make_scoped_ptr(new FixedReceivedData( |
| 266 alternative_data.data(), alternative_data.size(), |
| 267 alternative_data.size())); |
| 268 } else { |
| 269 data = factory->Create(data_offset, data_length, encoded_data_length); |
| 270 // |data| takes care of ACKing. |
| 271 send_ack = false; |
| 272 } |
| 273 request_info->peer->OnReceivedData(data.Pass()); |
| 251 } | 274 } |
| 252 } | 275 } |
| 253 | 276 |
| 254 if (!request_info->blocked_response || !alternative_data.empty()) { | |
| 255 if (request_info->threaded_data_provider) { | |
| 256 request_info->threaded_data_provider->OnReceivedDataOnForegroundThread( | |
| 257 data_ptr, data_length, encoded_data_length); | |
| 258 // A threaded data provider will take care of its own ACKing, as the | |
| 259 // data may be processed later on another thread. | |
| 260 send_ack = false; | |
| 261 } else { | |
| 262 request_info->peer->OnReceivedData( | |
| 263 data_ptr, data_length, encoded_data_length); | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime", | 277 UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime", |
| 268 base::TimeTicks::Now() - time_start); | 278 base::TimeTicks::Now() - time_start); |
| 269 } | 279 } |
| 270 | 280 |
| 271 // Acknowledge the reception of this data. | 281 // Acknowledge the reception of this data. |
| 272 if (send_ack) | 282 if (send_ack) |
| 273 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id)); | 283 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id)); |
| 274 } | 284 } |
| 275 | 285 |
| 276 void ResourceDispatcher::OnDownloadedData(int request_id, | 286 void ResourceDispatcher::OnDownloadedData(int request_id, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 void ResourceDispatcher::OnRequestComplete( | 339 void ResourceDispatcher::OnRequestComplete( |
| 330 int request_id, | 340 int request_id, |
| 331 const ResourceMsg_RequestCompleteData& request_complete_data) { | 341 const ResourceMsg_RequestCompleteData& request_complete_data) { |
| 332 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); | 342 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); |
| 333 | 343 |
| 334 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 344 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 335 if (!request_info) | 345 if (!request_info) |
| 336 return; | 346 return; |
| 337 request_info->completion_time = ConsumeIOTimestamp(); | 347 request_info->completion_time = ConsumeIOTimestamp(); |
| 338 request_info->buffer.reset(); | 348 request_info->buffer.reset(); |
| 349 if (request_info->received_data_factory) |
| 350 request_info->received_data_factory->Stop(); |
| 351 request_info->received_data_factory = nullptr; |
| 339 request_info->buffer_size = 0; | 352 request_info->buffer_size = 0; |
| 340 | 353 |
| 341 RequestPeer* peer = request_info->peer; | 354 RequestPeer* peer = request_info->peer; |
| 342 | 355 |
| 343 if (delegate_) { | 356 if (delegate_) { |
| 344 RequestPeer* new_peer = | 357 RequestPeer* new_peer = |
| 345 delegate_->OnRequestComplete( | 358 delegate_->OnRequestComplete( |
| 346 request_info->peer, request_info->resource_type, | 359 request_info->peer, request_info->resource_type, |
| 347 request_complete_data.error_code); | 360 request_complete_data.error_code); |
| 348 if (new_peer) | 361 if (new_peer) |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 extra_data->transferred_request_request_id(); | 803 extra_data->transferred_request_request_id(); |
| 791 request->service_worker_provider_id = | 804 request->service_worker_provider_id = |
| 792 extra_data->service_worker_provider_id(); | 805 extra_data->service_worker_provider_id(); |
| 793 request->request_body = request_body; | 806 request->request_body = request_body; |
| 794 if (frame_origin) | 807 if (frame_origin) |
| 795 *frame_origin = extra_data->frame_origin(); | 808 *frame_origin = extra_data->frame_origin(); |
| 796 return request.Pass(); | 809 return request.Pass(); |
| 797 } | 810 } |
| 798 | 811 |
| 799 } // namespace content | 812 } // namespace content |
| OLD | NEW |