[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

abarth at webkit.org abarth at webkit.org
Thu Apr 8 00:52:24 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 55bfb638e7dc69e777ecdaaf0b1a63e8dbaecfbe
Author: abarth at webkit.org <abarth at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Dec 30 18:22:56 2009 +0000

    2009-12-30  Adam Barth  <abarth at webkit.org>
    
            Reviewed by Eric Seidel.
    
            [v8] Move world-specific state out of V8Proxy
            https://bugs.webkit.org/show_bug.cgi?id=33034
    
            This is the first step towards unifying the V8 implementation of
            isolated worlds with the JSC implementation.  We need an object to
            encapulate all the world-specific bindings state.  Previoulsy, we used
            V8Proxy for this purpose (along with a million other things), but
            there's a one-to-one mapping between V8Proxy objects and Frame objects.
    
            This patch takes the world-specific state and moves it to a new object,
            affectionately called V8DOMWindowShell.  This object is the moral
            equivalent of JSDOMWindowShell but with more data members because life
            is more complicated in V8-land.
    
            This patch is almost entirely code motion.  Future patches will clean
            up this class as we use it to represent window shells in isolated
            worlds as well as the main world.
    
            * WebCore.gypi:
            * bindings/v8/ScriptController.cpp:
            (WebCore::ScriptController::updateSecurityOrigin):
            (WebCore::ScriptController::haveInterpreter):
            (WebCore::ScriptController::updateDocument):
            * bindings/v8/V8DOMWindowShell.cpp: Added.
            (WebCore::handleFatalErrorInV8):
            (WebCore::reportFatalErrorInV8):
            (WebCore::reportUnsafeJavaScriptAccess):
            (WebCore::V8DOMWindowShell::create):
            (WebCore::V8DOMWindowShell::V8DOMWindowShell):
            (WebCore::V8DOMWindowShell::isContextInitialized):
            (WebCore::V8DOMWindowShell::disposeContextHandles):
            (WebCore::V8DOMWindowShell::destroyGlobal):
            (WebCore::V8DOMWindowShell::clearForClose):
            (WebCore::V8DOMWindowShell::clearForNavigation):
            (WebCore::V8DOMWindowShell::initContextIfNeeded):
            (WebCore::V8DOMWindowShell::createNewContext):
            (WebCore::V8DOMWindowShell::installDOMWindow):
            (WebCore::V8DOMWindowShell::updateDocumentWrapper):
            (WebCore::V8DOMWindowShell::clearDocumentWrapper):
            (WebCore::V8DOMWindowShell::updateDocumentWrapperCache):
            (WebCore::V8DOMWindowShell::clearDocumentWrapperCache):
            (WebCore::V8DOMWindowShell::setSecurityToken):
            (WebCore::V8DOMWindowShell::updateDocument):
            (WebCore::V8DOMWindowShell::updateSecurityOrigin):
            (WebCore::V8DOMWindowShell::getHiddenObjectPrototype):
            (WebCore::V8DOMWindowShell::installHiddenObjectPrototype):
            (WebCore::V8DOMWindowShell::createWrapperFromCacheSlowCase):
            * bindings/v8/V8DOMWindowShell.h: Added.
            (WebCore::V8DOMWindowShell::context):
            (WebCore::V8DOMWindowShell::createWrapperFromCache):
            * bindings/v8/V8DOMWrapper.cpp:
            (WebCore::V8DOMWrapper::getConstructorForContext):
            (WebCore::V8DOMWrapper::instantiateV8Object):
            (WebCore::V8DOMWrapper::convertDocumentToV8Object):
            (WebCore::V8DOMWrapper::convertNewNodeToV8Object):
            * bindings/v8/V8IsolatedWorld.cpp:
            (WebCore::V8IsolatedWorld::V8IsolatedWorld):
            * bindings/v8/V8Proxy.cpp:
            (WebCore::V8Proxy::V8Proxy):
            (WebCore::V8Proxy::~V8Proxy):
            (WebCore::V8Proxy::handleOutOfMemory):
            (WebCore::V8Proxy::evaluateInIsolatedWorld):
            (WebCore::V8Proxy::evaluateInNewContext):
            (WebCore::V8Proxy::setInjectedScriptContextDebugId):
            (WebCore::V8Proxy::clearForClose):
            (WebCore::V8Proxy::clearForNavigation):
            (WebCore::V8Proxy::mainWorldContext):
            (WebCore::V8Proxy::setContextDebugId):
            * bindings/v8/V8Proxy.h:
            (WebCore::V8Proxy::windowShell):
            (WebCore::V8Proxy::extensions):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@52666 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 7122a62..a1b5f0b 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,79 @@
+2009-12-30  Adam Barth  <abarth at webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        [v8] Move world-specific state out of V8Proxy
+        https://bugs.webkit.org/show_bug.cgi?id=33034
+
+        This is the first step towards unifying the V8 implementation of
+        isolated worlds with the JSC implementation.  We need an object to
+        encapulate all the world-specific bindings state.  Previoulsy, we used
+        V8Proxy for this purpose (along with a million other things), but
+        there's a one-to-one mapping between V8Proxy objects and Frame objects.
+
+        This patch takes the world-specific state and moves it to a new object,
+        affectionately called V8DOMWindowShell.  This object is the moral
+        equivalent of JSDOMWindowShell but with more data members because life
+        is more complicated in V8-land.
+
+        This patch is almost entirely code motion.  Future patches will clean
+        up this class as we use it to represent window shells in isolated
+        worlds as well as the main world.
+
+        * WebCore.gypi:
+        * bindings/v8/ScriptController.cpp:
+        (WebCore::ScriptController::updateSecurityOrigin):
+        (WebCore::ScriptController::haveInterpreter):
+        (WebCore::ScriptController::updateDocument):
+        * bindings/v8/V8DOMWindowShell.cpp: Added.
+        (WebCore::handleFatalErrorInV8):
+        (WebCore::reportFatalErrorInV8):
+        (WebCore::reportUnsafeJavaScriptAccess):
+        (WebCore::V8DOMWindowShell::create):
+        (WebCore::V8DOMWindowShell::V8DOMWindowShell):
+        (WebCore::V8DOMWindowShell::isContextInitialized):
+        (WebCore::V8DOMWindowShell::disposeContextHandles):
+        (WebCore::V8DOMWindowShell::destroyGlobal):
+        (WebCore::V8DOMWindowShell::clearForClose):
+        (WebCore::V8DOMWindowShell::clearForNavigation):
+        (WebCore::V8DOMWindowShell::initContextIfNeeded):
+        (WebCore::V8DOMWindowShell::createNewContext):
+        (WebCore::V8DOMWindowShell::installDOMWindow):
+        (WebCore::V8DOMWindowShell::updateDocumentWrapper):
+        (WebCore::V8DOMWindowShell::clearDocumentWrapper):
+        (WebCore::V8DOMWindowShell::updateDocumentWrapperCache):
+        (WebCore::V8DOMWindowShell::clearDocumentWrapperCache):
+        (WebCore::V8DOMWindowShell::setSecurityToken):
+        (WebCore::V8DOMWindowShell::updateDocument):
+        (WebCore::V8DOMWindowShell::updateSecurityOrigin):
+        (WebCore::V8DOMWindowShell::getHiddenObjectPrototype):
+        (WebCore::V8DOMWindowShell::installHiddenObjectPrototype):
+        (WebCore::V8DOMWindowShell::createWrapperFromCacheSlowCase):
+        * bindings/v8/V8DOMWindowShell.h: Added.
+        (WebCore::V8DOMWindowShell::context):
+        (WebCore::V8DOMWindowShell::createWrapperFromCache):
+        * bindings/v8/V8DOMWrapper.cpp:
+        (WebCore::V8DOMWrapper::getConstructorForContext):
+        (WebCore::V8DOMWrapper::instantiateV8Object):
+        (WebCore::V8DOMWrapper::convertDocumentToV8Object):
+        (WebCore::V8DOMWrapper::convertNewNodeToV8Object):
+        * bindings/v8/V8IsolatedWorld.cpp:
+        (WebCore::V8IsolatedWorld::V8IsolatedWorld):
+        * bindings/v8/V8Proxy.cpp:
+        (WebCore::V8Proxy::V8Proxy):
+        (WebCore::V8Proxy::~V8Proxy):
+        (WebCore::V8Proxy::handleOutOfMemory):
+        (WebCore::V8Proxy::evaluateInIsolatedWorld):
+        (WebCore::V8Proxy::evaluateInNewContext):
+        (WebCore::V8Proxy::setInjectedScriptContextDebugId):
+        (WebCore::V8Proxy::clearForClose):
+        (WebCore::V8Proxy::clearForNavigation):
+        (WebCore::V8Proxy::mainWorldContext):
+        (WebCore::V8Proxy::setContextDebugId):
+        * bindings/v8/V8Proxy.h:
+        (WebCore::V8Proxy::windowShell):
+        (WebCore::V8Proxy::extensions):
+
 2009-12-30  Dirk Schulze  <krit at webkit.org>
 
         Reviewed by Eric Seidel.
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index 83d9449..d2cb40e 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -808,6 +808,8 @@
             'bindings/v8/V8DataGridDataSource.h',
             'bindings/v8/V8DOMMap.cpp',
             'bindings/v8/V8DOMMap.h',
+            'bindings/v8/V8DOMWindowShell.cpp',
+            'bindings/v8/V8DOMWindowShell.h',
             'bindings/v8/V8DOMWrapper.cpp',
             'bindings/v8/V8DOMWrapper.h',
             'bindings/v8/V8EventListenerList.cpp',
diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp
index f9e268f..e5487ce 100644
--- a/WebCore/bindings/v8/ScriptController.cpp
+++ b/WebCore/bindings/v8/ScriptController.cpp
@@ -140,7 +140,7 @@ void ScriptController::clearScriptObjects()
 
 void ScriptController::updateSecurityOrigin()
 {
-    m_proxy->updateSecurityOrigin();
+    m_proxy->windowShell()->updateSecurityOrigin();
 }
 
 void ScriptController::updatePlatformScriptObjects()
@@ -296,7 +296,7 @@ void ScriptController::lowMemoryNotification()
 
 bool ScriptController::haveInterpreter() const
 {
-    return m_proxy->isContextInitialized();
+    return m_proxy->windowShell()->isContextInitialized();
 }
 
 bool ScriptController::isEnabled() const
@@ -458,7 +458,7 @@ void ScriptController::attachDebugger(void*)
 
 void ScriptController::updateDocument()
 {
-    m_proxy->updateDocument();
+    m_proxy->windowShell()->updateDocument();
 }
 
 } // namespace WebCore
