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