Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(722)

Side by Side Diff: content/child/resource_dispatcher.cc

Issue 1103813002: Make WebURLLoader capable of retaining received buffers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698