diff --git a/WebCore/bindings/v8/V8DOMWindowShell.cpp b/WebCore/bindings/v8/V8DOMWindowShell.cpp
new file mode 100644
index 0000000..49b5bf9
--- /dev/null
+++ b/WebCore/bindings/v8/V8DOMWindowShell.cpp
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2008, 2009 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.
+ */
+
+#include "config.h"
+#include "V8DOMWindowShell.h"
+
+#include "ChromiumBridge.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "DateExtension.h"
+#include "DocumentLoader.h"
+#include "DOMObjectsInclude.h"
+#include "FrameLoaderClient.h"
+#include "InspectorTimelineAgent.h"
+#include "Page.h"
+#include "PageGroup.h"
+#include "ScriptController.h"
+#include "StorageNamespace.h"
+#include "V8Binding.h"
+#include "V8BindingState.h"
+#include "V8Collection.h"
+#include "V8ConsoleMessage.h"
+#include "V8CustomBinding.h"
+#include "V8DOMMap.h"
+#include "V8DOMWindow.h"
+#include "V8HiddenPropertyName.h"
+#include "V8Index.h"
+#include "V8IsolatedWorld.h"
+#include "V8Proxy.h"
+#include "WorkerContextExecutionProxy.h"
+
+#include <algorithm>
+#include <stdio.h>
+#include <utility>
+#include <v8-debug.h>
+#include <v8.h>
+#include <wtf/Assertions.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/StringExtras.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+static void handleFatalErrorInV8()
+{
+    // FIXME: We temporarily deal with V8 internal error situations
+    // such as out-of-memory by crashing the renderer.
+    CRASH();
+}
+
+static void reportFatalErrorInV8(const char* location, const char* message)
+{
+    // V8 is shutdown, we cannot use V8 api.
+    // The only thing we can do is to disable JavaScript.
+    // FIXME: clean up V8Proxy and disable JavaScript.
+    printf("V8 error: %s (%s)\n", message, location);
+    handleFatalErrorInV8();
+}
+
+static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data)
+{
+    Frame* target = V8Custom::GetTargetFrame(host, data);
+    if (target)
+        V8Proxy::reportUnsafeAccessTo(target, V8Proxy::ReportLater);
+}
+
+PassRefPtr<V8DOMWindowShell> V8DOMWindowShell::create(Frame* frame)
+{
+    return adoptRef(new V8DOMWindowShell(frame));
+}
+
+V8DOMWindowShell::V8DOMWindowShell(Frame* frame)
+    : m_frame(frame)
+{
+}
+
+bool V8DOMWindowShell::isContextInitialized()
+{
+    // m_context, m_global, and m_wrapperBoilerplates should
+    // all be non-empty if if m_context is non-empty.
+    ASSERT(m_context.IsEmpty() || !m_global.IsEmpty());
+    ASSERT(m_context.IsEmpty() || !m_wrapperBoilerplates.IsEmpty());
+    return !m_context.IsEmpty();
+}
+
+void V8DOMWindowShell::disposeContextHandles()
+{
+    if (!m_context.IsEmpty()) {
+        m_context.Dispose();
+        m_context.Clear();
+    }
+
+    if (!m_wrapperBoilerplates.IsEmpty()) {
+#ifndef NDEBUG
+        V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates);
+#endif
+        m_wrapperBoilerplates.Dispose();
+        m_wrapperBoilerplates.Clear();
+    }
+}
+
+void V8DOMWindowShell::destroyGlobal()
+{
+    if (!m_global.IsEmpty()) {
+#ifndef NDEBUG
+        V8GCController::unregisterGlobalHandle(this, m_global);
+#endif
+        m_global.Dispose();
+        m_global.Clear();
+    }
+}
+
+void V8DOMWindowShell::clearForClose()
+{
+    if (!m_context.IsEmpty()) {
+        v8::HandleScope handleScope;
+
+        clearDocumentWrapper();
+        disposeContextHandles();
+    }
+}
+
+void V8DOMWindowShell::clearForNavigation()
+{
+    if (!m_context.IsEmpty()) {
+        v8::HandleScope handle;
+        clearDocumentWrapper();
+
+        v8::Context::Scope contextScope(m_context);
+
+        // Clear the document wrapper cache before turning on access checks on
+        // the old DOMWindow wrapper. This way, access to the document wrapper
+        // will be protected by the security checks on the DOMWindow wrapper.
+        clearDocumentWrapperCache();
+
+        // Turn on access check on the old DOMWindow wrapper.
+        v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global);
+        ASSERT(!wrapper.IsEmpty());
+        wrapper->TurnOnAccessCheck();
+
+        // Separate the context from its global object.
+        m_context->DetachGlobal();
+
+        disposeContextHandles();
+    }
+}
+
+// Create a new environment and setup the global object.
+//
+// The global object corresponds to a DOMWindow instance. However, to
+// allow properties of the JS DOMWindow instance to be shadowed, we
+// use a shadow object as the global object and use the JS DOMWindow
+// instance as the prototype for that shadow object. The JS DOMWindow
+// instance is undetectable from javascript code because the __proto__
+// accessors skip that object.
+//
+// The shadow object and the DOMWindow instance are seen as one object
+// from javascript. The javascript object that corresponds to a
+// DOMWindow instance is the shadow object. When mapping a DOMWindow
+// instance to a V8 object, we return the shadow object.
+//
+// To implement split-window, see
+//   1) https://bugs.webkit.org/show_bug.cgi?id=17249
+//   2) https://wiki.mozilla.org/Gecko:SplitWindow
+//   3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639
+// we need to split the shadow object further into two objects:
+// an outer window and an inner window. The inner window is the hidden
+// prototype of the outer window. The inner window is the default
+// global object of the context. A variable declared in the global
+// scope is a property of the inner window.
+//
+// The outer window sticks to a Frame, it is exposed to JavaScript
+// via window.window, window.self, window.parent, etc. The outer window
+// has a security token which is the domain. The outer window cannot
+// have its own properties. window.foo = 'x' is delegated to the
+// inner window.
+//
+// When a frame navigates to a new page, the inner window is cut off
+// the outer window, and the outer window identify is preserved for
+// the frame. However, a new inner window is created for the new page.
+// If there are JS code holds a closure to the old inner window,
+// it won't be able to reach the outer window via its global object.
+void V8DOMWindowShell::initContextIfNeeded()
+{
+    // Bail out if the context has already been initialized.
+    if (!m_context.IsEmpty())
+        return;
+
+    // Create a handle scope for all local handles.
+    v8::HandleScope handleScope;
+
+    // Setup the security handlers and message listener. This only has
+    // to be done once.
+    static bool isV8Initialized = false;
+    if (!isV8Initialized) {
+        // Tells V8 not to call the default OOM handler, binding code
+        // will handle it.
+        v8::V8::IgnoreOutOfMemoryException();
+        v8::V8::SetFatalErrorHandler(reportFatalErrorInV8);
+
+        v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue);
+        v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue);
+
+        v8::V8::AddMessageListener(&V8ConsoleMessage::handler);
+
+        v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess);
+
+        isV8Initialized = true;
+    }
+
+
+    m_context = createNewContext(m_global, 0);
+    if (m_context.IsEmpty())
+        return;
+
+    v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context);
+    v8::Context::Scope contextScope(v8Context);
+
+    // Store the first global object created so we can reuse it.
+    if (m_global.IsEmpty()) {
+        m_global = v8::Persistent<v8::Object>::New(v8Context->Global());
+        // Bail out if allocation of the first global objects fails.
+        if (m_global.IsEmpty()) {
+            disposeContextHandles();
+            return;
+        }
+#ifndef NDEBUG
+        V8GCController::registerGlobalHandle(PROXY, this, m_global);
+#endif
+    }
+
+    installHiddenObjectPrototype(v8Context);
+    m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT));
+    // Bail out if allocation failed.
+    if (m_wrapperBoilerplates.IsEmpty()) {
+        disposeContextHandles();
+        return;
+    }
+#ifndef NDEBUG
+    V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates);
+#endif
+
+    if (!installDOMWindow(v8Context, m_frame->domWindow()))
+        disposeContextHandles();
+
+    updateDocument();
+
+    setSecurityToken();
+
+    m_frame->loader()->client()->didCreateScriptContextForFrame();
+
+    // FIXME: This is wrong. We should actually do this for the proper world once
+    // we do isolated worlds the WebCore way.
+    m_frame->loader()->dispatchDidClearWindowObjectInWorld(0);
+}
+
+v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Object> global, int extensionGroup)
+{
+    v8::Persistent<v8::Context> result;
+
+    // The activeDocumentLoader pointer could be 0 during frame shutdown.
+    if (!m_frame->loader()->activeDocumentLoader())
+        return result;
+
+    // Create a new environment using an empty template for the shadow
+    // object. Reuse the global object if one has been created earlier.
+    v8::Persistent<v8::ObjectTemplate> globalTemplate = V8DOMWindow::GetShadowObjectTemplate();
+    if (globalTemplate.IsEmpty())
+        return result;
+
+    // Install a security handler with V8.
+    globalTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW));
+    globalTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount);
+
+    // Used to avoid sleep calls in unload handlers.
+    if (!V8Proxy::registeredExtensionWithV8(DateExtension::get()))
+        V8Proxy::registerExtension(DateExtension::get(), String());
+
+    // Dynamically tell v8 about our extensions now.
+    const V8Extensions& extensions = V8Proxy::extensions();
+    OwnArrayPtr<const char*> extensionNames(new const char*[extensions.size()]);
+    int index = 0;
+    for (size_t i = 0; i < extensions.size(); ++i) {
+        if (extensions[i].group && extensions[i].group != extensionGroup)
+            continue;
+
+        // Note: we check the loader URL here instead of the document URL
+        // because we might be currently loading an URL into a blank page.
+        // See http://code.google.com/p/chromium/issues/detail?id=10924
+        if (extensions[i].scheme.length() > 0 && (extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || extensions[i].scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol()))
+            continue;
+
+        extensionNames[index++] = extensions[i].extension->name();
+    }
+    v8::ExtensionConfiguration extensionConfiguration(index, extensionNames.get());
+    result = v8::Context::New(&extensionConfiguration, globalTemplate, global);
+
+    return result;
+}
+
+bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window)
+{
+    v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__");
+    if (implicitProtoString.IsEmpty())
+        return false;
+
+    // Create a new JS window object and use it as the prototype for the  shadow global object.
+    v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(V8ClassIndex::DOMWINDOW, getHiddenObjectPrototype(context));
+    v8::Local<v8::Object> jsWindow = SafeAllocation::newInstance(windowConstructor);
+    // Bail out if allocation failed.
+    if (jsWindow.IsEmpty())
+        return false;
+
+    // Wrap the window.
+    V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
+    V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
+
+    window->ref();
+    V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow));
+
+    // Insert the window instance as the prototype of the shadow object.
+    v8::Handle<v8::Object> v8Global = context->Global();
+    V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(v8Global->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
+    v8Global->Set(implicitProtoString, jsWindow);
+    return true;
+}
+
+void V8DOMWindowShell::updateDocumentWrapper(v8::Handle<v8::Value> wrapper)
+{
+    clearDocumentWrapper();
+
+    ASSERT(m_document.IsEmpty());
+    m_document = v8::Persistent<v8::Value>::New(wrapper);
+#ifndef NDEBUG
+    V8GCController::registerGlobalHandle(PROXY, this, m_document);
+#endif
+}
+
+void V8DOMWindowShell::clearDocumentWrapper()
+{
+    if (!m_document.IsEmpty()) {
+#ifndef NDEBUG
+        V8GCController::unregisterGlobalHandle(this, m_document);
+#endif
+        m_document.Dispose();
+        m_document.Clear();
+    }
+}
+
+void V8DOMWindowShell::updateDocumentWrapperCache()
+{
+    v8::HandleScope handleScope;
+    v8::Context::Scope contextScope(m_context);
+
+    // If the document has no frame, NodeToV8Object might get the
+    // document wrapper for a document that is about to be deleted.
+    // If the ForceSet below causes a garbage collection, the document
+    // might get deleted and the global handle for the document
+    // wrapper cleared. Using the cleared global handle will lead to
+    // crashes. In this case we clear the cache and let the DOMWindow
+    // accessor handle access to the document.
+    if (!m_frame->document()->frame()) {
+        clearDocumentWrapperCache();
+        return;
+    }
+
+    v8::Handle<v8::Value> documentWrapper = V8DOMWrapper::convertNodeToV8Object(m_frame->document());
+
+    // If instantiation of the document wrapper fails, clear the cache
+    // and let the DOMWindow accessor handle access to the document.
+    if (documentWrapper.IsEmpty()) {
+        clearDocumentWrapperCache();
+        return;
+    }
+    m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
+}
+
+void V8DOMWindowShell::clearDocumentWrapperCache()
+{
+    ASSERT(!m_context.IsEmpty());
+    m_context->Global()->ForceDelete(v8::String::New("document"));
+}
+
+void V8DOMWindowShell::setSecurityToken()
+{
+    Document* document = m_frame->document();
+    // Setup security origin and security token.
+    if (!document) {
+        m_context->UseDefaultSecurityToken();
+        return;
+    }
+
+    // Ask the document's SecurityOrigin to generate a security token.
+    // If two tokens are equal, then the SecurityOrigins canAccess each other.
+    // If two tokens are not equal, then we have to call canAccess.
+    // Note: we can't use the HTTPOrigin if it was set from the DOM.
+    SecurityOrigin* origin = document->securityOrigin();
+    String token;
+    if (!origin->domainWasSetInDOM())
+        token = document->securityOrigin()->toString();
+
+    // An empty or "null" token means we always have to call
+    // canAccess. The toString method on securityOrigins returns the
+    // string "null" for empty security origins and for security
+    // origins that should only allow access to themselves. In this
+    // case, we use the global object as the security token to avoid
+    // calling canAccess when a script accesses its own objects.
+    if (token.isEmpty() || token == "null") {
+        m_context->UseDefaultSecurityToken();
+        return;
+    }
+
+    CString utf8Token = token.utf8();
+    // NOTE: V8 does identity comparison in fast path, must use a symbol
+    // as the security token.
+    m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length()));
+}
+
+void V8DOMWindowShell::updateDocument()
+{
+    if (!m_frame->document())
+        return;
+
+    if (m_global.IsEmpty())
+        return;
+
+    // There is an existing JavaScript wrapper for the global object
+    // of this frame. JavaScript code in other frames might hold a
+    // reference to this wrapper. We eagerly initialize the JavaScript
+    // context for the new document to make property access on the
+    // global object wrapper succeed.
+    initContextIfNeeded();
+
+    // Bail out if context initialization failed.
+    if (m_context.IsEmpty())
+        return;
+
+    // We have a new document and we need to update the cache.
+    updateDocumentWrapperCache();
+
+    updateSecurityOrigin();
+}
+
+void V8DOMWindowShell::updateSecurityOrigin()
+{
+    v8::HandleScope scope;
+    setSecurityToken();
+}
+
+v8::Handle<v8::Value> V8DOMWindowShell::getHiddenObjectPrototype(v8::Handle<v8::Context> context)
+{
+    return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype());
+}
+
+void V8DOMWindowShell::installHiddenObjectPrototype(v8::Handle<v8::Context> context)
+{
+    v8::Handle<v8::String> objectString = v8::String::New("Object");
+    v8::Handle<v8::String> prototypeString = v8::String::New("prototype");
+    v8::Handle<v8::String> hiddenObjectPrototypeString = V8HiddenPropertyName::objectPrototype();
+    // Bail out if allocation failed.
+    if (objectString.IsEmpty() || prototypeString.IsEmpty() || hiddenObjectPrototypeString.IsEmpty())
+        return;
+
+    v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString));
+    v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString);
+
+    context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype);
+}
+
+v8::Local<v8::Object> V8DOMWindowShell::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType type)
+{
+    // Not in cache.
+    int classIndex = V8ClassIndex::ToInt(type);
+    initContextIfNeeded();
+    v8::Context::Scope scope(m_context);
+    v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context));
+    v8::Local<v8::Object> instance = SafeAllocation::newInstance(function);
+    if (!instance.IsEmpty()) {
+        m_wrapperBoilerplates->Set(v8::Integer::New(classIndex), instance);
+        return instance->Clone();
+    }
+    return notHandledByInterceptor();
+}
+
+
+
+} // WebCore
diff --git a/WebCore/bindings/v8/V8DOMWindowShell.h b/WebCore/bindings/v8/V8DOMWindowShell.h
new file mode 100644
index 0000000..de149be
--- /dev/null
+++ b/WebCore/bindings/v8/V8DOMWindowShell.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef V8DOMWindowShell_h
+#define V8DOMWindowShell_h
+
+#include "V8CustomBinding.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class DOMWindow;
+class Frame;
+
+// V8WindowShell represents all the per-global object state for a Frame that
+// persist between navigations.
+class V8DOMWindowShell : public RefCounted<V8DOMWindowShell> {
+public:
+    static PassRefPtr<V8DOMWindowShell> create(Frame*);
+
+    v8::Handle<v8::Context> context() const { return m_context; }
+
+    // Update document object of the frame.
+    void updateDocument();
+
+    // Update the security origin of a document
+    // (e.g., after setting docoument.domain).
+    void updateSecurityOrigin();
+
+    bool isContextInitialized();
+
+    v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global, int extensionGroup);
+    static bool installDOMWindow(v8::Handle<v8::Context> context, DOMWindow*);
+
+    void initContextIfNeeded();
+    void updateDocumentWrapper(v8::Handle<v8::Value> wrapper);
+
+    void clearForNavigation();
+    void clearForClose();
+
+    void destroyGlobal();
+
+    static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>);
+    // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts!
+    static void installHiddenObjectPrototype(v8::Handle<v8::Context>);
+
+    // To create JS Wrapper objects, we create a cache of a 'boiler plate'
+    // object, and then simply Clone that object each time we need a new one.
+    // This is faster than going through the full object creation process.
+    v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType type)
+    {
+        int classIndex = V8ClassIndex::ToInt(type);
+        v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex));
+        return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone;
+    }
+
+private:
+    V8DOMWindowShell(Frame*);
+
+    void disposeContextHandles();
+
+    void setSecurityToken();
+    void clearDocumentWrapper();
+
+    // The JavaScript wrapper for the document object is cached on the global
+    // object for fast access. UpdateDocumentWrapperCache sets the wrapper
+    // for the current document on the global object. ClearDocumentWrapperCache
+    // deletes the document wrapper from the global object.
+    void updateDocumentWrapperCache();
+    void clearDocumentWrapperCache();
+
+    v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType);
+
+    Frame* m_frame;
+
+    // For each possible type of wrapper, we keep a boilerplate object.
+    // The boilerplate is used to create additional wrappers of the same
+    // type.  We keep a single persistent handle to an array of the
+    // activated boilerplates.
+    v8::Persistent<v8::Array> m_wrapperBoilerplates;
+
+    v8::Persistent<v8::Context> m_context;
+    v8::Persistent<v8::Object> m_global;
+    v8::Persistent<v8::Value> m_document;
+};
+
+} // namespace WebCore
+
+#endif // V8DOMWindowShell_h
diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp
index fa08743..141c160 100644
--- a/WebCore/bindings/v8/V8DOMWrapper.cpp
+++ b/WebCore/bindings/v8/V8DOMWrapper.cpp
@@ -563,7 +563,7 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8W
     // Enter the scope for this context to get the correct constructor.
     v8::Context::Scope scope(context);
 
