Chromium Code Reviews| 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" |
| 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 StringReceivedData final : public RequestPeer::ReceivedData { | |
| 41 public: | |
| 42 explicit StringReceivedData(scoped_ptr<std::string> string) | |
| 43 : string_(string.Pass()) {} | |
| 44 | |
| 45 const char* payload() const override { return string_->data(); } | |
| 46 int length() const override { return string_->size(); } | |
| 47 int encoded_length() const override { return string_->size(); } | |
| 48 | |
| 49 private: | |
| 50 const scoped_ptr<std::string> string_; | |
| 51 }; | |
| 52 | |
| 39 // Converts |time| from a remote to local TimeTicks, overwriting the original | 53 // Converts |time| from a remote to local TimeTicks, overwriting the original |
| 40 // value. | 54 // value. |
| 41 void RemoteToLocalTimeTicks( | 55 void RemoteToLocalTimeTicks( |
| 42 const InterProcessTimeTicksConverter& converter, | 56 const InterProcessTimeTicksConverter& converter, |
| 43 base::TimeTicks* time) { | 57 base::TimeTicks* time) { |
| 44 RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time); | 58 RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time); |
| 45 *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks(); | 59 *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks(); |
| 46 } | 60 } |
| 47 | 61 |
| 48 void CrashOnMapFailure() { | 62 void CrashOnMapFailure() { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer"); | 198 TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer"); |
| 185 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 199 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 186 if (!request_info) | 200 if (!request_info) |
| 187 return; | 201 return; |
| 188 | 202 |
| 189 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); | 203 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); |
| 190 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); | 204 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); |
| 191 | 205 |
| 192 request_info->buffer.reset( | 206 request_info->buffer.reset( |
| 193 new base::SharedMemory(shm_handle, true)); // read only | 207 new base::SharedMemory(shm_handle, true)); // read only |
| 208 request_info->received_data_factory = | |
| 209 make_scoped_refptr(new SharedMemoryReceivedDataFactory( | |
| 210 message_sender_, request_id, request_info->buffer)); | |
| 194 | 211 |
| 195 bool ok = request_info->buffer->Map(shm_size); | 212 bool ok = request_info->buffer->Map(shm_size); |
| 196 if (!ok) { | 213 if (!ok) { |
| 197 // Added to help debug crbug/160401. | 214 // Added to help debug crbug/160401. |
| 198 base::ProcessId renderer_pid_copy = renderer_pid; | 215 base::ProcessId renderer_pid_copy = renderer_pid; |
| 199 base::debug::Alias(&renderer_pid_copy); | 216 base::debug::Alias(&renderer_pid_copy); |
| 200 | 217 |
| 201 base::SharedMemoryHandle shm_handle_copy = shm_handle; | 218 base::SharedMemoryHandle shm_handle_copy = shm_handle; |
| 202 base::debug::Alias(&shm_handle_copy); | 219 base::debug::Alias(&shm_handle_copy); |
| 203 | 220 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 215 TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData"); | 232 TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData"); |
| 216 DCHECK_GT(data_length, 0); | 233 DCHECK_GT(data_length, 0); |
| 217 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 234 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 218 bool send_ack = true; | 235 bool send_ack = true; |
| 219 if (request_info && data_length > 0) { | 236 if (request_info && data_length > 0) { |
| 220 CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); | 237 CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); |
| 221 CHECK_GE(request_info->buffer_size, data_offset + data_length); | 238 CHECK_GE(request_info->buffer_size, data_offset + data_length); |
| 222 | 239 |
| 223 // Ensure that the SHM buffer remains valid for the duration of this scope. | 240 // 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. | 241 // It is possible for Cancel() to be called before we exit this scope. |
| 225 linked_ptr<base::SharedMemory> retain_buffer(request_info->buffer); | 242 // SharedMemoryReceivedDataFactory stores the SHM buffer inside it. |
| 243 scoped_refptr<SharedMemoryReceivedDataFactory> factory( | |
| 244 request_info->received_data_factory); | |
| 226 | 245 |
| 227 base::TimeTicks time_start = base::TimeTicks::Now(); | 246 base::TimeTicks time_start = base::TimeTicks::Now(); |
| 228 | 247 |
| 229 const char* data_start = static_cast<char*>(request_info->buffer->memory()); | 248 const char* data_start = static_cast<char*>(request_info->buffer->memory()); |
| 230 CHECK(data_start); | 249 CHECK(data_start); |
| 231 CHECK(data_start + data_offset); | 250 CHECK(data_start + data_offset); |
| 232 const char* data_ptr = data_start + data_offset; | 251 const char* data_ptr = data_start + data_offset; |
| 233 | 252 |
| 234 // Check whether this response data is compliant with our cross-site | 253 // Check whether this response data is compliant with our cross-site |
| 235 // document blocking policy. We only do this for the first packet. | 254 // document blocking policy. We only do this for the first packet. |
| 236 std::string alternative_data; | 255 scoped_ptr<std::string> alternative_data; |
| 237 if (request_info->site_isolation_metadata.get()) { | 256 if (request_info->site_isolation_metadata.get()) { |
| 238 request_info->blocked_response = | 257 alternative_data = make_scoped_ptr(new std::string); |
| 239 SiteIsolationPolicy::ShouldBlockResponse( | 258 request_info->blocked_response = SiteIsolationPolicy::ShouldBlockResponse( |
| 240 request_info->site_isolation_metadata, data_ptr, data_length, | 259 request_info->site_isolation_metadata, data_ptr, data_length, |
| 241 &alternative_data); | 260 alternative_data.get()); |
| 242 request_info->site_isolation_metadata.reset(); | 261 request_info->site_isolation_metadata.reset(); |
| 243 | 262 |
| 244 // When the response is blocked we may have any alternative data to | 263 // 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 | 264 // send to the renderer. |
| 246 // call peer's callback. | 265 // When |alternative_data| is zero-sized, we do not call peer's callback. |
| 247 if (request_info->blocked_response && !alternative_data.empty()) { | 266 if (alternative_data->empty()) |
| 248 data_ptr = alternative_data.data(); | 267 alternative_data.reset(); |
| 249 data_length = alternative_data.size(); | 268 } |
| 250 encoded_data_length = alternative_data.size(); | 269 |
| 270 if (!request_info->blocked_response || alternative_data) { | |
| 271 if (request_info->threaded_data_provider) { | |
| 272 // TODO(yhirano): Use |alternative_data| when it is not null. | |
| 273 // A threaded data provider will take care of its own ACKing, as the | |
| 274 // data may be processed later on another thread. | |
|
tyoshino (SeeGerritForStatus)
2015/05/27 04:32:08
write the reason why we can stop using alternative
yhirano
2015/05/27 04:51:37
Done. Note that I don't break a working code here:
| |
| 275 send_ack = false; | |
| 276 request_info->threaded_data_provider->OnReceivedDataOnForegroundThread( | |
| 277 data_ptr, data_length, encoded_data_length); | |
| 278 } else { | |
| 279 scoped_ptr<RequestPeer::ReceivedData> data; | |
| 280 if (alternative_data) { | |
| 281 data = | |
| 282 make_scoped_ptr(new StringReceivedData(alternative_data.Pass())); | |
| 283 } else { | |
| 284 data = factory->Create(data_offset, data_length, encoded_data_length); | |
| 285 // |data| takes care of ACKing. | |
| 286 send_ack = false; | |
| 287 } | |
| 288 if (data) | |
|
tyoshino (SeeGerritForStatus)
2015/05/27 04:32:08
Can data be null?
yhirano
2015/05/27 04:51:37
Done.
| |
| 289 request_info->peer->OnReceivedData(data.Pass()); | |
| 251 } | 290 } |
| 252 } | 291 } |
| 253 | 292 |
| 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", | 293 UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime", |
| 268 base::TimeTicks::Now() - time_start); | 294 base::TimeTicks::Now() - time_start); |
| 269 } | 295 } |
| 270 | 296 |
| 271 // Acknowledge the reception of this data. | 297 // Acknowledge the reception of this data. |
| 272 if (send_ack) | 298 if (send_ack) |
| 273 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id)); | 299 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id)); |
| 274 } | 300 } |
| 275 | 301 |
| 276 void ResourceDispatcher::OnDownloadedData(int request_id, | 302 void ResourceDispatcher::OnDownloadedData(int request_id, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 void ResourceDispatcher::OnRequestComplete( | 355 void ResourceDispatcher::OnRequestComplete( |
| 330 int request_id, | 356 int request_id, |
| 331 const ResourceMsg_RequestCompleteData& request_complete_data) { | 357 const ResourceMsg_RequestCompleteData& request_complete_data) { |
| 332 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); | 358 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); |
| 333 | 359 |
| 334 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 360 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 335 if (!request_info) | 361 if (!request_info) |
| 336 return; | 362 return; |
| 337 request_info->completion_time = ConsumeIOTimestamp(); | 363 request_info->completion_time = ConsumeIOTimestamp(); |
| 338 request_info->buffer.reset(); | 364 request_info->buffer.reset(); |
| 365 if (request_info->received_data_factory) | |
| 366 request_info->received_data_factory->Stop(); | |
| 367 request_info->received_data_factory = nullptr; | |
| 339 request_info->buffer_size = 0; | 368 request_info->buffer_size = 0; |
| 340 | 369 |
| 341 RequestPeer* peer = request_info->peer; | 370 RequestPeer* peer = request_info->peer; |
| 342 | 371 |
| 343 if (delegate_) { | 372 if (delegate_) { |
| 344 RequestPeer* new_peer = | 373 RequestPeer* new_peer = |
| 345 delegate_->OnRequestComplete( | 374 delegate_->OnRequestComplete( |
| 346 request_info->peer, request_info->resource_type, | 375 request_info->peer, request_info->resource_type, |
| 347 request_complete_data.error_code); | 376 request_complete_data.error_code); |
| 348 if (new_peer) | 377 if (new_peer) |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 extra_data->transferred_request_request_id(); | 824 extra_data->transferred_request_request_id(); |
| 796 request->service_worker_provider_id = | 825 request->service_worker_provider_id = |
| 797 extra_data->service_worker_provider_id(); | 826 extra_data->service_worker_provider_id(); |
| 798 request->request_body = request_body; | 827 request->request_body = request_body; |
| 799 if (frame_origin) | 828 if (frame_origin) |
| 800 *frame_origin = extra_data->frame_origin(); | 829 *frame_origin = extra_data->frame_origin(); |
| 801 return request.Pass(); | 830 return request.Pass(); |
| 802 } | 831 } |
| 803 | 832 |
| 804 } // namespace content | 833 } // namespace content |
| OLD | NEW |