WebCore/bindings/v8/V8DOMWindowShell.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
       
     3  * 
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  * 
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  * 
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 #include "V8DOMWindowShell.h"
       
    33 
       
    34 #include "PlatformBridge.h"
       
    35 #include "CSSMutableStyleDeclaration.h"
       
    36 #include "DateExtension.h"
       
    37 #include "DocumentLoader.h"
       
    38 #include "Frame.h"
       
    39 #include "FrameLoaderClient.h"
       
    40 #include "InspectorTimelineAgent.h"
       
    41 #include "Page.h"
       
    42 #include "PageGroup.h"
       
    43 #include "ScriptController.h"
       
    44 #include "StorageNamespace.h"
       
    45 #include "V8Binding.h"
       
    46 #include "V8BindingState.h"
       
    47 #include "V8Collection.h"
       
    48 #include "V8ConsoleMessage.h"
       
    49 #include "V8DOMMap.h"
       
    50 #include "V8DOMWindow.h"
       
    51 #include "V8Document.h"
       
    52 #include "V8GCForContextDispose.h"
       
    53 #include "V8HiddenPropertyName.h"
       
    54 #include "V8History.h"
       
    55 #include "V8Location.h"
       
    56 #include "V8Proxy.h"
       
    57 #include "WorkerContextExecutionProxy.h"
       
    58 
       
    59 #include <algorithm>
       
    60 #include <stdio.h>
       
    61 #include <utility>
       
    62 #include <v8-debug.h>
       
    63 #include <v8.h>
       
    64 #include <wtf/Assertions.h>
       
    65 #include <wtf/OwnArrayPtr.h>
       
    66 #include <wtf/StdLibExtras.h>
       
    67 #include <wtf/StringExtras.h>
       
    68 #include <wtf/UnusedParam.h>
       
    69 #include <wtf/text/CString.h>
       
    70 
       
    71 namespace WebCore {
       
    72 
       
    73 static void handleFatalErrorInV8()
       
    74 {
       
    75     // FIXME: We temporarily deal with V8 internal error situations
       
    76     // such as out-of-memory by crashing the renderer.
       
    77     CRASH();
       
    78 }
       
    79 
       
    80 static void reportFatalErrorInV8(const char* location, const char* message)
       
    81 {
       
    82     // V8 is shutdown, we cannot use V8 api.
       
    83     // The only thing we can do is to disable JavaScript.
       
    84     // FIXME: clean up V8Proxy and disable JavaScript.
       
    85     printf("V8 error: %s (%s)\n", message, location);
       
    86     handleFatalErrorInV8();
       
    87 }
       
    88 
       
    89 // Returns the owner frame pointer of a DOM wrapper object. It only works for
       
    90 // these DOM objects requiring cross-domain access check.
       
    91 static Frame* getTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data)
       
    92 {
       
    93     Frame* target = 0;
       
    94     WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
       
    95     if (V8DOMWindow::info.equals(type)) {
       
    96         v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host);
       
    97         if (window.IsEmpty())
       
    98             return target;
       
    99 
       
   100         DOMWindow* targetWindow = V8DOMWindow::toNative(window);
       
   101         target = targetWindow->frame();
       
   102     } else if (V8History::info.equals(type)) {
       
   103         History* history = V8History::toNative(host);
       
   104         target = history->frame();
       
   105     } else if (V8Location::info.equals(type)) {
       
   106         Location* location = V8Location::toNative(host);
       
   107         target = location->frame();
       
   108     }
       
   109     return target;
       
   110 }
       
   111 
       
   112 static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data)
       
   113 {
       
   114     Frame* target = getTargetFrame(host, data);
       
   115     if (target)
       
   116         V8Proxy::reportUnsafeAccessTo(target, V8Proxy::ReportLater);
       
   117 }
       
   118 
       
   119 PassRefPtr<V8DOMWindowShell> V8DOMWindowShell::create(Frame* frame)
       
   120 {
       
   121     return adoptRef(new V8DOMWindowShell(frame));
       
   122 }
       
   123 
       
   124 V8DOMWindowShell::V8DOMWindowShell(Frame* frame)
       
   125     : m_frame(frame)
       
   126 {
       
   127 }
       
   128 
       
   129 bool V8DOMWindowShell::isContextInitialized()
       
   130 {
       
   131     // m_context, m_global, and m_wrapperBoilerplates should
       
   132     // all be non-empty if if m_context is non-empty.
       
   133     ASSERT(m_context.IsEmpty() || !m_global.IsEmpty());
       
   134     return !m_context.IsEmpty();
       
   135 }
       
   136 
       
   137 void V8DOMWindowShell::disposeContextHandles()
       
   138 {
       
   139     if (!m_context.IsEmpty()) {
       
   140         m_frame->loader()->client()->didDestroyScriptContextForFrame();
       
   141         m_context.Dispose();
       
   142         m_context.Clear();
       
   143 
       
   144         // It's likely that disposing the context has created a lot of
       
   145         // garbage. Notify V8 about this so it'll have a chance of cleaning
       
   146         // it up when idle.
       
   147         V8GCForContextDispose::instance().notifyContextDisposed();
       
   148     }
       
   149 
       
   150     WrapperBoilerplateMap::iterator it = m_wrapperBoilerplates.begin();
       
   151     for (; it != m_wrapperBoilerplates.end(); ++it) {
       
   152         v8::Persistent<v8::Object> wrapper = it->second;
       
   153         wrapper.Dispose();
       
   154         wrapper.Clear();
       
   155     }
       
   156     m_wrapperBoilerplates.clear();
       
   157 }
       
   158 
       
   159 void V8DOMWindowShell::destroyGlobal()
       
   160 {
       
   161     if (!m_global.IsEmpty()) {
       
   162 #ifndef NDEBUG
       
   163         V8GCController::unregisterGlobalHandle(this, m_global);
       
   164 #endif
       
   165         m_global.Dispose();
       
   166         m_global.Clear();
       
   167     }
       
   168 }
       
   169 
       
   170 void V8DOMWindowShell::clearForClose()
       
   171 {
       
   172     if (!m_context.IsEmpty()) {
       
   173         v8::HandleScope handleScope;
       
   174 
       
   175         clearDocumentWrapper();
       
   176         disposeContextHandles();
       
   177     }
       
   178 }
       
   179 
       
   180 void V8DOMWindowShell::clearForNavigation()
       
   181 {
       
   182     if (!m_context.IsEmpty()) {
       
   183         v8::HandleScope handle;
       
   184         clearDocumentWrapper();
       
   185 
       
   186         v8::Context::Scope contextScope(m_context);
       
   187 
       
   188         // Clear the document wrapper cache before turning on access checks on
       
   189         // the old DOMWindow wrapper. This way, access to the document wrapper
       
   190         // will be protected by the security checks on the DOMWindow wrapper.
       
   191         clearDocumentWrapperCache();
       
   192 
       
   193         // Turn on access check on the old DOMWindow wrapper.
       
   194         v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), m_global);
       
   195         ASSERT(!wrapper.IsEmpty());
       
   196         wrapper->TurnOnAccessCheck();
       
   197 
       
   198         // Separate the context from its global object.
       
   199         m_context->DetachGlobal();
       
   200 
       
   201         disposeContextHandles();
       
   202     }
       
   203 }
       
   204 
       
   205 // Create a new environment and setup the global object.
       
   206 //
       
   207 // The global object corresponds to a DOMWindow instance. However, to
       
   208 // allow properties of the JS DOMWindow instance to be shadowed, we
       
   209 // use a shadow object as the global object and use the JS DOMWindow
       
   210 // instance as the prototype for that shadow object. The JS DOMWindow
       
   211 // instance is undetectable from javascript code because the __proto__
       
   212 // accessors skip that object.
       
   213 //
       
   214 // The shadow object and the DOMWindow instance are seen as one object
       
   215 // from javascript. The javascript object that corresponds to a
       
   216 // DOMWindow instance is the shadow object. When mapping a DOMWindow
       
   217 // instance to a V8 object, we return the shadow object.
       
   218 //
       
   219 // To implement split-window, see
       
   220 //   1) https://bugs.webkit.org/show_bug.cgi?id=17249
       
   221 //   2) https://wiki.mozilla.org/Gecko:SplitWindow
       
   222 //   3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639
       
   223 // we need to split the shadow object further into two objects:
       
   224 // an outer window and an inner window. The inner window is the hidden
       
   225 // prototype of the outer window. The inner window is the default
       
   226 // global object of the context. A variable declared in the global
       
   227 // scope is a property of the inner window.
       
   228 //
       
   229 // The outer window sticks to a Frame, it is exposed to JavaScript
       
   230 // via window.window, window.self, window.parent, etc. The outer window
       
   231 // has a security token which is the domain. The outer window cannot
       
   232 // have its own properties. window.foo = 'x' is delegated to the
       
   233 // inner window.
       
   234 //
       
   235 // When a frame navigates to a new page, the inner window is cut off
       
   236 // the outer window, and the outer window identify is preserved for
       
   237 // the frame. However, a new inner window is created for the new page.
       
   238 // If there are JS code holds a closure to the old inner window,
       
   239 // it won't be able to reach the outer window via its global object.
       
   240 void V8DOMWindowShell::initContextIfNeeded()
       
   241 {
       
   242     // Bail out if the context has already been initialized.
       
   243     if (!m_context.IsEmpty())
       
   244         return;
       
   245 
       
   246     // Create a handle scope for all local handles.
       
   247     v8::HandleScope handleScope;
       
   248 
       
   249     // Setup the security handlers and message listener. This only has
       
   250     // to be done once.
       
   251     static bool isV8Initialized = false;
       
   252     if (!isV8Initialized) {
       
   253         // Tells V8 not to call the default OOM handler, binding code
       
   254         // will handle it.
       
   255         v8::V8::IgnoreOutOfMemoryException();
       
   256         v8::V8::SetFatalErrorHandler(reportFatalErrorInV8);
       
   257 
       
   258         v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue);
       
   259         v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue);
       
   260 
       
   261         v8::V8::AddMessageListener(&V8ConsoleMessage::handler);
       
   262 
       
   263         v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess);
       
   264 
       
   265         isV8Initialized = true;
       
   266     }
       
   267 
       
   268 
       
   269     m_context = createNewContext(m_global, 0);
       
   270     if (m_context.IsEmpty())
       
   271         return;
       
   272 
       
   273     v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context);
       
   274     v8::Context::Scope contextScope(v8Context);
       
   275 
       
   276     // Store the first global object created so we can reuse it.
       
   277     if (m_global.IsEmpty()) {
       
   278         m_global = v8::Persistent<v8::Object>::New(v8Context->Global());
       
   279         // Bail out if allocation of the first global objects fails.
       
   280         if (m_global.IsEmpty()) {
       
   281             disposeContextHandles();
       
   282             return;
       
   283         }
       
   284 #ifndef NDEBUG
       
   285         V8GCController::registerGlobalHandle(PROXY, this, m_global);
       
   286 #endif
       
   287     }
       
   288 
       
   289     if (!installHiddenObjectPrototype(v8Context)) {
       
   290         disposeContextHandles();
       
   291         return;
       
   292     }
       
   293 
       
   294     if (!installDOMWindow(v8Context, m_frame->domWindow())) {
       
   295         disposeContextHandles();
       
   296         return;
       
   297     }
       
   298 
       
   299     updateDocument();
       
   300 
       
   301     setSecurityToken();
       
   302 
       
   303     m_frame->loader()->client()->didCreateScriptContextForFrame();
       
   304 
       
   305     // FIXME: This is wrong. We should actually do this for the proper world once
       
   306     // we do isolated worlds the WebCore way.
       
   307     m_frame->loader()->dispatchDidClearWindowObjectInWorld(0);
       
   308 }
       
   309 
       
   310 v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Object> global, int extensionGroup)
       
   311 {
       
   312     v8::Persistent<v8::Context> result;
       
   313 
       
   314     // The activeDocumentLoader pointer could be 0 during frame shutdown.
       
   315     if (!m_frame->loader()->activeDocumentLoader())
       
   316         return result;
       
   317 
       
   318     // Create a new environment using an empty template for the shadow
       
   319     // object. Reuse the global object if one has been created earlier.
       
   320     v8::Persistent<v8::ObjectTemplate> globalTemplate = V8DOMWindow::GetShadowObjectTemplate();
       
   321     if (globalTemplate.IsEmpty())
       
   322         return result;
       
   323 
       
   324     // Used to avoid sleep calls in unload handlers.
       
   325     if (!V8Proxy::registeredExtensionWithV8(DateExtension::get()))
       
   326         V8Proxy::registerExtension(DateExtension::get(), String());
       
   327 
       
   328     // Dynamically tell v8 about our extensions now.
       
   329     const V8Extensions& extensions = V8Proxy::extensions();
       
   330     OwnArrayPtr<const char*> extensionNames(new const char*[extensions.size()]);
       
   331     int index = 0;
       
   332     for (size_t i = 0; i < extensions.size(); ++i) {
       
   333         if (extensions[i].group && extensions[i].group != extensionGroup)
       
   334             continue;
       
   335 
       
   336         // Note: we check the loader URL here instead of the document URL
       
   337         // because we might be currently loading an URL into a blank page.
       
   338         // See http://code.google.com/p/chromium/issues/detail?id=10924
       
   339         if (extensions[i].scheme.length() > 0 && (extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol()))
       
   340             continue;
       
   341 
       
   342         extensionNames[index++] = extensions[i].extension->name();
       
   343     }
       
   344     v8::ExtensionConfiguration extensionConfiguration(index, extensionNames.get());
       
   345     result = v8::Context::New(&extensionConfiguration, globalTemplate, global);
       
   346 
       
   347     return result;
       
   348 }
       
   349 
       
   350 void V8DOMWindowShell::setContext(v8::Handle<v8::Context> context)
       
   351 {
       
   352     // if we already have a context, clear it before setting the new one.
       
   353     if (!m_context.IsEmpty()) {
       
   354         m_context.Dispose();
       
   355         m_context.Clear();
       
   356     }
       
   357     m_context = v8::Persistent<v8::Context>::New(context);
       
   358 }
       
   359 
       
   360 bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window)
       
   361 {
       
   362     // Create a new JS window object and use it as the prototype for the  shadow global object.
       
   363     v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(&V8DOMWindow::info, getHiddenObjectPrototype(context));
       
   364     v8::Local<v8::Object> jsWindow = SafeAllocation::newInstance(windowConstructor);
       
   365     // Bail out if allocation failed.
       
   366     if (jsWindow.IsEmpty())
       
   367         return false;
       
   368 
       
   369     // Wrap the window.
       
   370     V8DOMWrapper::setDOMWrapper(jsWindow, &V8DOMWindow::info, window);
       
   371     V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), &V8DOMWindow::info, window);
       
   372 
       
   373     window->ref();
       
   374     V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow));
       
   375 
       
   376     // Insert the window instance as the prototype of the shadow object.
       
   377     v8::Handle<v8::Object> v8RealGlobal = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype());
       
   378     V8DOMWrapper::setDOMWrapper(v8RealGlobal, &V8DOMWindow::info, window);
       
   379     v8RealGlobal->SetPrototype(jsWindow);
       
   380     return true;
       
   381 }
       
   382 
       
   383 void V8DOMWindowShell::updateDocumentWrapper(v8::Handle<v8::Object> wrapper)
       
   384 {
       
   385     clearDocumentWrapper();
       
   386 
       
   387     ASSERT(m_document.IsEmpty());
       
   388     m_document = v8::Persistent<v8::Object>::New(wrapper);
       
   389 #ifndef NDEBUG
       
   390     V8GCController::registerGlobalHandle(PROXY, this, m_document);
       
   391 #endif
       
   392 }
       
   393 
       
   394 void V8DOMWindowShell::clearDocumentWrapper()
       
   395 {
       
   396     if (!m_document.IsEmpty()) {
       
   397 #ifndef NDEBUG
       
   398         V8GCController::unregisterGlobalHandle(this, m_document);
       
   399 #endif
       
   400         m_document.Dispose();
       
   401         m_document.Clear();
       
   402     }
       
   403 }
       
   404 
       
   405 void V8DOMWindowShell::updateDocumentWrapperCache()
       
   406 {
       
   407     v8::HandleScope handleScope;
       
   408     v8::Context::Scope contextScope(m_context);
       
   409 
       
   410     // If the document has no frame, NodeToV8Object might get the
       
   411     // document wrapper for a document that is about to be deleted.
       
   412     // If the ForceSet below causes a garbage collection, the document
       
   413     // might get deleted and the global handle for the document
       
   414     // wrapper cleared. Using the cleared global handle will lead to
       
   415     // crashes. In this case we clear the cache and let the DOMWindow
       
   416     // accessor handle access to the document.
       
   417     if (!m_frame->document()->frame()) {
       
   418         clearDocumentWrapperCache();
       
   419         return;
       
   420     }
       
   421 
       
   422     v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document());
       
   423 
       
   424     // If instantiation of the document wrapper fails, clear the cache
       
   425     // and let the DOMWindow accessor handle access to the document.
       
   426     if (documentWrapper.IsEmpty()) {
       
   427         clearDocumentWrapperCache();
       
   428         return;
       
   429     }
       
   430     ASSERT(documentWrapper->IsObject());
       
   431     m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
       
   432 }
       
   433 
       
   434 void V8DOMWindowShell::clearDocumentWrapperCache()
       
   435 {
       
   436     ASSERT(!m_context.IsEmpty());
       
   437     m_context->Global()->ForceDelete(v8::String::New("document"));
       
   438 }
       
   439 
       
   440 void V8DOMWindowShell::setSecurityToken()
       
   441 {
       
   442     Document* document = m_frame->document();
       
   443     // Setup security origin and security token.
       
   444     if (!document) {
       
   445         m_context->UseDefaultSecurityToken();
       
   446         return;
       
   447     }
       
   448 
       
   449     // Ask the document's SecurityOrigin to generate a security token.
       
   450     // If two tokens are equal, then the SecurityOrigins canAccess each other.
       
   451     // If two tokens are not equal, then we have to call canAccess.
       
   452     // Note: we can't use the HTTPOrigin if it was set from the DOM.
       
   453     SecurityOrigin* origin = document->securityOrigin();
       
   454     String token;
       
   455     if (!origin->domainWasSetInDOM())
       
   456         token = document->securityOrigin()->toString();
       
   457 
       
   458     // An empty or "null" token means we always have to call
       
   459     // canAccess. The toString method on securityOrigins returns the
       
   460     // string "null" for empty security origins and for security
       
   461     // origins that should only allow access to themselves. In this
       
   462     // case, we use the global object as the security token to avoid
       
   463     // calling canAccess when a script accesses its own objects.
       
   464     if (token.isEmpty() || token == "null") {
       
   465         m_context->UseDefaultSecurityToken();
       
   466         return;
       
   467     }
       
   468 
       
   469     CString utf8Token = token.utf8();
       
   470     // NOTE: V8 does identity comparison in fast path, must use a symbol
       
   471     // as the security token.
       
   472     m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length()));
       
   473 }
       
   474 
       
   475 void V8DOMWindowShell::updateDocument()
       
   476 {
       
   477     if (!m_frame->document())
       
   478         return;
       
   479 
       
   480     if (m_global.IsEmpty())
       
   481         return;
       
   482 
       
   483     // There is an existing JavaScript wrapper for the global object
       
   484     // of this frame. JavaScript code in other frames might hold a
       
   485     // reference to this wrapper. We eagerly initialize the JavaScript
       
   486     // context for the new document to make property access on the
       
   487     // global object wrapper succeed.
       
   488     initContextIfNeeded();
       
   489 
       
   490     // Bail out if context initialization failed.
       
   491     if (m_context.IsEmpty())
       
   492         return;
       
   493 
       
   494     // We have a new document and we need to update the cache.
       
   495     updateDocumentWrapperCache();
       
   496 
       
   497     updateSecurityOrigin();
       
   498 }
       
   499 
       
   500 void V8DOMWindowShell::updateSecurityOrigin()
       
   501 {
       
   502     v8::HandleScope scope;
       
   503     setSecurityToken();
       
   504 }
       
   505 
       
   506 v8::Handle<v8::Value> V8DOMWindowShell::getHiddenObjectPrototype(v8::Handle<v8::Context> context)
       
   507 {
       
   508     return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype());
       
   509 }
       
   510 
       
   511 bool V8DOMWindowShell::installHiddenObjectPrototype(v8::Handle<v8::Context> context)
       
   512 {
       
   513     v8::Handle<v8::String> objectString = v8::String::New("Object");
       
   514     v8::Handle<v8::String> prototypeString = v8::String::New("prototype");
       
   515     v8::Handle<v8::String> hiddenObjectPrototypeString = V8HiddenPropertyName::objectPrototype();
       
   516     // Bail out if allocation failed.
       
   517     if (objectString.IsEmpty() || prototypeString.IsEmpty() || hiddenObjectPrototypeString.IsEmpty())
       
   518         return false;
       
   519 
       
   520     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString));
       
   521     // Bail out if fetching failed.
       
   522     if (object.IsEmpty())
       
   523         return false;
       
   524     v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString);
       
   525     // Bail out if fetching failed.
       
   526     if (objectPrototype.IsEmpty())
       
   527         return false;
       
   528 
       
   529     context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype);
       
   530 
       
   531     return true;
       
   532 }
       
   533 
       
   534 v8::Local<v8::Object> V8DOMWindowShell::createWrapperFromCacheSlowCase(WrapperTypeInfo* type)
       
   535 {
       
   536     // Not in cache.
       
   537     initContextIfNeeded();
       
   538     v8::Context::Scope scope(m_context);
       
   539     v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context));
       
   540     v8::Local<v8::Object> instance = SafeAllocation::newInstance(function);
       
   541     if (!instance.IsEmpty()) {
       
   542         m_wrapperBoilerplates.set(type, v8::Persistent<v8::Object>::New(instance));
       
   543         return instance->Clone();
       
   544     }
       
   545     return notHandledByInterceptor();
       
   546 }
       
   547 
       
   548 void V8DOMWindowShell::setLocation(DOMWindow* window, const String& relativeURL)
       
   549 {
       
   550     Frame* frame = window->frame();
       
   551     if (!frame)
       
   552         return;
       
   553 
       
   554     KURL url = completeURL(relativeURL);
       
   555     if (url.isNull())
       
   556         return;
       
   557 
       
   558     if (!shouldAllowNavigation(frame))
       
   559         return;
       
   560 
       
   561     navigateIfAllowed(frame, url, false, false);
       
   562 }
       
   563 
       
   564 } // WebCore