Add support for private names
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMWindowCustom.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "JSDOMWindowCustom.h"
23
24 #include "Frame.h"
25 #include "HTMLCollection.h"
26 #include "HTMLDocument.h"
27 #include "History.h"
28 #include "JSArrayBuffer.h"
29 #include "JSDataView.h"
30 #include "JSEvent.h"
31 #include "JSEventListener.h"
32 #include "JSEventSource.h"
33 #include "JSFloat32Array.h"
34 #include "JSFloat64Array.h"
35 #include "JSHTMLAudioElement.h"
36 #include "JSHTMLCollection.h"
37 #include "JSHTMLOptionElement.h"
38 #include "JSHistory.h"
39 #include "JSImageConstructor.h"
40 #include "JSInt16Array.h"
41 #include "JSInt32Array.h"
42 #include "JSInt8Array.h"
43 #include "JSLocation.h"
44 #include "JSMessageChannel.h"
45 #include "JSMessagePortCustom.h"
46 #include "JSUint16Array.h"
47 #include "JSUint32Array.h"
48 #include "JSUint8Array.h"
49 #include "JSUint8ClampedArray.h"
50 #include "JSWebKitCSSMatrix.h"
51 #include "JSWebKitPoint.h"
52 #include "JSXMLHttpRequest.h"
53 #include "JSXSLTProcessor.h"
54 #include "Location.h"
55 #include "MediaPlayer.h"
56 #include "ScheduledAction.h"
57 #include "Settings.h"
58 #include "SharedWorkerRepository.h"
59 #include <runtime/JSFunction.h>
60
61 #if ENABLE(WORKERS)
62 #include "JSWorker.h"
63 #endif
64
65 #if ENABLE(SHARED_WORKERS)
66 #include "JSSharedWorker.h"
67 #endif
68
69 #if ENABLE(WEB_AUDIO)
70 #include "JSAudioContext.h"
71 #endif
72
73 #if ENABLE(WEB_SOCKETS)
74 #include "JSWebSocket.h"
75 #endif
76
77 using namespace JSC;
78
79 namespace WebCore {
80
81 void JSDOMWindow::visitChildren(JSCell* cell, SlotVisitor& visitor)
82 {
83     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
84     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
85     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
86     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
87     Base::visitChildren(thisObject, visitor);
88
89     thisObject->impl()->visitJSEventListeners(visitor);
90     if (Frame* frame = thisObject->impl()->frame())
91         visitor.addOpaqueRoot(frame);
92 }
93
94 template<NativeFunction nativeFunction, int length>
95 JSValue nonCachingStaticFunctionGetter(ExecState* exec, JSValue, PropertyName propertyName)
96 {
97     return JSFunction::create(exec, exec->lexicalGlobalObject(), length, propertyName.publicName(), nativeFunction);
98 }
99
100 static JSValue childFrameGetter(ExecState* exec, JSValue slotBase, PropertyName propertyName)
101 {
102     return toJS(exec, jsCast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->scopedChild(propertyNameToAtomicString(propertyName))->domWindow());
103 }
104
105 static JSValue indexGetter(ExecState* exec, JSValue slotBase, unsigned index)
106 {
107     return toJS(exec, jsCast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->scopedChild(index)->domWindow());
108 }
109
110 static JSValue namedItemGetter(ExecState* exec, JSValue slotBase, PropertyName propertyName)
111 {
112     JSDOMWindowBase* thisObj = jsCast<JSDOMWindow*>(asObject(slotBase));
113     Document* document = thisObj->impl()->frame()->document();
114
115     ASSERT(thisObj->allowsAccessFrom(exec));
116     ASSERT(document);
117     ASSERT(document->isHTMLDocument());
118
119     HTMLCollection* collection = document->windowNamedItems(propertyNameToAtomicString(propertyName));
120     if (collection->length() == 1)
121         return toJS(exec, thisObj, collection->firstItem());
122     return toJS(exec, thisObj, collection);
123 }
124
125 bool JSDOMWindow::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
126 {
127     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
128     // When accessing a Window cross-domain, functions are always the native built-in ones, and they
129     // are not affected by properties changed on the Window or anything in its prototype chain.
130     // This is consistent with the behavior of Firefox.
131
132     const HashEntry* entry;
133
134     // We don't want any properties other than "close" and "closed" on a frameless window (i.e. one whose page got closed,
135     // or whose iframe got removed).
136     // FIXME: This doesn't fully match Firefox, which allows at least toString in addition to those.
137     if (!thisObject->impl()->frame()) {
138         // The following code is safe for cross-domain and same domain use.
139         // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
140         entry = s_info.propHashTable(exec)->entry(exec, propertyName);
141         if (entry && !(entry->attributes() & JSC::Function) && entry->propertyGetter() == jsDOMWindowClosed) {
142             slot.setCustom(thisObject, entry->propertyGetter());
143             return true;
144         }
145         entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
146         if (entry && (entry->attributes() & JSC::Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
147             slot.setCustom(thisObject, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
148             return true;
149         }
150
151         // FIXME: We should have a message here that explains why the property access/function call was
152         // not allowed. 
153         slot.setUndefined();
154         return true;
155     }
156
157     // We need to check for cross-domain access here without printing the generic warning message
158     // because we always allow access to some function, just different ones depending whether access
159     // is allowed.
160     String errorMessage;
161     bool allowsAccess = thisObject->allowsAccessFrom(exec, errorMessage);
162
163     // Look for overrides before looking at any of our own properties, but ignore overrides completely
164     // if this is cross-domain access.
165     if (allowsAccess && JSGlobalObject::getOwnPropertySlot(thisObject, exec, propertyName, slot))
166         return true;
167
168     // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
169     // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot.
170     // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
171     // what prototype is actually set on this object.
172     entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
173     if (entry) {
174         if (entry->attributes() & JSC::Function) {
175             if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
176                 if (!allowsAccess) {
177                     slot.setCustom(thisObject, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
178                     return true;
179                 }
180             } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
181                 if (!allowsAccess) {
182                     slot.setCustom(thisObject, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
183                     return true;
184                 }
185             } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
186                 if (!allowsAccess) {
187                     slot.setCustom(thisObject, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
188                     return true;
189                 }
190             } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
191                 if (!allowsAccess) {
192                     slot.setCustom(thisObject, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
193                     return true;
194                 }
195             } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
196                 if (!DOMWindow::canShowModalDialog(thisObject->impl()->frame())) {
197                     slot.setUndefined();
198                     return true;
199                 }
200             }
201         }
202     } else {
203         // Allow access to toString() cross-domain, but always Object.prototype.toString.
204         if (propertyName == exec->propertyNames().toString) {
205             if (!allowsAccess) {
206                 slot.setCustom(thisObject, objectToStringFunctionGetter);
207                 return true;
208             }
209         }
210     }
211
212     entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
213     if (entry) {
214         slot.setCustom(thisObject, entry->propertyGetter());
215         return true;
216     }
217
218     // Check for child frames by name before built-in properties to
219     // match Mozilla. This does not match IE, but some sites end up
220     // naming frames things that conflict with window properties that
221     // are in Moz but not IE. Since we have some of these, we have to do
222     // it the Moz way.
223     if (thisObject->impl()->frame()->tree()->scopedChild(propertyNameToAtomicString(propertyName))) {
224         slot.setCustom(thisObject, childFrameGetter);
225         return true;
226     }
227
228     // Do prototype lookup early so that functions and attributes in the prototype can have
229     // precedence over the index and name getters.  
230     JSValue proto = thisObject->prototype();
231     if (proto.isObject()) {
232         if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) {
233             if (!allowsAccess) {
234                 thisObject->printErrorMessage(errorMessage);
235                 slot.setUndefined();
236             }
237             return true;
238         }
239     }
240
241     // FIXME: Search the whole frame hierarchy somewhere around here.
242     // We need to test the correct priority order.
243
244     // allow window[1] or parent[1] etc. (#56983)
245     unsigned i = propertyName.asIndex();
246     if (i < thisObject->impl()->frame()->tree()->scopedChildCount()) {
247         ASSERT(i != PropertyName::NotAnIndex);
248         slot.setCustomIndex(thisObject, i, indexGetter);
249         return true;
250     }
251
252     if (!allowsAccess) {
253         thisObject->printErrorMessage(errorMessage);
254         slot.setUndefined();
255         return true;
256     }
257
258     // Allow shortcuts like 'Image1' instead of document.images.Image1
259     Document* document = thisObject->impl()->frame()->document();
260     if (document->isHTMLDocument()) {
261         AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
262         if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
263             slot.setCustom(thisObject, namedItemGetter);
264             return true;
265         }
266     }
267
268     return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
269 }
270
271 bool JSDOMWindow::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
272 {
273     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
274     // Never allow cross-domain getOwnPropertyDescriptor
275     if (!thisObject->allowsAccessFrom(exec))
276         return false;
277
278     const HashEntry* entry;
279     
280     // We don't want any properties other than "close" and "closed" on a closed window.
281     if (!thisObject->impl()->frame()) {
282         // The following code is safe for cross-domain and same domain use.
283         // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
284         entry = s_info.propHashTable(exec)->entry(exec, propertyName);
285         if (entry && !(entry->attributes() & JSC::Function) && entry->propertyGetter() == jsDOMWindowClosed) {
286             descriptor.setDescriptor(jsBoolean(true), ReadOnly | DontDelete | DontEnum);
287             return true;
288         }
289         entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
290         if (entry && (entry->attributes() & JSC::Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
291             PropertySlot slot;
292             slot.setCustom(thisObject, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
293             descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
294             return true;
295         }
296         descriptor.setUndefined();
297         return true;
298     }
299
300     entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
301     if (entry) {
302         PropertySlot slot;
303         slot.setCustom(thisObject, entry->propertyGetter());
304         descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
305         return true;
306     }
307     
308     // Check for child frames by name before built-in properties to
309     // match Mozilla. This does not match IE, but some sites end up
310     // naming frames things that conflict with window properties that
311     // are in Moz but not IE. Since we have some of these, we have to do
312     // it the Moz way.
313     if (thisObject->impl()->frame()->tree()->scopedChild(propertyNameToAtomicString(propertyName))) {
314         PropertySlot slot;
315         slot.setCustom(thisObject, childFrameGetter);
316         descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
317         return true;
318     }
319     
320     unsigned i = propertyName.asIndex();
321     if (i < thisObject->impl()->frame()->tree()->scopedChildCount()) {
322         ASSERT(i != PropertyName::NotAnIndex);
323         PropertySlot slot;
324         slot.setCustomIndex(thisObject, i, indexGetter);
325         descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
326         return true;
327     }
328
329     // Allow shortcuts like 'Image1' instead of document.images.Image1
330     Document* document = thisObject->impl()->frame()->document();
331     if (document->isHTMLDocument()) {
332         AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
333         if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
334             PropertySlot slot;
335             slot.setCustom(thisObject, namedItemGetter);
336             descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
337             return true;
338         }
339     }
340     
341     return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
342 }
343
344 void JSDOMWindow::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
345 {
346     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
347     if (!thisObject->impl()->frame())
348         return;
349
350     // Optimization: access JavaScript global variables directly before involving the DOM.
351     if (thisObject->JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) {
352         if (thisObject->allowsAccessFrom(exec))
353             JSGlobalObject::put(thisObject, exec, propertyName, value, slot);
354         return;
355     }
356
357     if (lookupPut<JSDOMWindow>(exec, propertyName, value, s_info.propHashTable(exec), thisObject))
358         return;
359
360     if (thisObject->allowsAccessFrom(exec))
361         Base::put(thisObject, exec, propertyName, value, slot);
362 }
363
364 bool JSDOMWindow::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
365 {
366     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
367     // Only allow deleting properties by frames in the same origin.
368     if (!thisObject->allowsAccessFrom(exec))
369         return false;
370     return Base::deleteProperty(thisObject, exec, propertyName);
371 }
372
373 void JSDOMWindow::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
374 {
375     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
376     // Only allow the window to enumerated by frames in the same origin.
377     if (!thisObject->allowsAccessFrom(exec))
378         return;
379     Base::getPropertyNames(thisObject, exec, propertyNames, mode);
380 }
381
382 void JSDOMWindow::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
383 {
384     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
385     // Only allow the window to enumerated by frames in the same origin.
386     if (!thisObject->allowsAccessFrom(exec))
387         return;
388     Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
389 }
390
391 bool JSDOMWindow::defineOwnProperty(JSC::JSObject* object, JSC::ExecState* exec, JSC::PropertyName propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
392 {
393     JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
394     // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
395     if (!thisObject->allowsAccessFrom(exec))
396         return false;
397
398     // Don't allow shadowing location using accessor properties.
399     if (descriptor.isAccessorDescriptor() && propertyName == Identifier(exec, "location"))
400         return false;
401
402     return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
403 }
404
405 // Custom Attributes
406
407 void JSDOMWindow::setLocation(ExecState* exec, JSValue value)
408 {
409 #if ENABLE(DASHBOARD_SUPPORT)
410     // To avoid breaking old widgets, make "var location =" in a top-level frame create
411     // a property named "location" instead of performing a navigation (<rdar://problem/5688039>).
412     if (Frame* activeFrame = activeDOMWindow(exec)->frame()) {
413         if (Settings* settings = activeFrame->settings()) {
414             if (settings->usesDashboardBackwardCompatibilityMode() && !activeFrame->tree()->parent()) {
415                 if (allowsAccessFrom(exec))
416                     putDirect(exec->globalData(), Identifier(exec, "location"), value);
417                 return;
418             }
419         }
420     }
421 #endif
422
423     UString locationString = value.toString(exec)->value(exec);
424     if (exec->hadException())
425         return;
426
427     if (Location* location = impl()->location())
428         location->setHref(ustringToString(locationString), activeDOMWindow(exec), firstDOMWindow(exec));
429 }
430
431 JSValue JSDOMWindow::event(ExecState* exec) const
432 {
433     Event* event = currentEvent();
434     if (!event)
435         return jsUndefined();
436     return toJS(exec, const_cast<JSDOMWindow*>(this), event);
437 }
438
439 JSValue JSDOMWindow::image(ExecState* exec) const
440 {
441     return getDOMConstructor<JSImageConstructor>(exec, this);
442 }
443
444 JSValue JSDOMWindow::option(ExecState* exec) const
445 {
446     return getDOMConstructor<JSHTMLOptionElementNamedConstructor>(exec, this);
447 }
448
449 #if ENABLE(VIDEO)
450 JSValue JSDOMWindow::audio(ExecState* exec) const
451 {
452     if (!MediaPlayer::isAvailable())
453         return jsUndefined();
454     return getDOMConstructor<JSHTMLAudioElementNamedConstructor>(exec, this);
455 }
456 #endif
457
458 #if ENABLE(SHARED_WORKERS)
459 JSValue JSDOMWindow::sharedWorker(ExecState* exec) const
460 {
461     if (SharedWorkerRepository::isAvailable())
462         return getDOMConstructor<JSSharedWorkerConstructor>(exec, this);
463     return jsUndefined();
464 }
465 #endif
466
467 // Custom functions
468
469 JSValue JSDOMWindow::open(ExecState* exec)
470 {
471     String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
472     if (exec->hadException())
473         return jsUndefined();
474     AtomicString frameName = exec->argument(1).isUndefinedOrNull() ? "_blank" : ustringToAtomicString(exec->argument(1).toString(exec)->value(exec));
475     if (exec->hadException())
476         return jsUndefined();
477     String windowFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
478     if (exec->hadException())
479         return jsUndefined();
480
481     RefPtr<DOMWindow> openedWindow = impl()->open(urlString, frameName, windowFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec));
482     if (!openedWindow)
483         return jsUndefined();
484     return toJS(exec, openedWindow.get());
485 }
486
487 class DialogHandler {
488 public:
489     explicit DialogHandler(ExecState* exec)
490         : m_exec(exec)
491     {
492     }
493
494     void dialogCreated(DOMWindow*);
495     JSValue returnValue() const;
496
497 private:
498     ExecState* m_exec;
499     RefPtr<Frame> m_frame;
500 };
501
502 inline void DialogHandler::dialogCreated(DOMWindow* dialog)
503 {
504     m_frame = dialog->frame();
505     // FIXME: This looks like a leak between the normal world and an isolated
506     //        world if dialogArguments comes from an isolated world.
507     JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->globalData()));
508     if (JSValue dialogArguments = m_exec->argument(1))
509         globalObject->putDirect(m_exec->globalData(), Identifier(m_exec, "dialogArguments"), dialogArguments);
510 }
511
512 inline JSValue DialogHandler::returnValue() const
513 {
514     JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->globalData()));
515     if (!globalObject)
516         return jsUndefined();
517     Identifier identifier(m_exec, "returnValue");
518     PropertySlot slot;
519     if (!JSGlobalObject::getOwnPropertySlot(globalObject, m_exec, identifier, slot))
520         return jsUndefined();
521     return slot.getValue(m_exec, identifier);
522 }
523
524 static void setUpDialog(DOMWindow* dialog, void* handler)
525 {
526     static_cast<DialogHandler*>(handler)->dialogCreated(dialog);
527 }
528
529 JSValue JSDOMWindow::showModalDialog(ExecState* exec)
530 {
531     String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
532     if (exec->hadException())
533         return jsUndefined();
534     String dialogFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
535     if (exec->hadException())
536         return jsUndefined();
537
538     DialogHandler handler(exec);
539
540     impl()->showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec), setUpDialog, &handler);
541
542     return handler.returnValue();
543 }
544
545 static JSValue handlePostMessage(DOMWindow* impl, ExecState* exec, bool doTransfer)
546 {
547     MessagePortArray messagePorts;
548     ArrayBufferArray arrayBuffers;
549
550     // This function has variable arguments and can be:
551     // Per current spec:
552     //   postMessage(message, targetOrigin)
553     //   postMessage(message, targetOrigin, {sequence of transferrables})
554     // Legacy non-standard implementations in webkit allowed:
555     //   postMessage(message, {sequence of transferrables}, targetOrigin);
556     int targetOriginArgIndex = 1;
557     if (exec->argumentCount() > 2) {
558         int transferablesArgIndex = 2;
559         if (exec->argument(2).isString()) {
560             targetOriginArgIndex = 2;
561             transferablesArgIndex = 1;
562         }
563         fillMessagePortArray(exec, exec->argument(transferablesArgIndex), messagePorts, arrayBuffers);
564     }
565     if (exec->hadException())
566         return jsUndefined();
567
568     RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, exec->argument(0),
569                                                                          doTransfer ? &messagePorts : 0,
570                                                                          doTransfer ? &arrayBuffers : 0);
571
572     if (exec->hadException())
573         return jsUndefined();
574
575     String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(targetOriginArgIndex));
576     if (exec->hadException())
577         return jsUndefined();
578
579     ExceptionCode ec = 0;
580     impl->postMessage(message.release(), &messagePorts, targetOrigin, activeDOMWindow(exec), ec);
581     setDOMException(exec, ec);
582
583     return jsUndefined();
584 }
585
586 JSValue JSDOMWindow::postMessage(ExecState* exec)
587 {
588     return handlePostMessage(impl(), exec, false);
589 }
590
591 JSValue JSDOMWindow::webkitPostMessage(ExecState* exec)
592 {
593     return handlePostMessage(impl(), exec, true);
594 }
595
596 JSValue JSDOMWindow::setTimeout(ExecState* exec)
597 {
598     ContentSecurityPolicy* contentSecurityPolicy = impl()->document() ? impl()->document()->contentSecurityPolicy() : 0;
599     OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
600     if (exec->hadException())
601         return jsUndefined();
602
603     if (!action)
604         return jsNumber(0);
605
606     int delay = exec->argument(1).toInt32(exec);
607
608     ExceptionCode ec = 0;
609     int result = impl()->setTimeout(action.release(), delay, ec);
610     setDOMException(exec, ec);
611
612     return jsNumber(result);
613 }
614
615 JSValue JSDOMWindow::setInterval(ExecState* exec)
616 {
617     ContentSecurityPolicy* contentSecurityPolicy = impl()->document() ? impl()->document()->contentSecurityPolicy() : 0;
618     OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
619     if (exec->hadException())
620         return jsUndefined();
621     int delay = exec->argument(1).toInt32(exec);
622
623     if (!action)
624         return jsNumber(0);
625
626     ExceptionCode ec = 0;
627     int result = impl()->setInterval(action.release(), delay, ec);
628     setDOMException(exec, ec);
629
630     return jsNumber(result);
631 }
632
633 JSValue JSDOMWindow::addEventListener(ExecState* exec)
634 {
635     Frame* frame = impl()->frame();
636     if (!frame)
637         return jsUndefined();
638
639     JSValue listener = exec->argument(1);
640     if (!listener.isObject())
641         return jsUndefined();
642
643     impl()->addEventListener(ustringToAtomicString(exec->argument(0).toString(exec)->value(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), exec->argument(2).toBoolean());
644     return jsUndefined();
645 }
646
647 JSValue JSDOMWindow::removeEventListener(ExecState* exec)
648 {
649     Frame* frame = impl()->frame();
650     if (!frame)
651         return jsUndefined();
652
653     JSValue listener = exec->argument(1);
654     if (!listener.isObject())
655         return jsUndefined();
656
657     impl()->removeEventListener(ustringToAtomicString(exec->argument(0).toString(exec)->value(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), exec->argument(2).toBoolean());
658     return jsUndefined();
659 }
660
661 DOMWindow* toDOMWindow(JSValue value)
662 {
663     if (!value.isObject())
664         return 0;
665     JSObject* object = asObject(value);
666     if (object->inherits(&JSDOMWindow::s_info))
667         return jsCast<JSDOMWindow*>(object)->impl();
668     if (object->inherits(&JSDOMWindowShell::s_info))
669         return jsCast<JSDOMWindowShell*>(object)->impl();
670     return 0;
671 }
672
673 } // namespace WebCore