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