-    return getConstructor(type, V8Proxy::getHiddenObjectPrototype(context));
+    return getConstructor(type, V8DOMWindowShell::getHiddenObjectPrototype(context));
 }
 
 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window)
@@ -838,7 +838,8 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassI
 
     v8::Local<v8::Object> instance;
     if (proxy)
-        instance = proxy->createWrapperFromCache(descriptorType);
+        // FIXME: Fix this to work properly with isolated worlds (see above).
+        instance = proxy->windowShell()->createWrapperFromCache(descriptorType);
     else {
         v8::Local<v8::Function> function = getTemplate(descriptorType)->GetFunction();
         instance = SafeAllocation::newInstance(function);
@@ -1241,7 +1242,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document
     // checking if the node already has a wrapper.
     V8Proxy* proxy = V8Proxy::retrieve(document->frame());
     if (proxy)
-        proxy->initContextIfNeeded();
+        proxy->windowShell()->initContextIfNeeded();
 
     DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap();
     v8::Handle<v8::Object> wrapper = domNodeMap.get(document);
@@ -1331,7 +1332,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy
 
     if (isDocument) {
         if (proxy)
-            proxy->updateDocumentWrapper(result);
+            proxy->windowShell()->updateDocumentWrapper(result);
 
         if (type == V8ClassIndex::HTMLDOCUMENT) {
             // Create marker object and insert it in two internal fields.
diff --git a/WebCore/bindings/v8/V8IsolatedWorld.cpp b/WebCore/bindings/v8/V8IsolatedWorld.cpp
index de1292d..6ec1539 100644
--- a/WebCore/bindings/v8/V8IsolatedWorld.cpp
+++ b/WebCore/bindings/v8/V8IsolatedWorld.cpp
@@ -57,7 +57,8 @@ V8IsolatedWorld::V8IsolatedWorld(V8Proxy* proxy, int extensionGroup)
     ++isolatedWorldCount;
 
     v8::HandleScope scope;
-    m_context = SharedPersistent<v8::Context>::create(proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup));
+    // FIXME: We should be creating a new V8DOMWindowShell here instead of riping out the context.
+    m_context = SharedPersistent<v8::Context>::create(proxy->windowShell()->createNewContext(v8::Handle<v8::Object>(), extensionGroup));
     if (m_context->get().IsEmpty())
         return;
 
@@ -66,8 +67,9 @@ V8IsolatedWorld::V8IsolatedWorld(V8Proxy* proxy, int extensionGroup)
 
     getGlobalObject(m_context->get())->SetPointerInInternalField(V8Custom::kDOMWindowEnteredIsolatedWorldIndex, this);
 
-    V8Proxy::installHiddenObjectPrototype(m_context->get());
-    proxy->installDOMWindow(m_context->get(), proxy->frame()->domWindow());
+    V8DOMWindowShell::installHiddenObjectPrototype(m_context->get());
+    // FIXME: This will go away once we have a windowShell for the isolated world.
+    proxy->windowShell()->installDOMWindow(m_context->get(), proxy->frame()->domWindow());
 
     // Using the default security token means that the canAccess is always
     // called, which is slow.
diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp
index c793469..32a7e25 100644
--- a/WebCore/bindings/v8/V8Proxy.cpp
+++ b/WebCore/bindings/v8/V8Proxy.cpp
@@ -204,13 +204,6 @@ void V8Proxy::reportUnsafeAccessTo(Frame* target, DelayReporting delay)
     }
 }
 
