| 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 |