Chromium Code Reviews| Index: content/child/resource_dispatcher.cc |
| diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc |
| index baa6f6f65fccb17e223a97bcac4862c61e71c268..6089f778b1161515054a3a350dbc14902f808017 100644 |
| --- a/content/child/resource_dispatcher.cc |
| +++ b/content/child/resource_dispatcher.cc |
| @@ -18,6 +18,7 @@ |
| #include "base/strings/string_util.h" |
| #include "content/child/request_extra_data.h" |
| #include "content/child/request_info.h" |
| +#include "content/child/shared_memory_received_data_factory.h" |
| #include "content/child/site_isolation_policy.h" |
| #include "content/child/sync_load_response.h" |
| #include "content/child/threaded_data_provider.h" |
| @@ -36,6 +37,19 @@ namespace content { |
| namespace { |
| +class StringReceivedData final : public RequestPeer::ReceivedData { |
| + public: |
| + explicit StringReceivedData(scoped_ptr<std::string> string) |
| + : string_(string.Pass()) {} |
| + |
| + const char* payload() const override { return string_->data(); } |
| + int length() const override { return string_->size(); } |
| + int encoded_length() const override { return string_->size(); } |
| + |
| + private: |
| + const scoped_ptr<std::string> string_; |
| +}; |
| + |
| // Converts |time| from a remote to local TimeTicks, overwriting the original |
| // value. |
| void RemoteToLocalTimeTicks( |
| @@ -191,6 +205,9 @@ void ResourceDispatcher::OnSetDataBuffer(int request_id, |
| request_info->buffer.reset( |
| new base::SharedMemory(shm_handle, true)); // read only |
| + request_info->received_data_factory = |
| + make_scoped_refptr(new SharedMemoryReceivedDataFactory( |
| + message_sender_, request_id, request_info->buffer)); |
| bool ok = request_info->buffer->Map(shm_size); |
| if (!ok) { |
| @@ -222,7 +239,9 @@ void ResourceDispatcher::OnReceivedData(int request_id, |
| // Ensure that the SHM buffer remains valid for the duration of this scope. |
| // It is possible for Cancel() to be called before we exit this scope. |
| - linked_ptr<base::SharedMemory> retain_buffer(request_info->buffer); |
| + // SharedMemoryReceivedDataFactory stores the SHM buffer inside it. |
| + scoped_refptr<SharedMemoryReceivedDataFactory> factory( |
| + request_info->received_data_factory); |
| base::TimeTicks time_start = base::TimeTicks::Now(); |
| @@ -233,34 +252,41 @@ void ResourceDispatcher::OnReceivedData(int request_id, |
| // Check whether this response data is compliant with our cross-site |
| // document blocking policy. We only do this for the first packet. |
| - std::string alternative_data; |
| + scoped_ptr<std::string> alternative_data; |
| if (request_info->site_isolation_metadata.get()) { |
| - request_info->blocked_response = |
| - SiteIsolationPolicy::ShouldBlockResponse( |
| - request_info->site_isolation_metadata, data_ptr, data_length, |
| - &alternative_data); |
| + alternative_data = make_scoped_ptr(new std::string); |
| + request_info->blocked_response = SiteIsolationPolicy::ShouldBlockResponse( |
| + request_info->site_isolation_metadata, data_ptr, data_length, |
| + alternative_data.get()); |
| request_info->site_isolation_metadata.reset(); |
| // When the response is blocked we may have any alternative data to |
| - // send to the renderer. When |alternative_data| is zero-sized, we do not |
| - // call peer's callback. |
| - if (request_info->blocked_response && !alternative_data.empty()) { |
| - data_ptr = alternative_data.data(); |
| - data_length = alternative_data.size(); |
| - encoded_data_length = alternative_data.size(); |
| - } |
| + // send to the renderer. |
| + // When |alternative_data| is zero-sized, we do not call peer's callback. |
| + if (alternative_data->empty()) |
| + alternative_data.reset(); |
| } |
| - if (!request_info->blocked_response || !alternative_data.empty()) { |
| + if (!request_info->blocked_response || alternative_data) { |
| if (request_info->threaded_data_provider) { |
| - request_info->threaded_data_provider->OnReceivedDataOnForegroundThread( |
| - data_ptr, data_length, encoded_data_length); |
| + // TODO(yhirano): Use |alternative_data| when it is not null. |
| // A threaded data provider will take care of its own ACKing, as the |
| // 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:
|
| send_ack = false; |
| - } else { |
| - request_info->peer->OnReceivedData( |
| + request_info->threaded_data_provider->OnReceivedDataOnForegroundThread( |
| data_ptr, data_length, encoded_data_length); |
| + } else { |
| + scoped_ptr<RequestPeer::ReceivedData> data; |
| + if (alternative_data) { |
| + data = |
| + make_scoped_ptr(new StringReceivedData(alternative_data.Pass())); |
| + } else { |
| + data = factory->Create(data_offset, data_length, encoded_data_length); |
| + // |data| takes care of ACKing. |
| + send_ack = false; |
| + } |
| + if (data) |
|
tyoshino (SeeGerritForStatus)
2015/05/27 04:32:08
Can data be null?
yhirano
2015/05/27 04:51:37
Done.
|
| + request_info->peer->OnReceivedData(data.Pass()); |
| } |
| } |
| @@ -336,6 +362,9 @@ void ResourceDispatcher::OnRequestComplete( |
| return; |
| request_info->completion_time = ConsumeIOTimestamp(); |
| request_info->buffer.reset(); |
| + if (request_info->received_data_factory) |
| + request_info->received_data_factory->Stop(); |
| + request_info->received_data_factory = nullptr; |
| request_info->buffer_size = 0; |
| RequestPeer* peer = request_info->peer; |