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 20namespace blink { 21 22// We define the default ChunkTypeTraits for frequently used types. 23template<typename ChunkType> 24class ReadableStreamChunkTypeTraits { }; 25 26template<> 27class ReadableStreamChunkTypeTraits<String> { 28public: 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 39template<> 40class ReadableStreamChunkTypeTraits<ArrayBuffer> { 41public: 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. 56template <typename ChunkTypeTraits> 57class ReadableStreamImpl : public ReadableStream { 58public: 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 74private: 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 87template <typename ChunkTypeTraits> 88bool 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 98template <typename ChunkTypeTraits> 99ScriptValue 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