49105e230163d1320289ea7388cd8bd9edd82088
[WebKit-https.git] / Source / WebCore / bindings / v8 / custom / V8DOMWindowCustom.cpp
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 "V8DOMWindow.h"
33
34 #include "Chrome.h"
35 #include "ContentSecurityPolicy.h"
36 #include "DOMTimer.h"
37 #include "DOMWindow.h"
38 #include "ExceptionCode.h"
39 #include "Frame.h"
40 #include "FrameLoadRequest.h"
41 #include "FrameView.h"
42 #include "HTMLCollection.h"
43 #include "HTMLDocument.h"
44 #include "MediaPlayer.h"
45 #include "Page.h"
46 #include "PlatformScreen.h"
47 #include "ScheduledAction.h"
48 #include "ScriptSourceCode.h"
49 #include "SerializedScriptValue.h"
50 #include "Settings.h"
51 #include "SharedWorkerRepository.h"
52 #include "Storage.h"
53 #include "V8Binding.h"
54 #include "V8BindingMacros.h"
55 #include "V8BindingState.h"
56 #include "V8EventListener.h"
57 #include "V8GCForContextDispose.h"
58 #include "V8HiddenPropertyName.h"
59 #include "V8HTMLAudioElementConstructor.h"
60 #include "V8HTMLCollection.h"
61 #include "V8HTMLImageElementConstructor.h"
62 #include "V8HTMLOptionElementConstructor.h"
63 #include "V8MessagePortCustom.h"
64 #include "V8Node.h"
65 #include "V8Proxy.h"
66 #include "V8Utilities.h"
67 #if ENABLE(WEB_SOCKETS)
68 #include "WebSocket.h"
69 #endif
70 #include "WindowFeatures.h"
71
72 namespace WebCore {
73
74 v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments& args, bool singleShot)
75 {
76     int argumentCount = args.Length();
77
78     if (argumentCount < 1)
79         return v8::Undefined();
80
81     DOMWindow* imp = V8DOMWindow::toNative(args.Holder());
82     ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->document());
83
84     if (!scriptContext) {
85         V8Proxy::setDOMException(INVALID_ACCESS_ERR);
86         return v8::Undefined();
87     }
88
89     v8::Handle<v8::Value> function = args[0];
90     WTF::String functionString;
91     if (!function->IsFunction()) {
92         if (function->IsString())
93             functionString = toWebCoreString(function);
94         else {
95             v8::Handle<v8::Value> v8String = function->ToString();
96
97             // Bail out if string conversion failed.
98             if (v8String.IsEmpty())
99                 return v8::Undefined();
100
101             functionString = toWebCoreString(v8String);
102         }
103
104         // Don't allow setting timeouts to run empty functions!
105         // (Bug 1009597)
106         if (functionString.length() == 0)
107             return v8::Undefined();
108     }
109
110     int32_t timeout = 0;
111     if (argumentCount >= 2)
112         timeout = args[1]->Int32Value();
113
114     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
115         return v8::Undefined();
116
117     int id;
118     if (function->IsFunction()) {
119         int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
120         v8::Local<v8::Value>* params = 0;
121         if (paramCount > 0) {
122             params = new v8::Local<v8::Value>[paramCount];
123             for (int i = 0; i < paramCount; i++)
124                 // parameters must be globalized
125                 params[i] = args[i+2];
126         }
127
128         // params is passed to action, and released in action's destructor
129         OwnPtr<ScheduledAction> action = adoptPtr(new ScheduledAction(V8Proxy::context(imp->frame()), v8::Handle<v8::Function>::Cast(function), paramCount, params));
130
131         // FIXME: We should use OwnArrayPtr for params.
132         delete[] params;
133
134         id = DOMTimer::install(scriptContext, action.release(), timeout, singleShot);
135     } else {
136         if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval())
137             return v8::Integer::New(0);
138         id = DOMTimer::install(scriptContext, adoptPtr(new ScheduledAction(V8Proxy::context(imp->frame()), functionString)), timeout, singleShot);
139     }
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::instance().notifyIdleSooner(maximumFireInterval);
146     }
147
148     return v8::Integer::New(id);
149 }
150
151 v8::Handle<v8::Value> V8DOMWindow::eventAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
152 {
153     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), info.This());
154     if (holder.IsEmpty())
155         return v8::Undefined();
156
157     Frame* frame = V8DOMWindow::toNative(holder)->frame();
158     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true))
159         return v8::Undefined();
160
161     v8::Local<v8::Context> context = V8Proxy::context(frame);
162     if (context.IsEmpty())
163         return v8::Undefined();
164
165     v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event();
166     v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol);
167     if (jsEvent.IsEmpty())
168         return v8::Undefined();
169     return jsEvent;
170 }
171
172 void V8DOMWindow::eventAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
173 {
174     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), info.This());
175     if (holder.IsEmpty())
176         return;
177
178     Frame* frame = V8DOMWindow::toNative(holder)->frame();
179     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true))
180         return;
181
182     v8::Local<v8::Context> context = V8Proxy::context(frame);
183     if (context.IsEmpty())
184         return;
185
186     v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event();
187     context->Global()->SetHiddenValue(eventSymbol, value);
188 }
189
190 void V8DOMWindow::locationAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
191 {
192     DOMWindow* imp = V8DOMWindow::toNative(info.Holder());
193     State<V8Binding>* state = V8BindingState::Only();
194
195     DOMWindow* activeWindow = state->activeWindow();
196     if (!activeWindow)
197       return;
198
199     DOMWindow* firstWindow = state->firstWindow();
200     if (!firstWindow)
201       return;
202
203     imp->setLocation(toWebCoreString(value), activeWindow, firstWindow);
204 }
205
206 void V8DOMWindow::openerAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
207 {
208     DOMWindow* imp = V8DOMWindow::toNative(info.Holder());
209
210     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
211         return;
212
213     // Opener can be shadowed if it is in the same domain.
214     // Have a special handling of null value to behave
215     // like Firefox. See bug http://b/1224887 & http://b/791706.
216     if (value->IsNull()) {
217         // imp->frame() cannot be null,
218         // otherwise, SameOrigin check would have failed.
219         ASSERT(imp->frame());
220         imp->frame()->loader()->setOpener(0);
221     }
222
223     // Delete the accessor from this object.
224     info.Holder()->Delete(name);
225
226     // Put property on the front (this) object.
227     info.This()->Set(name, value);
228 }
229
230 #if ENABLE(VIDEO)
231
232 v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
233 {
234     DOMWindow* window = V8DOMWindow::toNative(info.Holder());
235     return V8DOMWrapper::getConstructor(&V8HTMLAudioElementConstructor::info, window);
236 }
237
238 #endif
239
240 v8::Handle<v8::Value> V8DOMWindow::ImageAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
241 {
242     DOMWindow* window = V8DOMWindow::toNative(info.Holder());
243     return V8DOMWrapper::getConstructor(&V8HTMLImageElementConstructor::info, window);
244 }
245
246 v8::Handle<v8::Value> V8DOMWindow::OptionAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
247 {
248     DOMWindow* window = V8DOMWindow::toNative(info.Holder());
249     return V8DOMWrapper::getConstructor(&V8HTMLOptionElementConstructor::info, window);
250 }
251
252 v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& args)
253 {
254     INC_STATS("DOM.DOMWindow.addEventListener()");
255
256     String eventType = toWebCoreString(args[0]);
257     bool useCapture = args[2]->BooleanValue();
258
259     DOMWindow* imp = V8DOMWindow::toNative(args.Holder());
260
261     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
262         return v8::Undefined();
263
264     Document* doc = imp->document();
265
266     if (!doc)
267         return v8::Undefined();
268
269     // FIXME: Check if there is not enough arguments
270     V8Proxy* proxy = V8Proxy::retrieve(imp->frame());
271     if (!proxy)
272         return v8::Undefined();
273
274     RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOrCreate);
275
276     if (listener) {
277         imp->addEventListener(eventType, listener, useCapture);
278         createHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex);
279     }
280
281     return v8::Undefined();
282 }
283
284
285 v8::Handle<v8::Value> V8DOMWindow::removeEventListenerCallback(const v8::Arguments& args)
286 {
287     INC_STATS("DOM.DOMWindow.removeEventListener()");
288
289     String eventType = toWebCoreString(args[0]);
290     bool useCapture = args[2]->BooleanValue();
291
292     DOMWindow* imp = V8DOMWindow::toNative(args.Holder());
293
294     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
295         return v8::Undefined();
296
297     Document* doc = imp->document();
298
299     if (!doc)
300         return v8::Undefined();
301
302     V8Proxy* proxy = V8Proxy::retrieve(imp->frame());
303     if (!proxy)
304         return v8::Undefined();
305
306     RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOnly);
307
308     if (listener) {
309         imp->removeEventListener(eventType, listener.get(), useCapture);
310         removeHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex);
311     }
312
313     return v8::Undefined();
314 }
315
316 static v8::Handle<v8::Value> handlePostMessageCallback(const v8::Arguments& args)
317 {
318     DOMWindow* window = V8DOMWindow::toNative(args.Holder());
319
320     DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow();
321     ASSERT(source->frame());
322
323     bool didThrow = false;
324     RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow);
325     if (didThrow)
326         return v8::Undefined();
327
328     MessagePortArray portArray;
329     String targetOrigin;
330
331     // This function has variable arguments and can either be:
332     //   postMessage(message, port, targetOrigin);
333     // or
334     //   postMessage(message, targetOrigin);
335     v8::TryCatch tryCatch;
336     if (args.Length() > 2) {
337         if (!getMessagePortArray(args[1], portArray))
338             return v8::Undefined();
339         targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
340     } else {
341         targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]);
342     }
343
344     if (tryCatch.HasCaught())
345         return v8::Undefined();
346
347     ExceptionCode ec = 0;
348     window->postMessage(message.release(), &portArray, targetOrigin, source, ec);
349     return throwError(ec);
350 }
351
352 v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args)
353 {
354     INC_STATS("DOM.DOMWindow.postMessage()");
355     return handlePostMessageCallback(args);
356 }
357
358 v8::Handle<v8::Value> V8DOMWindow::webkitPostMessageCallback(const v8::Arguments& args)
359 {
360     INC_STATS("DOM.DOMWindow.webkitPostMessage()");
361     return handlePostMessageCallback(args);
362 }
363
364 // FIXME(fqian): returning string is cheating, and we should
365 // fix this by calling toString function on the receiver.
366 // However, V8 implements toString in JavaScript, which requires
367 // switching context of receiver. I consider it is dangerous.
368 v8::Handle<v8::Value> V8DOMWindow::toStringCallback(const v8::Arguments& args)
369 {
370     INC_STATS("DOM.DOMWindow.toString()");
371     v8::Handle<v8::Object> domWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), args.This());
372     if (domWrapper.IsEmpty())
373         return args.This()->ObjectProtoToString();
374     return domWrapper->ObjectProtoToString();
375 }
376
377 v8::Handle<v8::Value> V8DOMWindow::releaseEventsCallback(const v8::Arguments& args)
378 {
379     INC_STATS("DOM.DOMWindow.nop()");
380     return v8::Undefined();
381 }
382
383 v8::Handle<v8::Value> V8DOMWindow::captureEventsCallback(const v8::Arguments& args)
384 {
385     INC_STATS("DOM.DOMWindow.nop()");
386     return v8::Undefined();
387 }
388
389 class DialogHandler {
390 public:
391     explicit DialogHandler(v8::Handle<v8::Value> dialogArguments)
392         : m_dialogArguments(dialogArguments)
393     {
394     }
395
396     void dialogCreated(DOMWindow*);
397     v8::Handle<v8::Value> returnValue() const;
398
399 private:
400     v8::Handle<v8::Value> m_dialogArguments;
401     v8::Handle<v8::Context> m_dialogContext;
402 };
403
404 inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame)
405 {
406     m_dialogContext = V8Proxy::context(dialogFrame->frame());
407     if (m_dialogContext.IsEmpty())
408         return;
409     if (m_dialogArguments.IsEmpty())
410         return;
411     v8::Context::Scope scope(m_dialogContext);
412     m_dialogContext->Global()->Set(v8::String::New("dialogArguments"), m_dialogArguments);
413 }
414
415 inline v8::Handle<v8::Value> DialogHandler::returnValue() const
416 {
417     if (m_dialogContext.IsEmpty())
418         return v8::Undefined();
419     v8::Context::Scope scope(m_dialogContext);
420     v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8::String::New("returnValue"));
421     if (returnValue.IsEmpty())
422         return v8::Undefined();
423     return returnValue;
424 }
425
426 static void setUpDialog(DOMWindow* dialog, void* handler)
427 {
428     static_cast<DialogHandler*>(handler)->dialogCreated(dialog);
429 }
430
431 v8::Handle<v8::Value> V8DOMWindow::showModalDialogCallback(const v8::Arguments& args)
432 {
433     INC_STATS("DOM.DOMWindow.showModalDialog()");
434     DOMWindow* impl = V8DOMWindow::toNative(args.Holder());
435
436     V8BindingState* state = V8BindingState::Only();
437
438     DOMWindow* activeWindow = state->activeWindow();
439     DOMWindow* firstWindow = state->firstWindow();
440
441     // FIXME: Handle exceptions properly.
442     String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
443     String dialogFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
444
445     DialogHandler handler(args[1]);
446
447     impl->showModalDialog(urlString, dialogFeaturesString, activeWindow, firstWindow, setUpDialog, &handler);
448
449     return handler.returnValue();
450 }
451
452 v8::Handle<v8::Value> V8DOMWindow::openCallback(const v8::Arguments& args)
453 {
454     INC_STATS("DOM.DOMWindow.open()");
455     DOMWindow* impl = V8DOMWindow::toNative(args.Holder());
456
457     V8BindingState* state = V8BindingState::Only();
458
459     DOMWindow* activeWindow = state->activeWindow();
460     DOMWindow* firstWindow = state->firstWindow();
461
462     // FIXME: Handle exceptions properly.
463     String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
464     AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1]));
465     String windowFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
466
467     RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, activeWindow, firstWindow);
468     if (!openedWindow)
469         return v8::Undefined();
470     return toV8(openedWindow.release());
471 }
472
473 v8::Handle<v8::Value> V8DOMWindow::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info)
474 {
475     INC_STATS("DOM.DOMWindow.IndexedPropertyGetter");
476
477     DOMWindow* window = V8DOMWindow::toNative(info.Holder());
478     if (!window)
479         return notHandledByInterceptor();
480
481     Frame* frame = window->frame();
482     if (!frame)
483         return notHandledByInterceptor();
484
485     Frame* child = frame->tree()->child(index);
486     if (child)
487         return toV8(child->domWindow());
488
489     return notHandledByInterceptor();
490 }
491
492
493 v8::Handle<v8::Value> V8DOMWindow::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
494 {
495     INC_STATS("DOM.DOMWindow.NamedPropertyGetter");
496
497     DOMWindow* window = V8DOMWindow::toNative(info.Holder());
498     if (!window)
499         return notHandledByInterceptor();
500
501     Frame* frame = window->frame();
502     // window is detached from a frame.
503     if (!frame)
504         return notHandledByInterceptor();
505
506     // Search sub-frames.
507     AtomicString propName = v8StringToAtomicWebCoreString(name);
508     Frame* child = frame->tree()->child(propName);
509     if (child)
510         return toV8(child->domWindow());
511
512     // Search IDL functions defined in the prototype
513     if (!info.Holder()->GetRealNamedProperty(name).IsEmpty())
514         return notHandledByInterceptor();
515
516     // Search named items in the document.
517     Document* doc = frame->document();
518
519     if (doc && doc->isHTMLDocument()) {
520         if (static_cast<HTMLDocument*>(doc)->hasNamedItem(propName.impl()) || doc->hasElementWithId(propName.impl())) {
521             RefPtr<HTMLCollection> items = doc->windowNamedItems(propName);
522             if (items->length() >= 1) {
523                 if (items->length() == 1)
524                     return toV8(items->firstItem());
525                 return toV8(items.release());
526             }
527         }
528     }
529
530     return notHandledByInterceptor();
531 }
532
533
534 v8::Handle<v8::Value> V8DOMWindow::setTimeoutCallback(const v8::Arguments& args)
535 {
536     INC_STATS("DOM.DOMWindow.setTimeout()");
537     return WindowSetTimeoutImpl(args, true);
538 }
539
540
541 v8::Handle<v8::Value> V8DOMWindow::setIntervalCallback(const v8::Arguments& args)
542 {
543     INC_STATS("DOM.DOMWindow.setInterval()");
544     return WindowSetTimeoutImpl(args, false);
545 }
546
547 bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
548 {
549     v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host);
550     if (window.IsEmpty())
551         return false;  // the frame is gone.
552
553     DOMWindow* targetWindow = V8DOMWindow::toNative(window);
554
555     ASSERT(targetWindow);
556
557     Frame* target = targetWindow->frame();
558     if (!target)
559         return false;
560
561     if (key->IsString()) {
562         DEFINE_STATIC_LOCAL(AtomicString, nameOfProtoProperty, ("__proto__"));
563
564         String name = toWebCoreString(key);
565         // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
566         // because that would generate infinite recursion.
567         if (type == v8::ACCESS_HAS && target->tree()->child(name))
568             return true;
569         // We need to explicitly compare against nameOfProtoProperty because
570         // V8's JSObject::LocalLookup finds __proto__ before
571         // interceptors and even when __proto__ isn't a "real named property".
572         if (type == v8::ACCESS_GET && target->tree()->child(name) && !host->HasRealNamedProperty(key->ToString()) && name != nameOfProtoProperty)
573             return true;
574     }
575
576     return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false);
577 }
578
579 bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
580 {
581     v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host);
582     if (window.IsEmpty())
583         return false;
584
585     DOMWindow* targetWindow = V8DOMWindow::toNative(window);
586
587     ASSERT(targetWindow);
588
589     Frame* target = targetWindow->frame();
590     if (!target)
591         return false;
592
593     // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
594     // because that would generate infinite recursion.
595     if (type == v8::ACCESS_HAS && target->tree()->child(index))
596         return true;
597     if (type == v8::ACCESS_GET && target->tree()->child(index) && !host->HasRealIndexedProperty(index))
598         return true;
599
600     return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false);
601 }
602
603 v8::Handle<v8::Value> toV8(DOMWindow* window)
604 {
605     if (!window)
606         return v8::Null();
607     // Initializes environment of a frame, and return the global object
608     // of the frame.
609     Frame* frame = window->frame();
610     if (!frame)
611         return v8::Handle<v8::Object>();
612
613     // Special case: Because of evaluateInIsolatedWorld() one DOMWindow can have
614     // multiple contexts and multiple global objects associated with it. When
615     // code running in one of those contexts accesses the window object, we
616     // want to return the global object associated with that context, not
617     // necessarily the first global object associated with that DOMWindow.
618     v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent();
619     v8::Handle<v8::Object> currentGlobal = currentContext->Global();
620     v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), currentGlobal);
621     if (!windowWrapper.IsEmpty()) {
622         if (V8DOMWindow::toNative(windowWrapper) == window)
623             return currentGlobal;
624     }
625
626     // Otherwise, return the global object associated with this frame.
627     v8::Handle<v8::Context> context = V8Proxy::context(frame);
628     if (context.IsEmpty())
629         return v8::Handle<v8::Object>();
630
631     v8::Handle<v8::Object> global = context->Global();
632     ASSERT(!global.IsEmpty());
633     return global;
634 }
635
636 } // namespace WebCore