Home | History | Annotate | Download | only in v8
      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<DOMWrapperWorld>);
     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->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex));
     60         // ScriptState::from() must not be called for a context that does not have
     61         // valid embedder data in the embedder field.
     62         RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState);
     63         RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState->context() == context);
     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_isolate); }
     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 DOMWrapperWorld 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>, PassRefPtr<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 ScriptState 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
    146