OLD | NEW |
| (Empty) |
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 ScriptState_h | |
6 #define ScriptState_h | |
7 | |
8 #include "bindings/v8/ScopedPersistent.h" | |
9 #include "bindings/v8/V8PerContextData.h" | |
10 #include "wtf/RefCounted.h" | |
11 #include <v8.h> | |
12 | |
13 namespace WebCore { | |
14 | |
15 class LocalDOMWindow; | |
16 class DOMWrapperWorld; | |
17 class ExecutionContext; | |
18 class LocalFrame; | |
19 class ScriptValue; | |
20 | |
21 // ScriptState is created when v8::Context is created. | |
22 // ScriptState is destroyed when v8::Context is garbage-collected and | |
23 // all V8 proxy objects that have references to the ScriptState are destructed. | |
24 class ScriptState : public RefCounted<ScriptState> { | |
25 WTF_MAKE_NONCOPYABLE(ScriptState); | |
26 public: | |
27 class Scope { | |
28 public: | |
29 // You need to make sure that scriptState->context() is not empty before
creating a Scope. | |
30 explicit Scope(ScriptState* scriptState) | |
31 : m_handleScope(scriptState->isolate()) | |
32 , m_context(scriptState->context()) | |
33 { | |
34 ASSERT(!m_context.IsEmpty()); | |
35 m_context->Enter(); | |
36 } | |
37 | |
38 ~Scope() | |
39 { | |
40 m_context->Exit(); | |
41 } | |
42 | |
43 private: | |
44 v8::HandleScope m_handleScope; | |
45 v8::Handle<v8::Context> m_context; | |
46 }; | |
47 | |
48 static PassRefPtr<ScriptState> create(v8::Handle<v8::Context>, PassRefPtr<DO
MWrapperWorld>); | |
49 virtual ~ScriptState(); | |
50 | |
51 static ScriptState* current(v8::Isolate* isolate) | |
52 { | |
53 return from(isolate->GetCurrentContext()); | |
54 } | |
55 | |
56 static ScriptState* from(v8::Handle<v8::Context> context) | |
57 { | |
58 ASSERT(!context.IsEmpty()); | |
59 ScriptState* scriptState = static_cast<ScriptState*>(context->GetAligned
PointerFromEmbedderData(v8ContextPerContextDataIndex)); | |
60 // ScriptState::from() must not be called for a context that does not ha
ve | |
61 // valid embedder data in the embedder field. | |
62 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState); | |
63 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState->context() == conte
xt); | |
64 return scriptState; | |
65 } | |
66 | |
67 static ScriptState* forMainWorld(LocalFrame*); | |
68 | |
69 v8::Isolate* isolate() const { return m_isolate; } | |
70 DOMWrapperWorld& world() const { return *m_world; } | |
71 LocalDOMWindow* domWindow() const; | |
72 virtual ExecutionContext* executionContext() const; | |
73 virtual void setExecutionContext(ExecutionContext*); | |
74 | |
75 // This can return an empty handle if the v8::Context is gone. | |
76 v8::Handle<v8::Context> context() const { return m_context.newLocal(m_isolat
e); } | |
77 bool contextIsEmpty() const { return m_context.isEmpty(); } | |
78 void clearContext() { return m_context.clear(); } | |
79 | |
80 V8PerContextData* perContextData() const { return m_perContextData.get(); } | |
81 void disposePerContextData() { m_perContextData = nullptr; } | |
82 | |
83 bool evalEnabled() const; | |
84 void setEvalEnabled(bool); | |
85 ScriptValue getFromGlobalObject(const char* name); | |
86 | |
87 protected: | |
88 ScriptState(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); | |
89 | |
90 private: | |
91 v8::Isolate* m_isolate; | |
92 // This persistent handle is weak. | |
93 ScopedPersistent<v8::Context> m_context; | |
94 | |
95 // This RefPtr doesn't cause a cycle because all persistent handles that DOM
WrapperWorld holds are weak. | |
96 RefPtr<DOMWrapperWorld> m_world; | |
97 | |
98 // This OwnPtr causes a cycle: | |
99 // V8PerContextData --(Persistent)--> v8::Context --(RefPtr)--> ScriptState
--(OwnPtr)--> V8PerContextData | |
100 // So you must explicitly clear the OwnPtr by calling disposePerContextData(
) | |
101 // once you no longer need V8PerContextData. Otherwise, the v8::Context will
leak. | |
102 OwnPtr<V8PerContextData> m_perContextData; | |
103 }; | |
104 | |
105 class ScriptStateForTesting : public ScriptState { | |
106 public: | |
107 static PassRefPtr<ScriptStateForTesting> create(v8::Handle<v8::Context>, Pas
sRefPtr<DOMWrapperWorld>); | |
108 | |
109 virtual ExecutionContext* executionContext() const OVERRIDE; | |
110 virtual void setExecutionContext(ExecutionContext*) OVERRIDE; | |
111 | |
112 private: | |
113 ScriptStateForTesting(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); | |
114 | |
115 ExecutionContext* m_executionContext; | |
116 }; | |
117 | |
118 // ScriptStateProtectingContext keeps the context associated with the ScriptStat
e alive. | |
119 // You need to call clear() once you no longer need the context. Otherwise, the
context will leak. | |
120 class ScriptStateProtectingContext { | |
121 WTF_MAKE_NONCOPYABLE(ScriptStateProtectingContext); | |
122 public: | |
123 ScriptStateProtectingContext(ScriptState* scriptState) | |
124 : m_scriptState(scriptState) | |
125 { | |
126 if (m_scriptState) | |
127 m_context.set(m_scriptState->isolate(), m_scriptState->context()); | |
128 } | |
129 | |
130 ScriptState* operator->() const { return m_scriptState.get(); } | |
131 ScriptState* get() const { return m_scriptState.get(); } | |
132 void clear() | |
133 { | |
134 m_scriptState = nullptr; | |
135 m_context.clear(); | |
136 } | |
137 | |
138 private: | |
139 RefPtr<ScriptState> m_scriptState; | |
140 ScopedPersistent<v8::Context> m_context; | |
141 }; | |
142 | |
143 } | |
144 | |
145 #endif // ScriptState_h | |
OLD | NEW |