-static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data)
-{
-    Frame* target = V8Custom::GetTargetFrame(host, data);
-    if (target)
-        V8Proxy::reportUnsafeAccessTo(target, V8Proxy::ReportLater);
-}
-
 static void handleFatalErrorInV8()
 {
     // FIXME: We temporarily deal with V8 internal error situations
@@ -218,17 +211,9 @@ static void handleFatalErrorInV8()
     CRASH();
 }
 
-static void reportFatalErrorInV8(const char* location, const char* message)
-{
-    // V8 is shutdown, we cannot use V8 api.
-    // The only thing we can do is to disable JavaScript.
-    // FIXME: clean up V8Proxy and disable JavaScript.
-    printf("V8 error: %s (%s)\n", message, location);
-    handleFatalErrorInV8();
-}
-
 V8Proxy::V8Proxy(Frame* frame)
     : m_frame(frame)
+    , m_windowShell(V8DOMWindowShell::create(frame))
     , m_inlineCode(false)
     , m_timerCallback(false)
     , m_recursion(0)
@@ -238,18 +223,7 @@ V8Proxy::V8Proxy(Frame* frame)
 V8Proxy::~V8Proxy()
 {
     clearForClose();
-    destroyGlobal();
-}
-
-void V8Proxy::destroyGlobal()
-{
-    if (!m_global.IsEmpty()) {
-#ifndef NDEBUG
-        V8GCController::unregisterGlobalHandle(this, m_global);
-#endif
-        m_global.Dispose();
-        m_global.Clear();
-    }
+    windowShell()->destroyGlobal();
 }
 
 v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine)
