• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #include "config.h"
21 #include "JSDOMWindowCustom.h"
22 
23 #include "Frame.h"
24 #include "HTMLCollection.h"
25 #include "HTMLDocument.h"
26 #include "History.h"
27 #include "JSArrayBuffer.h"
28 #include "JSAudioConstructor.h"
29 #include "JSDataView.h"
30 #include "JSEvent.h"
31 #include "JSEventListener.h"
32 #include "JSEventSource.h"
33 #include "JSFloat32Array.h"
34 #include "JSHTMLCollection.h"
35 #include "JSHistory.h"
36 #include "JSImageConstructor.h"
37 #include "JSInt16Array.h"
38 #include "JSInt32Array.h"
39 #include "JSInt8Array.h"
40 #include "JSLocation.h"
41 #include "JSMessageChannel.h"
42 #include "JSMessagePortCustom.h"
43 #include "JSOptionConstructor.h"
44 #include "JSUint16Array.h"
45 #include "JSUint32Array.h"
46 #include "JSUint8Array.h"
47 #include "JSWebKitCSSMatrix.h"
48 #include "JSWebKitPoint.h"
49 #include "JSWorker.h"
50 #include "JSXMLHttpRequest.h"
51 #include "JSXSLTProcessor.h"
52 #include "Location.h"
53 #include "MediaPlayer.h"
54 #include "ScheduledAction.h"
55 #include "Settings.h"
56 #include "SharedWorkerRepository.h"
57 #include <runtime/JSFunction.h>
58 
59 #if ENABLE(SHARED_WORKERS)
60 #include "JSSharedWorker.h"
61 #endif
62 
63 #if ENABLE(WEB_AUDIO)
64 #include "JSAudioContext.h"
65 #endif
66 
67 #if ENABLE(WEB_SOCKETS)
68 #include "JSWebSocket.h"
69 #endif
70 
71 using namespace JSC;
72 
73 namespace WebCore {
74 
markChildren(MarkStack & markStack)75 void JSDOMWindow::markChildren(MarkStack& markStack)
76 {
77     Base::markChildren(markStack);
78 
79     impl()->markJSEventListeners(markStack);
80 
81     JSGlobalData& globalData = *Heap::heap(this)->globalData();
82 
83     markDOMObjectWrapper(markStack, globalData, impl()->optionalConsole());
84     markDOMObjectWrapper(markStack, globalData, impl()->optionalHistory());
85     markDOMObjectWrapper(markStack, globalData, impl()->optionalLocationbar());
86     markDOMObjectWrapper(markStack, globalData, impl()->optionalMenubar());
87     markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator());
88     markDOMObjectWrapper(markStack, globalData, impl()->optionalPersonalbar());
89     markDOMObjectWrapper(markStack, globalData, impl()->optionalScreen());
90     markDOMObjectWrapper(markStack, globalData, impl()->optionalScrollbars());
91     markDOMObjectWrapper(markStack, globalData, impl()->optionalSelection());
92     markDOMObjectWrapper(markStack, globalData, impl()->optionalStatusbar());
93     markDOMObjectWrapper(markStack, globalData, impl()->optionalToolbar());
94     markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation());
95     markDOMObjectWrapper(markStack, globalData, impl()->optionalMedia());
96 #if ENABLE(DOM_STORAGE)
97     markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage());
98     markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage());
99 #endif
100 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
101     markDOMObjectWrapper(markStack, globalData, impl()->optionalApplicationCache());
102 #endif
103 }
104 
105 template<NativeFunction nativeFunction, int length>
nonCachingStaticFunctionGetter(ExecState * exec,JSValue,const Identifier & propertyName)106 JSValue nonCachingStaticFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
107 {
108     return new (exec) JSFunction(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->functionStructure(), length, propertyName, nativeFunction);
109 }
110 
childFrameGetter(ExecState * exec,JSValue slotBase,const Identifier & propertyName)111 static JSValue childFrameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
112 {
113     return toJS(exec, static_cast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->child(identifierToAtomicString(propertyName))->domWindow());
114 }
115 
indexGetter(ExecState * exec,JSValue slotBase,unsigned index)116 static JSValue indexGetter(ExecState* exec, JSValue slotBase, unsigned index)
117 {
118     return toJS(exec, static_cast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->child(index)->domWindow());
119 }
120 
namedItemGetter(ExecState * exec,JSValue slotBase,const Identifier & propertyName)121 static JSValue namedItemGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
122 {
123     JSDOMWindowBase* thisObj = static_cast<JSDOMWindow*>(asObject(slotBase));
124     Document* document = thisObj->impl()->frame()->document();
125 
126     ASSERT(thisObj->allowsAccessFrom(exec));
127     ASSERT(document);
128     ASSERT(document->isHTMLDocument());
129 
130     RefPtr<HTMLCollection> collection = document->windowNamedItems(identifierToString(propertyName));
131     if (collection->length() == 1)
132         return toJS(exec, collection->firstItem());
133     return toJS(exec, collection.get());
134 }
135 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)136 bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
137 {
138     // When accessing a Window cross-domain, functions are always the native built-in ones, and they
139     // are not affected by properties changed on the Window or anything in its prototype chain.
140     // This is consistent with the behavior of Firefox.
141 
142     const HashEntry* entry;
143 
144     // We don't want any properties other than "close" and "closed" on a closed window.
145     if (!impl()->frame()) {
146         // The following code is safe for cross-domain and same domain use.
147         // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
148         entry = s_info.propHashTable(exec)->entry(exec, propertyName);
149         if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
150             slot.setCustom(this, entry->propertyGetter());
151             return true;
152         }
153         entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
154         if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
155             slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
156             return true;
157         }
158 
159         // FIXME: We should have a message here that explains why the property access/function call was
160         // not allowed.
161         slot.setUndefined();
162         return true;
163     }
164 
165     // We need to check for cross-domain access here without printing the generic warning message
166     // because we always allow access to some function, just different ones depending whether access
167     // is allowed.
168     String errorMessage;
169     bool allowsAccess = allowsAccessFrom(exec, errorMessage);
170 
171     // Look for overrides before looking at any of our own properties, but ignore overrides completely
172     // if this is cross-domain access.
173     if (allowsAccess && JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot))
174         return true;
175 
176     // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
177     // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot.
178     // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
179     // what prototype is actually set on this object.
180     entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
181     if (entry) {
182         if (entry->attributes() & Function) {
183             if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
184                 if (!allowsAccess) {
185                     slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
186                     return true;
187                 }
188             } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
189                 if (!allowsAccess) {
190                     slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
191                     return true;
192                 }
193             } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
194                 if (!allowsAccess) {
195                     slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
196                     return true;
197                 }
198             } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
199                 if (!allowsAccess) {
200                     slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
201                     return true;
202                 }
203             } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
204                 if (!DOMWindow::canShowModalDialog(impl()->frame())) {
205                     slot.setUndefined();
206                     return true;
207                 }
208             }
209         }
210     } else {
211         // Allow access to toString() cross-domain, but always Object.prototype.toString.
212         if (propertyName == exec->propertyNames().toString) {
213             if (!allowsAccess) {
214                 slot.setCustom(this, objectToStringFunctionGetter);
215                 return true;
216             }
217         }
218     }
219 
220     entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
221     if (entry) {
222         slot.setCustom(this, entry->propertyGetter());
223         return true;
224     }
225 
226     // Check for child frames by name before built-in properties to
227     // match Mozilla. This does not match IE, but some sites end up
228     // naming frames things that conflict with window properties that
229     // are in Moz but not IE. Since we have some of these, we have to do
230     // it the Moz way.
231     if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) {
232         slot.setCustom(this, childFrameGetter);
233         return true;
234     }
235 
236     // Do prototype lookup early so that functions and attributes in the prototype can have
237     // precedence over the index and name getters.
238     JSValue proto = prototype();
239     if (proto.isObject()) {
240         if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) {
241             if (!allowsAccess) {
242                 printErrorMessage(errorMessage);
243                 slot.setUndefined();
244             }
245             return true;
246         }
247     }
248 
249     // FIXME: Search the whole frame hierarchy somewhere around here.
250     // We need to test the correct priority order.
251 
252     // allow window[1] or parent[1] etc. (#56983)
253     bool ok;
254     unsigned i = propertyName.toArrayIndex(ok);
255     if (ok && i < impl()->frame()->tree()->childCount()) {
256         slot.setCustomIndex(this, i, indexGetter);
257         return true;
258     }
259 
260     if (!allowsAccess) {
261         printErrorMessage(errorMessage);
262         slot.setUndefined();
263         return true;
264     }
265 
266     // Allow shortcuts like 'Image1' instead of document.images.Image1
267     Document* document = impl()->frame()->document();
268     if (document->isHTMLDocument()) {
269         AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
270         if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
271             slot.setCustom(this, namedItemGetter);
272             return true;
273         }
274     }
275 
276     return Base::getOwnPropertySlot(exec, propertyName, slot);
277 }
278 
getOwnPropertyDescriptor(ExecState * exec,const Identifier & propertyName,PropertyDescriptor & descriptor)279 bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
280 {
281     // Never allow cross-domain getOwnPropertyDescriptor
282     if (!allowsAccessFrom(exec))
283         return false;
284 
285     const HashEntry* entry;
286 
287     // We don't want any properties other than "close" and "closed" on a closed window.
288     if (!impl()->frame()) {
289         // The following code is safe for cross-domain and same domain use.
290         // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
291         entry = s_info.propHashTable(exec)->entry(exec, propertyName);
292         if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
293             descriptor.setDescriptor(jsBoolean(true), ReadOnly | DontDelete | DontEnum);
294             return true;
295         }
296         entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
297         if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
298             PropertySlot slot;
299             slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
300             descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
301             return true;
302         }
303         descriptor.setUndefined();
304         return true;
305     }
306 
307     entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
308     if (entry) {
309         PropertySlot slot;
310         slot.setCustom(this, entry->propertyGetter());
311         descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
312         return true;
313     }
314 
315     // Check for child frames by name before built-in properties to
316     // match Mozilla. This does not match IE, but some sites end up
317     // naming frames things that conflict with window properties that
318     // are in Moz but not IE. Since we have some of these, we have to do
319     // it the Moz way.
320     if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) {
321         PropertySlot slot;
322         slot.setCustom(this, childFrameGetter);
323         descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
324         return true;
325     }
326 
327     bool ok;
328     unsigned i = propertyName.toArrayIndex(ok);
329     if (ok && i < impl()->frame()->tree()->childCount()) {
330         PropertySlot slot;
331         slot.setCustomIndex(this, i, indexGetter);
332         descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
333         return true;
334     }
335 
336     // Allow shortcuts like 'Image1' instead of document.images.Image1
337     Document* document = impl()->frame()->document();
338     if (document->isHTMLDocument()) {
339         AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
340         if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
341             PropertySlot slot;
342             slot.setCustom(this, namedItemGetter);
343             descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
344             return true;
345         }
346     }
347 
348     return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
349 }
350 
put(ExecState * exec,const Identifier & propertyName,JSValue value,PutPropertySlot & slot)351 void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
352 {
353     if (!impl()->frame())
354         return;
355 
356     // Optimization: access JavaScript global variables directly before involving the DOM.
357     if (JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) {
358         if (allowsAccessFrom(exec))
359             JSGlobalObject::put(exec, propertyName, value, slot);
360         return;
361     }
362 
363     if (lookupPut<JSDOMWindow>(exec, propertyName, value, s_info.propHashTable(exec), this))
364         return;
365 
366     if (allowsAccessFrom(exec))
367         Base::put(exec, propertyName, value, slot);
368 }
369 
deleteProperty(ExecState * exec,const Identifier & propertyName)370 bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName)
371 {
372     // Only allow deleting properties by frames in the same origin.
373     if (!allowsAccessFrom(exec))
374         return false;
375     return Base::deleteProperty(exec, propertyName);
376 }
377 
getPropertyNames(ExecState * exec,PropertyNameArray & propertyNames,EnumerationMode mode)378 void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
379 {
380     // Only allow the window to enumerated by frames in the same origin.
381     if (!allowsAccessFrom(exec))
382         return;
383     Base::getPropertyNames(exec, propertyNames, mode);
384 }
385 
getOwnPropertyNames(ExecState * exec,PropertyNameArray & propertyNames,EnumerationMode mode)386 void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
387 {
388     // Only allow the window to enumerated by frames in the same origin.
389     if (!allowsAccessFrom(exec))
390         return;
391     Base::getOwnPropertyNames(exec, propertyNames, mode);
392 }
393 
defineGetter(ExecState * exec,const Identifier & propertyName,JSObject * getterFunction,unsigned attributes)394 void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
395 {
396     // Only allow defining getters by frames in the same origin.
397     if (!allowsAccessFrom(exec))
398         return;
399 
400     // Don't allow shadowing location using defineGetter.
401     if (propertyName == "location")
402         return;
403 
404     Base::defineGetter(exec, propertyName, getterFunction, attributes);
405 }
406 
defineSetter(ExecState * exec,const Identifier & propertyName,JSObject * setterFunction,unsigned attributes)407 void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
408 {
409     // Only allow defining setters by frames in the same origin.
410     if (!allowsAccessFrom(exec))
411         return;
412     Base::defineSetter(exec, propertyName, setterFunction, attributes);
413 }
414 
defineOwnProperty(JSC::ExecState * exec,const JSC::Identifier & propertyName,JSC::PropertyDescriptor & descriptor,bool shouldThrow)415 bool JSDOMWindow::defineOwnProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
416 {
417     // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
418     if (!allowsAccessFrom(exec))
419         return false;
420     return Base::defineOwnProperty(exec, propertyName, descriptor, shouldThrow);
421 }
422 
lookupGetter(ExecState * exec,const Identifier & propertyName)423 JSValue JSDOMWindow::lookupGetter(ExecState* exec, const Identifier& propertyName)
424 {
425     // Only allow looking-up getters by frames in the same origin.
426     if (!allowsAccessFrom(exec))
427         return jsUndefined();
428     return Base::lookupGetter(exec, propertyName);
429 }
430 
lookupSetter(ExecState * exec,const Identifier & propertyName)431 JSValue JSDOMWindow::lookupSetter(ExecState* exec, const Identifier& propertyName)
432 {
433     // Only allow looking-up setters by frames in the same origin.
434     if (!allowsAccessFrom(exec))
435         return jsUndefined();
436     return Base::lookupSetter(exec, propertyName);
437 }
438 
439 // Custom Attributes
440 
history(ExecState * exec) const441 JSValue JSDOMWindow::history(ExecState* exec) const
442 {
443     History* history = impl()->history();
444     if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), history))
445         return wrapper;
446 
447     JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
448     JSHistory* jsHistory = new (exec) JSHistory(getDOMStructure<JSHistory>(exec, window), window, history);
449     cacheWrapper(currentWorld(exec), history, jsHistory);
450     return jsHistory;
451 }
452 
location(ExecState * exec) const453 JSValue JSDOMWindow::location(ExecState* exec) const
454 {
455     Location* location = impl()->location();
456     if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), location))
457         return wrapper;
458 
459     JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
460     JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, window), window, location);
461     cacheWrapper(currentWorld(exec), location, jsLocation);
462     return jsLocation;
463 }
464 
setLocation(ExecState * exec,JSValue value)465 void JSDOMWindow::setLocation(ExecState* exec, JSValue value)
466 {
467 #if ENABLE(DASHBOARD_SUPPORT)
468     // To avoid breaking old widgets, make "var location =" in a top-level frame create
469     // a property named "location" instead of performing a navigation (<rdar://problem/5688039>).
470     if (Frame* activeFrame = activeDOMWindow(exec)->frame()) {
471         if (Settings* settings = activeFrame->settings()) {
472             if (settings->usesDashboardBackwardCompatibilityMode() && !activeFrame->tree()->parent()) {
473                 if (allowsAccessFrom(exec))
474                     putDirect(exec->globalData(), Identifier(exec, "location"), value);
475                 return;
476             }
477         }
478     }
479 #endif
480 
481     UString locationString = value.toString(exec);
482     if (exec->hadException())
483         return;
484 
485     impl()->setLocation(ustringToString(locationString), activeDOMWindow(exec), firstDOMWindow(exec));
486 }
487 
event(ExecState * exec) const488 JSValue JSDOMWindow::event(ExecState* exec) const
489 {
490     Event* event = currentEvent();
491     if (!event)
492         return jsUndefined();
493     return toJS(exec, event);
494 }
495 
496 #if ENABLE(EVENTSOURCE)
eventSource(ExecState * exec) const497 JSValue JSDOMWindow::eventSource(ExecState* exec) const
498 {
499     return getDOMConstructor<JSEventSourceConstructor>(exec, this);
500 }
501 #endif
502 
image(ExecState * exec) const503 JSValue JSDOMWindow::image(ExecState* exec) const
504 {
505     return getDOMConstructor<JSImageConstructor>(exec, this);
506 }
507 
option(ExecState * exec) const508 JSValue JSDOMWindow::option(ExecState* exec) const
509 {
510     return getDOMConstructor<JSOptionConstructor>(exec, this);
511 }
512 
513 #if ENABLE(VIDEO)
audio(ExecState * exec) const514 JSValue JSDOMWindow::audio(ExecState* exec) const
515 {
516     if (!MediaPlayer::isAvailable())
517         return jsUndefined();
518     return getDOMConstructor<JSAudioConstructor>(exec, this);
519 }
520 #endif
521 
webKitPoint(ExecState * exec) const522 JSValue JSDOMWindow::webKitPoint(ExecState* exec) const
523 {
524     return getDOMConstructor<JSWebKitPointConstructor>(exec, this);
525 }
526 
webKitCSSMatrix(ExecState * exec) const527 JSValue JSDOMWindow::webKitCSSMatrix(ExecState* exec) const
528 {
529     return getDOMConstructor<JSWebKitCSSMatrixConstructor>(exec, this);
530 }
531 
arrayBuffer(ExecState * exec) const532 JSValue JSDOMWindow::arrayBuffer(ExecState* exec) const
533 {
534     return getDOMConstructor<JSArrayBufferConstructor>(exec, this);
535 }
536 
int8Array(ExecState * exec) const537 JSValue JSDOMWindow::int8Array(ExecState* exec) const
538 {
539     return getDOMConstructor<JSInt8ArrayConstructor>(exec, this);
540 }
541 
uint8Array(ExecState * exec) const542 JSValue JSDOMWindow::uint8Array(ExecState* exec) const
543 {
544     return getDOMConstructor<JSUint8ArrayConstructor>(exec, this);
545 }
546 
int32Array(ExecState * exec) const547 JSValue JSDOMWindow::int32Array(ExecState* exec) const
548 {
549     return getDOMConstructor<JSInt32ArrayConstructor>(exec, this);
550 }
551 
uint32Array(ExecState * exec) const552 JSValue JSDOMWindow::uint32Array(ExecState* exec) const
553 {
554     return getDOMConstructor<JSUint32ArrayConstructor>(exec, this);
555 }
556 
int16Array(ExecState * exec) const557 JSValue JSDOMWindow::int16Array(ExecState* exec) const
558 {
559     return getDOMConstructor<JSInt16ArrayConstructor>(exec, this);
560 }
561 
uint16Array(ExecState * exec) const562 JSValue JSDOMWindow::uint16Array(ExecState* exec) const
563 {
564     return getDOMConstructor<JSUint16ArrayConstructor>(exec, this);
565 }
566 
float32Array(ExecState * exec) const567 JSValue JSDOMWindow::float32Array(ExecState* exec) const
568 {
569     return getDOMConstructor<JSFloat32ArrayConstructor>(exec, this);
570 }
571 
dataView(ExecState * exec) const572 JSValue JSDOMWindow::dataView(ExecState* exec) const
573 {
574     return getDOMConstructor<JSDataViewConstructor>(exec, this);
575 }
576 
xmlHttpRequest(ExecState * exec) const577 JSValue JSDOMWindow::xmlHttpRequest(ExecState* exec) const
578 {
579     return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this);
580 }
581 
582 #if ENABLE(XSLT)
xsltProcessor(ExecState * exec) const583 JSValue JSDOMWindow::xsltProcessor(ExecState* exec) const
584 {
585     return getDOMConstructor<JSXSLTProcessorConstructor>(exec, this);
586 }
587 #endif
588 
589 #if ENABLE(CHANNEL_MESSAGING)
messageChannel(ExecState * exec) const590 JSValue JSDOMWindow::messageChannel(ExecState* exec) const
591 {
592     return getDOMConstructor<JSMessageChannelConstructor>(exec, this);
593 }
594 #endif
595 
596 #if ENABLE(WORKERS)
worker(ExecState * exec) const597 JSValue JSDOMWindow::worker(ExecState* exec) const
598 {
599     return getDOMConstructor<JSWorkerConstructor>(exec, this);
600 }
601 #endif
602 
603 #if ENABLE(SHARED_WORKERS)
sharedWorker(ExecState * exec) const604 JSValue JSDOMWindow::sharedWorker(ExecState* exec) const
605 {
606     if (SharedWorkerRepository::isAvailable())
607         return getDOMConstructor<JSSharedWorkerConstructor>(exec, this);
608     return jsUndefined();
609 }
610 #endif
611 
612 #if ENABLE(WEB_AUDIO)
webkitAudioContext(ExecState * exec) const613 JSValue JSDOMWindow::webkitAudioContext(ExecState* exec) const
614 {
615     return getDOMConstructor<JSAudioContextConstructor>(exec, this);
616 }
617 #endif
618 
619 #if ENABLE(WEB_SOCKETS)
webSocket(ExecState * exec) const620 JSValue JSDOMWindow::webSocket(ExecState* exec) const
621 {
622     Frame* frame = impl()->frame();
623     if (!frame)
624         return jsUndefined();
625     Settings* settings = frame->settings();
626     if (!settings)
627         return jsUndefined();
628     return getDOMConstructor<JSWebSocketConstructor>(exec, this);
629 }
630 #endif
631 
632 // Custom functions
633 
open(ExecState * exec)634 JSValue JSDOMWindow::open(ExecState* exec)
635 {
636     String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
637     if (exec->hadException())
638         return jsUndefined();
639     AtomicString frameName = exec->argument(1).isUndefinedOrNull() ? "_blank" : ustringToAtomicString(exec->argument(1).toString(exec));
640     if (exec->hadException())
641         return jsUndefined();
642     String windowFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
643     if (exec->hadException())
644         return jsUndefined();
645 
646     RefPtr<DOMWindow> openedWindow = impl()->open(urlString, frameName, windowFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec));
647     if (!openedWindow)
648         return jsUndefined();
649     return toJS(exec, openedWindow.get());
650 }
651 
652 class DialogHandler {
653 public:
DialogHandler(ExecState * exec)654     explicit DialogHandler(ExecState* exec)
655         : m_exec(exec)
656         , m_globalObject(0)
657     {
658     }
659 
660     void dialogCreated(DOMWindow*);
661     JSValue returnValue() const;
662 
663 private:
664     ExecState* m_exec;
665     JSDOMWindow* m_globalObject;
666 };
667 
dialogCreated(DOMWindow * dialog)668 inline void DialogHandler::dialogCreated(DOMWindow* dialog)
669 {
670     // FIXME: This looks like a leak between the normal world and an isolated
671     //        world if dialogArguments comes from an isolated world.
672     m_globalObject = toJSDOMWindow(dialog->frame(), normalWorld(m_exec->globalData()));
673     if (JSValue dialogArguments = m_exec->argument(1))
674         m_globalObject->putDirect(m_exec->globalData(), Identifier(m_exec, "dialogArguments"), dialogArguments);
675 }
676 
returnValue() const677 inline JSValue DialogHandler::returnValue() const
678 {
679     if (!m_globalObject)
680         return jsUndefined();
681     Identifier identifier(m_exec, "returnValue");
682     PropertySlot slot;
683     if (!m_globalObject->JSGlobalObject::getOwnPropertySlot(m_exec, identifier, slot))
684         return jsUndefined();
685     return slot.getValue(m_exec, identifier);
686 }
687 
setUpDialog(DOMWindow * dialog,void * handler)688 static void setUpDialog(DOMWindow* dialog, void* handler)
689 {
690     static_cast<DialogHandler*>(handler)->dialogCreated(dialog);
691 }
692 
showModalDialog(ExecState * exec)693 JSValue JSDOMWindow::showModalDialog(ExecState* exec)
694 {
695     String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
696     if (exec->hadException())
697         return jsUndefined();
698     String dialogFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
699     if (exec->hadException())
700         return jsUndefined();
701 
702     DialogHandler handler(exec);
703 
704     impl()->showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec), setUpDialog, &handler);
705 
706     return handler.returnValue();
707 }
708 
postMessage(ExecState * exec)709 JSValue JSDOMWindow::postMessage(ExecState* exec)
710 {
711     PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, exec->argument(0));
712 
713     if (exec->hadException())
714         return jsUndefined();
715 
716     MessagePortArray messagePorts;
717     if (exec->argumentCount() > 2)
718         fillMessagePortArray(exec, exec->argument(1), messagePorts);
719     if (exec->hadException())
720         return jsUndefined();
721 
722     String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, exec->argument((exec->argumentCount() == 2) ? 1 : 2));
723     if (exec->hadException())
724         return jsUndefined();
725 
726     ExceptionCode ec = 0;
727     impl()->postMessage(message, &messagePorts, targetOrigin, activeDOMWindow(exec), ec);
728     setDOMException(exec, ec);
729 
730     return jsUndefined();
731 }
732 
setTimeout(ExecState * exec)733 JSValue JSDOMWindow::setTimeout(ExecState* exec)
734 {
735     ContentSecurityPolicy* contentSecurityPolicy = impl()->document() ? impl()->document()->contentSecurityPolicy() : 0;
736     OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
737     if (exec->hadException())
738         return jsUndefined();
739 
740     if (!action)
741         return jsNumber(0);
742 
743     int delay = exec->argument(1).toInt32(exec);
744 
745     ExceptionCode ec = 0;
746     int result = impl()->setTimeout(action.release(), delay, ec);
747     setDOMException(exec, ec);
748 
749     return jsNumber(result);
750 }
751 
setInterval(ExecState * exec)752 JSValue JSDOMWindow::setInterval(ExecState* exec)
753 {
754     ContentSecurityPolicy* contentSecurityPolicy = impl()->document() ? impl()->document()->contentSecurityPolicy() : 0;
755     OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
756     if (exec->hadException())
757         return jsUndefined();
758     int delay = exec->argument(1).toInt32(exec);
759 
760     if (!action)
761         return jsNumber(0);
762 
763     ExceptionCode ec = 0;
764     int result = impl()->setInterval(action.release(), delay, ec);
765     setDOMException(exec, ec);
766 
767     return jsNumber(result);
768 }
769 
addEventListener(ExecState * exec)770 JSValue JSDOMWindow::addEventListener(ExecState* exec)
771 {
772     Frame* frame = impl()->frame();
773     if (!frame)
774         return jsUndefined();
775 
776     JSValue listener = exec->argument(1);
777     if (!listener.isObject())
778         return jsUndefined();
779 
780     impl()->addEventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), exec->argument(2).toBoolean(exec));
781     return jsUndefined();
782 }
783 
removeEventListener(ExecState * exec)784 JSValue JSDOMWindow::removeEventListener(ExecState* exec)
785 {
786     Frame* frame = impl()->frame();
787     if (!frame)
788         return jsUndefined();
789 
790     JSValue listener = exec->argument(1);
791     if (!listener.isObject())
792         return jsUndefined();
793 
794     impl()->removeEventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), exec->argument(2).toBoolean(exec));
795     return jsUndefined();
796 }
797 
toDOMWindow(JSValue value)798 DOMWindow* toDOMWindow(JSValue value)
799 {
800     if (!value.isObject())
801         return 0;
802     JSObject* object = asObject(value);
803     if (object->inherits(&JSDOMWindow::s_info))
804         return static_cast<JSDOMWindow*>(object)->impl();
805     if (object->inherits(&JSDOMWindowShell::s_info))
806         return static_cast<JSDOMWindowShell*>(object)->impl();
807     return 0;
808 }
809 
810 } // namespace WebCore
811