https://bugs.webkit.org/show_bug.cgi?id=70120
[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, bool doTransfer)
317 {
318     DOMWindow* window = V8DOMWindow::toNative(args.Holder());
319
320     DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow();
321     ASSERT(source->frame());
322
323     // This function has variable arguments and can either be:
324     //   postMessage(message, port, targetOrigin);
325     // or
326     //   postMessage(message, targetOrigin);
327     MessagePortArray portArray;
328     String targetOrigin;
329     {
330         v8::TryCatch tryCatch;
331         if (args.Length() > 2) {
332             if (!getMessagePortArray(args[1], portArray))
333                 return v8::Undefined();
334             targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
335         } else
336             targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]);
337
338         if (tryCatch.HasCaught())
339             return v8::Undefined();
340     }
341
342
343     bool didThrow = false;
344     RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], doTransfer ? &portArray : 0, didThrow);
345     if (didThrow)
346         return v8::Undefined();
347
348     ExceptionCode ec = 0;
349     window->postMessage(message.release(), &portArray, targetOrigin, source, ec);
350     return throwError(ec);
351 }
352
353 v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args)
354 {
355     INC_STATS("DOM.DOMWindow.postMessage()");
356     return handlePostMessageCallback(args, false);
357 }
358
359 v8::Handle<v8::Value> V8DOMWindow::webkitPostMessageCallback(const v8::Arguments& args)
360 {
361     INC_STATS("DOM.DOMWindow.webkitPostMessage()");
362     return handlePostMessageCallback(args, true);
363 }
364
365 // FIXME(fqian): returning string is cheating, and we should
366 // fix this by calling toString function on the receiver.
367 // However, V8 implements toString in JavaScript, which requires
368 // switching context of receiver. I consider it is dangerous.
369 v8::Handle<v8::Value> V8DOMWindow::toStringCallback(const v8::Arguments& args)
370 {
371     INC_STATS("DOM.DOMWindow.toString()");
372     v8::Handle<v8::Object> domWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), args.This());
373     if (domWrapper.IsEmpty())
374         return args.This()->ObjectProtoToString();
375     return domWrapper->ObjectProtoToString();
376 }
377
378 v8::Handle<v8::Value> V8DOMWindow::releaseEventsCallback(const v8::Arguments& args)
379 {
380     INC_STATS("DOM.DOMWindow.nop()");
381     return v8::Undefined();
382 }
383
384 v8::Handle<v8::Value> V8DOMWindow::captureEventsCallback(const v8::Arguments& args)
385 {
386     INC_STATS("DOM.DOMWindow.nop()");
387     return v8::Undefined();
388 }
389
390 class DialogHandler {
391 public:
392     explicit DialogHandler(v8::Handle<v8::Value> dialogArguments)
393         : m_dialogArguments(dialogArguments)
394     {
395     }
396
397     void dialogCreated(DOMWindow*);
398     v8::Handle<v8::Value> returnValue() const;
399
400 private:
401     v8::Handle<v8::Value> m_dialogArguments;
402     v8::Handle<v8::Context> m_dialogContext;
403 };
404
405 inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame)
406 {
407     m_dialogContext = V8Proxy::context(dialogFrame->frame());
408     if (m_dialogContext.IsEmpty())
409         return;
410     if (m_dialogArguments.IsEmpty())
411         return;
412     v8::Context::Scope scope(m_dialogContext);
413     m_dialogContext->Global()->Set(v8::String::New("dialogArguments"), m_dialogArguments);
414 }
415
416 inline v8::Handle<v8::Value> DialogHandler::returnValue() const
417 {
418     if (m_dialogContext.IsEmpty())
419         return v8::Undefined();
420     v8::Context::Scope scope(m_dialogContext);
421     v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8::String::New("returnValue"));
422     if (returnValue.IsEmpty())
423         return v8::Undefined();
424     return returnValue;
425 }
426
427 static void setUpDialog(DOMWindow* dialog, void* handler)
428 {
429     static_cast<DialogHandler*>(handler)->dialogCreated(dialog);
430 }
431
432 v8::Handle<v8::Value> V8DOMWindow::showModalDialogCallback(const v8::Arguments& args)
433 {
434     INC_STATS("DOM.DOMWindow.showModalDialog()");
435     DOMWindow* impl = V8DOMWindow::toNative(args.Holder());
436
437     V8BindingState* state = V8BindingState::Only();
438
439     DOMWindow* activeWindow = state->activeWindow();
440     DOMWindow* firstWindow = state->firstWindow();
441
442     // FIXME: Handle exceptions properly.
443     String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
444     String dialogFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
445
446     DialogHandler handler(args[1]);
447
448     impl->showModalDialog(urlString, dialogFeaturesString, activeWindow, firstWindow, setUpDialog, &handler);
449
450     return handler.returnValue();
451 }
452
453 v8::Handle<v8::Value> V8DOMWindow::openCallback(const v8::Arguments& args)
454 {
455     INC_STATS("DOM.DOMWindow.open()");
456     DOMWindow* impl = V8DOMWindow::toNative(args.Holder());
457
458     V8BindingState* state = V8BindingState::Only();
459
460     DOMWindow* activeWindow = state->activeWindow();
461     DOMWindow* firstWindow = state->firstWindow();
462
463     // FIXME: Handle exceptions properly.
464     String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
465     AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1]));
466     String windowFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
467
468     RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, activeWindow, firstWindow);
469     if (!openedWindow)
470         return v8::Undefined();
471     return toV8(openedWindow.release());
472 }
473
474 v8::Handle<v8::Value> V8DOMWindow::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info)
475 {
476     INC_STATS("DOM.DOMWindow.IndexedPropertyGetter");
477
478     DOMWindow* window = V8DOMWindow::toNative(info.Holder());
479     if (!window)
480         return notHandledByInterceptor();
481
482     Frame* frame = window->frame();
483     if (!frame)
484         return notHandledByInterceptor();
485
486     Frame* child = frame->tree()->child(index);
487     if (child)
488         return toV8(child->domWindow());
489
490     return notHandledByInterceptor();
491 }
492
493
494 v8::Handle<v8::Value> V8DOMWindow::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
495 {
496     INC_STATS("DOM.DOMWindow.NamedPropertyGetter");
497
498     DOMWindow* window = V8DOMWindow::toNative(info.Holder());
499     if (!window)
500         return notHandledByInterceptor();
501
502     Frame* frame = window->frame();
503     // window is detached from a frame.
504     if (!frame)
505         return notHandledByInterceptor();
506
507     // Search sub-frames.
508     AtomicString propName = v8StringToAtomicWebCoreString(name);
509     Frame* child = frame->tree()->child(propName);
510     if (child)
511         return toV8(child->domWindow());
512
513     // Search IDL functions defined in the prototype
514     if (!info.Holder()->GetRealNamedProperty(name).IsEmpty())
515         return notHandledByInterceptor();
516
517     // Search named items in the document.
518     Document* doc = frame->document();
519
520     if (doc && doc->isHTMLDocument()) {
521         if (static_cast<HTMLDocument*>(doc)->hasNamedItem(propName.impl()) || doc->hasElementWithId(propName.impl())) {
522             RefPtr<HTMLCollection> items = doc->windowNamedItems(propName);
523             if (items->length() >= 1) {
524                 if (items->length() == 1)
525                     return toV8(items->firstItem());
526                 return toV8(items.release());
527             }
528         }
529     }
530
531     return notHandledByInterceptor();
532 }
533
534
535 v8::Handle<v8::Value> V8DOMWindow::setTimeoutCallback(const v8::Arguments& args)
536 {
537     INC_STATS("DOM.DOMWindow.setTimeout()");
538     return WindowSetTimeoutImpl(args, true);
539 }
540
541
542 v8::Handle<v8::Value> V8DOMWindow::setIntervalCallback(const v8::Arguments& args)
543 {
544     INC_STATS("DOM.DOMWindow.setInterval()");
545     return WindowSetTimeoutImpl(args, false);
546 }
547
548 bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
549 {
550     v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host);
551     if (window.IsEmpty())
552         return false;  // the frame is gone.
553
554     DOMWindow* targetWindow = V8DOMWindow::toNative(window);
555
556     ASSERT(targetWindow);
557
558     Frame* target = targetWindow->frame();
559     if (!target)
560         return false;
561
562     if (key->IsString()) {
563         DEFINE_STATIC_LOCAL(AtomicString, nameOfProtoProperty, ("__proto__"));
564
565         String name = toWebCoreString(key);
566         // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
567         // because that would generate infinite recursion.
568         if (type == v8::ACCESS_HAS && target->tree()->child(name))
569             return true;
570         // We need to explicitly compare against nameOfProtoProperty because
571         // V8's JSObject::LocalLookup finds __proto__ before
572         // interceptors and even when __proto__ isn't a "real named property".
573         if (type == v8::ACCESS_GET && target->tree()->child(name) && !host->HasRealNamedProperty(key->ToString()) && name != nameOfProtoProperty)
574             return true;
575     }
576
577     return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false);
578 }
579
580 bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
581 {
582     v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host);
583     if (window.IsEmpty())
584         return false;
585
586     DOMWindow* targetWindow = V8DOMWindow::toNative(window);
587
588     ASSERT(targetWindow);
589
590     Frame* target = targetWindow->frame();
591     if (!target)
592         return false;
593
594     // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
595     // because that would generate infinite recursion.
596     if (type == v8::ACCESS_HAS && target->tree()->child(index))
597         return true;
598     if (type == v8::ACCESS_GET && target->tree()->child(index) && !host->HasRealIndexedProperty(index))
599         return true;
600
601     return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false);
602 }
603
604 v8::Handle<v8::Value> toV8(DOMWindow* window)
605 {
606     if (!window)
607         return v8::Null();
608     // Initializes environment of a frame, and return the global object
609     // of the frame.
610     Frame* frame = window->frame();
611     if (!frame)
612         return v8::Handle<v8::Object>();
613
614     // Special case: Because of evaluateInIsolatedWorld() one DOMWindow can have
615     // multiple contexts and multiple global objects associated with it. When
616     // code running in one of those contexts accesses the window object, we
617     // want to return the global object associated with that context, not
618     // necessarily the first global object associated with that DOMWindow.
619     v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent();
620     v8::Handle<v8::Object> currentGlobal = currentContext->Global();
621     v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), currentGlobal);
622     if (!windowWrapper.IsEmpty()) {
623         if (V8DOMWindow::toNative(windowWrapper) == window)
624             return currentGlobal;
625     }
626
627     // Otherwise, return the global object associated with this frame.
628     v8::Handle<v8::Context> context = V8Proxy::context(frame);
629     if (context.IsEmpty())
630         return v8::Handle<v8::Object>();
631
632     v8::Handle<v8::Object> global = context->Global();
633     ASSERT(!global.IsEmpty());
634     return global;
635 }
636
637 } // namespace WebCore