@@ -277,7 +251,7 @@ bool V8Proxy::handleOutOfMemory()
         // Clean m_context, and event handlers.
         proxy->clearForClose();
 
-        proxy->destroyGlobal();
+        proxy->windowShell()->destroyGlobal();
     }
 
     ChromiumBridge::notifyJSOutOfMemory(frame);
@@ -292,7 +266,8 @@ bool V8Proxy::handleOutOfMemory()
 
 void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup)
 {
-    initContextIfNeeded();
+    // FIXME: This will need to get reorganized once we have a windowShell for the isolated world.
+    windowShell()->initContextIfNeeded();
 
     v8::HandleScope handleScope;
     V8IsolatedWorld* world = 0;
@@ -334,20 +309,21 @@ void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode
       world->destroy();
 }
 
+// FIXME: We should remove this function!
 void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup)
 {
-    initContextIfNeeded();
+    windowShell()->initContextIfNeeded();
 
     v8::HandleScope handleScope;
 
     // Set up the DOM window as the prototype of the new global object.
-    v8::Handle<v8::Context> windowContext = m_context;
+    v8::Handle<v8::Context> windowContext = windowShell()->context();
     v8::Handle<v8::Object> windowGlobal = windowContext->Global();
     v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal);
 
     ASSERT(V8DOMWrapper::convertDOMWrapperToNative<DOMWindow>(windowWrapper) == m_frame->domWindow());
 
