Home | History | Annotate | Download | only in streams
      1 // Copyright 2014 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 #ifndef ReadableStreamImpl_h
      6 #define ReadableStreamImpl_h
      7 
      8 #include "bindings/core/v8/ExceptionState.h"
      9 #include "bindings/core/v8/ScriptState.h"
     10 #include "bindings/core/v8/ScriptValue.h"
     11 #include "bindings/core/v8/V8Binding.h"
     12 #include "core/streams/ReadableStream.h"
     13 #include "wtf/ArrayBuffer.h"
     14 #include "wtf/Deque.h"
     15 #include "wtf/Forward.h"
     16 #include "wtf/OwnPtr.h"
     17 #include "wtf/RefPtr.h"
     18 #include "wtf/text/WTFString.h"
     19 
     20 namespace blink {
     21 
     22 // We define the default ChunkTypeTraits for frequently used types.
     23 template<typename ChunkType>
     24 class ReadableStreamChunkTypeTraits { };
     25 
     26 template<>
     27 class ReadableStreamChunkTypeTraits<String> {
     28 public:
     29     typedef String HoldType;
     30     typedef const String& PassType;
     31 
     32     static size_t size(const String& value) { return value.length(); }
     33     static ScriptValue toScriptValue(ScriptState* scriptState, const HoldType& value)
     34     {
     35         return ScriptValue(scriptState, v8String(scriptState->isolate(), value));
     36     }
     37 };
     38 
     39 template<>
     40 class ReadableStreamChunkTypeTraits<ArrayBuffer> {
     41 public:
     42     typedef RefPtr<ArrayBuffer> HoldType;
     43     typedef PassRefPtr<ArrayBuffer> PassType;
     44 
     45     static size_t size(const PassType& value) { return value->byteLength(); }
     46     static size_t size(const HoldType& value) { return value->byteLength(); }
     47     static ScriptValue toScriptValue(ScriptState* scriptState, const HoldType& value)
     48     {
     49         return ScriptValue(scriptState, toV8NoInline(value.get(), scriptState->context()->Global(), scriptState->isolate()));
     50     }
     51 };
     52 
     53 // ReadableStreamImpl<ChunkTypeTraits> is a ReadableStream subtype. It has a
     54 // queue whose type depends on ChunkTypeTraits and it implements queue-related
     55 // ReadableStream pure virtual methods.
     56 template <typename ChunkTypeTraits>
     57 class ReadableStreamImpl : public ReadableStream {
     58 public:
     59     ReadableStreamImpl(ExecutionContext* executionContext, UnderlyingSource* source)
     60         : ReadableStream(executionContext, source)
     61         , m_totalQueueSize(0) { }
     62     virtual ~ReadableStreamImpl() { }
     63 
     64     // ReadableStream methods
     65     virtual ScriptValue read(ScriptState*, ExceptionState&) OVERRIDE;
     66 
     67     bool enqueue(typename ChunkTypeTraits::PassType);
     68 
     69     virtual void trace(Visitor* visitor) OVERRIDE
     70     {
     71         ReadableStream::trace(visitor);
     72     }
     73 
     74 private:
     75     // ReadableStream methods
     76     virtual bool isQueueEmpty() const OVERRIDE { return m_queue.isEmpty(); }
     77     virtual void clearQueue() OVERRIDE
     78     {
     79         m_queue.clear();
     80         m_totalQueueSize = 0;
     81     }
     82 
     83     Deque<typename ChunkTypeTraits::HoldType> m_queue;
     84     size_t m_totalQueueSize;
     85 };
     86 
     87 template <typename ChunkTypeTraits>
     88 bool ReadableStreamImpl<ChunkTypeTraits>::enqueue(typename ChunkTypeTraits::PassType chunk)
     89 {
     90     size_t size = ChunkTypeTraits::size(chunk);
     91     if (!enqueuePreliminaryCheck(size))
     92         return false;
     93     m_queue.append(chunk);
     94     m_totalQueueSize += size;
     95     return enqueuePostAction(m_totalQueueSize);
     96 }
     97 
     98 template <typename ChunkTypeTraits>
     99 ScriptValue ReadableStreamImpl<ChunkTypeTraits>::read(ScriptState* scriptState, ExceptionState& exceptionState)
    100 {
    101     readPreliminaryCheck(exceptionState);
    102     if (exceptionState.hadException())
    103         return ScriptValue();
    104     ASSERT(state() == Readable);
    105     ASSERT(!m_queue.isEmpty());
    106     typename ChunkTypeTraits::HoldType chunk = m_queue.takeFirst();
    107     m_totalQueueSize -= ChunkTypeTraits::size(chunk);
    108     readPostAction();
    109     return ChunkTypeTraits::toScriptValue(scriptState, chunk);
    110 }
    111 
    112 } // namespace blink
    113 
    114 #endif // ReadableStreamImpl_h
    115 
    116