OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/fetch/DataConsumerTee.h" | 5 #include "modules/fetch/DataConsumerTee.h" |
6 | 6 |
7 #include "core/dom/ActiveDOMObject.h" | 7 #include "core/dom/ActiveDOMObject.h" |
8 #include "core/dom/ExecutionContext.h" | 8 #include "core/dom/ExecutionContext.h" |
9 #include "modules/fetch/DataConsumerHandleUtil.h" | 9 #include "modules/fetch/DataConsumerHandleUtil.h" |
10 #include "modules/fetch/FetchBlobDataConsumerHandle.h" | 10 #include "modules/fetch/FetchBlobDataConsumerHandle.h" |
11 #include "platform/ThreadSafeFunctional.h" | 11 #include "platform/ThreadSafeFunctional.h" |
12 #include "platform/heap/Handle.h" | 12 #include "platform/heap/Handle.h" |
13 #include "public/platform/Platform.h" | 13 #include "public/platform/Platform.h" |
14 #include "public/platform/WebTaskRunner.h" | 14 #include "public/platform/WebTaskRunner.h" |
15 #include "public/platform/WebThread.h" | 15 #include "public/platform/WebThread.h" |
16 #include "public/platform/WebTraceLocation.h" | 16 #include "public/platform/WebTraceLocation.h" |
17 #include "wtf/Deque.h" | 17 #include "wtf/Deque.h" |
18 #include "wtf/Functional.h" | 18 #include "wtf/Functional.h" |
| 19 #include "wtf/PtrUtil.h" |
19 #include "wtf/ThreadSafeRefCounted.h" | 20 #include "wtf/ThreadSafeRefCounted.h" |
20 #include "wtf/ThreadingPrimitives.h" | 21 #include "wtf/ThreadingPrimitives.h" |
21 #include "wtf/Vector.h" | 22 #include "wtf/Vector.h" |
| 23 #include <memory> |
22 | 24 |
23 namespace blink { | 25 namespace blink { |
24 | 26 |
25 using Result = WebDataConsumerHandle::Result; | 27 using Result = WebDataConsumerHandle::Result; |
26 using Flags = WebDataConsumerHandle::Flags; | 28 using Flags = WebDataConsumerHandle::Flags; |
27 | 29 |
28 namespace { | 30 namespace { |
29 | 31 |
30 // This file contains the "tee" implementation. There are several classes and | 32 // This file contains the "tee" implementation. There are several classes and |
31 // their relationship is complicated, so let me describe here. | 33 // their relationship is complicated, so let me describe here. |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 }; | 143 }; |
142 | 144 |
143 static PassRefPtr<DestinationContext> create() { return adoptRef(new Destina
tionContext()); } | 145 static PassRefPtr<DestinationContext> create() { return adoptRef(new Destina
tionContext()); } |
144 | 146 |
145 void enqueue(const char* buffer, size_t size) | 147 void enqueue(const char* buffer, size_t size) |
146 { | 148 { |
147 bool needsNotification = false; | 149 bool needsNotification = false; |
148 { | 150 { |
149 MutexLocker locker(m_mutex); | 151 MutexLocker locker(m_mutex); |
150 needsNotification = m_queue.isEmpty(); | 152 needsNotification = m_queue.isEmpty(); |
151 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>); | 153 std::unique_ptr<Vector<char>> data = wrapUnique(new Vector<char>); |
152 data->append(buffer, size); | 154 data->append(buffer, size); |
153 m_queue.append(std::move(data)); | 155 m_queue.append(std::move(data)); |
154 } | 156 } |
155 if (needsNotification) | 157 if (needsNotification) |
156 notify(); | 158 notify(); |
157 } | 159 } |
158 | 160 |
159 void setResult(Result r) | 161 void setResult(Result r) |
160 { | 162 { |
161 ASSERT(r != WebDataConsumerHandle::Ok); | 163 ASSERT(r != WebDataConsumerHandle::Ok); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 ASSERT(!m_client); | 204 ASSERT(!m_client); |
203 m_readerThread = Platform::current()->currentThread(); | 205 m_readerThread = Platform::current()->currentThread(); |
204 m_client = client; | 206 m_client = client; |
205 } | 207 } |
206 void detachReader() | 208 void detachReader() |
207 { | 209 { |
208 ASSERT(m_readerThread && m_readerThread->isCurrentThread()); | 210 ASSERT(m_readerThread && m_readerThread->isCurrentThread()); |
209 m_readerThread = nullptr; | 211 m_readerThread = nullptr; |
210 m_client = nullptr; | 212 m_client = nullptr; |
211 } | 213 } |
212 const OwnPtr<Vector<char>>& top() const { return m_queue.first(); } | 214 const std::unique_ptr<Vector<char>>& top() const { return m_queue.first(); } |
213 bool isEmpty() const { return m_queue.isEmpty(); } | 215 bool isEmpty() const { return m_queue.isEmpty(); } |
214 size_t offset() const { return m_offset; } | 216 size_t offset() const { return m_offset; } |
215 void consume(size_t size) | 217 void consume(size_t size) |
216 { | 218 { |
217 const auto& top = m_queue.first(); | 219 const auto& top = m_queue.first(); |
218 ASSERT(m_offset <= m_offset + size); | 220 ASSERT(m_offset <= m_offset + size); |
219 ASSERT(m_offset + size <= top->size()); | 221 ASSERT(m_offset + size <= top->size()); |
220 if (top->size() <= m_offset + size) { | 222 if (top->size() <= m_offset + size) { |
221 m_offset = 0; | 223 m_offset = 0; |
222 m_queue.removeFirst(); | 224 m_queue.removeFirst(); |
(...skipping 15 matching lines...) Expand all Loading... |
238 | 240 |
239 void detach() | 241 void detach() |
240 { | 242 { |
241 MutexLocker locker(m_mutex); | 243 MutexLocker locker(m_mutex); |
242 ASSERT(!m_client); | 244 ASSERT(!m_client); |
243 ASSERT(!m_readerThread); | 245 ASSERT(!m_readerThread); |
244 m_queue.clear(); | 246 m_queue.clear(); |
245 } | 247 } |
246 | 248 |
247 Result m_result; | 249 Result m_result; |
248 Deque<OwnPtr<Vector<char>>> m_queue; | 250 Deque<std::unique_ptr<Vector<char>>> m_queue; |
249 // Note: Holding a WebThread raw pointer is not generally safe, but we can | 251 // Note: Holding a WebThread raw pointer is not generally safe, but we can |
250 // do that in this case because: | 252 // do that in this case because: |
251 // 1. Destructing a ReaderImpl when the bound thread ends is a user's | 253 // 1. Destructing a ReaderImpl when the bound thread ends is a user's |
252 // responsibility. | 254 // responsibility. |
253 // 2. |m_readerThread| will never be used after the associated reader is | 255 // 2. |m_readerThread| will never be used after the associated reader is |
254 // detached. | 256 // detached. |
255 WebThread* m_readerThread; | 257 WebThread* m_readerThread; |
256 WebDataConsumerHandle::Client* m_client; | 258 WebDataConsumerHandle::Client* m_client; |
257 size_t m_offset; | 259 size_t m_offset; |
258 bool m_isTwoPhaseReadInProgress; | 260 bool m_isTwoPhaseReadInProgress; |
(...skipping 21 matching lines...) Expand all Loading... |
280 } | 282 } |
281 | 283 |
282 Result beginRead(const void** buffer, Flags, size_t* available) override | 284 Result beginRead(const void** buffer, Flags, size_t* available) override |
283 { | 285 { |
284 MutexLocker locker(context()->mutex()); | 286 MutexLocker locker(context()->mutex()); |
285 *available = 0; | 287 *available = 0; |
286 *buffer = nullptr; | 288 *buffer = nullptr; |
287 if (context()->isEmpty()) | 289 if (context()->isEmpty()) |
288 return context()->getResult(); | 290 return context()->getResult(); |
289 | 291 |
290 const OwnPtr<Vector<char>>& chunk = context()->top(); | 292 const std::unique_ptr<Vector<char>>& chunk = context()->top(); |
291 *available = chunk->size() - context()->offset(); | 293 *available = chunk->size() - context()->offset(); |
292 *buffer = chunk->data() + context()->offset(); | 294 *buffer = chunk->data() + context()->offset(); |
293 return WebDataConsumerHandle::Ok; | 295 return WebDataConsumerHandle::Ok; |
294 } | 296 } |
295 | 297 |
296 Result endRead(size_t readSize) override | 298 Result endRead(size_t readSize) override |
297 { | 299 { |
298 MutexLocker locker(context()->mutex()); | 300 MutexLocker locker(context()->mutex()); |
299 if (context()->isEmpty()) | 301 if (context()->isEmpty()) |
300 return WebDataConsumerHandle::UnexpectedError; | 302 return WebDataConsumerHandle::UnexpectedError; |
301 context()->consume(readSize); | 303 context()->consume(readSize); |
302 return WebDataConsumerHandle::Ok; | 304 return WebDataConsumerHandle::Ok; |
303 } | 305 } |
304 | 306 |
305 private: | 307 private: |
306 DestinationContext* context() { return m_contextProxy->context(); } | 308 DestinationContext* context() { return m_contextProxy->context(); } |
307 | 309 |
308 RefPtr<DestinationContext::Proxy> m_contextProxy; | 310 RefPtr<DestinationContext::Proxy> m_contextProxy; |
309 }; | 311 }; |
310 | 312 |
311 class DestinationHandle final : public WebDataConsumerHandle { | 313 class DestinationHandle final : public WebDataConsumerHandle { |
312 public: | 314 public: |
313 static PassOwnPtr<WebDataConsumerHandle> create(PassRefPtr<DestinationContex
t::Proxy> contextProxy) | 315 static std::unique_ptr<WebDataConsumerHandle> create(PassRefPtr<DestinationC
ontext::Proxy> contextProxy) |
314 { | 316 { |
315 return adoptPtr(new DestinationHandle(contextProxy)); | 317 return wrapUnique(new DestinationHandle(contextProxy)); |
316 } | 318 } |
317 | 319 |
318 private: | 320 private: |
319 DestinationHandle(PassRefPtr<DestinationContext::Proxy> contextProxy) : m_co
ntextProxy(contextProxy) { } | 321 DestinationHandle(PassRefPtr<DestinationContext::Proxy> contextProxy) : m_co
ntextProxy(contextProxy) { } |
320 DestinationReader* obtainReaderInternal(Client* client) { return new Destina
tionReader(m_contextProxy, client); } | 322 DestinationReader* obtainReaderInternal(Client* client) { return new Destina
tionReader(m_contextProxy, client); } |
321 const char* debugName() const override { return "DestinationHandle"; } | 323 const char* debugName() const override { return "DestinationHandle"; } |
322 | 324 |
323 RefPtr<DestinationContext::Proxy> m_contextProxy; | 325 RefPtr<DestinationContext::Proxy> m_contextProxy; |
324 }; | 326 }; |
325 | 327 |
326 // Bound to the created thread. | 328 // Bound to the created thread. |
327 class SourceContext final : public GarbageCollectedFinalized<SourceContext>, pub
lic ActiveDOMObject, public WebDataConsumerHandle::Client { | 329 class SourceContext final : public GarbageCollectedFinalized<SourceContext>, pub
lic ActiveDOMObject, public WebDataConsumerHandle::Client { |
328 USING_GARBAGE_COLLECTED_MIXIN(SourceContext); | 330 USING_GARBAGE_COLLECTED_MIXIN(SourceContext); |
329 public: | 331 public: |
330 SourceContext( | 332 SourceContext( |
331 PassRefPtr<TeeRootObject> root, | 333 PassRefPtr<TeeRootObject> root, |
332 PassOwnPtr<WebDataConsumerHandle> src, | 334 std::unique_ptr<WebDataConsumerHandle> src, |
333 PassRefPtr<DestinationContext> dest1, | 335 PassRefPtr<DestinationContext> dest1, |
334 PassRefPtr<DestinationContext> dest2, | 336 PassRefPtr<DestinationContext> dest2, |
335 ExecutionContext* executionContext) | 337 ExecutionContext* executionContext) |
336 : ActiveDOMObject(executionContext) | 338 : ActiveDOMObject(executionContext) |
337 , m_root(root) | 339 , m_root(root) |
338 , m_reader(src->obtainReader(this)) | 340 , m_reader(src->obtainReader(this)) |
339 , m_dest1(dest1) | 341 , m_dest1(dest1) |
340 , m_dest2(dest2) | 342 , m_dest2(dest2) |
341 { | 343 { |
342 suspendIfNeeded(); | 344 suspendIfNeeded(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 m_dest1->setResult(WebDataConsumerHandle::UnexpectedError); | 389 m_dest1->setResult(WebDataConsumerHandle::UnexpectedError); |
388 m_dest2->setResult(WebDataConsumerHandle::UnexpectedError); | 390 m_dest2->setResult(WebDataConsumerHandle::UnexpectedError); |
389 m_root->stop(); | 391 m_root->stop(); |
390 m_root = nullptr; | 392 m_root = nullptr; |
391 m_reader = nullptr; | 393 m_reader = nullptr; |
392 m_dest1 = nullptr; | 394 m_dest1 = nullptr; |
393 m_dest2 = nullptr; | 395 m_dest2 = nullptr; |
394 } | 396 } |
395 | 397 |
396 RefPtr<TeeRootObject> m_root; | 398 RefPtr<TeeRootObject> m_root; |
397 OwnPtr<WebDataConsumerHandle::Reader> m_reader; | 399 std::unique_ptr<WebDataConsumerHandle::Reader> m_reader; |
398 RefPtr<DestinationContext> m_dest1; | 400 RefPtr<DestinationContext> m_dest1; |
399 RefPtr<DestinationContext> m_dest2; | 401 RefPtr<DestinationContext> m_dest2; |
400 }; | 402 }; |
401 | 403 |
402 } // namespace | 404 } // namespace |
403 | 405 |
404 void DataConsumerTee::create(ExecutionContext* executionContext, PassOwnPtr<WebD
ataConsumerHandle> src, OwnPtr<WebDataConsumerHandle>* dest1, OwnPtr<WebDataCons
umerHandle>* dest2) | 406 void DataConsumerTee::create(ExecutionContext* executionContext, std::unique_ptr
<WebDataConsumerHandle> src, std::unique_ptr<WebDataConsumerHandle>* dest1, std:
:unique_ptr<WebDataConsumerHandle>* dest2) |
405 { | 407 { |
406 RefPtr<TeeRootObject> root = TeeRootObject::create(); | 408 RefPtr<TeeRootObject> root = TeeRootObject::create(); |
407 RefPtr<DestinationTracker> tracker = DestinationTracker::create(root); | 409 RefPtr<DestinationTracker> tracker = DestinationTracker::create(root); |
408 RefPtr<DestinationContext> context1 = DestinationContext::create(); | 410 RefPtr<DestinationContext> context1 = DestinationContext::create(); |
409 RefPtr<DestinationContext> context2 = DestinationContext::create(); | 411 RefPtr<DestinationContext> context2 = DestinationContext::create(); |
410 | 412 |
411 root->initialize(new SourceContext(root, std::move(src), context1, context2,
executionContext)); | 413 root->initialize(new SourceContext(root, std::move(src), context1, context2,
executionContext)); |
412 | 414 |
413 *dest1 = DestinationHandle::create(DestinationContext::Proxy::create(context
1, tracker)); | 415 *dest1 = DestinationHandle::create(DestinationContext::Proxy::create(context
1, tracker)); |
414 *dest2 = DestinationHandle::create(DestinationContext::Proxy::create(context
2, tracker)); | 416 *dest2 = DestinationHandle::create(DestinationContext::Proxy::create(context
2, tracker)); |
415 } | 417 } |
416 | 418 |
417 void DataConsumerTee::create(ExecutionContext* executionContext, PassOwnPtr<Fetc
hDataConsumerHandle> src, OwnPtr<FetchDataConsumerHandle>* dest1, OwnPtr<FetchDa
taConsumerHandle>* dest2) | 419 void DataConsumerTee::create(ExecutionContext* executionContext, std::unique_ptr
<FetchDataConsumerHandle> src, std::unique_ptr<FetchDataConsumerHandle>* dest1,
std::unique_ptr<FetchDataConsumerHandle>* dest2) |
418 { | 420 { |
419 RefPtr<BlobDataHandle> blobDataHandle = src->obtainReader(nullptr)->drainAsB
lobDataHandle(FetchDataConsumerHandle::Reader::AllowBlobWithInvalidSize); | 421 RefPtr<BlobDataHandle> blobDataHandle = src->obtainReader(nullptr)->drainAsB
lobDataHandle(FetchDataConsumerHandle::Reader::AllowBlobWithInvalidSize); |
420 if (blobDataHandle) { | 422 if (blobDataHandle) { |
421 *dest1 = FetchBlobDataConsumerHandle::create(executionContext, blobDataH
andle); | 423 *dest1 = FetchBlobDataConsumerHandle::create(executionContext, blobDataH
andle); |
422 *dest2 = FetchBlobDataConsumerHandle::create(executionContext, blobDataH
andle); | 424 *dest2 = FetchBlobDataConsumerHandle::create(executionContext, blobDataH
andle); |
423 return; | 425 return; |
424 } | 426 } |
425 | 427 |
426 OwnPtr<WebDataConsumerHandle> webDest1, webDest2; | 428 std::unique_ptr<WebDataConsumerHandle> webDest1, webDest2; |
427 DataConsumerTee::create(executionContext, static_cast<PassOwnPtr<WebDataCons
umerHandle>>(std::move(src)), &webDest1, &webDest2); | 429 DataConsumerTee::create(executionContext, static_cast<std::unique_ptr<WebDat
aConsumerHandle>>(std::move(src)), &webDest1, &webDest2); |
428 *dest1 = createFetchDataConsumerHandleFromWebHandle(std::move(webDest1)); | 430 *dest1 = createFetchDataConsumerHandleFromWebHandle(std::move(webDest1)); |
429 *dest2 = createFetchDataConsumerHandleFromWebHandle(std::move(webDest2)); | 431 *dest2 = createFetchDataConsumerHandleFromWebHandle(std::move(webDest2)); |
430 return; | 432 return; |
431 } | 433 } |
432 | 434 |
433 } // namespace blink | 435 } // namespace blink |
OLD | NEW |