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

Side by Side Diff: content/browser/service_worker/service_worker_data_pipe_reader.cc

Issue 2703343002: ServiceWorker: Use mojo's data pipe for respondWith(stream) (Closed)
Patch Set: Addressed falken's comments Created 3 years, 8 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
(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 stream_pending_buffer_size_(0),
21 handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC),
22 stream_(std::move(stream_handle->stream)),
23 binding_(this, std::move(stream_handle->callback_request)),
24 producer_state_(State::STREAMING) {
25 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerDataPipeReader", this,
26 "Url", owner->request()->url().spec());
27 streaming_version_->AddStreamingURLRequestJob(owner_);
28 binding_.set_connection_error_handler(base::Bind(
29 &ServiceWorkerDataPipeReader::OnAborted, base::Unretained(this)));
30 }
31
32 ServiceWorkerDataPipeReader::~ServiceWorkerDataPipeReader() {
33 DCHECK(streaming_version_);
34 streaming_version_->RemoveStreamingURLRequestJob(owner_);
35 streaming_version_ = nullptr;
36
37 TRACE_EVENT_ASYNC_END0("ServiceWorker", "ServiceWorkerDataPipeReader", this);
38 }
39
40 void ServiceWorkerDataPipeReader::Start() {
41 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader",
42 this, "Start");
43 handle_watcher_.Watch(
44 stream_.get(),
45 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
46 base::Bind(&ServiceWorkerDataPipeReader::OnHandleGotSignal,
47 base::Unretained(this)));
48 owner_->OnResponseStarted();
49 }
50
51 void ServiceWorkerDataPipeReader::OnHandleGotSignal(MojoResult) {
falken 2017/04/19 06:56:52 It's a little surprising MojoResult is not used. I
shimazu 2017/04/19 08:32:16 Yes, it is. MojoResult indicates the state of the
52 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader",
53 this, "OnHandleGotReadable");
falken 2017/04/19 06:56:52 OnHandleGotSignal?
shimazu 2017/04/19 08:32:16 Oops, thanks. Done.
54 // Do nothing if stream_pending_buffer_ is empty, i.e. there's no ReadRawData
55 // operation waiting for IO completion.
56 if (!stream_pending_buffer_)
57 return;
58
59 // If state() is not STREAMING, it means the data pipe was disconnected and
60 // OnCompleted/OnAborted has already been called.
61 if (state() != State::STREAMING) {
62 handle_watcher_.Cancel();
63 AsyncComplete();
64 }
65
66 // |stream_pending_buffer_| is set to the IOBuffer instance provided to
67 // ReadRawData() by URLRequestJob.
68 uint32_t size_to_pass = stream_pending_buffer_size_;
69 MojoResult mojo_result =
70 mojo::ReadDataRaw(stream_.get(), stream_pending_buffer_->data(),
71 &size_to_pass, MOJO_READ_DATA_FLAG_NONE);
72
73 switch (mojo_result) {
74 case MOJO_RESULT_OK:
75 stream_pending_buffer_ = nullptr;
76 stream_pending_buffer_size_ = 0;
77 owner_->OnReadRawDataComplete(size_to_pass);
78 return;
79 case MOJO_RESULT_FAILED_PRECONDITION:
80 stream_.reset();
81 handle_watcher_.Cancel();
82 // If OnCompleted/OnAborted has already been called, let this request
83 // complete.
84 if (state() != State::STREAMING)
85 AsyncComplete();
86 return;
87 case MOJO_RESULT_SHOULD_WAIT:
88 return;
89 case MOJO_RESULT_BUSY:
kinuko 2017/04/19 09:17:47 Why is this handled as an error, is that because t
shimazu 2017/04/20 04:20:41 Yes, this won't happen. NOTREACHED might be prefer
90 case MOJO_RESULT_INVALID_ARGUMENT:
91 stream_pending_buffer_ = nullptr;
92 stream_pending_buffer_size_ = 0;
93 stream_.reset();
94 handle_watcher_.Cancel();
95 owner_->OnReadRawDataComplete(net::ERR_FAILED);
96 return;
97 }
98 NOTREACHED();
99 }
100
101 int ServiceWorkerDataPipeReader::ReadRawData(net::IOBuffer* buf, int buf_size) {
102 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader",
103 this, "ReadRawData");
104 DCHECK(!stream_pending_buffer_);
105 // If state() is not STREAMING, it means the data pipe was disconnected and
106 // OnCompleted/OnAborted has already been called.
107 if (state() != State::STREAMING)
108 return SyncComplete();
109
110 uint32_t size_to_pass = buf_size;
111 MojoResult mojo_result = mojo::ReadDataRaw(
112 stream_.get(), buf->data(), &size_to_pass, MOJO_READ_DATA_FLAG_NONE);
113 switch (mojo_result) {
114 case MOJO_RESULT_OK:
115 return size_to_pass;
116 case MOJO_RESULT_FAILED_PRECONDITION:
117 stream_.reset();
118 handle_watcher_.Cancel();
119 // Complete/Abort asynchronously if OnCompleted/OnAborted has not been
120 // called yet.
121 if (state() == State::STREAMING) {
122 stream_pending_buffer_ = buf;
123 stream_pending_buffer_size_ = buf_size;
124 return net::ERR_IO_PENDING;
125 }
126 return SyncComplete();
127 case MOJO_RESULT_SHOULD_WAIT:
128 stream_pending_buffer_ = buf;
129 stream_pending_buffer_size_ = buf_size;
130 return net::ERR_IO_PENDING;
131 case MOJO_RESULT_BUSY:
132 case MOJO_RESULT_INVALID_ARGUMENT:
133 return net::ERR_FAILED;
134 }
135 NOTREACHED();
136 return net::ERR_FAILED;
137 }
138
139 void ServiceWorkerDataPipeReader::OnCompleted() {
140 producer_state_ = State::COMPLETED;
141 if (stream_pending_buffer_ && state() != State::STREAMING)
142 AsyncComplete();
143 }
144
145 void ServiceWorkerDataPipeReader::OnAborted() {
146 producer_state_ = State::ABORTED;
147 if (stream_pending_buffer_ && state() != State::STREAMING)
148 AsyncComplete();
149 }
150
151 void ServiceWorkerDataPipeReader::AsyncComplete() {
152 // This works only after ReadRawData returns net::ERR_IO_PENDING.
153 DCHECK(stream_pending_buffer_);
154
155 switch (state()) {
156 case State::STREAMING:
157 NOTREACHED();
158 case State::COMPLETED:
159 stream_pending_buffer_ = nullptr;
160 stream_pending_buffer_size_ = 0;
161 handle_watcher_.Cancel();
162 owner_->RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE);
163 owner_->OnReadRawDataComplete(net::OK);
164 return;
165 case State::ABORTED:
166 stream_pending_buffer_ = nullptr;
167 stream_pending_buffer_size_ = 0;
168 handle_watcher_.Cancel();
169 owner_->RecordResult(
170 ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED);
171 owner_->OnReadRawDataComplete(net::ERR_CONNECTION_RESET);
172 return;
173 }
174 }
175
176 int ServiceWorkerDataPipeReader::SyncComplete() {
177 // This works only in ReadRawData.
178 DCHECK(!stream_pending_buffer_);
179
180 switch (state()) {
181 case State::STREAMING:
182 break;
183 case State::COMPLETED:
184 owner_->RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE);
185 return net::OK;
186 case State::ABORTED:
187 owner_->RecordResult(
188 ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED);
189 return net::ERR_CONNECTION_RESET;
190 }
191 NOTREACHED();
192 return net::ERR_FAILED;
193 }
194
195 ServiceWorkerDataPipeReader::State ServiceWorkerDataPipeReader::state() {
196 if (!stream_.is_valid())
197 return producer_state_;
198 return State::STREAMING;
199 }
200
201 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698