1f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 2f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Use of this source code is governed by a BSD-style license that can be 3f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// found in the LICENSE file. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef ScriptState_h 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define ScriptState_h 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/ScopedPersistent.h" 9f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "bindings/v8/V8PerContextData.h" 10f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "wtf/RefCounted.h" 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <v8.h> 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)class LocalDOMWindow; 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class DOMWrapperWorld; 171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class ExecutionContext; 18f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuclass LocalFrame; 19d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)class ScriptValue; 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// ScriptState is created when v8::Context is created. 22f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// ScriptState is destroyed when v8::Context is garbage-collected and 23f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// all V8 proxy objects that have references to the ScriptState are destructed. 24f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuclass ScriptState : public RefCounted<ScriptState> { 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WTF_MAKE_NONCOPYABLE(ScriptState); 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 27f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu class Scope { 28f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu public: 29f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // You need to make sure that scriptState->context() is not empty before creating a Scope. 30f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu explicit Scope(ScriptState* scriptState) 31f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu : m_handleScope(scriptState->isolate()) 32f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu , m_context(scriptState->context()) 33f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu { 34f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ASSERT(!m_context.IsEmpty()); 35f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu m_context->Enter(); 36f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 37f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 38f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ~Scope() 39f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu { 40f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu m_context->Exit(); 41f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 42f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 43f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu private: 44f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu v8::HandleScope m_handleScope; 45f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu v8::Handle<v8::Context> m_context; 46f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu }; 47f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 48f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu static PassRefPtr<ScriptState> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); 49d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) virtual ~ScriptState(); 50f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 51f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu static ScriptState* current(v8::Isolate* isolate) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 53f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return from(isolate->GetCurrentContext()); 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu static ScriptState* from(v8::Handle<v8::Context> context) 57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) { 58f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ASSERT(!context.IsEmpty()); 59f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ScriptState* scriptState = static_cast<ScriptState*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); 60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // ScriptState::from() must not be called for a context that does not have 61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // valid embedder data in the embedder field. 62f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState); 63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState->context() == context); 64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return scriptState; 65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 67f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu static ScriptState* forMainWorld(LocalFrame*); 68f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 69f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu v8::Isolate* isolate() const { return m_isolate; } 70f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu DOMWrapperWorld& world() const { return *m_world; } 7176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) LocalDOMWindow* domWindow() const; 72d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) virtual ExecutionContext* executionContext() const; 73f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) virtual void setExecutionContext(ExecutionContext*); 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 75f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // This can return an empty handle if the v8::Context is gone. 76f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu v8::Handle<v8::Context> context() const { return m_context.newLocal(m_isolate); } 77f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu bool contextIsEmpty() const { return m_context.isEmpty(); } 78f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu void clearContext() { return m_context.clear(); } 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 80f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu V8PerContextData* perContextData() const { return m_perContextData.get(); } 81f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu void disposePerContextData() { m_perContextData = nullptr; } 8293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 83f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu bool evalEnabled() const; 84f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu void setEvalEnabled(bool); 85d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ScriptValue getFromGlobalObject(const char* name); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 87d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)protected: 88f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ScriptState(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 90d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)private: 9193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) v8::Isolate* m_isolate; 92f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // This persistent handle is weak. 93f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ScopedPersistent<v8::Context> m_context; 94f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 95f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // This RefPtr doesn't cause a cycle because all persistent handles that DOMWrapperWorld holds are weak. 96f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu RefPtr<DOMWrapperWorld> m_world; 97f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 98f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // This OwnPtr causes a cycle: 99f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // V8PerContextData --(Persistent)--> v8::Context --(RefPtr)--> ScriptState --(OwnPtr)--> V8PerContextData 100f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // So you must explicitly clear the OwnPtr by calling disposePerContextData() 101f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // once you no longer need V8PerContextData. Otherwise, the v8::Context will leak. 102f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu OwnPtr<V8PerContextData> m_perContextData; 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 105d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)class ScriptStateForTesting : public ScriptState { 106d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)public: 107d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) static PassRefPtr<ScriptStateForTesting> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); 108d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 109d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) virtual ExecutionContext* executionContext() const OVERRIDE; 110f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) virtual void setExecutionContext(ExecutionContext*) OVERRIDE; 111d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 112d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)private: 113d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ScriptStateForTesting(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); 114d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 115f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) ExecutionContext* m_executionContext; 116d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}; 117d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 118f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// ScriptStateProtectingContext keeps the context associated with the ScriptState alive. 119f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// You need to call clear() once you no longer need the context. Otherwise, the context will leak. 120f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuclass ScriptStateProtectingContext { 121f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu WTF_MAKE_NONCOPYABLE(ScriptStateProtectingContext); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 123f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ScriptStateProtectingContext(ScriptState* scriptState) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_scriptState(scriptState) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 126f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_scriptState) 127f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu m_context.set(m_scriptState->isolate(), m_scriptState->context()); 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 130f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ScriptState* operator->() const { return m_scriptState.get(); } 131f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ScriptState* get() const { return m_scriptState.get(); } 132a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void clear() 133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { 134f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu m_scriptState = nullptr; 135a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch m_context.clear(); 136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private: 139f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu RefPtr<ScriptState> m_scriptState; 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ScopedPersistent<v8::Context> m_context; 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ScriptState_h 146