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