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

Side by Side Diff: third_party/WebKit/Source/modules/fetch/BlobBytesConsumer.cpp

Issue 2287323002: Implement BlobBytesConsumer (Closed)
Patch Set: fix Created 4 years, 2 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 2016 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 "modules/fetch/BlobBytesConsumer.h"
6
7 #include "core/fetch/FetchInitiatorTypeNames.h"
8 #include "core/loader/ThreadableLoader.h"
9 #include "modules/fetch/BytesConsumerForDataConsumerHandle.h"
10 #include "modules/fetch/DataConsumerHandleUtil.h"
11 #include "platform/blob/BlobData.h"
12 #include "platform/blob/BlobRegistry.h"
13 #include "platform/blob/BlobURL.h"
14 #include "platform/network/ResourceError.h"
15 #include "platform/network/ResourceRequest.h"
16 #include "platform/weborigin/KURL.h"
17 #include "platform/weborigin/SecurityOrigin.h"
18
19 namespace blink {
20
21 BlobBytesConsumer::BlobBytesConsumer(ExecutionContext* executionContext, PassRef Ptr<BlobDataHandle> blobDataHandle, ThreadableLoader* loader)
22 : ContextLifecycleObserver(executionContext)
23 , m_blobDataHandle(blobDataHandle)
24 , m_loader(loader)
25 {
26 ThreadState::current()->registerPreFinalizer(this);
27 if (!m_blobDataHandle) {
28 // Note that |m_loader| is non-null only in tests.
29 if (m_loader) {
30 m_loader->cancel();
31 m_loader = nullptr;
32 }
33 m_state = PublicState::Closed;
34 }
35 }
36
37 BlobBytesConsumer::BlobBytesConsumer(ExecutionContext* executionContext, PassRef Ptr<BlobDataHandle> blobDataHandle)
38 : BlobBytesConsumer(executionContext, blobDataHandle, nullptr)
39 {
40 }
41
42 BlobBytesConsumer::~BlobBytesConsumer()
43 {
44 }
45
46 BytesConsumer::Result BlobBytesConsumer::beginRead(const char** buffer, size_t* available)
47 {
48 *buffer = nullptr;
49 *available = 0;
50
51 if (m_state == PublicState::Closed) {
52 // It's possible that |cancel| has been called before the first
53 // |beginRead| call. That's why we need to check this condition
54 // before checking |isClean()|.
55 return Result::Done;
56 }
57
58 if (isClean()) {
59 KURL m_blobURL = BlobURL::createPublicURL(getExecutionContext()->getSecu rityOrigin());
60 if (m_blobURL.isEmpty()) {
61 error();
62 } else {
63 BlobRegistry::registerPublicBlobURL(getExecutionContext()->getSecuri tyOrigin(), m_blobURL, m_blobDataHandle);
64
65 // m_loader is non-null only in tests.
66 if (!m_loader)
67 m_loader = createLoader();
68
69 ResourceRequest request(m_blobURL);
70 request.setRequestContext(WebURLRequest::RequestContextInternal);
71 request.setUseStreamOnResponse(true);
72 // We intentionally skip
73 // 'setExternalRequestStateFromRequestorAddressSpace', as 'blob:'
74 // can never be external.
75 m_loader->start(request);
76 }
77 m_blobDataHandle = nullptr;
78 }
79 DCHECK_NE(m_state, PublicState::Closed);
80
81 if (m_state == PublicState::Errored)
82 return Result::Error;
83
84 if (!m_body) {
85 // The response has not arrived.
86 return Result::ShouldWait;
87 }
88
89 auto result = m_body->beginRead(buffer, available);
90 switch (result) {
91 case Result::Ok:
92 case Result::ShouldWait:
93 break;
94 case Result::Done:
95 m_hasSeenEndOfData = true;
96 if (m_hasFinishedLoading)
97 close();
98 return m_state == PublicState::Closed ? Result::Done : Result::ShouldWai t;
99 case Result::Error:
100 error();
101 break;
102 }
103 return result;
104 }
105
106 BytesConsumer::Result BlobBytesConsumer::endRead(size_t read)
107 {
108 DCHECK(m_body);
109 return m_body->endRead(read);
110 }
111
112 PassRefPtr<BlobDataHandle> BlobBytesConsumer::drainAsBlobDataHandle(BlobSizePoli cy policy)
113 {
114 if (!isClean())
115 return nullptr;
116 DCHECK(m_blobDataHandle);
117 if (policy == BlobSizePolicy::DisallowBlobWithInvalidSize && m_blobDataHandl e->size() == UINT64_MAX)
118 return nullptr;
119 close();
120 return m_blobDataHandle.release();
121 }
122
123 PassRefPtr<EncodedFormData> BlobBytesConsumer::drainAsFormData()
124 {
125 RefPtr<BlobDataHandle> handle = drainAsBlobDataHandle(BlobSizePolicy::AllowB lobWithInvalidSize);
126 if (!handle)
127 return nullptr;
128 RefPtr<EncodedFormData> formData = EncodedFormData::create();
129 formData->appendBlob(handle->uuid(), handle);
130 return formData.release();
131 }
132
133 void BlobBytesConsumer::setClient(BytesConsumer::Client* client)
134 {
135 DCHECK(!m_client);
136 DCHECK(client);
137 m_client = client;
138 }
139
140 void BlobBytesConsumer::clearClient()
haraken 2016/09/27 08:36:20 Where is this used?
yhirano 2016/09/27 09:12:50 This is an override function and called via the By
141 {
142 m_client = nullptr;
143 }
144
145 void BlobBytesConsumer::cancel()
146 {
147 if (m_state == PublicState::Closed || m_state == PublicState::Errored)
148 return;
149 close();
150 if (m_body) {
151 m_body->cancel();
152 m_body = nullptr;
153 }
154 if (!m_blobURL.isEmpty()) {
155 BlobRegistry::revokePublicBlobURL(m_blobURL);
156 m_blobURL = KURL();
157 }
158 m_blobDataHandle = nullptr;
159 }
160
161 BytesConsumer::Error BlobBytesConsumer::getError() const
162 {
163 DCHECK_EQ(PublicState::Errored, m_state);
164 return Error("Failed to load a blob.");
165 }
166
167 BytesConsumer::PublicState BlobBytesConsumer::getPublicState() const
168 {
169 return m_state;
170 }
171
172 void BlobBytesConsumer::contextDestroyed()
173 {
174 if (m_state != PublicState::ReadableOrWaiting)
175 return;
176
177 BytesConsumer::Client* client = m_client;
178 error();
179 if (client)
180 client->onStateChange();
181 }
182
183 void BlobBytesConsumer::onStateChange()
184 {
185 if (m_state != PublicState::ReadableOrWaiting)
186 return;
187 DCHECK(m_body);
188
189 BytesConsumer::Client* client = m_client;
190 switch (m_body->getPublicState()) {
191 case PublicState::ReadableOrWaiting:
192 break;
193 case PublicState::Closed:
194 m_hasSeenEndOfData = true;
195 if (m_hasFinishedLoading)
196 close();
197 break;
198 case PublicState::Errored:
199 error();
200 break;
201 }
202 if (client)
203 client->onStateChange();
204 }
205
206 void BlobBytesConsumer::didReceiveResponse(unsigned long identifier, const Resou rceResponse&, std::unique_ptr<WebDataConsumerHandle> handle)
207 {
208 DCHECK(handle);
209 DCHECK(!m_body);
210 DCHECK_EQ(PublicState::ReadableOrWaiting, m_state);
211
212 m_body = new BytesConsumerForDataConsumerHandle(getExecutionContext(), creat eFetchDataConsumerHandleFromWebHandle(std::move(handle)));
213 m_body->setClient(this);
214
215 if (isClean()) {
216 // This function is called synchronously in ThreadableLoader::start.
217 return;
218 }
219 onStateChange();
220 }
221
222 void BlobBytesConsumer::didFinishLoading(unsigned long identifier, double finish Time)
223 {
224 DCHECK_EQ(PublicState::ReadableOrWaiting, m_state);
225 m_hasFinishedLoading = true;
226 m_loader = nullptr;
227 if (!m_hasSeenEndOfData)
228 return;
229 DCHECK(!isClean());
230 BytesConsumer::Client* client = m_client;
231 close();
232 if (client)
233 client->onStateChange();
234 }
235
236 void BlobBytesConsumer::didFail(const ResourceError& e)
237 {
238 if (e.isCancellation()) {
239 DCHECK_EQ(PublicState::Closed, m_state);
240 return;
241 }
242 DCHECK_EQ(PublicState::ReadableOrWaiting, m_state);
243 m_loader = nullptr;
244 BytesConsumer::Client* client = m_client;
245 error();
246 if (isClean()) {
247 // This function is called synchronously in ThreadableLoader::start.
248 return;
249 }
250 if (client) {
251 client->onStateChange();
252 client = nullptr;
253 }
254 }
255
256 void BlobBytesConsumer::didFailRedirectCheck()
257 {
258 NOTREACHED();
259 }
260
261 DEFINE_TRACE(BlobBytesConsumer)
262 {
263 visitor->trace(m_body);
264 visitor->trace(m_client);
265 visitor->trace(m_loader);
266 BytesConsumer::trace(visitor);
267 BytesConsumer::Client::trace(visitor);
268 ContextLifecycleObserver::trace(visitor);
269 }
270
271 BlobBytesConsumer* BlobBytesConsumer::createForTesting(ExecutionContext* executi onContext, PassRefPtr<BlobDataHandle> blobDataHandle, ThreadableLoader* loader)
272 {
273 return new BlobBytesConsumer(executionContext, blobDataHandle, loader);
274 }
275
276 ThreadableLoader* BlobBytesConsumer::createLoader()
277 {
278 ThreadableLoaderOptions options;
279 options.preflightPolicy = ConsiderPreflight;
280 options.crossOriginRequestPolicy = DenyCrossOriginRequests;
281 options.contentSecurityPolicyEnforcement = DoNotEnforceContentSecurityPolicy ;
282 options.initiator = FetchInitiatorTypeNames::internal;
283
284 ResourceLoaderOptions resourceLoaderOptions;
285 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
286
287 return ThreadableLoader::create(*getExecutionContext(), this, options, resou rceLoaderOptions);
288 }
289
290 void BlobBytesConsumer::close()
291 {
292 DCHECK_EQ(m_state, PublicState::ReadableOrWaiting);
293 m_state = PublicState::Closed;
294 clear();
295 }
296
297 void BlobBytesConsumer::error()
298 {
299 DCHECK_EQ(m_state, PublicState::ReadableOrWaiting);
300 m_state = PublicState::Errored;
301 clear();
302 }
303
304 void BlobBytesConsumer::clear()
305 {
306 DCHECK_NE(m_state, PublicState::ReadableOrWaiting);
307 if (m_loader) {
308 m_loader->cancel();
309 m_loader = nullptr;
310 }
311 m_client = nullptr;
312 }
313
314 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698