1/* 2 * Copyright (C) 2000 Harri Porten (porten@kde.org) 3 * Copyright (C) 2006 Jon Shier (jshier@iastate.edu) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reseved. 5 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 20 * USA 21 */ 22 23#include "config.h" 24#include "JSLocation.h" 25 26#include "JSDOMBinding.h" 27#include <runtime/JSFunction.h> 28 29using namespace JSC; 30 31namespace WebCore { 32 33bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot) 34{ 35 Frame* frame = impl().frame(); 36 if (!frame) { 37 slot.setUndefined(); 38 return true; 39 } 40 41 // When accessing Location cross-domain, functions are always the native built-in ones. 42 // See JSDOMWindow::getOwnPropertySlotDelegate for additional details. 43 44 // Our custom code is only needed to implement the Window cross-domain scheme, so if access is 45 // allowed, return false so the normal lookup will take place. 46 String message; 47 if (shouldAllowAccessToFrame(exec, frame, message)) 48 return false; 49 50 // Check for the few functions that we allow, even when called cross-domain. 51 // Make these read-only / non-configurable to prevent writes via defineProperty. 52 if (propertyName == exec->propertyNames().replace) { 53 slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsLocationPrototypeFunctionReplace, 1>); 54 return true; 55 } 56 if (propertyName == exec->propertyNames().reload) { 57 slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsLocationPrototypeFunctionReload, 0>); 58 return true; 59 } 60 if (propertyName == exec->propertyNames().assign) { 61 slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsLocationPrototypeFunctionAssign, 1>); 62 return true; 63 } 64 65 // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString, 66 // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in 67 // such cases when normally the string form of Location would be the URL. 68 69 printErrorMessageForFrame(frame, message); 70 slot.setUndefined(); 71 return true; 72} 73 74bool JSLocation::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) 75{ 76 Frame* frame = impl().frame(); 77 if (!frame) 78 return true; 79 80 if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf) 81 return true; 82 83 bool sameDomainAccess = shouldAllowAccessToFrame(exec, frame); 84 85 const HashTableValue* entry = JSLocation::info()->propHashTable(exec)->entry(exec, propertyName); 86 if (!entry) { 87 if (sameDomainAccess) 88 JSObject::put(this, exec, propertyName, value, slot); 89 return true; 90 } 91 92 // Cross-domain access to the location is allowed when assigning the whole location, 93 // but not when assigning the individual pieces, since that might inadvertently 94 // disclose other parts of the original location. 95 if (propertyName != exec->propertyNames().href && !sameDomainAccess) 96 return true; 97 98 return false; 99} 100 101bool JSLocation::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) 102{ 103 JSLocation* thisObject = jsCast<JSLocation*>(cell); 104 // Only allow deleting by frames in the same origin. 105 if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) 106 return false; 107 return Base::deleteProperty(thisObject, exec, propertyName); 108} 109 110bool JSLocation::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) 111{ 112 JSLocation* thisObject = jsCast<JSLocation*>(cell); 113 // Only allow deleting by frames in the same origin. 114 if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) 115 return false; 116 return Base::deletePropertyByIndex(thisObject, exec, propertyName); 117} 118 119void JSLocation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) 120{ 121 JSLocation* thisObject = jsCast<JSLocation*>(object); 122 // Only allow the location object to enumerated by frames in the same origin. 123 if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) 124 return; 125 Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); 126} 127 128bool JSLocation::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException) 129{ 130 if (descriptor.isAccessorDescriptor() && (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)) 131 return false; 132 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); 133} 134 135void JSLocation::setHref(ExecState* exec, JSValue value) 136{ 137 String href = value.toString(exec)->value(exec); 138 if (exec->hadException()) 139 return; 140 impl().setHref(href, activeDOMWindow(exec), firstDOMWindow(exec)); 141} 142 143void JSLocation::setProtocol(ExecState* exec, JSValue value) 144{ 145 String protocol = value.toString(exec)->value(exec); 146 if (exec->hadException()) 147 return; 148 ExceptionCode ec = 0; 149 impl().setProtocol(protocol, activeDOMWindow(exec), firstDOMWindow(exec), ec); 150 setDOMException(exec, ec); 151} 152 153void JSLocation::setHost(ExecState* exec, JSValue value) 154{ 155 String host = value.toString(exec)->value(exec); 156 if (exec->hadException()) 157 return; 158 impl().setHost(host, activeDOMWindow(exec), firstDOMWindow(exec)); 159} 160 161void JSLocation::setHostname(ExecState* exec, JSValue value) 162{ 163 String hostname = value.toString(exec)->value(exec); 164 if (exec->hadException()) 165 return; 166 impl().setHostname(hostname, activeDOMWindow(exec), firstDOMWindow(exec)); 167} 168 169void JSLocation::setPort(ExecState* exec, JSValue value) 170{ 171 String port = value.toWTFString(exec); 172 if (exec->hadException()) 173 return; 174 impl().setPort(port, activeDOMWindow(exec), firstDOMWindow(exec)); 175} 176 177void JSLocation::setPathname(ExecState* exec, JSValue value) 178{ 179 String pathname = value.toString(exec)->value(exec); 180 if (exec->hadException()) 181 return; 182 impl().setPathname(pathname, activeDOMWindow(exec), firstDOMWindow(exec)); 183} 184 185void JSLocation::setSearch(ExecState* exec, JSValue value) 186{ 187 String pathname = value.toString(exec)->value(exec); 188 if (exec->hadException()) 189 return; 190 impl().setSearch(pathname, activeDOMWindow(exec), firstDOMWindow(exec)); 191} 192 193void JSLocation::setHash(ExecState* exec, JSValue value) 194{ 195 String hash = value.toString(exec)->value(exec); 196 if (exec->hadException()) 197 return; 198 impl().setHash(hash, activeDOMWindow(exec), firstDOMWindow(exec)); 199} 200 201JSValue JSLocation::replace(ExecState* exec) 202{ 203 String urlString = exec->argument(0).toString(exec)->value(exec); 204 if (exec->hadException()) 205 return jsUndefined(); 206 impl().replace(urlString, activeDOMWindow(exec), firstDOMWindow(exec)); 207 return jsUndefined(); 208} 209 210JSValue JSLocation::reload(ExecState* exec) 211{ 212 impl().reload(activeDOMWindow(exec)); 213 return jsUndefined(); 214} 215 216JSValue JSLocation::assign(ExecState* exec) 217{ 218 String urlString = exec->argument(0).toString(exec)->value(exec); 219 if (exec->hadException()) 220 return jsUndefined(); 221 impl().assign(urlString, activeDOMWindow(exec), firstDOMWindow(exec)); 222 return jsUndefined(); 223} 224 225JSValue JSLocation::toStringFunction(ExecState* exec) 226{ 227 Frame* frame = impl().frame(); 228 if (!frame || !shouldAllowAccessToFrame(exec, frame)) 229 return jsUndefined(); 230 231 return jsStringWithCache(exec, impl().toString()); 232} 233 234bool JSLocationPrototype::putDelegate(ExecState* exec, PropertyName propertyName, JSValue, PutPropertySlot&) 235{ 236 return (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf); 237} 238 239bool JSLocationPrototype::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException) 240{ 241 if (descriptor.isAccessorDescriptor() && (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)) 242 return false; 243 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); 244} 245 246} // namespace WebCore 247