-    v8::Persistent<v8::Context> context = createNewContext(v8::Handle<v8::Object>(), extensionGroup);
+    v8::Persistent<v8::Context> context = windowShell()->createNewContext(v8::Handle<v8::Object>(), extensionGroup);
     if (context.IsEmpty())
         return;
 
@@ -387,9 +363,10 @@ bool V8Proxy::setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetCont
 {
     // Setup context id for JS debugger.
     v8::Context::Scope contextScope(targetContext);
-    if (m_context.IsEmpty())
+    v8::Handle<v8::Context> context = windowShell()->context();
+    if (context.IsEmpty())
         return false;
-    int debugId = contextDebugId(m_context);
+    int debugId = contextDebugId(context);
 
     char buffer[32];
     if (debugId == -1)
@@ -563,30 +540,6 @@ v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor,
     return result;
 }
 
-v8::Local<v8::Object> V8Proxy::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType type)
-{
-    // Not in cache.
-    int classIndex = V8ClassIndex::ToInt(type);
-    initContextIfNeeded();
-    v8::Context::Scope scope(m_context);
-    v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context));
-    v8::Local<v8::Object> instance = SafeAllocation::newInstance(function);
-    if (!instance.IsEmpty()) {
-        m_wrapperBoilerplates->Set(v8::Integer::New(classIndex), instance);
-        return instance->Clone();
-    }
-    return notHandledByInterceptor();
-}
-
-bool V8Proxy::isContextInitialized()
-{
-    // m_context, m_global, and m_wrapperBoilerplates should
-    // all be non-empty if if m_context is non-empty.
-    ASSERT(m_context.IsEmpty() || !m_global.IsEmpty());
-    ASSERT(m_context.IsEmpty() || !m_wrapperBoilerplates.IsEmpty());
-    return !m_context.IsEmpty();
-}
-
 DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context)
 {
     v8::Handle<v8::Object> global = context->Global();
@@ -657,79 +610,6 @@ void V8Proxy::disconnectFrame()
 {
 }
 
-void V8Proxy::updateDocumentWrapper(v8::Handle<v8::Value> wrapper)
-{
-    clearDocumentWrapper();
-
-    ASSERT(m_document.IsEmpty());
-    m_document = v8::Persistent<v8::Value>::New(wrapper);
-#ifndef NDEBUG
-    V8GCController::registerGlobalHandle(PROXY, this, m_document);
-#endif
-}
-
-void V8Proxy::clearDocumentWrapper()
-{
-    if (!m_document.IsEmpty()) {
-#ifndef NDEBUG
-        V8GCController::unregisterGlobalHandle(this, m_document);
-#endif
-        m_document.Dispose();
-        m_document.Clear();
-    }
-}
-
-void V8Proxy::updateDocumentWrapperCache()
-{
-    v8::HandleScope handleScope;
-    v8::Context::Scope contextScope(m_context);
-
-    // If the document has no frame, NodeToV8Object might get the
-    // document wrapper for a document that is about to be deleted.
-    // If the ForceSet below causes a garbage collection, the document
-    // might get deleted and the global handle for the document
-    // wrapper cleared. Using the cleared global handle will lead to
-    // crashes. In this case we clear the cache and let the DOMWindow
-    // accessor handle access to the document.
-    if (!m_frame->document()->frame()) {
-        clearDocumentWrapperCache();
-        return;
-    }
-
-    v8::Handle<v8::Value> documentWrapper = V8DOMWrapper::convertNodeToV8Object(m_frame->document());
-
-    // If instantiation of the document wrapper fails, clear the cache
-    // and let the DOMWindow accessor handle access to the document.
-    if (documentWrapper.IsEmpty()) {
-        clearDocumentWrapperCache();
-        return;
-    }
-    m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
-}
-
-void V8Proxy::clearDocumentWrapperCache()
-{
-    ASSERT(!m_context.IsEmpty());
-    m_context->Global()->ForceDelete(v8::String::New("document"));
-}
-
-void V8Proxy::disposeContextHandles()
-{
-    if (!m_context.IsEmpty()) {
-        m_frame->loader()->client()->didDestroyScriptContextForFrame();
-        m_context.Dispose();
-        m_context.Clear();
-    }
-
-    if (!m_wrapperBoilerplates.IsEmpty()) {
-#ifndef NDEBUG
-        V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates);
-#endif
-        m_wrapperBoilerplates.Dispose();
-        m_wrapperBoilerplates.Clear();
-    }
-}
-
 void V8Proxy::releaseStorageMutex()
 {
     // If we've just left a top level script context and local storage has been
@@ -756,285 +636,13 @@ void V8Proxy::resetIsolatedWorlds()
 void V8Proxy::clearForClose()
 {
     resetIsolatedWorlds();
-
-    if (!m_context.IsEmpty()) {
-        v8::HandleScope handleScope;
-
-        clearDocumentWrapper();
-        disposeContextHandles();
-    }
+    windowShell()->clearForClose();
 }
 
 void V8Proxy::clearForNavigation()
 {
     resetIsolatedWorlds();
-
-    if (!m_context.IsEmpty()) {
-        v8::HandleScope handle;
-        clearDocumentWrapper();
-
-        v8::Context::Scope contextScope(m_context);
-
-        // Clear the document wrapper cache before turning on access checks on
-        // the old DOMWindow wrapper. This way, access to the document wrapper
-        // will be protected by the security checks on the DOMWindow wrapper.
-        clearDocumentWrapperCache();
-
-        // Turn on access check on the old DOMWindow wrapper.
-        v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global);
-        ASSERT(!wrapper.IsEmpty());
-        wrapper->TurnOnAccessCheck();
-
-        // Separate the context from its global object.
-        m_context->DetachGlobal();
-
-        disposeContextHandles();
-    }
-}
-
-void V8Proxy::setSecurityToken()
-{
-    Document* document = m_frame->document();
-    // Setup security origin and security token.
-    if (!document) {
-        m_context->UseDefaultSecurityToken();
-        return;
-    }
-
-    // Ask the document's SecurityOrigin to generate a security token.
-    // If two tokens are equal, then the SecurityOrigins canAccess each other.
-    // If two tokens are not equal, then we have to call canAccess.
-    // Note: we can't use the HTTPOrigin if it was set from the DOM.
-    SecurityOrigin* origin = document->securityOrigin();
-    String token;
-    if (!origin->domainWasSetInDOM())
-        token = document->securityOrigin()->toString();
-
-    // An empty or "null" token means we always have to call
-    // canAccess. The toString method on securityOrigins returns the
-    // string "null" for empty security origins and for security
-    // origins that should only allow access to themselves. In this
-    // case, we use the global object as the security token to avoid
-    // calling canAccess when a script accesses its own objects.
-    if (token.isEmpty() || token == "null") {
-        m_context->UseDefaultSecurityToken();
-        return;
-    }
-
-    CString utf8Token = token.utf8();
-    // NOTE: V8 does identity comparison in fast path, must use a symbol
-    // as the security token.
-    m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length()));
-}
-
-void V8Proxy::updateDocument()
-{
-    if (!m_frame->document())
-        return;
-
-    if (m_global.IsEmpty())
-        return;
-
-    // There is an existing JavaScript wrapper for the global object
-    // of this frame. JavaScript code in other frames might hold a
-    // reference to this wrapper. We eagerly initialize the JavaScript
-    // context for the new document to make property access on the
-    // global object wrapper succeed.
-    initContextIfNeeded();
-
-    // Bail out if context initialization failed.
-    if (m_context.IsEmpty())
-        return;
-
-    // We have a new document and we need to update the cache.
-    updateDocumentWrapperCache();
-
-    updateSecurityOrigin();
-}
-
-void V8Proxy::updateSecurityOrigin()
-{
-    v8::HandleScope scope;
-    setSecurityToken();
-}
-
-v8::Persistent<v8::Context> V8Proxy::createNewContext(v8::Handle<v8::Object> global, int extensionGroup)
-{
-    v8::Persistent<v8::Context> result;
-
-    // The activeDocumentLoader pointer could be NULL during frame shutdown.
-    if (!m_frame->loader()->activeDocumentLoader())
-        return result;
-
-    // Create a new environment using an empty template for the shadow
-    // object. Reuse the global object if one has been created earlier.
-    v8::Persistent<v8::ObjectTemplate> globalTemplate = V8DOMWindow::GetShadowObjectTemplate();
-    if (globalTemplate.IsEmpty())
-        return result;
-
-    // Install a security handler with V8.
-    globalTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW));
-    globalTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount);
-
-    // Used to avoid sleep calls in unload handlers.
-    if (!registeredExtensionWithV8(DateExtension::get()))
-        registerExtension(DateExtension::get(), String());
-
-    // Dynamically tell v8 about our extensions now.
-    OwnArrayPtr<const char*> extensionNames(new const char*[m_extensions.size()]);
-    int index = 0;
-    for (size_t i = 0; i < m_extensions.size(); ++i) {
-        if (m_extensions[i].group && m_extensions[i].group != extensionGroup)
-            continue;
-
-        // Note: we check the loader URL here instead of the document URL
-        // because we might be currently loading an URL into a blank page.
-        // See http://code.google.com/p/chromium/issues/detail?id=10924
-        if (m_extensions[i].scheme.length() > 0 && (m_extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || m_extensions[i].scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol()))
-            continue;
-
-        extensionNames[index++] = m_extensions[i].extension->name();
-    }
-    v8::ExtensionConfiguration extensions(index, extensionNames.get());
-    result = v8::Context::New(&extensions, globalTemplate, global);
-
-    return result;
-}
-
-bool V8Proxy::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window)
-{
-    v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__");
-    if (implicitProtoString.IsEmpty())
-        return false;
-
-    // Create a new JS window object and use it as the prototype for the  shadow global object.
-    v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(V8ClassIndex::DOMWINDOW, getHiddenObjectPrototype(context));
-    v8::Local<v8::Object> jsWindow = SafeAllocation::newInstance(windowConstructor);
-    // Bail out if allocation failed.
-    if (jsWindow.IsEmpty())
-        return false;
-
-    // Wrap the window.
-    V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
-    V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
-
-    window->ref();
-    V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow));
-
-    // Insert the window instance as the prototype of the shadow object.
-    v8::Handle<v8::Object> v8Global = context->Global();
-    V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(v8Global->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
-    v8Global->Set(implicitProtoString, jsWindow);
-    return true;
-}
-
-// Create a new environment and setup the global object.
-//
-// The global object corresponds to a DOMWindow instance. However, to
-// allow properties of the JS DOMWindow instance to be shadowed, we
-// use a shadow object as the global object and use the JS DOMWindow
-// instance as the prototype for that shadow object. The JS DOMWindow
-// instance is undetectable from javascript code because the __proto__
-// accessors skip that object.
-//
-// The shadow object and the DOMWindow instance are seen as one object
-// from javascript. The javascript object that corresponds to a
-// DOMWindow instance is the shadow object. When mapping a DOMWindow
-// instance to a V8 object, we return the shadow object.
-//
-// To implement split-window, see
-//   1) https://bugs.webkit.org/show_bug.cgi?id=17249
-//   2) https://wiki.mozilla.org/Gecko:SplitWindow
-//   3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639
-// we need to split the shadow object further into two objects:
-// an outer window and an inner window. The inner window is the hidden
-// prototype of the outer window. The inner window is the default
-// global object of the context. A variable declared in the global
-// scope is a property of the inner window.
-//
-// The outer window sticks to a Frame, it is exposed to JavaScript
-// via window.window, window.self, window.parent, etc. The outer window
-// has a security token which is the domain. The outer window cannot
-// have its own properties. window.foo = 'x' is delegated to the
-// inner window.
-//
-// When a frame navigates to a new page, the inner window is cut off
-// the outer window, and the outer window identify is preserved for
-// the frame. However, a new inner window is created for the new page.
-// If there are JS code holds a closure to the old inner window,
-// it won't be able to reach the outer window via its global object.
-void V8Proxy::initContextIfNeeded()
-{
-    // Bail out if the context has already been initialized.
-    if (!m_context.IsEmpty())
-        return;
-
-    // Create a handle scope for all local handles.
-    v8::HandleScope handleScope;
-
-    // Setup the security handlers and message listener. This only has
-    // to be done once.
-    static bool isV8Initialized = false;
-    if (!isV8Initialized) {
-        // Tells V8 not to call the default OOM handler, binding code
-        // will handle it.
-        v8::V8::IgnoreOutOfMemoryException();
-        v8::V8::SetFatalErrorHandler(reportFatalErrorInV8);
-
-        v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue);
-        v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue);
-
-        v8::V8::AddMessageListener(&V8ConsoleMessage::handler);
-
-        v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess);
-
-        isV8Initialized = true;
-    }
-
-
-    m_context = createNewContext(m_global, 0);
-    if (m_context.IsEmpty())
-        return;
-
-    v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context);
-    v8::Context::Scope contextScope(v8Context);
-
-    // Store the first global object created so we can reuse it.
-    if (m_global.IsEmpty()) {
-        m_global = v8::Persistent<v8::Object>::New(v8Context->Global());
-        // Bail out if allocation of the first global objects fails.
-        if (m_global.IsEmpty()) {
-            disposeContextHandles();
-            return;
-        }
-#ifndef NDEBUG
-        V8GCController::registerGlobalHandle(PROXY, this, m_global);
-#endif
-    }
-
-    installHiddenObjectPrototype(v8Context);
-    m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT));
-    // Bail out if allocation failed.
-    if (m_wrapperBoilerplates.IsEmpty()) {
-        disposeContextHandles();
-        return;
-    }
-#ifndef NDEBUG
-    V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates);
-#endif
-
-    if (!installDOMWindow(v8Context, m_frame->domWindow()))
-        disposeContextHandles();
-
-    updateDocument();
-
-    setSecurityToken();
-
-    m_frame->loader()->client()->didCreateScriptContextForFrame();
-
-    // FIXME: This is wrong. We should actually do this for the proper world once
-    // we do isolated worlds the WebCore way.
-    m_frame->loader()->dispatchDidClearWindowObjectInWorld(0);
+    windowShell()->clearForNavigation();
 }
 
 void V8Proxy::setDOMException(int exceptionCode)
