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