blob: 2804b3ce6578abcbd9b55a7cf5b6ab307c8ce88b [file] [log] [blame]
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001/*
Feng Qian5f1ab042009-06-17 12:12:20 -07002 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08003 *
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 "AtomicString.h"
24#include "Base64.h"
25#include "DOMWindow.h"
26#include "Document.h"
27#include "ExceptionCode.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070028#include "FloatRect.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080029#include "Frame.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070030#include "FrameLoadRequest.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080031#include "FrameLoader.h"
32#include "FrameTree.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070033#include "FrameView.h"
Ben Murdoch0bf48ef2009-08-11 17:01:47 +010034#include "HTMLCollection.h"
35#include "HTMLDocument.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070036#include "History.h"
37#include "JSAudioConstructor.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080038#include "JSDOMWindowShell.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070039#include "JSEvent.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080040#include "JSEventListener.h"
Steve Block231d4e32009-10-08 17:19:54 +010041#include "JSEventSourceConstructor.h"
Ben Murdoch0bf48ef2009-08-11 17:01:47 +010042#include "JSHTMLCollection.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070043#include "JSHistory.h"
44#include "JSImageConstructor.h"
45#include "JSLocation.h"
46#include "JSMessageChannelConstructor.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080047#include "JSMessagePort.h"
Steve Block231d4e32009-10-08 17:19:54 +010048#include "JSMessagePortCustom.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070049#include "JSOptionConstructor.h"
Steve Block231d4e32009-10-08 17:19:54 +010050
51#if ENABLE(SHARED_WORKERS)
Ben Murdoch0bf48ef2009-08-11 17:01:47 +010052#include "JSSharedWorkerConstructor.h"
Steve Block231d4e32009-10-08 17:19:54 +010053#endif
54
55#if ENABLE(3D_CANVAS)
56#include "JSCanvasArrayBufferConstructor.h"
57#include "JSCanvasByteArrayConstructor.h"
58#include "JSCanvasUnsignedByteArrayConstructor.h"
59#include "JSCanvasIntArrayConstructor.h"
60#include "JSCanvasUnsignedIntArrayConstructor.h"
61#include "JSCanvasShortArrayConstructor.h"
62#include "JSCanvasUnsignedShortArrayConstructor.h"
63#include "JSCanvasFloatArrayConstructor.h"
64#endif
Feng Qian5f1ab042009-06-17 12:12:20 -070065#include "JSWebKitCSSMatrixConstructor.h"
66#include "JSWebKitPointConstructor.h"
Steve Block231d4e32009-10-08 17:19:54 +010067#if ENABLE(WEB_SOCKETS)
68#include "JSWebSocketConstructor.h"
69#endif
Feng Qian5f1ab042009-06-17 12:12:20 -070070#include "JSWorkerConstructor.h"
71#include "JSXMLHttpRequestConstructor.h"
72#include "JSXSLTProcessorConstructor.h"
73#include "Location.h"
74#include "MediaPlayer.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080075#include "MessagePort.h"
Steve Block231d4e32009-10-08 17:19:54 +010076#include "NotificationCenter.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070077#include "Page.h"
78#include "PlatformScreen.h"
79#include "RegisteredEventListener.h"
80#include "ScheduledAction.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080081#include "ScriptController.h"
Steve Block231d4e32009-10-08 17:19:54 +010082#include "SerializedScriptValue.h"
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080083#include "Settings.h"
Steve Block231d4e32009-10-08 17:19:54 +010084#include "SharedWorkerRepository.h"
Feng Qian5f1ab042009-06-17 12:12:20 -070085#include "WindowFeatures.h"
Steve Block231d4e32009-10-08 17:19:54 +010086#include <runtime/Error.h>
87#include <runtime/JSFunction.h>
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080088#include <runtime/JSObject.h>
Ben Murdoch0bf48ef2009-08-11 17:01:47 +010089#include <runtime/PrototypeFunction.h>
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080090
91using namespace JSC;
92
93namespace WebCore {
94
Ben Murdoch0bf48ef2009-08-11 17:01:47 +010095void JSDOMWindow::markChildren(MarkStack& markStack)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080096{
Ben Murdoch0bf48ef2009-08-11 17:01:47 +010097 Base::markChildren(markStack);
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -080098
Steve Block231d4e32009-10-08 17:19:54 +010099 impl()->markEventListeners(markStack);
Feng Qian5f1ab042009-06-17 12:12:20 -0700100
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800101 JSGlobalData& globalData = *Heap::heap(this)->globalData();
102
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100103 markDOMObjectWrapper(markStack, globalData, impl()->optionalConsole());
104 markDOMObjectWrapper(markStack, globalData, impl()->optionalHistory());
105 markDOMObjectWrapper(markStack, globalData, impl()->optionalLocationbar());
106 markDOMObjectWrapper(markStack, globalData, impl()->optionalMenubar());
107 markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator());
108 markDOMObjectWrapper(markStack, globalData, impl()->optionalPersonalbar());
109 markDOMObjectWrapper(markStack, globalData, impl()->optionalScreen());
110 markDOMObjectWrapper(markStack, globalData, impl()->optionalScrollbars());
111 markDOMObjectWrapper(markStack, globalData, impl()->optionalSelection());
112 markDOMObjectWrapper(markStack, globalData, impl()->optionalStatusbar());
113 markDOMObjectWrapper(markStack, globalData, impl()->optionalToolbar());
114 markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation());
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800115#if ENABLE(DOM_STORAGE)
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100116 markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage());
117 markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage());
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800118#endif
119#if ENABLE(OFFLINE_WEB_APPLICATIONS)
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100120 markDOMObjectWrapper(markStack, globalData, impl()->optionalApplicationCache());
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800121#endif
122}
123
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100124template<NativeFunction nativeFunction, int length>
125JSValue nonCachingStaticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&)
126{
127 return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction);
128}
129
130static JSValue childFrameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
131{
132 return toJS(exec, static_cast<JSDOMWindow*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(AtomicString(propertyName))->domWindow());
133}
134
135static JSValue indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
136{
137 return toJS(exec, static_cast<JSDOMWindow*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(slot.index())->domWindow());
138}
139
140static JSValue namedItemGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
141{
142 JSDOMWindowBase* thisObj = static_cast<JSDOMWindow*>(asObject(slot.slotBase()));
143 Document* document = thisObj->impl()->frame()->document();
144
145 ASSERT(thisObj->allowsAccessFrom(exec));
146 ASSERT(document);
147 ASSERT(document->isHTMLDocument());
148
149 RefPtr<HTMLCollection> collection = document->windowNamedItems(propertyName);
150 if (collection->length() == 1)
151 return toJS(exec, collection->firstItem());
152 return toJS(exec, collection.get());
153}
154
155bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
156{
157 // When accessing a Window cross-domain, functions are always the native built-in ones, and they
158 // are not affected by properties changed on the Window or anything in its prototype chain.
159 // This is consistent with the behavior of Firefox.
160
161 const HashEntry* entry;
162
163 // We don't want any properties other than "close" and "closed" on a closed window.
164 if (!impl()->frame()) {
165 // The following code is safe for cross-domain and same domain use.
166 // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
167 entry = s_info.propHashTable(exec)->entry(exec, propertyName);
168 if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
169 slot.setCustom(this, entry->propertyGetter());
170 return true;
171 }
172 entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
173 if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
174 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
175 return true;
176 }
177
178 // FIXME: We should have a message here that explains why the property access/function call was
179 // not allowed.
180 slot.setUndefined();
181 return true;
182 }
183
184 // We need to check for cross-domain access here without printing the generic warning message
185 // because we always allow access to some function, just different ones depending whether access
186 // is allowed.
187 String errorMessage;
188 bool allowsAccess = allowsAccessFrom(exec, errorMessage);
189
190 // Look for overrides before looking at any of our own properties, but ignore overrides completely
191 // if this is cross-domain access.
192 if (allowsAccess && JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot))
193 return true;
194
195 // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
196 // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot.
197 // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
198 // what prototype is actually set on this object.
199 entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
200 if (entry) {
201 if (entry->attributes() & Function) {
202 if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
203 if (!allowsAccess) {
204 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
205 return true;
206 }
207 } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
208 if (!allowsAccess) {
209 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
210 return true;
211 }
212 } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
213 if (!allowsAccess) {
214 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
215 return true;
216 }
217 } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
218 if (!allowsAccess) {
219 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
220 return true;
221 }
222 } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
223 if (!DOMWindow::canShowModalDialog(impl()->frame())) {
224 slot.setUndefined();
225 return true;
226 }
227 }
228 }
229 } else {
230 // Allow access to toString() cross-domain, but always Object.prototype.toString.
231 if (propertyName == exec->propertyNames().toString) {
232 if (!allowsAccess) {
233 slot.setCustom(this, objectToStringFunctionGetter);
234 return true;
235 }
236 }
237 }
238
239 entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
240 if (entry) {
241 slot.setCustom(this, entry->propertyGetter());
242 return true;
243 }
244
245 // Check for child frames by name before built-in properties to
246 // match Mozilla. This does not match IE, but some sites end up
247 // naming frames things that conflict with window properties that
248 // are in Moz but not IE. Since we have some of these, we have to do
249 // it the Moz way.
250 if (impl()->frame()->tree()->child(propertyName)) {
251 slot.setCustom(this, childFrameGetter);
252 return true;
253 }
254
255 // Do prototype lookup early so that functions and attributes in the prototype can have
256 // precedence over the index and name getters.
257 JSValue proto = prototype();
258 if (proto.isObject()) {
259 if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) {
260 if (!allowsAccess) {
261 printErrorMessage(errorMessage);
262 slot.setUndefined();
263 }
264 return true;
265 }
266 }
267
268 // FIXME: Search the whole frame hierachy somewhere around here.
269 // We need to test the correct priority order.
270
271 // allow window[1] or parent[1] etc. (#56983)
272 bool ok;
273 unsigned i = propertyName.toArrayIndex(&ok);
274 if (ok && i < impl()->frame()->tree()->childCount()) {
275 slot.setCustomIndex(this, i, indexGetter);
276 return true;
277 }
278
279 if (!allowsAccess) {
280 printErrorMessage(errorMessage);
281 slot.setUndefined();
282 return true;
283 }
284
285 // Allow shortcuts like 'Image1' instead of document.images.Image1
286 Document* document = impl()->frame()->document();
287 if (document->isHTMLDocument()) {
288 AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName);
289 if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
290 slot.setCustom(this, namedItemGetter);
291 return true;
292 }
293 }
294
295 return Base::getOwnPropertySlot(exec, propertyName, slot);
296}
297
Steve Block231d4e32009-10-08 17:19:54 +0100298bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
299{
300 // When accessing a Window cross-domain, functions are always the native built-in ones, and they
301 // are not affected by properties changed on the Window or anything in its prototype chain.
302 // This is consistent with the behavior of Firefox.
303
304 const HashEntry* entry;
305
306 // We don't want any properties other than "close" and "closed" on a closed window.
307 if (!impl()->frame()) {
308 // The following code is safe for cross-domain and same domain use.
309 // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
310 entry = s_info.propHashTable(exec)->entry(exec, propertyName);
311 if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
312 descriptor.setDescriptor(jsBoolean(true), ReadOnly | DontDelete | DontEnum);
313 return true;
314 }
315 entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
316 if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
317 PropertySlot slot;
318 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
319 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
320 return true;
321 }
322 descriptor.setUndefined();
323 return true;
324 }
325
326 String errorMessage;
327 bool allowsAccess = allowsAccessFrom(exec, errorMessage);
328 if (allowsAccess && JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor))
329 return true;
330
331 // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
332 // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot.
333 // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
334 // what prototype is actually set on this object.
335 entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
336 if (entry) {
337 if (entry->attributes() & Function) {
338 if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
339 if (!allowsAccess) {
340 PropertySlot slot;
341 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
342 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
343 return true;
344 }
345 } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
346 if (!allowsAccess) {
347 PropertySlot slot;
348 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
349 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
350 return true;
351 }
352 } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
353 if (!allowsAccess) {
354 PropertySlot slot;
355 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
356 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
357 return true;
358 }
359 } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
360 if (!allowsAccess) {
361 PropertySlot slot;
362 slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
363 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
364 return true;
365 }
366 } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
367 if (!DOMWindow::canShowModalDialog(impl()->frame())) {
368 descriptor.setUndefined();
369 return true;
370 }
371 }
372 }
373 } else {
374 // Allow access to toString() cross-domain, but always Object.prototype.toString.
375 if (propertyName == exec->propertyNames().toString) {
376 if (!allowsAccess) {
377 PropertySlot slot;
378 slot.setCustom(this, objectToStringFunctionGetter);
379 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
380 return true;
381 }
382 }
383 }
384
385 entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
386 if (entry) {
387 PropertySlot slot;
388 slot.setCustom(this, entry->propertyGetter());
389 descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
390 return true;
391 }
392
393 // Check for child frames by name before built-in properties to
394 // match Mozilla. This does not match IE, but some sites end up
395 // naming frames things that conflict with window properties that
396 // are in Moz but not IE. Since we have some of these, we have to do
397 // it the Moz way.
398 if (impl()->frame()->tree()->child(propertyName)) {
399 PropertySlot slot;
400 slot.setCustom(this, childFrameGetter);
401 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
402 return true;
403 }
404
405 // Do prototype lookup early so that functions and attributes in the prototype can have
406 // precedence over the index and name getters.
407 JSValue proto = prototype();
408 if (proto.isObject()) {
409 if (asObject(proto)->getPropertyDescriptor(exec, propertyName, descriptor)) {
410 if (!allowsAccess) {
411 printErrorMessage(errorMessage);
412 descriptor.setUndefined();
413 }
414 return true;
415 }
416 }
417
418 bool ok;
419 unsigned i = propertyName.toArrayIndex(&ok);
420 if (ok && i < impl()->frame()->tree()->childCount()) {
421 PropertySlot slot;
422 slot.setCustomIndex(this, i, indexGetter);
423 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
424 return true;
425 }
426
427 // Allow shortcuts like 'Image1' instead of document.images.Image1
428 Document* document = impl()->frame()->document();
429 if (document->isHTMLDocument()) {
430 AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName);
431 if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
432 PropertySlot slot;
433 slot.setCustom(this, namedItemGetter);
434 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
435 return true;
436 }
437 }
438
439 return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
440}
441
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100442void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
443{
444 if (!impl()->frame())
445 return;
446
447 // Optimization: access JavaScript global variables directly before involving the DOM.
448 if (JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) {
449 if (allowsAccessFrom(exec))
450 JSGlobalObject::put(exec, propertyName, value, slot);
451 return;
452 }
453
454 if (lookupPut<JSDOMWindow>(exec, propertyName, value, s_info.propHashTable(exec), this))
455 return;
456
457 if (allowsAccessFrom(exec))
458 Base::put(exec, propertyName, value, slot);
459}
460
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800461bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName)
462{
463 // Only allow deleting properties by frames in the same origin.
464 if (!allowsAccessFrom(exec))
465 return false;
466 return Base::deleteProperty(exec, propertyName);
467}
468
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100469void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800470{
471 // Only allow the window to enumerated by frames in the same origin.
472 if (!allowsAccessFrom(exec))
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100473 return;
474 Base::getPropertyNames(exec, propertyNames);
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800475}
476
Steve Block231d4e32009-10-08 17:19:54 +0100477void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
478{
479 // Only allow the window to enumerated by frames in the same origin.
480 if (!allowsAccessFrom(exec))
481 return;
482 Base::getOwnPropertyNames(exec, propertyNames);
483}
484
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100485bool JSDOMWindow::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800486{
487 // Only allow getting property attributes properties by frames in the same origin.
488 if (!allowsAccessFrom(exec))
489 return false;
490 return Base::getPropertyAttributes(exec, propertyName, attributes);
491}
492
Steve Block231d4e32009-10-08 17:19:54 +0100493void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800494{
495 // Only allow defining getters by frames in the same origin.
496 if (!allowsAccessFrom(exec))
497 return;
Feng Qian5f1ab042009-06-17 12:12:20 -0700498
499 // Don't allow shadowing location using defineGetter.
500 if (propertyName == "location")
501 return;
502
Steve Block231d4e32009-10-08 17:19:54 +0100503 Base::defineGetter(exec, propertyName, getterFunction, attributes);
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800504}
505
Steve Block231d4e32009-10-08 17:19:54 +0100506void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800507{
508 // Only allow defining setters by frames in the same origin.
509 if (!allowsAccessFrom(exec))
510 return;
Steve Block231d4e32009-10-08 17:19:54 +0100511 Base::defineSetter(exec, propertyName, setterFunction, attributes);
512}
513
514bool JSDOMWindow::defineOwnProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
515{
516 // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
517 if (!allowsAccessFrom(exec))
518 return false;
519 return Base::defineOwnProperty(exec, propertyName, descriptor, shouldThrow);
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800520}
521
Feng Qian5f1ab042009-06-17 12:12:20 -0700522JSValue JSDOMWindow::lookupGetter(ExecState* exec, const Identifier& propertyName)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800523{
524 // Only allow looking-up getters by frames in the same origin.
525 if (!allowsAccessFrom(exec))
526 return jsUndefined();
527 return Base::lookupGetter(exec, propertyName);
528}
529
Feng Qian5f1ab042009-06-17 12:12:20 -0700530JSValue JSDOMWindow::lookupSetter(ExecState* exec, const Identifier& propertyName)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800531{
532 // Only allow looking-up setters by frames in the same origin.
533 if (!allowsAccessFrom(exec))
534 return jsUndefined();
535 return Base::lookupSetter(exec, propertyName);
536}
537
Feng Qian5f1ab042009-06-17 12:12:20 -0700538// Custom Attributes
539
540JSValue JSDOMWindow::history(ExecState* exec) const
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800541{
Feng Qian5f1ab042009-06-17 12:12:20 -0700542 History* history = impl()->history();
543 if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), history))
544 return wrapper;
545
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100546 JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
547 JSHistory* jsHistory = new (exec) JSHistory(getDOMStructure<JSHistory>(exec, window), window, history);
Feng Qian5f1ab042009-06-17 12:12:20 -0700548 cacheDOMObjectWrapper(exec->globalData(), history, jsHistory);
549 return jsHistory;
550}
551
552JSValue JSDOMWindow::location(ExecState* exec) const
553{
554 Location* location = impl()->location();
555 if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), location))
556 return wrapper;
557
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100558 JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
559 JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, window), window, location);
Feng Qian5f1ab042009-06-17 12:12:20 -0700560 cacheDOMObjectWrapper(exec->globalData(), location, jsLocation);
561 return jsLocation;
562}
563
564void JSDOMWindow::setLocation(ExecState* exec, JSValue value)
565{
566 Frame* lexicalFrame = toLexicalFrame(exec);
567 if (!lexicalFrame)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800568 return;
569
570#if ENABLE(DASHBOARD_SUPPORT)
571 // To avoid breaking old widgets, make "var location =" in a top-level frame create
572 // a property named "location" instead of performing a navigation (<rdar://problem/5688039>).
Feng Qian5f1ab042009-06-17 12:12:20 -0700573 if (Settings* settings = lexicalFrame->settings()) {
574 if (settings->usesDashboardBackwardCompatibilityMode() && !lexicalFrame->tree()->parent()) {
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800575 if (allowsAccessFrom(exec))
576 putDirect(Identifier(exec, "location"), value);
577 return;
578 }
579 }
580#endif
581
Feng Qian5f1ab042009-06-17 12:12:20 -0700582 Frame* frame = impl()->frame();
583 ASSERT(frame);
584
Feng Qian5f1ab042009-06-17 12:12:20 -0700585 KURL url = completeURL(exec, value.toString(exec));
586 if (url.isNull())
587 return;
588
Steve Block231d4e32009-10-08 17:19:54 +0100589 if (!shouldAllowNavigation(exec, frame))
590 return;
591
Feng Qian5f1ab042009-06-17 12:12:20 -0700592 if (!protocolIsJavaScript(url) || allowsAccessFrom(exec)) {
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800593 // We want a new history item if this JS was called via a user gesture
Steve Block231d4e32009-10-08 17:19:54 +0100594 frame->redirectScheduler()->scheduleLocationChange(url, lexicalFrame->loader()->outgoingReferrer(), !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, processingUserGesture(exec));
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800595 }
596}
597
Feng Qian5f1ab042009-06-17 12:12:20 -0700598JSValue JSDOMWindow::crypto(ExecState*) const
599{
600 return jsUndefined();
601}
602
603JSValue JSDOMWindow::event(ExecState* exec) const
604{
605 Event* event = currentEvent();
606 if (!event)
607 return jsUndefined();
608 return toJS(exec, event);
609}
610
Steve Block231d4e32009-10-08 17:19:54 +0100611#if ENABLE(EVENTSOURCE)
612JSValue JSDOMWindow::eventSource(ExecState* exec) const
613{
614 return getDOMConstructor<JSEventSourceConstructor>(exec, this);
615}
616#endif
617
Feng Qian5f1ab042009-06-17 12:12:20 -0700618JSValue JSDOMWindow::image(ExecState* exec) const
619{
620 return getDOMConstructor<JSImageConstructor>(exec, this);
621}
622
623JSValue JSDOMWindow::option(ExecState* exec) const
624{
625 return getDOMConstructor<JSOptionConstructor>(exec, this);
626}
627
628#if ENABLE(VIDEO)
629JSValue JSDOMWindow::audio(ExecState* exec) const
630{
631 if (!MediaPlayer::isAvailable())
632 return jsUndefined();
633 return getDOMConstructor<JSAudioConstructor>(exec, this);
634}
635#endif
636
637JSValue JSDOMWindow::webKitPoint(ExecState* exec) const
638{
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100639 return getDOMConstructor<JSWebKitPointConstructor>(exec, this);
Feng Qian5f1ab042009-06-17 12:12:20 -0700640}
641
642JSValue JSDOMWindow::webKitCSSMatrix(ExecState* exec) const
643{
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100644 return getDOMConstructor<JSWebKitCSSMatrixConstructor>(exec, this);
Feng Qian5f1ab042009-06-17 12:12:20 -0700645}
646
Steve Block231d4e32009-10-08 17:19:54 +0100647#if ENABLE(3D_CANVAS)
648JSValue JSDOMWindow::canvasArrayBuffer(ExecState* exec) const
649{
650 return getDOMConstructor<JSCanvasArrayBufferConstructor>(exec, this);
651}
652
653JSValue JSDOMWindow::canvasByteArray(ExecState* exec) const
654{
655 return getDOMConstructor<JSCanvasByteArrayConstructor>(exec, this);
656}
657
658JSValue JSDOMWindow::canvasUnsignedByteArray(ExecState* exec) const
659{
660 return getDOMConstructor<JSCanvasUnsignedByteArrayConstructor>(exec, this);
661}
662
663JSValue JSDOMWindow::canvasIntArray(ExecState* exec) const
664{
665 return getDOMConstructor<JSCanvasIntArrayConstructor>(exec, this);
666}
667
668JSValue JSDOMWindow::canvasUnsignedIntArray(ExecState* exec) const
669{
670 return getDOMConstructor<JSCanvasUnsignedIntArrayConstructor>(exec, this);
671}
672
673JSValue JSDOMWindow::canvasShortArray(ExecState* exec) const
674{
675 return getDOMConstructor<JSCanvasShortArrayConstructor>(exec, this);
676}
677
678JSValue JSDOMWindow::canvasUnsignedShortArray(ExecState* exec) const
679{
680 return getDOMConstructor<JSCanvasUnsignedShortArrayConstructor>(exec, this);
681}
682
683JSValue JSDOMWindow::canvasFloatArray(ExecState* exec) const
684{
685 return getDOMConstructor<JSCanvasFloatArrayConstructor>(exec, this);
686}
687#endif
688
Feng Qian5f1ab042009-06-17 12:12:20 -0700689JSValue JSDOMWindow::xmlHttpRequest(ExecState* exec) const
690{
691 return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this);
692}
693
694#if ENABLE(XSLT)
695JSValue JSDOMWindow::xsltProcessor(ExecState* exec) const
696{
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100697 return getDOMConstructor<JSXSLTProcessorConstructor>(exec, this);
Feng Qian5f1ab042009-06-17 12:12:20 -0700698}
699#endif
700
701#if ENABLE(CHANNEL_MESSAGING)
702JSValue JSDOMWindow::messageChannel(ExecState* exec) const
703{
704 return getDOMConstructor<JSMessageChannelConstructor>(exec, this);
705}
706#endif
707
708#if ENABLE(WORKERS)
709JSValue JSDOMWindow::worker(ExecState* exec) const
710{
Ben Murdoch0bf48ef2009-08-11 17:01:47 +0100711 return getDOMConstructor<JSWorkerConstructor>(exec, this);
712}
713#endif
714
715#if ENABLE(SHARED_WORKERS)
716JSValue JSDOMWindow::sharedWorker(ExecState* exec) const
717{
Steve Block231d4e32009-10-08 17:19:54 +0100718 if (SharedWorkerRepository::isAvailable())
719 return getDOMConstructor<JSSharedWorkerConstructor>(exec, this);
720 return jsUndefined();
721}
722#endif
723
724#if ENABLE(WEB_SOCKETS)
725JSValue JSDOMWindow::webSocket(ExecState* exec) const
726{
727 Frame* frame = impl()->frame();
728 if (!frame)
729 return jsUndefined();
730 Settings* settings = frame->settings();
731 if (!settings)
732 return jsUndefined();
Steve Block231d4e32009-10-08 17:19:54 +0100733 return getDOMConstructor<JSWebSocketConstructor>(exec, this);
Feng Qian5f1ab042009-06-17 12:12:20 -0700734}
735#endif
736
737// Custom functions
738
739// Helper for window.open() and window.showModalDialog()
740static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicFrame,
741 Frame* openerFrame, const String& url, const String& frameName,
742 const WindowFeatures& windowFeatures, JSValue dialogArgs)
743{
744 ASSERT(lexicalFrame);
745 ASSERT(dynamicFrame);
746
747 ResourceRequest request;
748
749 // For whatever reason, Firefox uses the dynamicGlobalObject to determine
750 // the outgoingReferrer. We replicate that behavior here.
751 String referrer = dynamicFrame->loader()->outgoingReferrer();
752 request.setHTTPReferrer(referrer);
753 FrameLoader::addHTTPOriginIfNeeded(request, dynamicFrame->loader()->outgoingOrigin());
754 FrameLoadRequest frameRequest(request, frameName);
755
756 // FIXME: It's much better for client API if a new window starts with a URL, here where we
757 // know what URL we are going to open. Unfortunately, this code passes the empty string
758 // for the URL, but there's a reason for that. Before loading we have to set up the opener,
759 // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently
760 // do an allowsAccessFrom call using the window we create, which can't be done before creating it.
761 // We'd have to resolve all those issues to pass the URL instead of "".
762
763 bool created;
764 // We pass in the opener frame here so it can be used for looking up the frame name, in case the active frame
765 // is different from the opener frame, and the name references a frame relative to the opener frame, for example
766 // "_self" or "_parent".
767 Frame* newFrame = lexicalFrame->loader()->createWindow(openerFrame->loader(), frameRequest, windowFeatures, created);
768 if (!newFrame)
769 return 0;
770
771 newFrame->loader()->setOpener(openerFrame);
Steve Block231d4e32009-10-08 17:19:54 +0100772 newFrame->page()->setOpenedByDOM();
Feng Qian5f1ab042009-06-17 12:12:20 -0700773
Steve Blockcac0f672009-11-05 09:23:40 +0000774 // FIXME: If a window is created from an isolated world, what are the consequences of this? 'dialogArguments' only appears back in the normal world?
775 JSDOMWindow* newWindow = toJSDOMWindow(newFrame, normalWorld(exec->globalData()));
Feng Qian5f1ab042009-06-17 12:12:20 -0700776
777 if (dialogArgs)
778 newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs);
779
780 if (!protocolIsJavaScript(url) || newWindow->allowsAccessFrom(exec)) {
Steve Block231d4e32009-10-08 17:19:54 +0100781 KURL completedURL = url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(exec, url);
Feng Qian5f1ab042009-06-17 12:12:20 -0700782 bool userGesture = processingUserGesture(exec);
783
784 if (created)
785 newFrame->loader()->changeLocation(completedURL, referrer, false, false, userGesture);
786 else if (!url.isEmpty())
Steve Block231d4e32009-10-08 17:19:54 +0100787 newFrame->redirectScheduler()->scheduleLocationChange(completedURL.string(), referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
Feng Qian5f1ab042009-06-17 12:12:20 -0700788 }
789
790 return newFrame;
791}
792
793JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args)
794{
Steve Block231d4e32009-10-08 17:19:54 +0100795 String urlString = valueToStringWithUndefinedOrNullCheck(exec, args.at(0));
796 AtomicString frameName = args.at(1).isUndefinedOrNull() ? "_blank" : AtomicString(args.at(1).toString(exec));
797 WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args.at(2)));
798
Feng Qian5f1ab042009-06-17 12:12:20 -0700799 Frame* frame = impl()->frame();
800 if (!frame)
801 return jsUndefined();
802 Frame* lexicalFrame = toLexicalFrame(exec);
803 if (!lexicalFrame)
804 return jsUndefined();
805 Frame* dynamicFrame = toDynamicFrame(exec);
806 if (!dynamicFrame)
807 return jsUndefined();
808
809 Page* page = frame->page();
810
Feng Qian5f1ab042009-06-17 12:12:20 -0700811 // Because FrameTree::find() returns true for empty strings, we must check for empty framenames.
812 // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
813 if (!DOMWindow::allowPopUp(dynamicFrame) && (frameName.isEmpty() || !frame->tree()->find(frameName)))
814 return jsUndefined();
815
816 // Get the target frame for the special cases of _top and _parent. In those
817 // cases, we can schedule a location change right now and return early.
818 bool topOrParent = false;
819 if (frameName == "_top") {
820 frame = frame->tree()->top();
821 topOrParent = true;
822 } else if (frameName == "_parent") {
823 if (Frame* parent = frame->tree()->parent())
824 frame = parent;
825 topOrParent = true;
826 }
827 if (topOrParent) {
Feng Qian5f1ab042009-06-17 12:12:20 -0700828 String completedURL;
829 if (!urlString.isEmpty())
830 completedURL = completeURL(exec, urlString).string();
831
Steve Block231d4e32009-10-08 17:19:54 +0100832 if (!shouldAllowNavigation(exec, frame))
833 return jsUndefined();
834
Steve Blockcac0f672009-11-05 09:23:40 +0000835 const JSDOMWindow* targetedWindow = toJSDOMWindow(frame, currentWorld(exec));
Feng Qian5f1ab042009-06-17 12:12:20 -0700836 if (!completedURL.isEmpty() && (!protocolIsJavaScript(completedURL) || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) {
837 bool userGesture = processingUserGesture(exec);
838
839 // For whatever reason, Firefox uses the dynamicGlobalObject to
840 // determine the outgoingReferrer. We replicate that behavior
841 // here.
842 String referrer = dynamicFrame->loader()->outgoingReferrer();
843
Steve Block231d4e32009-10-08 17:19:54 +0100844 frame->redirectScheduler()->scheduleLocationChange(completedURL, referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
Feng Qian5f1ab042009-06-17 12:12:20 -0700845 }
846 return toJS(exec, frame->domWindow());
847 }
848
849 // In the case of a named frame or a new window, we'll use the createWindow() helper
Feng Qian5f1ab042009-06-17 12:12:20 -0700850 FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
851 windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
852 DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
853
854 windowFeatures.x = windowRect.x();
855 windowFeatures.y = windowRect.y();
856 windowFeatures.height = windowRect.height();
857 windowFeatures.width = windowRect.width();
858
859 frame = createWindow(exec, lexicalFrame, dynamicFrame, frame, urlString, frameName, windowFeatures, JSValue());
860
861 if (!frame)
862 return jsUndefined();
863
864 return toJS(exec, frame->domWindow());
865}
866
867JSValue JSDOMWindow::showModalDialog(ExecState* exec, const ArgList& args)
868{
Steve Block231d4e32009-10-08 17:19:54 +0100869 String url = valueToStringWithUndefinedOrNullCheck(exec, args.at(0));
870 JSValue dialogArgs = args.at(1);
871 String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, args.at(2));
872
Feng Qian5f1ab042009-06-17 12:12:20 -0700873 Frame* frame = impl()->frame();
874 if (!frame)
875 return jsUndefined();
876 Frame* lexicalFrame = toLexicalFrame(exec);
877 if (!lexicalFrame)
878 return jsUndefined();
879 Frame* dynamicFrame = toDynamicFrame(exec);
880 if (!dynamicFrame)
881 return jsUndefined();
882
883 if (!DOMWindow::canShowModalDialogNow(frame) || !DOMWindow::allowPopUp(dynamicFrame))
884 return jsUndefined();
885
Feng Qian5f1ab042009-06-17 12:12:20 -0700886 HashMap<String, String> features;
887 DOMWindow::parseModalDialogFeatures(featureArgs, features);
888
889 const bool trusted = false;
890
891 // The following features from Microsoft's documentation are not implemented:
892 // - default font settings
893 // - width, height, left, and top specified in units other than "px"
894 // - edge (sunken or raised, default is raised)
895 // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
896 // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
897 // - unadorned: trusted && boolFeature(features, "unadorned");
898
899 FloatRect screenRect = screenAvailableRect(frame->view());
900
901 WindowFeatures wargs;
902 wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE
903 wargs.widthSet = true;
904 wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
905 wargs.heightSet = true;
906
907 wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1);
908 wargs.xSet = wargs.x > 0;
909 wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1);
910 wargs.ySet = wargs.y > 0;
911
912 if (WindowFeatures::boolFeature(features, "center", true)) {
913 if (!wargs.xSet) {
914 wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2;
915 wargs.xSet = true;
916 }
917 if (!wargs.ySet) {
918 wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2;
919 wargs.ySet = true;
920 }
921 }
922
923 wargs.dialog = true;
924 wargs.resizable = WindowFeatures::boolFeature(features, "resizable");
925 wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true);
926 wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted);
927 wargs.menuBarVisible = false;
928 wargs.toolBarVisible = false;
929 wargs.locationBarVisible = false;
930 wargs.fullscreen = false;
931
932 Frame* dialogFrame = createWindow(exec, lexicalFrame, dynamicFrame, frame, url, "", wargs, dialogArgs);
933 if (!dialogFrame)
934 return jsUndefined();
935
Steve Blockcac0f672009-11-05 09:23:40 +0000936 JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame, currentWorld(exec));
Feng Qian5f1ab042009-06-17 12:12:20 -0700937 dialogFrame->page()->chrome()->runModal();
938
Steve Block231d4e32009-10-08 17:19:54 +0100939 Identifier returnValue(exec, "returnValue");
940 if (dialogWindow->allowsAccessFromNoErrorMessage(exec)) {
941 PropertySlot slot;
942 // This is safe, we have already performed the origin security check and we are
943 // not interested in any of the DOM properties of the window.
944 if (dialogWindow->JSGlobalObject::getOwnPropertySlot(exec, returnValue, slot))
945 return slot.getValue(exec, returnValue);
946 }
947 return jsUndefined();
Feng Qian5f1ab042009-06-17 12:12:20 -0700948}
949
950JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800951{
952 DOMWindow* window = impl();
953
Feng Qian5f1ab042009-06-17 12:12:20 -0700954 DOMWindow* source = asJSDOMWindow(exec->lexicalGlobalObject())->impl();
Steve Block231d4e32009-10-08 17:19:54 +0100955 PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, args.at(0));
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800956
957 if (exec->hadException())
958 return jsUndefined();
959
Steve Block231d4e32009-10-08 17:19:54 +0100960 MessagePortArray messagePorts;
961 if (args.size() > 2)
962 fillMessagePortArray(exec, args.at(1), messagePorts);
963 if (exec->hadException())
964 return jsUndefined();
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800965
Feng Qian5f1ab042009-06-17 12:12:20 -0700966 String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, args.at((args.size() == 2) ? 1 : 2));
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800967 if (exec->hadException())
968 return jsUndefined();
969
970 ExceptionCode ec = 0;
Steve Block231d4e32009-10-08 17:19:54 +0100971 window->postMessage(message, &messagePorts, targetOrigin, source, ec);
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800972 setDOMException(exec, ec);
973
974 return jsUndefined();
975}
976
Feng Qian5f1ab042009-06-17 12:12:20 -0700977JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800978{
Steve Blockcac0f672009-11-05 09:23:40 +0000979 ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec));
Feng Qian5f1ab042009-06-17 12:12:20 -0700980 if (exec->hadException())
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800981 return jsUndefined();
Feng Qian5f1ab042009-06-17 12:12:20 -0700982 int delay = args.at(1).toInt32(exec);
983 return jsNumber(exec, impl()->setTimeout(action, delay));
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800984}
985
Feng Qian5f1ab042009-06-17 12:12:20 -0700986JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800987{
Steve Blockcac0f672009-11-05 09:23:40 +0000988 ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec));
Feng Qian5f1ab042009-06-17 12:12:20 -0700989 if (exec->hadException())
990 return jsUndefined();
991 int delay = args.at(1).toInt32(exec);
992 return jsNumber(exec, impl()->setInterval(action, delay));
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800993}
994
Feng Qian5f1ab042009-06-17 12:12:20 -0700995JSValue JSDOMWindow::atob(ExecState* exec, const ArgList& args)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -0800996{
997 if (args.size() < 1)
998 return throwError(exec, SyntaxError, "Not enough arguments");
999
Feng Qian5f1ab042009-06-17 12:12:20 -07001000 JSValue v = args.at(0);
The Android Open Source Project63586082009-03-05 14:34:32 -08001001 if (v.isNull())
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001002 return jsEmptyString(exec);
1003
The Android Open Source Project63586082009-03-05 14:34:32 -08001004 UString s = v.toString(exec);
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001005 if (!s.is8Bit()) {
1006 setDOMException(exec, INVALID_CHARACTER_ERR);
1007 return jsUndefined();
1008 }
1009
1010 Vector<char> in(s.size());
1011 for (int i = 0; i < s.size(); ++i)
1012 in[i] = static_cast<char>(s.data()[i]);
1013 Vector<char> out;
1014
1015 if (!base64Decode(in, out))
1016 return throwError(exec, GeneralError, "Cannot decode base64");
1017
1018 return jsString(exec, String(out.data(), out.size()));
1019}
1020
Feng Qian5f1ab042009-06-17 12:12:20 -07001021JSValue JSDOMWindow::btoa(ExecState* exec, const ArgList& args)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001022{
1023 if (args.size() < 1)
1024 return throwError(exec, SyntaxError, "Not enough arguments");
1025
Feng Qian5f1ab042009-06-17 12:12:20 -07001026 JSValue v = args.at(0);
The Android Open Source Project63586082009-03-05 14:34:32 -08001027 if (v.isNull())
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001028 return jsEmptyString(exec);
1029
The Android Open Source Project63586082009-03-05 14:34:32 -08001030 UString s = v.toString(exec);
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001031 if (!s.is8Bit()) {
1032 setDOMException(exec, INVALID_CHARACTER_ERR);
1033 return jsUndefined();
1034 }
1035
1036 Vector<char> in(s.size());
1037 for (int i = 0; i < s.size(); ++i)
1038 in[i] = static_cast<char>(s.data()[i]);
1039 Vector<char> out;
1040
1041 base64Encode(in, out);
1042
1043 return jsString(exec, String(out.data(), out.size()));
1044}
1045
Feng Qian5f1ab042009-06-17 12:12:20 -07001046JSValue JSDOMWindow::addEventListener(ExecState* exec, const ArgList& args)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001047{
1048 Frame* frame = impl()->frame();
1049 if (!frame)
1050 return jsUndefined();
1051
Steve Block231d4e32009-10-08 17:19:54 +01001052 JSValue listener = args.at(1);
1053 if (!listener.isObject())
1054 return jsUndefined();
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001055
Steve Blockcac0f672009-11-05 09:23:40 +00001056 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001057 return jsUndefined();
1058}
1059
Feng Qian5f1ab042009-06-17 12:12:20 -07001060JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001061{
1062 Frame* frame = impl()->frame();
1063 if (!frame)
1064 return jsUndefined();
1065
Steve Block231d4e32009-10-08 17:19:54 +01001066 JSValue listener = args.at(1);
1067 if (!listener.isObject())
1068 return jsUndefined();
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001069
Steve Blockcac0f672009-11-05 09:23:40 +00001070 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001071 return jsUndefined();
1072}
1073
Feng Qian5f1ab042009-06-17 12:12:20 -07001074DOMWindow* toDOMWindow(JSValue value)
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001075{
The Android Open Source Project63586082009-03-05 14:34:32 -08001076 if (!value.isObject())
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001077 return 0;
1078 JSObject* object = asObject(value);
1079 if (object->inherits(&JSDOMWindow::s_info))
1080 return static_cast<JSDOMWindow*>(object)->impl();
1081 if (object->inherits(&JSDOMWindowShell::s_info))
1082 return static_cast<JSDOMWindowShell*>(object)->impl();
1083 return 0;
1084}
1085
The Android Open Source Project8e35f3c2009-03-03 19:30:52 -08001086} // namespace WebCore