| 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/ref_counted_shared_memory.h" |
| 19 #include "content/child/request_extra_data.h" | 20 #include "content/child/request_extra_data.h" |
| 20 #include "content/child/request_info.h" | 21 #include "content/child/request_info.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" |
| 31 #include "net/base/net_util.h" | 32 #include "net/base/net_util.h" |
| 32 #include "net/base/request_priority.h" | 33 #include "net/base/request_priority.h" |
| 33 #include "net/http/http_response_headers.h" | 34 #include "net/http/http_response_headers.h" |
| 34 | 35 |
| 35 namespace content { | 36 namespace content { |
| 36 | 37 |
| 37 namespace { | 38 namespace { |
| 38 | 39 |
| 40 class SharedMemoryReceivedData final : public RequestPeer::ReceivedData { |
| 41 public: |
| 42 SharedMemoryReceivedData(const char* payload, |
| 43 int length, |
| 44 int encoded_length, |
| 45 IPC::Sender* message_sender, |
| 46 int request_id, |
| 47 scoped_refptr<RefCountedSharedMemory> shm_buffer) |
| 48 : payload_(payload), |
| 49 length_(length), |
| 50 encoded_length_(encoded_length), |
| 51 message_sender_(message_sender), |
| 52 request_id_(request_id), |
| 53 shm_buffer_(shm_buffer) {} |
| 54 ~SharedMemoryReceivedData() override { |
| 55 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id_)); |
| 56 } |
| 57 |
| 58 const char* payload() const override { return payload_; } |
| 59 int length() const override { return length_; } |
| 60 int encoded_length() const override { return encoded_length_; } |
| 61 |
| 62 private: |
| 63 const char* const payload_; |
| 64 const int length_; |
| 65 const int encoded_length_; |
| 66 |
| 67 // We assume that |message_sender_| outlives this object. This is true because |
| 68 // the sender is provided from |ResourceDispatcher::sender_| and it's a |
| 69 // ChildThreadImpl. |
| 70 IPC::Sender* const message_sender_; |
| 71 const int request_id_; |
| 72 // Just to keep |payload_| alive while this object is alive. |
| 73 scoped_refptr<RefCountedSharedMemory> shm_buffer_; |
| 74 |
| 75 DISALLOW_COPY_AND_ASSIGN(SharedMemoryReceivedData); |
| 76 }; |
| 77 |
| 39 // Converts |time| from a remote to local TimeTicks, overwriting the original | 78 // Converts |time| from a remote to local TimeTicks, overwriting the original |
| 40 // value. | 79 // value. |
| 41 void RemoteToLocalTimeTicks( | 80 void RemoteToLocalTimeTicks( |
| 42 const InterProcessTimeTicksConverter& converter, | 81 const InterProcessTimeTicksConverter& converter, |
| 43 base::TimeTicks* time) { | 82 base::TimeTicks* time) { |
| 44 RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time); | 83 RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time); |
| 45 *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks(); | 84 *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks(); |
| 46 } | 85 } |
| 47 | 86 |
| 48 void CrashOnMapFailure() { | 87 void CrashOnMapFailure() { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 int shm_size, | 221 int shm_size, |
| 183 base::ProcessId renderer_pid) { | 222 base::ProcessId renderer_pid) { |
| 184 TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer"); | 223 TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer"); |
| 185 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 224 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 186 if (!request_info) | 225 if (!request_info) |
| 187 return; | 226 return; |
| 188 | 227 |
| 189 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); | 228 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); |
| 190 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); | 229 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); |
| 191 | 230 |
| 192 request_info->buffer.reset( | 231 request_info->buffer = make_scoped_refptr( |
| 193 new base::SharedMemory(shm_handle, true)); // read only | 232 new RefCountedSharedMemory(shm_handle, true)); // read only |
| 194 | 233 |
| 195 bool ok = request_info->buffer->Map(shm_size); | 234 bool ok = request_info->buffer->memory().Map(shm_size); |
| 196 if (!ok) { | 235 if (!ok) { |
| 197 // Added to help debug crbug/160401. | 236 // Added to help debug crbug/160401. |
| 198 base::ProcessId renderer_pid_copy = renderer_pid; | 237 base::ProcessId renderer_pid_copy = renderer_pid; |
| 199 base::debug::Alias(&renderer_pid_copy); | 238 base::debug::Alias(&renderer_pid_copy); |
| 200 | 239 |
| 201 base::SharedMemoryHandle shm_handle_copy = shm_handle; | 240 base::SharedMemoryHandle shm_handle_copy = shm_handle; |
| 202 base::debug::Alias(&shm_handle_copy); | 241 base::debug::Alias(&shm_handle_copy); |
| 203 | 242 |
| 204 CrashOnMapFailure(); | 243 CrashOnMapFailure(); |
| 205 return; | 244 return; |
| 206 } | 245 } |
| 207 | 246 |
| 208 request_info->buffer_size = shm_size; | 247 request_info->buffer_size = shm_size; |
| 209 } | 248 } |
| 210 | 249 |
| 211 void ResourceDispatcher::OnReceivedData(int request_id, | 250 void ResourceDispatcher::OnReceivedData(int request_id, |
| 212 int data_offset, | 251 int data_offset, |
| 213 int data_length, | 252 int data_length, |
| 214 int encoded_data_length) { | 253 int encoded_data_length) { |
| 215 TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData"); | 254 TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData"); |
| 216 DCHECK_GT(data_length, 0); | 255 DCHECK_GT(data_length, 0); |
| 217 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 256 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 218 bool send_ack = true; | 257 bool send_ack = true; |
| 219 if (request_info && data_length > 0) { | 258 if (request_info && data_length > 0) { |
| 220 CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); | 259 CHECK(base::SharedMemory::IsHandleValid( |
| 260 request_info->buffer->memory().handle())); |
| 221 CHECK_GE(request_info->buffer_size, data_offset + data_length); | 261 CHECK_GE(request_info->buffer_size, data_offset + data_length); |
| 222 | 262 |
| 223 // Ensure that the SHM buffer remains valid for the duration of this scope. | 263 // 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. | 264 // It is possible for Cancel() to be called before we exit this scope. |
| 225 linked_ptr<base::SharedMemory> retain_buffer(request_info->buffer); | 265 scoped_refptr<RefCountedSharedMemory> retain_buffer(request_info->buffer); |
| 226 | 266 |
| 227 base::TimeTicks time_start = base::TimeTicks::Now(); | 267 base::TimeTicks time_start = base::TimeTicks::Now(); |
| 228 | 268 |
| 229 const char* data_start = static_cast<char*>(request_info->buffer->memory()); | 269 const char* data_start = |
| 270 static_cast<char*>(request_info->buffer->memory().memory()); |
| 230 CHECK(data_start); | 271 CHECK(data_start); |
| 231 CHECK(data_start + data_offset); | 272 CHECK(data_start + data_offset); |
| 232 const char* data_ptr = data_start + data_offset; | 273 const char* data_ptr = data_start + data_offset; |
| 233 | 274 |
| 234 // Check whether this response data is compliant with our cross-site | 275 // Check whether this response data is compliant with our cross-site |
| 235 // document blocking policy. We only do this for the first packet. | 276 // document blocking policy. We only do this for the first packet. |
| 236 std::string alternative_data; | 277 std::string alternative_data; |
| 237 if (request_info->site_isolation_metadata.get()) { | 278 if (request_info->site_isolation_metadata.get()) { |
| 238 request_info->blocked_response = | 279 request_info->blocked_response = |
| 239 SiteIsolationPolicy::ShouldBlockResponse( | 280 SiteIsolationPolicy::ShouldBlockResponse( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 252 } | 293 } |
| 253 | 294 |
| 254 if (!request_info->blocked_response || !alternative_data.empty()) { | 295 if (!request_info->blocked_response || !alternative_data.empty()) { |
| 255 if (request_info->threaded_data_provider) { | 296 if (request_info->threaded_data_provider) { |
| 256 request_info->threaded_data_provider->OnReceivedDataOnForegroundThread( | 297 request_info->threaded_data_provider->OnReceivedDataOnForegroundThread( |
| 257 data_ptr, data_length, encoded_data_length); | 298 data_ptr, data_length, encoded_data_length); |
| 258 // A threaded data provider will take care of its own ACKing, as the | 299 // A threaded data provider will take care of its own ACKing, as the |
| 259 // data may be processed later on another thread. | 300 // data may be processed later on another thread. |
| 260 send_ack = false; | 301 send_ack = false; |
| 261 } else { | 302 } else { |
| 303 // The SharedMemoryReceivedData sends the ack signal on destruction. |
| 304 send_ack = false; |
| 305 // It's OK to pass the buffer because we don't use |data_ptr| in this |
| 306 // function from now. |
| 262 request_info->peer->OnReceivedData( | 307 request_info->peer->OnReceivedData( |
| 263 data_ptr, data_length, encoded_data_length); | 308 make_scoped_ptr(new SharedMemoryReceivedData( |
| 309 data_ptr, data_length, encoded_data_length, message_sender_, |
| 310 request_id, retain_buffer.Pass()))); |
| 264 } | 311 } |
| 265 } | 312 } |
| 266 | 313 |
| 267 UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime", | 314 UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime", |
| 268 base::TimeTicks::Now() - time_start); | 315 base::TimeTicks::Now() - time_start); |
| 269 } | 316 } |
| 270 | 317 |
| 271 // Acknowledge the reception of this data. | 318 // Acknowledge the reception of this data. |
| 272 if (send_ack) | 319 if (send_ack) |
| 273 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id)); | 320 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id)); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 | 375 |
| 329 void ResourceDispatcher::OnRequestComplete( | 376 void ResourceDispatcher::OnRequestComplete( |
| 330 int request_id, | 377 int request_id, |
| 331 const ResourceMsg_RequestCompleteData& request_complete_data) { | 378 const ResourceMsg_RequestCompleteData& request_complete_data) { |
| 332 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); | 379 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); |
| 333 | 380 |
| 334 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 381 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 335 if (!request_info) | 382 if (!request_info) |
| 336 return; | 383 return; |
| 337 request_info->completion_time = ConsumeIOTimestamp(); | 384 request_info->completion_time = ConsumeIOTimestamp(); |
| 338 request_info->buffer.reset(); | 385 request_info->buffer = nullptr; |
| 339 request_info->buffer_size = 0; | 386 request_info->buffer_size = 0; |
| 340 | 387 |
| 341 RequestPeer* peer = request_info->peer; | 388 RequestPeer* peer = request_info->peer; |
| 342 | 389 |
| 343 if (delegate_) { | 390 if (delegate_) { |
| 344 RequestPeer* new_peer = | 391 RequestPeer* new_peer = |
| 345 delegate_->OnRequestComplete( | 392 delegate_->OnRequestComplete( |
| 346 request_info->peer, request_info->resource_type, | 393 request_info->peer, request_info->resource_type, |
| 347 request_complete_data.error_code); | 394 request_complete_data.error_code); |
| 348 if (new_peer) | 395 if (new_peer) |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 extra_data->transferred_request_request_id(); | 842 extra_data->transferred_request_request_id(); |
| 796 request->service_worker_provider_id = | 843 request->service_worker_provider_id = |
| 797 extra_data->service_worker_provider_id(); | 844 extra_data->service_worker_provider_id(); |
| 798 request->request_body = request_body; | 845 request->request_body = request_body; |
| 799 if (frame_origin) | 846 if (frame_origin) |
| 800 *frame_origin = extra_data->frame_origin(); | 847 *frame_origin = extra_data->frame_origin(); |
| 801 return request.Pass(); | 848 return request.Pass(); |
| 802 } | 849 } |
| 803 | 850 |
| 804 } // namespace content | 851 } // namespace content |
| OLD | NEW |