The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1 | /* |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 2 | * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 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 "AtomicString.h" |
| 24 | #include "Base64.h" |
| 25 | #include "DOMWindow.h" |
| 26 | #include "Document.h" |
| 27 | #include "ExceptionCode.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 28 | #include "FloatRect.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 29 | #include "Frame.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 30 | #include "FrameLoadRequest.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 31 | #include "FrameLoader.h" |
| 32 | #include "FrameTree.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 33 | #include "FrameView.h" |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 34 | #include "HTMLCollection.h" |
| 35 | #include "HTMLDocument.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 36 | #include "History.h" |
| 37 | #include "JSAudioConstructor.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 38 | #include "JSDOMWindowShell.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 39 | #include "JSEvent.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 40 | #include "JSEventListener.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 41 | #include "JSEventSourceConstructor.h" |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 42 | #include "JSHTMLCollection.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 43 | #include "JSHistory.h" |
| 44 | #include "JSImageConstructor.h" |
| 45 | #include "JSLocation.h" |
| 46 | #include "JSMessageChannelConstructor.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 47 | #include "JSMessagePort.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 48 | #include "JSMessagePortCustom.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 49 | #include "JSOptionConstructor.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 50 | |
| 51 | #if ENABLE(SHARED_WORKERS) |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 52 | #include "JSSharedWorkerConstructor.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 53 | #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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 65 | #include "JSWebKitCSSMatrixConstructor.h" |
| 66 | #include "JSWebKitPointConstructor.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 67 | #if ENABLE(WEB_SOCKETS) |
| 68 | #include "JSWebSocketConstructor.h" |
| 69 | #endif |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 70 | #include "JSWorkerConstructor.h" |
| 71 | #include "JSXMLHttpRequestConstructor.h" |
| 72 | #include "JSXSLTProcessorConstructor.h" |
| 73 | #include "Location.h" |
| 74 | #include "MediaPlayer.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 75 | #include "MessagePort.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 76 | #include "NotificationCenter.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 77 | #include "Page.h" |
| 78 | #include "PlatformScreen.h" |
| 79 | #include "RegisteredEventListener.h" |
| 80 | #include "ScheduledAction.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 81 | #include "ScriptController.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 82 | #include "SerializedScriptValue.h" |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 83 | #include "Settings.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 84 | #include "SharedWorkerRepository.h" |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 85 | #include "WindowFeatures.h" |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 86 | #include <runtime/Error.h> |
| 87 | #include <runtime/JSFunction.h> |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 88 | #include <runtime/JSObject.h> |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 89 | #include <runtime/PrototypeFunction.h> |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 90 | |
| 91 | using namespace JSC; |
| 92 | |
| 93 | namespace WebCore { |
| 94 | |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 95 | void JSDOMWindow::markChildren(MarkStack& markStack) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 96 | { |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 97 | Base::markChildren(markStack); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 98 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 99 | impl()->markEventListeners(markStack); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 100 | |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 101 | JSGlobalData& globalData = *Heap::heap(this)->globalData(); |
| 102 | |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 103 | 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 Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 115 | #if ENABLE(DOM_STORAGE) |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 116 | markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage()); |
| 117 | markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage()); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 118 | #endif |
| 119 | #if ENABLE(OFFLINE_WEB_APPLICATIONS) |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 120 | markDOMObjectWrapper(markStack, globalData, impl()->optionalApplicationCache()); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 121 | #endif |
| 122 | } |
| 123 | |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 124 | template<NativeFunction nativeFunction, int length> |
| 125 | JSValue nonCachingStaticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) |
| 126 | { |
| 127 | return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction); |
| 128 | } |
| 129 | |
| 130 | static 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 | |
| 135 | static 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 | |
| 140 | static 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 | |
| 155 | bool 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 Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 298 | bool 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 Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 442 | void 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 Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 461 | bool 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 Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 469 | void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 470 | { |
| 471 | // Only allow the window to enumerated by frames in the same origin. |
| 472 | if (!allowsAccessFrom(exec)) |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 473 | return; |
| 474 | Base::getPropertyNames(exec, propertyNames); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 475 | } |
| 476 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 477 | void 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 Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 485 | bool JSDOMWindow::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 486 | { |
| 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 Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 493 | void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 494 | { |
| 495 | // Only allow defining getters by frames in the same origin. |
| 496 | if (!allowsAccessFrom(exec)) |
| 497 | return; |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 498 | |
| 499 | // Don't allow shadowing location using defineGetter. |
| 500 | if (propertyName == "location") |
| 501 | return; |
| 502 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 503 | Base::defineGetter(exec, propertyName, getterFunction, attributes); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 504 | } |
| 505 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 506 | void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 507 | { |
| 508 | // Only allow defining setters by frames in the same origin. |
| 509 | if (!allowsAccessFrom(exec)) |
| 510 | return; |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 511 | Base::defineSetter(exec, propertyName, setterFunction, attributes); |
| 512 | } |
| 513 | |
| 514 | bool 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 Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 520 | } |
| 521 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 522 | JSValue JSDOMWindow::lookupGetter(ExecState* exec, const Identifier& propertyName) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 523 | { |
| 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 530 | JSValue JSDOMWindow::lookupSetter(ExecState* exec, const Identifier& propertyName) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 531 | { |
| 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 538 | // Custom Attributes |
| 539 | |
| 540 | JSValue JSDOMWindow::history(ExecState* exec) const |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 541 | { |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 542 | History* history = impl()->history(); |
| 543 | if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), history)) |
| 544 | return wrapper; |
| 545 | |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 546 | JSDOMWindow* window = const_cast<JSDOMWindow*>(this); |
| 547 | JSHistory* jsHistory = new (exec) JSHistory(getDOMStructure<JSHistory>(exec, window), window, history); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 548 | cacheDOMObjectWrapper(exec->globalData(), history, jsHistory); |
| 549 | return jsHistory; |
| 550 | } |
| 551 | |
| 552 | JSValue JSDOMWindow::location(ExecState* exec) const |
| 553 | { |
| 554 | Location* location = impl()->location(); |
| 555 | if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), location)) |
| 556 | return wrapper; |
| 557 | |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 558 | JSDOMWindow* window = const_cast<JSDOMWindow*>(this); |
| 559 | JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, window), window, location); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 560 | cacheDOMObjectWrapper(exec->globalData(), location, jsLocation); |
| 561 | return jsLocation; |
| 562 | } |
| 563 | |
| 564 | void JSDOMWindow::setLocation(ExecState* exec, JSValue value) |
| 565 | { |
| 566 | Frame* lexicalFrame = toLexicalFrame(exec); |
| 567 | if (!lexicalFrame) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 568 | 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 573 | if (Settings* settings = lexicalFrame->settings()) { |
| 574 | if (settings->usesDashboardBackwardCompatibilityMode() && !lexicalFrame->tree()->parent()) { |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 575 | if (allowsAccessFrom(exec)) |
| 576 | putDirect(Identifier(exec, "location"), value); |
| 577 | return; |
| 578 | } |
| 579 | } |
| 580 | #endif |
| 581 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 582 | Frame* frame = impl()->frame(); |
| 583 | ASSERT(frame); |
| 584 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 585 | KURL url = completeURL(exec, value.toString(exec)); |
| 586 | if (url.isNull()) |
| 587 | return; |
| 588 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 589 | if (!shouldAllowNavigation(exec, frame)) |
| 590 | return; |
| 591 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 592 | if (!protocolIsJavaScript(url) || allowsAccessFrom(exec)) { |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 593 | // We want a new history item if this JS was called via a user gesture |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 594 | frame->redirectScheduler()->scheduleLocationChange(url, lexicalFrame->loader()->outgoingReferrer(), !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, processingUserGesture(exec)); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 595 | } |
| 596 | } |
| 597 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 598 | JSValue JSDOMWindow::crypto(ExecState*) const |
| 599 | { |
| 600 | return jsUndefined(); |
| 601 | } |
| 602 | |
| 603 | JSValue JSDOMWindow::event(ExecState* exec) const |
| 604 | { |
| 605 | Event* event = currentEvent(); |
| 606 | if (!event) |
| 607 | return jsUndefined(); |
| 608 | return toJS(exec, event); |
| 609 | } |
| 610 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 611 | #if ENABLE(EVENTSOURCE) |
| 612 | JSValue JSDOMWindow::eventSource(ExecState* exec) const |
| 613 | { |
| 614 | return getDOMConstructor<JSEventSourceConstructor>(exec, this); |
| 615 | } |
| 616 | #endif |
| 617 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 618 | JSValue JSDOMWindow::image(ExecState* exec) const |
| 619 | { |
| 620 | return getDOMConstructor<JSImageConstructor>(exec, this); |
| 621 | } |
| 622 | |
| 623 | JSValue JSDOMWindow::option(ExecState* exec) const |
| 624 | { |
| 625 | return getDOMConstructor<JSOptionConstructor>(exec, this); |
| 626 | } |
| 627 | |
| 628 | #if ENABLE(VIDEO) |
| 629 | JSValue JSDOMWindow::audio(ExecState* exec) const |
| 630 | { |
| 631 | if (!MediaPlayer::isAvailable()) |
| 632 | return jsUndefined(); |
| 633 | return getDOMConstructor<JSAudioConstructor>(exec, this); |
| 634 | } |
| 635 | #endif |
| 636 | |
| 637 | JSValue JSDOMWindow::webKitPoint(ExecState* exec) const |
| 638 | { |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 639 | return getDOMConstructor<JSWebKitPointConstructor>(exec, this); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 640 | } |
| 641 | |
| 642 | JSValue JSDOMWindow::webKitCSSMatrix(ExecState* exec) const |
| 643 | { |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 644 | return getDOMConstructor<JSWebKitCSSMatrixConstructor>(exec, this); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 645 | } |
| 646 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 647 | #if ENABLE(3D_CANVAS) |
| 648 | JSValue JSDOMWindow::canvasArrayBuffer(ExecState* exec) const |
| 649 | { |
| 650 | return getDOMConstructor<JSCanvasArrayBufferConstructor>(exec, this); |
| 651 | } |
| 652 | |
| 653 | JSValue JSDOMWindow::canvasByteArray(ExecState* exec) const |
| 654 | { |
| 655 | return getDOMConstructor<JSCanvasByteArrayConstructor>(exec, this); |
| 656 | } |
| 657 | |
| 658 | JSValue JSDOMWindow::canvasUnsignedByteArray(ExecState* exec) const |
| 659 | { |
| 660 | return getDOMConstructor<JSCanvasUnsignedByteArrayConstructor>(exec, this); |
| 661 | } |
| 662 | |
| 663 | JSValue JSDOMWindow::canvasIntArray(ExecState* exec) const |
| 664 | { |
| 665 | return getDOMConstructor<JSCanvasIntArrayConstructor>(exec, this); |
| 666 | } |
| 667 | |
| 668 | JSValue JSDOMWindow::canvasUnsignedIntArray(ExecState* exec) const |
| 669 | { |
| 670 | return getDOMConstructor<JSCanvasUnsignedIntArrayConstructor>(exec, this); |
| 671 | } |
| 672 | |
| 673 | JSValue JSDOMWindow::canvasShortArray(ExecState* exec) const |
| 674 | { |
| 675 | return getDOMConstructor<JSCanvasShortArrayConstructor>(exec, this); |
| 676 | } |
| 677 | |
| 678 | JSValue JSDOMWindow::canvasUnsignedShortArray(ExecState* exec) const |
| 679 | { |
| 680 | return getDOMConstructor<JSCanvasUnsignedShortArrayConstructor>(exec, this); |
| 681 | } |
| 682 | |
| 683 | JSValue JSDOMWindow::canvasFloatArray(ExecState* exec) const |
| 684 | { |
| 685 | return getDOMConstructor<JSCanvasFloatArrayConstructor>(exec, this); |
| 686 | } |
| 687 | #endif |
| 688 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 689 | JSValue JSDOMWindow::xmlHttpRequest(ExecState* exec) const |
| 690 | { |
| 691 | return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this); |
| 692 | } |
| 693 | |
| 694 | #if ENABLE(XSLT) |
| 695 | JSValue JSDOMWindow::xsltProcessor(ExecState* exec) const |
| 696 | { |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 697 | return getDOMConstructor<JSXSLTProcessorConstructor>(exec, this); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 698 | } |
| 699 | #endif |
| 700 | |
| 701 | #if ENABLE(CHANNEL_MESSAGING) |
| 702 | JSValue JSDOMWindow::messageChannel(ExecState* exec) const |
| 703 | { |
| 704 | return getDOMConstructor<JSMessageChannelConstructor>(exec, this); |
| 705 | } |
| 706 | #endif |
| 707 | |
| 708 | #if ENABLE(WORKERS) |
| 709 | JSValue JSDOMWindow::worker(ExecState* exec) const |
| 710 | { |
Ben Murdoch | 0bf48ef | 2009-08-11 17:01:47 +0100 | [diff] [blame] | 711 | return getDOMConstructor<JSWorkerConstructor>(exec, this); |
| 712 | } |
| 713 | #endif |
| 714 | |
| 715 | #if ENABLE(SHARED_WORKERS) |
| 716 | JSValue JSDOMWindow::sharedWorker(ExecState* exec) const |
| 717 | { |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 718 | if (SharedWorkerRepository::isAvailable()) |
| 719 | return getDOMConstructor<JSSharedWorkerConstructor>(exec, this); |
| 720 | return jsUndefined(); |
| 721 | } |
| 722 | #endif |
| 723 | |
| 724 | #if ENABLE(WEB_SOCKETS) |
| 725 | JSValue 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 Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 733 | return getDOMConstructor<JSWebSocketConstructor>(exec, this); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 734 | } |
| 735 | #endif |
| 736 | |
| 737 | // Custom functions |
| 738 | |
| 739 | // Helper for window.open() and window.showModalDialog() |
| 740 | static 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 Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 772 | newFrame->page()->setOpenedByDOM(); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 773 | |
Steve Block | cac0f67 | 2009-11-05 09:23:40 +0000 | [diff] [blame] | 774 | // 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 776 | |
| 777 | if (dialogArgs) |
| 778 | newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs); |
| 779 | |
| 780 | if (!protocolIsJavaScript(url) || newWindow->allowsAccessFrom(exec)) { |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 781 | KURL completedURL = url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(exec, url); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 782 | bool userGesture = processingUserGesture(exec); |
| 783 | |
| 784 | if (created) |
| 785 | newFrame->loader()->changeLocation(completedURL, referrer, false, false, userGesture); |
| 786 | else if (!url.isEmpty()) |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 787 | newFrame->redirectScheduler()->scheduleLocationChange(completedURL.string(), referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 788 | } |
| 789 | |
| 790 | return newFrame; |
| 791 | } |
| 792 | |
| 793 | JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args) |
| 794 | { |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 795 | 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 799 | 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 811 | // 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 828 | String completedURL; |
| 829 | if (!urlString.isEmpty()) |
| 830 | completedURL = completeURL(exec, urlString).string(); |
| 831 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 832 | if (!shouldAllowNavigation(exec, frame)) |
| 833 | return jsUndefined(); |
| 834 | |
Steve Block | cac0f67 | 2009-11-05 09:23:40 +0000 | [diff] [blame] | 835 | const JSDOMWindow* targetedWindow = toJSDOMWindow(frame, currentWorld(exec)); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 836 | 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 Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 844 | frame->redirectScheduler()->scheduleLocationChange(completedURL, referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 845 | } |
| 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 850 | 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 | |
| 867 | JSValue JSDOMWindow::showModalDialog(ExecState* exec, const ArgList& args) |
| 868 | { |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 869 | String url = valueToStringWithUndefinedOrNullCheck(exec, args.at(0)); |
| 870 | JSValue dialogArgs = args.at(1); |
| 871 | String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, args.at(2)); |
| 872 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 873 | 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 886 | 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 Block | cac0f67 | 2009-11-05 09:23:40 +0000 | [diff] [blame] | 936 | JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame, currentWorld(exec)); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 937 | dialogFrame->page()->chrome()->runModal(); |
| 938 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 939 | 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 948 | } |
| 949 | |
| 950 | JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 951 | { |
| 952 | DOMWindow* window = impl(); |
| 953 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 954 | DOMWindow* source = asJSDOMWindow(exec->lexicalGlobalObject())->impl(); |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 955 | PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, args.at(0)); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 956 | |
| 957 | if (exec->hadException()) |
| 958 | return jsUndefined(); |
| 959 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 960 | 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 Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 965 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 966 | String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, args.at((args.size() == 2) ? 1 : 2)); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 967 | if (exec->hadException()) |
| 968 | return jsUndefined(); |
| 969 | |
| 970 | ExceptionCode ec = 0; |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 971 | window->postMessage(message, &messagePorts, targetOrigin, source, ec); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 972 | setDOMException(exec, ec); |
| 973 | |
| 974 | return jsUndefined(); |
| 975 | } |
| 976 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 977 | JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 978 | { |
Steve Block | cac0f67 | 2009-11-05 09:23:40 +0000 | [diff] [blame] | 979 | ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 980 | if (exec->hadException()) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 981 | return jsUndefined(); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 982 | int delay = args.at(1).toInt32(exec); |
| 983 | return jsNumber(exec, impl()->setTimeout(action, delay)); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 984 | } |
| 985 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 986 | JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 987 | { |
Steve Block | cac0f67 | 2009-11-05 09:23:40 +0000 | [diff] [blame] | 988 | ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 989 | 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 Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 993 | } |
| 994 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 995 | JSValue JSDOMWindow::atob(ExecState* exec, const ArgList& args) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 996 | { |
| 997 | if (args.size() < 1) |
| 998 | return throwError(exec, SyntaxError, "Not enough arguments"); |
| 999 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 1000 | JSValue v = args.at(0); |
The Android Open Source Project | 6358608 | 2009-03-05 14:34:32 -0800 | [diff] [blame] | 1001 | if (v.isNull()) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1002 | return jsEmptyString(exec); |
| 1003 | |
The Android Open Source Project | 6358608 | 2009-03-05 14:34:32 -0800 | [diff] [blame] | 1004 | UString s = v.toString(exec); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1005 | 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 1021 | JSValue JSDOMWindow::btoa(ExecState* exec, const ArgList& args) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1022 | { |
| 1023 | if (args.size() < 1) |
| 1024 | return throwError(exec, SyntaxError, "Not enough arguments"); |
| 1025 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 1026 | JSValue v = args.at(0); |
The Android Open Source Project | 6358608 | 2009-03-05 14:34:32 -0800 | [diff] [blame] | 1027 | if (v.isNull()) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1028 | return jsEmptyString(exec); |
| 1029 | |
The Android Open Source Project | 6358608 | 2009-03-05 14:34:32 -0800 | [diff] [blame] | 1030 | UString s = v.toString(exec); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1031 | 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 Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 1046 | JSValue JSDOMWindow::addEventListener(ExecState* exec, const ArgList& args) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1047 | { |
| 1048 | Frame* frame = impl()->frame(); |
| 1049 | if (!frame) |
| 1050 | return jsUndefined(); |
| 1051 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 1052 | JSValue listener = args.at(1); |
| 1053 | if (!listener.isObject()) |
| 1054 | return jsUndefined(); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1055 | |
Steve Block | cac0f67 | 2009-11-05 09:23:40 +0000 | [diff] [blame] | 1056 | impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1057 | return jsUndefined(); |
| 1058 | } |
| 1059 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 1060 | JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1061 | { |
| 1062 | Frame* frame = impl()->frame(); |
| 1063 | if (!frame) |
| 1064 | return jsUndefined(); |
| 1065 | |
Steve Block | 231d4e3 | 2009-10-08 17:19:54 +0100 | [diff] [blame] | 1066 | JSValue listener = args.at(1); |
| 1067 | if (!listener.isObject()) |
| 1068 | return jsUndefined(); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1069 | |
Steve Block | cac0f67 | 2009-11-05 09:23:40 +0000 | [diff] [blame] | 1070 | impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1071 | return jsUndefined(); |
| 1072 | } |
| 1073 | |
Feng Qian | 5f1ab04 | 2009-06-17 12:12:20 -0700 | [diff] [blame] | 1074 | DOMWindow* toDOMWindow(JSValue value) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1075 | { |
The Android Open Source Project | 6358608 | 2009-03-05 14:34:32 -0800 | [diff] [blame] | 1076 | if (!value.isObject()) |
The Android Open Source Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1077 | 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 Project | 8e35f3c | 2009-03-03 19:30:52 -0800 | [diff] [blame] | 1086 | } // namespace WebCore |