File: ScriptState.h

package info (click to toggle)
chromium-browser 41.0.2272.118-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,189,132 kB
  • sloc: cpp: 9,691,462; ansic: 3,341,451; python: 712,689; asm: 518,779; xml: 208,926; java: 169,820; sh: 119,353; perl: 68,907; makefile: 28,311; yacc: 13,305; objc: 11,385; tcl: 3,186; cs: 2,225; sql: 2,217; lex: 2,215; lisp: 1,349; pascal: 1,256; awk: 407; ruby: 155; sed: 53; php: 14; exp: 11
file content (158 lines) | stat: -rw-r--r-- 5,317 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ScriptState_h
#define ScriptState_h

#include "bindings/core/v8/ScopedPersistent.h"
#include "bindings/core/v8/V8PerContextData.h"
#include "wtf/RefCounted.h"
#include "wtf/Vector.h"
#include <v8.h>

namespace blink {

class LocalDOMWindow;
class DOMWrapperWorld;
class ExecutionContext;
class LocalFrame;
class ScriptValue;

// ScriptState is created when v8::Context is created.
// ScriptState is destroyed when v8::Context is garbage-collected and
// all V8 proxy objects that have references to the ScriptState are destructed.
class ScriptState : public RefCounted<ScriptState> {
    WTF_MAKE_NONCOPYABLE(ScriptState);
public:
    class Scope {
    public:
        // You need to make sure that scriptState->context() is not empty before creating a Scope.
        explicit Scope(ScriptState* scriptState)
            : m_handleScope(scriptState->isolate())
            , m_context(scriptState->context())
        {
            ASSERT(scriptState->contextIsValid());
            m_context->Enter();
        }

        ~Scope()
        {
            m_context->Exit();
        }

    private:
        v8::HandleScope m_handleScope;
        v8::Handle<v8::Context> m_context;
    };

    static PassRefPtr<ScriptState> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>);
    virtual ~ScriptState();

    static ScriptState* current(v8::Isolate* isolate)
    {
        return from(isolate->GetCurrentContext());
    }

    static ScriptState* from(v8::Handle<v8::Context> context)
    {
        ASSERT(!context.IsEmpty());
        ScriptState* scriptState = static_cast<ScriptState*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex));
        // ScriptState::from() must not be called for a context that does not have
        // valid embedder data in the embedder field.
        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState);
        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState->context() == context);
        return scriptState;
    }

    static ScriptState* forMainWorld(LocalFrame*);

    v8::Isolate* isolate() const { return m_isolate; }
    DOMWrapperWorld& world() const { return *m_world; }
    LocalDOMWindow* domWindow() const;
    virtual ExecutionContext* executionContext() const;
    virtual void setExecutionContext(ExecutionContext*);

    // This can return an empty handle if the v8::Context is gone.
    v8::Handle<v8::Context> context() const { return m_context.newLocal(m_isolate); }
    bool contextIsValid() const { return !m_context.isEmpty() && !m_globalObjectDetached; }
    void detachGlobalObject();
    void clearContext() { return m_context.clear(); }

    V8PerContextData* perContextData() const { return m_perContextData.get(); }
    void disposePerContextData();

    class Observer {
    public:
        virtual ~Observer() { }
        virtual void willDisposeScriptState(ScriptState*) = 0;
    };
    void addObserver(Observer*);
    void removeObserver(Observer*);

    bool evalEnabled() const;
    void setEvalEnabled(bool);
    ScriptValue getFromGlobalObject(const char* name);

protected:
    ScriptState(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>);

private:
    v8::Isolate* m_isolate;
    // This persistent handle is weak.
    ScopedPersistent<v8::Context> m_context;

    // This RefPtr doesn't cause a cycle because all persistent handles that DOMWrapperWorld holds are weak.
    RefPtr<DOMWrapperWorld> m_world;

    // This OwnPtr causes a cycle:
    // V8PerContextData --(Persistent)--> v8::Context --(RefPtr)--> ScriptState --(OwnPtr)--> V8PerContextData
    // So you must explicitly clear the OwnPtr by calling disposePerContextData()
    // once you no longer need V8PerContextData. Otherwise, the v8::Context will leak.
    OwnPtr<V8PerContextData> m_perContextData;

    bool m_globalObjectDetached;
    Vector<Observer*> m_observers;
};

class ScriptStateForTesting : public ScriptState {
public:
    static PassRefPtr<ScriptStateForTesting> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>);

    virtual ExecutionContext* executionContext() const override;
    virtual void setExecutionContext(ExecutionContext*) override;

private:
    ScriptStateForTesting(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>);

    ExecutionContext* m_executionContext;
};

// ScriptStateProtectingContext keeps the context associated with the ScriptState alive.
// You need to call clear() once you no longer need the context. Otherwise, the context will leak.
class ScriptStateProtectingContext {
    WTF_MAKE_NONCOPYABLE(ScriptStateProtectingContext);
public:
    ScriptStateProtectingContext(ScriptState* scriptState)
        : m_scriptState(scriptState)
    {
        if (m_scriptState)
            m_context.set(m_scriptState->isolate(), m_scriptState->context());
    }

    ScriptState* operator->() const { return m_scriptState.get(); }
    ScriptState* get() const { return m_scriptState.get(); }
    void clear()
    {
        m_scriptState = nullptr;
        m_context.clear();
    }

private:
    RefPtr<ScriptState> m_scriptState;
    ScopedPersistent<v8::Context> m_context;
};

}

#endif // ScriptState_h