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