Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/browser/service_worker/service_worker_data_pipe_reader.h" | |
| 6 | |
| 7 #include "base/trace_event/trace_event.h" | |
| 8 #include "content/browser/service_worker/service_worker_url_request_job.h" | |
| 9 #include "content/browser/service_worker/service_worker_version.h" | |
| 10 #include "net/base/io_buffer.h" | |
| 11 | |
| 12 namespace content { | |
| 13 | |
| 14 ServiceWorkerDataPipeReader::ServiceWorkerDataPipeReader( | |
| 15 ServiceWorkerURLRequestJob* owner, | |
| 16 scoped_refptr<ServiceWorkerVersion> streaming_version, | |
| 17 blink::mojom::ServiceWorkerStreamHandlePtr stream_handle) | |
| 18 : owner_(owner), | |
| 19 streaming_version_(streaming_version), | |
| 20 handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC), | |
| 21 stream_(std::move(stream_handle->stream)), | |
| 22 binding_(this, std::move(stream_handle->callback_request)), | |
| 23 producer_state_(State::STREAMING) { | |
| 24 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerDataPipeReader", this, | |
| 25 "Url", owner->request()->url().spec()); | |
| 26 streaming_version_->AddStreamingURLRequestJob(owner_); | |
| 27 binding_.set_connection_error_handler(base::Bind( | |
| 28 &ServiceWorkerDataPipeReader::OnAborted, base::Unretained(this))); | |
| 29 } | |
| 30 | |
| 31 ServiceWorkerDataPipeReader::~ServiceWorkerDataPipeReader() { | |
| 32 if (streaming_version_) { | |
| 33 streaming_version_->RemoveStreamingURLRequestJob(owner_); | |
| 34 streaming_version_ = nullptr; | |
| 35 } | |
| 36 TRACE_EVENT_ASYNC_END0("ServiceWorker", "ServiceWorkerDataPipeReader", this); | |
| 37 } | |
| 38 | |
| 39 void ServiceWorkerDataPipeReader::Start() { | |
| 40 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader", | |
| 41 this, "Start"); | |
| 42 handle_watcher_.Watch( | |
| 43 stream_.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
| 44 base::Bind(&ServiceWorkerDataPipeReader::OnHandleGotReadable, | |
| 45 base::Unretained(this))); | |
| 46 owner_->OnResponseStarted(); | |
| 47 } | |
| 48 | |
| 49 void ServiceWorkerDataPipeReader::OnHandleGotReadable(MojoResult) { | |
|
horo
2017/04/06 05:22:08
DCHECK_EQ(State::STREAMING, producer_state_)?
shimazu
2017/04/07 08:52:29
Done.
| |
| 50 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader", | |
| 51 this, "OnHandleGotReadable"); | |
| 52 // Do nothing if stream_pending_buffer_ is empty, i.e. there's no ReadRawData | |
| 53 // operation waiting for IO completion. | |
| 54 if (!stream_pending_buffer_) | |
| 55 return; | |
| 56 | |
| 57 // |stream_pending_buffer_| is set to the IOBuffer instance provided to | |
| 58 // ReadRawData() by URLRequestJob. | |
| 59 uint32_t size_to_pass = stream_pending_buffer_size_; | |
| 60 MojoResult mojo_result = | |
| 61 mojo::ReadDataRaw(stream_.get(), stream_pending_buffer_->data(), | |
| 62 &size_to_pass, MOJO_READ_DATA_FLAG_NONE); | |
| 63 | |
| 64 switch (mojo_result) { | |
| 65 case MOJO_RESULT_OK: | |
| 66 stream_pending_buffer_ = nullptr; | |
| 67 stream_pending_buffer_size_ = 0; | |
| 68 owner_->OnReadRawDataComplete(size_to_pass); | |
| 69 return; | |
| 70 case MOJO_RESULT_FAILED_PRECONDITION: | |
| 71 stream_.reset(); | |
| 72 handle_watcher_.Cancel(); | |
| 73 MaybeComplete(); | |
| 74 return; | |
| 75 case MOJO_RESULT_SHOULD_WAIT: | |
| 76 return; | |
| 77 case MOJO_RESULT_BUSY: | |
| 78 case MOJO_RESULT_RESOURCE_EXHAUSTED: | |
|
horo
2017/04/06 05:22:08
mojo::ReadDataRaw doesn't return MOJO_RESULT_RESOU
shimazu
2017/04/07 08:52:29
Done.
| |
| 79 stream_pending_buffer_ = nullptr; | |
| 80 stream_pending_buffer_size_ = 0; | |
| 81 stream_.reset(); | |
| 82 handle_watcher_.Cancel(); | |
| 83 owner_->OnReadRawDataComplete(net::ERR_FAILED); | |
| 84 return; | |
| 85 } | |
|
horo
2017/04/06 05:22:08
ASSERT_NOT_REACHED();
shimazu
2017/04/07 08:52:29
Done.
| |
| 86 } | |
| 87 | |
| 88 int ServiceWorkerDataPipeReader::ReadRawData(net::IOBuffer* buf, int buf_size) { | |
| 89 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader", | |
| 90 this, "ReadRawData"); | |
| 91 if (producer_state_ == State::ABORTED) { | |
| 92 // ABORT has been already notified. | |
| 93 // Handle this as connection reset. | |
| 94 stream_.reset(); | |
| 95 handle_watcher_.Cancel(); | |
| 96 owner_->RecordResult( | |
| 97 ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED); | |
| 98 return net::ERR_CONNECTION_RESET; | |
| 99 } | |
| 100 | |
| 101 uint32_t size_to_pass = buf_size; | |
| 102 MojoResult mojo_result = mojo::ReadDataRaw( | |
| 103 stream_.get(), buf->data(), &size_to_pass, MOJO_READ_DATA_FLAG_NONE); | |
| 104 switch (mojo_result) { | |
| 105 case MOJO_RESULT_OK: | |
| 106 return size_to_pass; | |
| 107 case MOJO_RESULT_FAILED_PRECONDITION: | |
| 108 stream_.reset(); | |
| 109 handle_watcher_.Cancel(); | |
| 110 if (state() == State::COMPLETED) | |
| 111 return 0; | |
| 112 // Complete/Abort asynchronously. | |
| 113 stream_pending_buffer_ = buf; | |
| 114 stream_pending_buffer_size_ = buf_size; | |
| 115 return net::ERR_IO_PENDING; | |
| 116 case MOJO_RESULT_BUSY: | |
| 117 return net::ERR_FAILED; | |
| 118 case MOJO_RESULT_SHOULD_WAIT: | |
| 119 stream_pending_buffer_ = buf; | |
| 120 stream_pending_buffer_size_ = buf_size; | |
| 121 return net::ERR_IO_PENDING; | |
| 122 case MOJO_RESULT_RESOURCE_EXHAUSTED: | |
|
horo
2017/04/06 05:22:08
mojo::ReadDataRaw doesn't return MOJO_RESULT_RESOU
shimazu
2017/04/07 08:52:29
Done.
| |
| 123 return net::ERR_FAILED; | |
| 124 } | |
| 125 return net::ERR_FAILED; | |
|
horo
2017/04/06 05:22:08
ASSERT_NOT_REACHED();?
shimazu
2017/04/07 08:52:29
Done.
| |
| 126 } | |
| 127 | |
| 128 void ServiceWorkerDataPipeReader::OnCompleted() { | |
| 129 producer_state_ = State::COMPLETED; | |
| 130 MaybeComplete(); | |
| 131 } | |
| 132 | |
| 133 void ServiceWorkerDataPipeReader::OnAborted() { | |
| 134 producer_state_ = State::ABORTED; | |
| 135 MaybeComplete(); | |
| 136 } | |
| 137 | |
| 138 void ServiceWorkerDataPipeReader::MaybeComplete() { | |
| 139 // This works only after ReadRawData returns net::ERR_IO_PENDING. | |
| 140 if (!stream_pending_buffer_) | |
| 141 return; | |
| 142 | |
| 143 switch (state()) { | |
| 144 case State::STREAMING: | |
| 145 return; | |
| 146 case State::COMPLETED: | |
| 147 stream_pending_buffer_ = nullptr; | |
| 148 stream_pending_buffer_size_ = 0; | |
| 149 handle_watcher_.Cancel(); | |
| 150 owner_->RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE); | |
| 151 owner_->OnReadRawDataComplete(0); | |
| 152 return; | |
| 153 case State::ABORTED: | |
| 154 stream_pending_buffer_ = nullptr; | |
| 155 stream_pending_buffer_size_ = 0; | |
| 156 handle_watcher_.Cancel(); | |
| 157 owner_->RecordResult( | |
| 158 ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED); | |
| 159 owner_->OnReadRawDataComplete(net::ERR_CONNECTION_RESET); | |
| 160 return; | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 ServiceWorkerDataPipeReader::State ServiceWorkerDataPipeReader::state() { | |
| 165 if (!stream_.is_valid()) | |
| 166 return producer_state_; | |
| 167 return State::STREAMING; | |
| 168 } | |
| 169 | |
| 170 } // namespace content | |
| OLD | NEW |