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

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

Issue 2342233002: Remove Fetch[Blob|FormData]ConsumerHandle (Closed)
Patch Set: rebase Created 4 years, 3 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 2015 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/FetchBlobDataConsumerHandle.h"
6
7 #include "core/dom/ExecutionContext.h"
8 #include "core/fetch/FetchInitiatorTypeNames.h"
9 #include "core/loader/ThreadableLoaderClient.h"
10 #include "modules/fetch/CompositeDataConsumerHandle.h"
11 #include "modules/fetch/CrossThreadHolder.h"
12 #include "modules/fetch/DataConsumerHandleUtil.h"
13 #include "platform/blob/BlobRegistry.h"
14 #include "platform/blob/BlobURL.h"
15 #include "platform/network/ResourceRequest.h"
16 #include "wtf/PtrUtil.h"
17 #include <memory>
18
19 namespace blink {
20
21 using Result = FetchBlobDataConsumerHandle::Result;
22
23 namespace {
24
25 // Object graph:
26 // +-------------+
27 // |ReaderContext|
28 // +-------------+ +-----------+ +---+ | |
29 // |LoaderContext|<-|CTH::Bridge|<->|CTH|<-| |
30 // +-------------+ +-----------+ +---+ +-------------+
31 // |
32 // +--> ThreadableLoader
33 //
34 // When the loader thread is stopped, CrossThreadHolder::Bridge and
35 // LoaderContext (and thus ThreadableLoader) is destructed:
36 // +-------------+
37 // |ReaderContext|
38 // +---+ | |
39 // |CTH|<-| |
40 // +---+ +-------------+
41 // and the rest will be destructed when ReaderContext is destructed.
42 //
43 // When ReaderContext is destructed, CrossThreadHolder is destructed:
44 //
45 // +-------------+ +-----------+
46 // |LoaderContext|<-|CTH::Bridge|
47 // +-------------+ +-----------+
48 // |
49 // +--> ThreadableLoader
50 // and the rest will be shortly destructed when CrossThreadHolder::Bridge
51 // is garbage collected.
52
53 // LoaderContext is created and destructed on the same thread
54 // (call this thread loader thread).
55 // All methods must be called on the loader thread.
56 class LoaderContext {
57 public:
58 virtual ~LoaderContext() { }
59 virtual void start(ExecutionContext*) = 0;
60 };
61
62 // All methods must be called on the loader thread.
63 class BlobLoaderContext final
64 : public LoaderContext
65 , public ThreadableLoaderClient {
66 public:
67 BlobLoaderContext(CompositeDataConsumerHandle::Updater* updater, PassRefPtr< BlobDataHandle> blobDataHandle, FetchBlobDataConsumerHandle::LoaderFactory* load erFactory)
68 : m_updater(updater)
69 , m_blobDataHandle(blobDataHandle)
70 , m_loaderFactory(loaderFactory)
71 , m_receivedResponse(false) { }
72
73 ~BlobLoaderContext() override
74 {
75 if (m_loader && !m_receivedResponse)
76 m_updater->update(createUnexpectedErrorDataConsumerHandle());
77 if (m_loader) {
78 m_loader->cancel();
79 m_loader = nullptr;
80 }
81 if (!m_registeredBlobURL.isEmpty())
82 BlobRegistry::revokePublicBlobURL(m_registeredBlobURL);
83 }
84
85 void start(ExecutionContext* executionContext) override
86 {
87 ASSERT(executionContext->isContextThread());
88 ASSERT(!m_loader);
89
90 m_registeredBlobURL = BlobURL::createPublicURL(executionContext->getSecu rityOrigin());
91 if (m_registeredBlobURL.isEmpty()) {
92 m_updater->update(createUnexpectedErrorDataConsumerHandle());
93 return;
94 }
95 BlobRegistry::registerPublicBlobURL(executionContext->getSecurityOrigin( ), m_registeredBlobURL, m_blobDataHandle);
96
97 m_loader = createLoader(executionContext, this);
98 ASSERT(m_loader);
99
100 ResourceRequest request(m_registeredBlobURL);
101 request.setRequestContext(WebURLRequest::RequestContextInternal);
102 request.setUseStreamOnResponse(true);
103 // We intentionally skip 'setExternalRequestStateFromRequestorAddressSpa ce', as 'data:' can never be external.
104 m_loader->start(request);
105 }
106
107 private:
108 ThreadableLoader* createLoader(ExecutionContext* executionContext, Threadabl eLoaderClient* client) const
109 {
110 ThreadableLoaderOptions options;
111 options.preflightPolicy = ConsiderPreflight;
112 options.crossOriginRequestPolicy = DenyCrossOriginRequests;
113 options.contentSecurityPolicyEnforcement = DoNotEnforceContentSecurityPo licy;
114 options.initiator = FetchInitiatorTypeNames::internal;
115
116 ResourceLoaderOptions resourceLoaderOptions;
117 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
118
119 return m_loaderFactory->create(*executionContext, client, options, resou rceLoaderOptions);
120 }
121
122 // ThreadableLoaderClient
123 void didReceiveResponse(unsigned long, const ResourceResponse&, std::unique_ ptr<WebDataConsumerHandle> handle) override
124 {
125 ASSERT(!m_receivedResponse);
126 m_receivedResponse = true;
127 if (!handle) {
128 // Here we assume WebURLLoader must return the response body as
129 // |WebDataConsumerHandle| since we call
130 // request.setUseStreamOnResponse().
131 m_updater->update(createUnexpectedErrorDataConsumerHandle());
132 return;
133 }
134 m_updater->update(std::move(handle));
135 }
136
137 void didFinishLoading(unsigned long, double) override
138 {
139 m_loader = nullptr;
140 }
141
142 void didFail(const ResourceError&) override
143 {
144 if (!m_receivedResponse)
145 m_updater->update(createUnexpectedErrorDataConsumerHandle());
146 m_loader = nullptr;
147 }
148
149 void didFailRedirectCheck() override
150 {
151 // We don't expect redirects for Blob loading.
152 ASSERT_NOT_REACHED();
153 }
154
155 Persistent<CompositeDataConsumerHandle::Updater> m_updater;
156
157 RefPtr<BlobDataHandle> m_blobDataHandle;
158 Persistent<FetchBlobDataConsumerHandle::LoaderFactory> m_loaderFactory;
159 Persistent<ThreadableLoader> m_loader;
160 KURL m_registeredBlobURL;
161
162 bool m_receivedResponse;
163 };
164
165 class DefaultLoaderFactory final : public FetchBlobDataConsumerHandle::LoaderFac tory {
166 public:
167 ThreadableLoader* create(
168 ExecutionContext& executionContext,
169 ThreadableLoaderClient* client,
170 const ThreadableLoaderOptions& options,
171 const ResourceLoaderOptions& resourceLoaderOptions) override
172 {
173 return ThreadableLoader::create(executionContext, client, options, resou rceLoaderOptions);
174 }
175 };
176
177 } // namespace
178
179 // ReaderContext is referenced from FetchBlobDataConsumerHandle and
180 // ReaderContext::ReaderImpl.
181 // All functions/members must be called/accessed only on the reader thread,
182 // except for constructor, destructor, and obtainReader().
183 class FetchBlobDataConsumerHandle::ReaderContext final : public ThreadSafeRefCou nted<ReaderContext> {
184 public:
185 class ReaderImpl : public FetchDataConsumerHandle::Reader {
186 public:
187 ReaderImpl(Client* client, PassRefPtr<ReaderContext> readerContext, std: :unique_ptr<WebDataConsumerHandle::Reader> reader)
188 : m_readerContext(readerContext)
189 , m_reader(std::move(reader))
190 , m_notifier(client) { }
191 ~ReaderImpl() override { }
192
193 Result read(void* data, size_t size, Flags flags, size_t* readSize) over ride
194 {
195 if (m_readerContext->drained())
196 return Done;
197 Result r = m_reader->read(data, size, flags, readSize);
198 if (!(size == 0 && (r == Ok || r == ShouldWait))) {
199 // We read non-empty data, so we cannot use the blob data
200 // handle which represents the whole data.
201 m_readerContext->clearBlobDataHandleForDrain();
202 m_readerContext->ensureStartLoader();
203 }
204 return r;
205 }
206
207 Result beginRead(const void** buffer, Flags flags, size_t* available) ov erride
208 {
209 if (m_readerContext->drained())
210 return Done;
211 m_readerContext->ensureStartLoader();
212 m_readerContext->clearBlobDataHandleForDrain();
213 return m_reader->beginRead(buffer, flags, available);
214 }
215
216 Result endRead(size_t readSize) override
217 {
218 return m_reader->endRead(readSize);
219 }
220
221 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy blobSize Policy) override
222 {
223 if (!m_readerContext->m_blobDataHandleForDrain)
224 return nullptr;
225 if (blobSizePolicy == DisallowBlobWithInvalidSize && m_readerContext ->m_blobDataHandleForDrain->size() == UINT64_MAX)
226 return nullptr;
227 RefPtr<BlobDataHandle> blobDataHandle = m_readerContext->m_blobDataH andleForDrain;
228 m_readerContext->setDrained();
229 m_readerContext->clearBlobDataHandleForDrain();
230 return blobDataHandle.release();
231 }
232
233 PassRefPtr<EncodedFormData> drainAsFormData() override
234 {
235 RefPtr<BlobDataHandle> handle = drainAsBlobDataHandle(AllowBlobWithI nvalidSize);
236 if (!handle)
237 return nullptr;
238 RefPtr<EncodedFormData> formData = EncodedFormData::create();
239 formData->appendBlob(handle->uuid(), handle);
240 return formData.release();
241 }
242
243 private:
244 RefPtr<ReaderContext> m_readerContext;
245 std::unique_ptr<WebDataConsumerHandle::Reader> m_reader;
246 NotifyOnReaderCreationHelper m_notifier;
247 };
248
249 ReaderContext(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle, FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
250 : m_blobDataHandleForDrain(blobDataHandle)
251 , m_loaderStarted(false)
252 , m_drained(false)
253 {
254 CompositeDataConsumerHandle::Updater* updater = nullptr;
255 m_handle = CompositeDataConsumerHandle::create(createWaitingDataConsumer Handle(), &updater);
256 m_loaderContextHolder = CrossThreadHolder<LoaderContext>::create(executi onContext, wrapUnique(new BlobLoaderContext(updater, m_blobDataHandleForDrain, l oaderFactory)));
257 }
258
259 std::unique_ptr<FetchDataConsumerHandle::Reader> obtainReader(WebDataConsume rHandle::Client* client)
260 {
261 return wrapUnique(new ReaderImpl(client, this, m_handle->obtainReader(cl ient)));
262 }
263
264 private:
265 void ensureStartLoader()
266 {
267 if (m_loaderStarted)
268 return;
269 m_loaderStarted = true;
270 m_loaderContextHolder->postTask(crossThreadBind(&LoaderContext::start));
271 }
272
273 void clearBlobDataHandleForDrain()
274 {
275 m_blobDataHandleForDrain.clear();
276 }
277
278 bool drained() const { return m_drained; }
279 void setDrained() { m_drained = true; }
280
281 std::unique_ptr<WebDataConsumerHandle> m_handle;
282 RefPtr<BlobDataHandle> m_blobDataHandleForDrain;
283 std::unique_ptr<CrossThreadHolder<LoaderContext>> m_loaderContextHolder;
284
285 bool m_loaderStarted;
286 bool m_drained;
287 };
288
289 FetchBlobDataConsumerHandle::FetchBlobDataConsumerHandle(ExecutionContext* execu tionContext, PassRefPtr<BlobDataHandle> blobDataHandle, LoaderFactory* loaderFac tory)
290 : m_readerContext(adoptRef(new ReaderContext(executionContext, std::move(blo bDataHandle), loaderFactory)))
291 {
292 }
293
294 FetchBlobDataConsumerHandle::~FetchBlobDataConsumerHandle()
295 {
296 }
297
298 std::unique_ptr<FetchDataConsumerHandle> FetchBlobDataConsumerHandle::create(Exe cutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle, Load erFactory* loaderFactory)
299 {
300 if (!blobDataHandle)
301 return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumer Handle());
302
303 return wrapUnique(new FetchBlobDataConsumerHandle(executionContext, std::mov e(blobDataHandle), loaderFactory));
304 }
305
306 std::unique_ptr<FetchDataConsumerHandle> FetchBlobDataConsumerHandle::create(Exe cutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle)
307 {
308 if (!blobDataHandle)
309 return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumer Handle());
310
311 return wrapUnique(new FetchBlobDataConsumerHandle(executionContext, std::mov e(blobDataHandle), new DefaultLoaderFactory));
312 }
313
314 std::unique_ptr<FetchDataConsumerHandle::Reader> FetchBlobDataConsumerHandle::ob tainFetchDataReader(Client* client)
315 {
316 return m_readerContext->obtainReader(client);
317 }
318
319 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698