@@ -1122,8 +730,8 @@ v8::Local<v8::Context> V8Proxy::context()
 
 v8::Local<v8::Context> V8Proxy::mainWorldContext()
 {
-    initContextIfNeeded();
-    return v8::Local<v8::Context>::New(m_context);
+    windowShell()->initContextIfNeeded();
+    return v8::Local<v8::Context>::New(windowShell()->context());
 }
 
 v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame)
@@ -1271,17 +879,18 @@ void V8Proxy::registerExtension(v8::Extension* extension, int extensionGroup)
 bool V8Proxy::setContextDebugId(int debugId)
 {
     ASSERT(debugId > 0);
-    if (m_context.IsEmpty())
+    v8::Handle<v8::Context> context = windowShell()->context();
+    if (context.IsEmpty())
         return false;
     v8::HandleScope scope;
-    if (!m_context->GetData()->IsUndefined())
+    if (!context->GetData()->IsUndefined())
         return false;
 
-    v8::Context::Scope contextScope(m_context);
+    v8::Context::Scope contextScope(context);
 
     char buffer[32];
     snprintf(buffer, sizeof(buffer), "page,%d", debugId);
-    m_context->SetData(v8::String::New(buffer));
+    context->SetData(v8::String::New(buffer));
 
     return true;
 }
