Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / core / v8 / ScriptPromiseResolver.h
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 ScriptPromiseResolver_h
6 #define ScriptPromiseResolver_h
7
8 #include "bindings/core/v8/ScopedPersistent.h"
9 #include "bindings/core/v8/ScriptPromise.h"
10 #include "bindings/core/v8/ScriptState.h"
11 #include "bindings/core/v8/V8Binding.h"
12 #include "core/dom/ActiveDOMObject.h"
13 #include "core/dom/ExecutionContext.h"
14 #include "platform/Timer.h"
15 #include "wtf/RefCounted.h"
16 #include <v8.h>
17
18 namespace blink {
19
20 // This class wraps v8::Promise::Resolver and provides the following
21 // functionalities.
22 //  - A ScriptPromiseResolver retains a ScriptState. A caller
23 //    can call resolve or reject from outside of a V8 context.
24 //  - This class is an ActiveDOMObject and keeps track of the associated
25 //    ExecutionContext state. When the ExecutionContext is suspended,
26 //    resolve or reject will be delayed. When it is stopped, resolve or reject
27 //    will be ignored.
28 class ScriptPromiseResolver : public ActiveDOMObject, public RefCounted<ScriptPromiseResolver> {
29     WTF_MAKE_NONCOPYABLE(ScriptPromiseResolver);
30
31 public:
32     static PassRefPtr<ScriptPromiseResolver> create(ScriptState* scriptState)
33     {
34         RefPtr<ScriptPromiseResolver> resolver = adoptRef(new ScriptPromiseResolver(scriptState));
35         resolver->suspendIfNeeded();
36         return resolver.release();
37     }
38
39     virtual ~ScriptPromiseResolver()
40     {
41         // This assertion fails if:
42         //  - promise() is called at least once and
43         //  - this resolver is destructed before it is resolved, rejected or
44         //    the associated ExecutionContext is stopped.
45         ASSERT(m_state == ResolvedOrRejected || !m_isPromiseCalled);
46     }
47
48     // Anything that can be passed to toV8Value can be passed to this function.
49     template <typename T>
50     void resolve(T value)
51     {
52         resolveOrReject(value, Resolving);
53     }
54
55     // Anything that can be passed to toV8Value can be passed to this function.
56     template <typename T>
57     void reject(T value)
58     {
59         resolveOrReject(value, Rejecting);
60     }
61
62     void resolve() { resolve(V8UndefinedType()); }
63     void reject() { reject(V8UndefinedType()); }
64
65     ScriptState* scriptState() { return m_scriptState.get(); }
66
67     // Note that an empty ScriptPromise will be returned after resolve or
68     // reject is called.
69     ScriptPromise promise()
70     {
71 #if ENABLE(ASSERT)
72         m_isPromiseCalled = true;
73 #endif
74         return m_resolver.promise();
75     }
76
77     ScriptState* scriptState() const { return m_scriptState.get(); }
78
79     // ActiveDOMObject implementation.
80     virtual void suspend() override;
81     virtual void resume() override;
82     virtual void stop() override;
83
84     // Once this function is called this resolver stays alive while the
85     // promise is pending and the associated ExecutionContext isn't stopped.
86     void keepAliveWhilePending();
87
88 protected:
89     // You need to call suspendIfNeeded after the construction because
90     // this is an ActiveDOMObject.
91     explicit ScriptPromiseResolver(ScriptState*);
92
93 private:
94     typedef ScriptPromise::InternalResolver Resolver;
95     enum ResolutionState {
96         Pending,
97         Resolving,
98         Rejecting,
99         ResolvedOrRejected,
100     };
101     enum LifetimeMode {
102         Default,
103         KeepAliveWhilePending,
104     };
105
106     template<typename T>
107     v8::Handle<v8::Value> toV8Value(const T& value)
108     {
109         return V8ValueTraits<T>::toV8Value(value, m_scriptState->context()->Global(), m_scriptState->isolate());
110     }
111
112     template <typename T>
113     void resolveOrReject(T value, ResolutionState newState)
114     {
115         if (m_state != Pending || !executionContext() || executionContext()->activeDOMObjectsAreStopped())
116             return;
117         ASSERT(newState == Resolving || newState == Rejecting);
118         m_state = newState;
119         // Retain this object until it is actually resolved or rejected.
120         // |deref| will be called in |clear|.
121         ref();
122
123         ScriptState::Scope scope(m_scriptState.get());
124         m_value.set(m_scriptState->isolate(), toV8Value(value));
125         if (!executionContext()->activeDOMObjectsAreSuspended())
126             resolveOrRejectImmediately();
127     }
128
129     void resolveOrRejectImmediately();
130     void onTimerFired(Timer<ScriptPromiseResolver>*);
131     void clear();
132
133     ResolutionState m_state;
134     const RefPtr<ScriptState> m_scriptState;
135     LifetimeMode m_mode;
136     Timer<ScriptPromiseResolver> m_timer;
137     Resolver m_resolver;
138     ScopedPersistent<v8::Value> m_value;
139 #if ENABLE(ASSERT)
140     // True if promise() is called.
141     bool m_isPromiseCalled;
142 #endif
143 };
144
145 } // namespace blink
146
147 #endif // #ifndef ScriptPromiseResolver_h