Home | History | Annotate | Download | only in custom
      1 /*
      2  * Copyright (C) 2009, 2011 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 "bindings/core/v8/V8Window.h"
     33 
     34 #include "bindings/core/v8/V8HTMLCollection.h"
     35 #include "bindings/core/v8/V8Node.h"
     36 #include "bindings/v8/BindingSecurity.h"
     37 #include "bindings/v8/ExceptionMessages.h"
     38 #include "bindings/v8/ExceptionState.h"
     39 #include "bindings/v8/ScheduledAction.h"
     40 #include "bindings/v8/ScriptController.h"
     41 #include "bindings/v8/ScriptSourceCode.h"
     42 #include "bindings/v8/SerializedScriptValue.h"
     43 #include "bindings/v8/V8Binding.h"
     44 #include "bindings/v8/V8EventListener.h"
     45 #include "bindings/v8/V8EventListenerList.h"
     46 #include "bindings/v8/V8GCForContextDispose.h"
     47 #include "bindings/v8/V8HiddenValue.h"
     48 #include "core/dom/ExceptionCode.h"
     49 #include "core/dom/MessagePort.h"
     50 #include "core/html/HTMLCollection.h"
     51 #include "core/html/HTMLDocument.h"
     52 #include "core/inspector/ScriptCallStack.h"
     53 #include "core/loader/FrameLoadRequest.h"
     54 #include "core/loader/FrameLoader.h"
     55 #include "core/frame/DOMTimer.h"
     56 #include "core/frame/LocalDOMWindow.h"
     57 #include "core/frame/DOMWindowTimers.h"
     58 #include "core/frame/FrameView.h"
     59 #include "core/frame/LocalFrame.h"
     60 #include "core/frame/Settings.h"
     61 #include "core/frame/csp/ContentSecurityPolicy.h"
     62 #include "core/storage/Storage.h"
     63 #include "platform/PlatformScreen.h"
     64 #include "platform/graphics/media/MediaPlayer.h"
     65 #include "wtf/ArrayBuffer.h"
     66 #include "wtf/Assertions.h"
     67 #include "wtf/OwnPtr.h"
     68 
     69 namespace WebCore {
     70 
     71 // FIXME: There is a lot of duplication with SetTimeoutOrInterval() in V8WorkerGlobalScopeCustom.cpp.
     72 // We should refactor this.
     73 static void windowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot, ExceptionState& exceptionState)
     74 {
     75     int argumentCount = info.Length();
     76 
     77     if (argumentCount < 1)
     78         return;
     79 
     80     LocalDOMWindow* impl = V8Window::toNative(info.Holder());
     81     if (!impl->frame() || !impl->document()) {
     82         exceptionState.throwDOMException(InvalidAccessError, "No script context is available in which to execute the script.");
     83         return;
     84     }
     85     ScriptState* scriptState = ScriptState::current(info.GetIsolate());
     86     v8::Handle<v8::Value> function = info[0];
     87     String functionString;
     88     if (!function->IsFunction()) {
     89         if (function->IsString()) {
     90             functionString = toCoreString(function.As<v8::String>());
     91         } else {
     92             v8::Handle<v8::String> v8String = function->ToString();
     93 
     94             // Bail out if string conversion failed.
     95             if (v8String.IsEmpty())
     96                 return;
     97 
     98             functionString = toCoreString(v8String);
     99         }
    100 
    101         // Don't allow setting timeouts to run empty functions!
    102         // (Bug 1009597)
    103         if (!functionString.length())
    104             return;
    105     }
    106 
    107     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState))
    108         return;
    109 
    110     OwnPtr<ScheduledAction> action;
    111     if (function->IsFunction()) {
    112         int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
    113         OwnPtr<v8::Local<v8::Value>[]> params;
    114         if (paramCount > 0) {
    115             params = adoptArrayPtr(new v8::Local<v8::Value>[paramCount]);
    116             for (int i = 0; i < paramCount; i++) {
    117                 // parameters must be globalized
    118                 params[i] = info[i+2];
    119             }
    120         }
    121 
    122         // params is passed to action, and released in action's destructor
    123         ASSERT(impl->frame());
    124         action = adoptPtr(new ScheduledAction(scriptState, v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate()));
    125     } else {
    126         if (impl->document() && !impl->document()->contentSecurityPolicy()->allowEval()) {
    127             v8SetReturnValue(info, 0);
    128             return;
    129         }
    130         ASSERT(impl->frame());
    131         action = adoptPtr(new ScheduledAction(scriptState, functionString, KURL(), info.GetIsolate()));
    132     }
    133 
    134     int32_t timeout = argumentCount >= 2 ? info[1]->Int32Value() : 0;
    135     int timerId;
    136     if (singleShot)
    137         timerId = DOMWindowTimers::setTimeout(*impl, action.release(), timeout);
    138     else
    139         timerId = DOMWindowTimers::setInterval(*impl, action.release(), timeout);
    140 
    141     // Try to do the idle notification before the timeout expires to get better
    142     // use of any idle time. Aim for the middle of the interval for simplicity.
    143     if (timeout >= 0) {
    144         double maximumFireInterval = static_cast<double>(timeout) / 1000 / 2;
    145         V8GCForContextDispose::instanceTemplate().notifyIdleSooner(maximumFireInterval);
    146     }
    147 
    148     v8SetReturnValue(info, timerId);
    149 }
    150 
    151 void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info)
    152 {
    153     LocalFrame* frame = V8Window::toNative(info.Holder())->frame();
    154     ExceptionState exceptionState(ExceptionState::GetterContext, "event", "Window", info.Holder(), info.GetIsolate());
    155     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exceptionState)) {
    156         exceptionState.throwIfNeeded();
    157         return;
    158     }
    159 
    160     v8::Handle<v8::Value> jsEvent = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder()->CreationContext()->Global(), V8HiddenValue::event(info.GetIsolate()));
    161     if (jsEvent.IsEmpty())
    162         return;
    163     v8SetReturnValue(info, jsEvent);
    164 }
    165 
    166 void V8Window::eventAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
    167 {
    168     LocalFrame* frame = V8Window::toNative(info.Holder())->frame();
    169     ExceptionState exceptionState(ExceptionState::SetterContext, "event", "Window", info.Holder(), info.GetIsolate());
    170     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exceptionState)) {
    171         exceptionState.throwIfNeeded();
    172         return;
    173     }
    174 
    175     V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder()->CreationContext()->Global(), V8HiddenValue::event(info.GetIsolate()), value);
    176 }
    177 
    178 void V8Window::frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info)
    179 {
    180     LocalDOMWindow* impl = V8Window::toNative(info.Holder());
    181     ExceptionState exceptionState(ExceptionState::GetterContext, "frame", "Window", info.Holder(), info.GetIsolate());
    182     if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), impl->frameElement(), exceptionState)) {
    183         v8SetReturnValueNull(info);
    184         exceptionState.throwIfNeeded();
    185         return;
    186     }
    187 
    188     // The wrapper for an <iframe> should get its prototype from the context of the frame it's in, rather than its own frame.
    189     // So, use its containing document as the creation context when wrapping.
    190     v8::Handle<v8::Value> creationContext = toV8(&impl->frameElement()->document(), info.Holder(), info.GetIsolate());
    191     RELEASE_ASSERT(!creationContext.IsEmpty());
    192     v8::Handle<v8::Value> wrapper = toV8(impl->frameElement(), v8::Handle<v8::Object>::Cast(creationContext), info.GetIsolate());
    193     v8SetReturnValue(info, wrapper);
    194 }
    195 
    196 void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
    197 {
    198     LocalDOMWindow* impl = V8Window::toNative(info.Holder());
    199     ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Window", info.Holder(), info.GetIsolate());
    200     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) {
    201         exceptionState.throwIfNeeded();
    202         return;
    203     }
    204 
    205     // Opener can be shadowed if it is in the same domain.
    206     // Have a special handling of null value to behave
    207     // like Firefox. See bug http://b/1224887 & http://b/791706.
    208     if (value->IsNull()) {
    209         // impl->frame() cannot be null,
    210         // otherwise, SameOrigin check would have failed.
    211         ASSERT(impl->frame());
    212         impl->frame()->loader().setOpener(0);
    213     }
    214 
    215     // Delete the accessor from this object.
    216     info.Holder()->Delete(v8AtomicString(info.GetIsolate(), "opener"));
    217 
    218     // Put property on the front (this) object.
    219     if (info.This()->IsObject())
    220         v8::Handle<v8::Object>::Cast(info.This())->Set(v8AtomicString(info.GetIsolate(), "opener"), value);
    221 }
    222 
    223 static bool isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value)
    224 {
    225     if (value->IsString() || value->IsStringObject())
    226         return true;
    227     return false;
    228 }
    229 
    230 
    231 void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
    232 {
    233     // None of these need to be RefPtr because info and context are guaranteed
    234     // to hold on to them.
    235     LocalDOMWindow* window = V8Window::toNative(info.Holder());
    236     LocalDOMWindow* source = callingDOMWindow(info.GetIsolate());
    237 
    238     ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "Window", info.Holder(), info.GetIsolate());
    239 
    240     // If called directly by WebCore we don't have a calling context.
    241     if (!source) {
    242         exceptionState.throwTypeError("No active calling context exists.");
    243         exceptionState.throwIfNeeded();
    244         return;
    245     }
    246 
    247     // This function has variable arguments and can be:
    248     // Per current spec:
    249     //   postMessage(message, targetOrigin)
    250     //   postMessage(message, targetOrigin, {sequence of transferrables})
    251     // Legacy non-standard implementations in webkit allowed:
    252     //   postMessage(message, {sequence of transferrables}, targetOrigin);
    253     MessagePortArray portArray;
    254     ArrayBufferArray arrayBufferArray;
    255     int targetOriginArgIndex = 1;
    256     if (info.Length() > 2) {
    257         int transferablesArgIndex = 2;
    258         if (isLegacyTargetOriginDesignation(info[2])) {
    259             targetOriginArgIndex = 2;
    260             transferablesArgIndex = 1;
    261         }
    262         if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, portArray, arrayBufferArray, exceptionState, info.GetIsolate())) {
    263             exceptionState.throwIfNeeded();
    264             return;
    265         }
    266     }
    267     TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, targetOrigin, info[targetOriginArgIndex]);
    268 
    269     RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, exceptionState, info.GetIsolate());
    270     if (exceptionState.throwIfNeeded())
    271         return;
    272 
    273     window->postMessage(message.release(), &portArray, targetOrigin, source, exceptionState);
    274     exceptionState.throwIfNeeded();
    275 }
    276 
    277 // FIXME(fqian): returning string is cheating, and we should
    278 // fix this by calling toString function on the receiver.
    279 // However, V8 implements toString in JavaScript, which requires
    280 // switching context of receiver. I consider it is dangerous.
    281 void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
    282 {
    283     v8::Handle<v8::Object> domWrapper = V8Window::findInstanceInPrototypeChain(info.This(), info.GetIsolate());
    284     if (domWrapper.IsEmpty()) {
    285         v8SetReturnValue(info, info.This()->ObjectProtoToString());
    286         return;
    287     }
    288     v8SetReturnValue(info, domWrapper->ObjectProtoToString());
    289 }
    290 
    291 class DialogHandler {
    292 public:
    293     explicit DialogHandler(v8::Handle<v8::Value> dialogArguments, ScriptState* scriptState)
    294         : m_scriptState(scriptState)
    295         , m_dialogArguments(dialogArguments)
    296     {
    297     }
    298 
    299     void dialogCreated(LocalDOMWindow*);
    300     v8::Handle<v8::Value> returnValue() const;
    301 
    302 private:
    303     RefPtr<ScriptState> m_scriptState;
    304     RefPtr<ScriptState> m_scriptStateForDialogFrame;
    305     v8::Handle<v8::Value> m_dialogArguments;
    306 };
    307 
    308 void DialogHandler::dialogCreated(LocalDOMWindow* dialogFrame)
    309 {
    310     if (m_dialogArguments.IsEmpty())
    311         return;
    312     v8::Handle<v8::Context> context = toV8Context(dialogFrame->frame(), m_scriptState->world());
    313     if (context.IsEmpty())
    314         return;
    315     m_scriptStateForDialogFrame = ScriptState::from(context);
    316 
    317     ScriptState::Scope scope(m_scriptStateForDialogFrame.get());
    318     m_scriptStateForDialogFrame->context()->Global()->Set(v8AtomicString(m_scriptState->isolate(), "dialogArguments"), m_dialogArguments);
    319 }
    320 
    321 v8::Handle<v8::Value> DialogHandler::returnValue() const
    322 {
    323     if (!m_scriptStateForDialogFrame)
    324         return v8Undefined();
    325     ASSERT(!m_scriptStateForDialogFrame->contextIsEmpty());
    326 
    327     v8::Isolate* isolate = m_scriptStateForDialogFrame->isolate();
    328     v8::EscapableHandleScope handleScope(isolate);
    329     ScriptState::Scope scope(m_scriptStateForDialogFrame.get());
    330     v8::Local<v8::Value> returnValue = m_scriptStateForDialogFrame->context()->Global()->Get(v8AtomicString(isolate, "returnValue"));
    331     if (returnValue.IsEmpty())
    332         return v8Undefined();
    333     return handleScope.Escape(returnValue);
    334 }
    335 
    336 static void setUpDialog(LocalDOMWindow* dialog, void* handler)
    337 {
    338     static_cast<DialogHandler*>(handler)->dialogCreated(dialog);
    339 }
    340 
    341 void V8Window::showModalDialogMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
    342 {
    343     LocalDOMWindow* impl = V8Window::toNative(info.Holder());
    344     ExceptionState exceptionState(ExceptionState::ExecutionContext, "showModalDialog", "Window", info.Holder(), info.GetIsolate());
    345     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) {
    346         exceptionState.throwIfNeeded();
    347         return;
    348     }
    349 
    350     TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]);
    351     DialogHandler handler(info[1], ScriptState::current(info.GetIsolate()));
    352     TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, dialogFeaturesString, info[2]);
    353 
    354     impl->showModalDialog(urlString, dialogFeaturesString, callingDOMWindow(info.GetIsolate()), enteredDOMWindow(info.GetIsolate()), setUpDialog, &handler);
    355 
    356     v8SetReturnValue(info, handler.returnValue());
    357 }
    358 
    359 void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
    360 {
    361     LocalDOMWindow* impl = V8Window::toNative(info.Holder());
    362     ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Window", info.Holder(), info.GetIsolate());
    363     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) {
    364         exceptionState.throwIfNeeded();
    365         return;
    366     }
    367 
    368     TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]);
    369     AtomicString frameName;
    370     if (info[1]->IsUndefined() || info[1]->IsNull()) {
    371         frameName = "_blank";
    372     } else {
    373         TOSTRING_VOID(V8StringResource<>, frameNameResource, info[1]);
    374         frameName = frameNameResource;
    375     }
    376     TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, windowFeaturesString, info[2]);
    377 
    378     RefPtrWillBeRawPtr<LocalDOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, callingDOMWindow(info.GetIsolate()), enteredDOMWindow(info.GetIsolate()));
    379     if (!openedWindow)
    380         return;
    381 
    382     v8SetReturnValueFast(info, openedWindow.release(), impl);
    383 }
    384 
    385 void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
    386 {
    387 
    388     LocalDOMWindow* window = V8Window::toNative(info.Holder());
    389     if (!window)
    390         return;
    391 
    392     LocalFrame* frame = window->frame();
    393     // window is detached from a frame.
    394     if (!frame)
    395         return;
    396 
    397     // Search sub-frames.
    398     AtomicString propName = toCoreAtomicString(name);
    399     Frame* child = frame->tree().scopedChild(propName);
    400     if (child) {
    401         v8SetReturnValueFast(info, child->domWindow(), window);
    402         return;
    403     }
    404 
    405     // Search IDL functions defined in the prototype
    406     if (!info.Holder()->GetRealNamedProperty(name).IsEmpty())
    407         return;
    408 
    409     // Search named items in the document.
    410     Document* doc = frame->document();
    411 
    412     if (doc && doc->isHTMLDocument()) {
    413         if (toHTMLDocument(doc)->hasNamedItem(propName) || doc->hasElementWithId(propName.impl())) {
    414             RefPtrWillBeRawPtr<HTMLCollection> items = doc->windowNamedItems(propName);
    415             if (!items->isEmpty()) {
    416                 if (items->hasExactlyOneItem()) {
    417                     v8SetReturnValueFast(info, items->item(0), window);
    418                     return;
    419                 }
    420                 v8SetReturnValueFast(info, items.release(), window);
    421                 return;
    422             }
    423         }
    424     }
    425 }
    426 
    427 
    428 void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
    429 {
    430     ExceptionState exceptionState(ExceptionState::ExecutionContext, "setTimeout", "Window", info.Holder(), info.GetIsolate());
    431     windowSetTimeoutImpl(info, true, exceptionState);
    432     exceptionState.throwIfNeeded();
    433 }
    434 
    435 
    436 void V8Window::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
    437 {
    438     ExceptionState exceptionState(ExceptionState::ExecutionContext, "setInterval", "Window", info.Holder(), info.GetIsolate());
    439     windowSetTimeoutImpl(info, false, exceptionState);
    440     exceptionState.throwIfNeeded();
    441 }
    442 
    443 bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
    444 {
    445     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    446     v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host, isolate);
    447     if (window.IsEmpty())
    448         return false; // the frame is gone.
    449 
    450     LocalDOMWindow* targetWindow = V8Window::toNative(window);
    451 
    452     ASSERT(targetWindow);
    453 
    454     LocalFrame* target = targetWindow->frame();
    455     if (!target)
    456         return false;
    457 
    458     // Notify the loader's client if the initial document has been accessed.
    459     if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument())
    460         target->loader().didAccessInitialDocument();
    461 
    462     if (key->IsString()) {
    463         DEFINE_STATIC_LOCAL(const AtomicString, nameOfProtoProperty, ("__proto__", AtomicString::ConstructFromLiteral));
    464 
    465         AtomicString name = toCoreAtomicString(key.As<v8::String>());
    466         Frame* childFrame = target->tree().scopedChild(name);
    467         // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
    468         // because that would generate infinite recursion.
    469         if (type == v8::ACCESS_HAS && childFrame)
    470             return true;
    471         // We need to explicitly compare against nameOfProtoProperty because
    472         // V8's JSObject::LocalLookup finds __proto__ before
    473         // interceptors and even when __proto__ isn't a "real named property".
    474         v8::Handle<v8::String> keyString = key.As<v8::String>();
    475         if (type == v8::ACCESS_GET
    476             && childFrame
    477             && !host->HasRealNamedProperty(keyString)
    478             && !window->HasRealNamedProperty(keyString)
    479             && name != nameOfProtoProperty)
    480             return true;
    481     }
    482 
    483     return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotReportSecurityError);
    484 }
    485 
    486 bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
    487 {
    488     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    489     v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host, isolate);
    490     if (window.IsEmpty())
    491         return false;
    492 
    493     LocalDOMWindow* targetWindow = V8Window::toNative(window);
    494 
    495     ASSERT(targetWindow);
    496 
    497     LocalFrame* target = targetWindow->frame();
    498     if (!target)
    499         return false;
    500 
    501     // Notify the loader's client if the initial document has been accessed.
    502     if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument())
    503         target->loader().didAccessInitialDocument();
    504 
    505     Frame* childFrame = target->tree().scopedChild(index);
    506 
    507     // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
    508     // because that would generate infinite recursion.
    509     if (type == v8::ACCESS_HAS && childFrame)
    510         return true;
    511     if (type == v8::ACCESS_GET
    512         && childFrame
    513         && !host->HasRealIndexedProperty(index)
    514         && !window->HasRealIndexedProperty(index))
    515         return true;
    516 
    517     return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotReportSecurityError);
    518 }
    519 
    520 v8::Handle<v8::Value> toV8(LocalDOMWindow* window, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    521 {
    522     // Notice that we explicitly ignore creationContext because the LocalDOMWindow is its own creationContext.
    523 
    524     if (!window)
    525         return v8::Null(isolate);
    526     // Initializes environment of a frame, and return the global object
    527     // of the frame.
    528     LocalFrame* frame = window->frame();
    529     if (!frame)
    530         return v8Undefined();
    531 
    532     v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::current(isolate));
    533     if (context.IsEmpty())
    534         return v8Undefined();
    535 
    536     v8::Handle<v8::Object> global = context->Global();
    537     ASSERT(!global.IsEmpty());
    538     return global;
    539 }
    540 
    541 } // namespace WebCore
    542