diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h')
-rw-r--r-- | chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h | 179 |
1 files changed, 97 insertions, 82 deletions
diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h index ac93b551167..81bc5840070 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h @@ -1,130 +1,145 @@ -/* - * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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/v8/ScopedPersistent.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/V8PerContextData.h" +#include "wtf/RefCounted.h" #include <v8.h> -#include "wtf/Noncopyable.h" namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class DOMWrapperWorld; -class Frame; class ExecutionContext; -class WorkerGlobalScope; +class LocalFrame; +class ScriptValue; -class ScriptState { +// 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: - bool hadException() { return !m_exception.isEmpty(); } - void setException(v8::Local<v8::Value> exception) + 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(!m_context.IsEmpty()); + 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) { - m_exception.set(m_isolate, exception); + return from(isolate->GetCurrentContext()); } - v8::Local<v8::Value> exception() { return m_exception.newLocal(m_isolate); } - void clearException() { m_exception.clear(); } - v8::Local<v8::Context> context() const + static ScriptState* from(v8::Handle<v8::Context> context) { - return m_context.newLocal(m_isolate); + 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; } - v8::Isolate* isolate() - { - return m_isolate; - } + 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 contextIsEmpty() const { return m_context.isEmpty(); } + void clearContext() { return m_context.clear(); } + + V8PerContextData* perContextData() const { return m_perContextData.get(); } + void disposePerContextData() { m_perContextData = nullptr; } - DOMWindow* domWindow() const; - ExecutionContext* executionContext() const; bool evalEnabled() const; void setEvalEnabled(bool); - - static ScriptState* forContext(v8::Handle<v8::Context>); - static ScriptState* current(); + ScriptValue getFromGlobalObject(const char* name); protected: - ScriptState() - : m_isolate(v8::Isolate::GetCurrent()) - { - } - - ~ScriptState(); + ScriptState(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); private: - friend ScriptState* mainWorldScriptState(Frame*); - explicit ScriptState(v8::Handle<v8::Context>); + v8::Isolate* m_isolate; + // This persistent handle is weak. + ScopedPersistent<v8::Context> m_context; - static void setWeakCallback(const v8::WeakCallbackData<v8::Context, ScriptState>&); + // This RefPtr doesn't cause a cycle because all persistent handles that DOMWrapperWorld holds are weak. + RefPtr<DOMWrapperWorld> m_world; - ScopedPersistent<v8::Value> m_exception; - ScopedPersistent<v8::Context> m_context; - v8::Isolate* m_isolate; + // 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; }; -class EmptyScriptState : public ScriptState { +class ScriptStateForTesting : public ScriptState { public: - EmptyScriptState() : ScriptState() { } - ~EmptyScriptState() { } + 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; }; -class ScriptStateProtectedPtr { - WTF_MAKE_NONCOPYABLE(ScriptStateProtectedPtr); +// 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: - ScriptStateProtectedPtr() - : m_scriptState(0) + ScriptStateProtectingContext(ScriptState* scriptState) + : m_scriptState(scriptState) { + if (m_scriptState) + m_context.set(m_scriptState->isolate(), m_scriptState->context()); } - ScriptStateProtectedPtr(ScriptState* scriptState) - : m_scriptState(scriptState) + ScriptState* operator->() const { return m_scriptState.get(); } + ScriptState* get() const { return m_scriptState.get(); } + void clear() { - v8::HandleScope handleScope(scriptState->isolate()); - // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live. - m_context.set(scriptState->isolate(), scriptState->context()); + m_scriptState = nullptr; + m_context.clear(); } - ScriptState* get() const { return m_scriptState; } - private: - ScriptState* m_scriptState; + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Context> m_context; }; -ScriptState* mainWorldScriptState(Frame*); - -ScriptState* scriptStateFromWorkerGlobalScope(WorkerGlobalScope*); - } #endif // ScriptState_h |