@@ -1298,26 +907,6 @@ int V8Proxy::contextDebugId(v8::Handle<v8::Context> context)
     return atoi(comma + 1);
 }
 
-v8::Handle<v8::Value> V8Proxy::getHiddenObjectPrototype(v8::Handle<v8::Context> context)
-{
-    return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype());
-}
-
-void V8Proxy::installHiddenObjectPrototype(v8::Handle<v8::Context> context)
-{
-    v8::Handle<v8::String> objectString = v8::String::New("Object");
-    v8::Handle<v8::String> prototypeString = v8::String::New("prototype");
-    v8::Handle<v8::String> hiddenObjectPrototypeString = V8HiddenPropertyName::objectPrototype();
-    // Bail out if allocation failed.
-    if (objectString.IsEmpty() || prototypeString.IsEmpty() || hiddenObjectPrototypeString.IsEmpty())
-        return;
-
-    v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString));
-    v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString);
-
-    context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype);
-}
-
 v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, const WorldContextHandle& worldContext)
 {
     if (context->isDocument()) {
diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h
index dd157fa..80ecaff 100644
--- a/WebCore/bindings/v8/V8Proxy.h
+++ b/WebCore/bindings/v8/V8Proxy.h
@@ -36,6 +36,7 @@
 #include "SecurityOrigin.h" // for WebCore::SecurityOrigin
 #include "SharedPersistent.h"
 #include "V8AbstractEventListener.h"
+#include "V8DOMWindowShell.h"
 #include "V8DOMWrapper.h"
 #include "V8GCController.h"
 #include "V8Index.h"
@@ -151,22 +152,9 @@ namespace WebCore {
 
         Frame* frame() { return m_frame; }
 
-        // Clear page-specific data, but keep the global object identify.
         void clearForNavigation();
-
-        // Clear page-specific data before shutting down the proxy object.
         void clearForClose();
 
-        // Update document object of the frame.
-        void updateDocument();
-
-        // Update the security origin of a document
-        // (e.g., after setting docoument.domain).
-        void updateSecurityOrigin();
-
-        // Destroy the global object.
-        void destroyGlobal();
-
         // FIXME: Need comment. User Gesture related.
         bool inlineCode() const { return m_inlineCode; }
         void setInlineCode(bool value) { m_inlineCode = value; }
@@ -174,9 +162,6 @@ namespace WebCore {
         bool timerCallback() const { return m_timerCallback; }
         void setTimerCallback(bool value) { m_timerCallback = value; }
 
-        // Has the context for this proxy been initialized?
-        bool isContextInitialized();
-
         // Disconnects the proxy from its owner frame,
         // and clears all timeouts on the DOM window.
         void disconnectFrame();
@@ -241,16 +226,6 @@ namespace WebCore {
         // Call the function as constructor with the given arguments.
         v8::Local<v8::Value> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]);
 
-        // To create JS Wrapper objects, we create a cache of a 'boiler plate'
-        // object, and then simply Clone that object each time we need a new one.
-        // This is faster than going through the full object creation process.
-        v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType type)
-        {
-            int classIndex = V8ClassIndex::ToInt(type);
-            v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex));
-            return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone;
-        }
-
         // Returns the window object associated with a context.
         static DOMWindow* retrieveWindow(v8::Handle<v8::Context>);
         // Returns V8Proxy object of the currently executing context.
@@ -341,13 +316,12 @@ namespace WebCore {
         v8::Local<v8::Context> context();
         v8::Local<v8::Context> mainWorldContext();
 
+        // FIXME: This should eventually take DOMWrapperWorld argument!
+        V8DOMWindowShell* windowShell() const { return m_windowShell.get(); }
+
         bool setContextDebugId(int id);
         static int contextDebugId(v8::Handle<v8::Context>);
 
-        static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>);
-        // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts!
-        static void installHiddenObjectPrototype(v8::Handle<v8::Context>);
-
         // Registers a v8 extension to be available on webpages. The two forms
         // offer various restrictions on what types of contexts the extension is
         // loaded into. If a scheme is provided, only pages whose URL has the given
@@ -358,30 +332,15 @@ namespace WebCore {
         static void registerExtension(v8::Extension*, const String& schemeRestriction);
         static void registerExtension(v8::Extension*, int extensionGroup);
 
-        // FIXME: Separate these concerns from V8Proxy?
-        v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global, int extensionGroup);
-        static bool installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window);
+        static void registerExtensionWithV8(v8::Extension*);
+        static bool registeredExtensionWithV8(v8::Extension*);
+
+        static const V8Extensions& extensions() { return m_extensions; }
 
-        void initContextIfNeeded();
-        void updateDocumentWrapper(v8::Handle<v8::Value> wrapper);
-        
         // Report an unsafe attempt to access the given frame on the console.
         static void reportUnsafeAccessTo(Frame* target, DelayReporting delay);
 
     private:
-        void setSecurityToken();
-        void clearDocumentWrapper();
-
-        // The JavaScript wrapper for the document object is cached on the global
-        // object for fast access. UpdateDocumentWrapperCache sets the wrapper
-        // for the current document on the global object. ClearDocumentWrapperCache
-        // deletes the document wrapper from the global object.
-        void updateDocumentWrapperCache();
-        void clearDocumentWrapperCache();
-
-        // Dispose global handles of m_contexts and friends.
-        void disposeContextHandles();
-
         // If m_recursionCount is 0, let LocalStorage know so we can release
         // the storage mutex.
         void releaseStorageMutex();
@@ -414,24 +373,11 @@ namespace WebCore {
             return v8::Local<v8::Context>::New(m_utilityContext);
         }
 
-        v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType);
-
-        static void registerExtensionWithV8(v8::Extension*);
-        static bool registeredExtensionWithV8(v8::Extension*);
-
         Frame* m_frame;
 
-        v8::Persistent<v8::Context> m_context;
-
-        // For each possible type of wrapper, we keep a boilerplate object.
-        // The boilerplate is used to create additional wrappers of the same
-        // type.  We keep a single persistent handle to an array of the
-        // activated boilerplates.
-        v8::Persistent<v8::Array> m_wrapperBoilerplates;
-
-        v8::Persistent<v8::Object> m_global;
-        v8::Persistent<v8::Value> m_document;
-
+        // For the moment, we have one of these.  Soon we will have one per DOMWrapperWorld.
+        RefPtr<V8DOMWindowShell> m_windowShell;
+        
         // Utility context holding JavaScript functions used internally.
         static v8::Persistent<v8::Context> m_utilityContext;
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list