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)
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.
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.
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
24 #include "JSLocationCustom.h"
27 #include <runtime/JSFunction.h>
33 static JSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
35 return JSFunction::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->functionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace);
38 static JSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
40 return JSFunction::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->functionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload);
43 static JSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
45 return JSFunction::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->functionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign);
48 bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
50 Frame* frame = impl()->frame();
56 // When accessing Location cross-domain, functions are always the native built-in ones.
57 // See JSDOMWindow::getOwnPropertySlotDelegate for additional details.
59 // Our custom code is only needed to implement the Window cross-domain scheme, so if access is
60 // allowed, return false so the normal lookup will take place.
62 if (allowsAccessFromFrame(exec, frame, message))
65 // Check for the few functions that we allow, even when called cross-domain.
66 const HashEntry* entry = JSLocationPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
67 if (entry && (entry->attributes() & Function)) {
68 if (entry->function() == jsLocationPrototypeFunctionReplace) {
69 slot.setCustom(this, nonCachingStaticReplaceFunctionGetter);
71 } else if (entry->function() == jsLocationPrototypeFunctionReload) {
72 slot.setCustom(this, nonCachingStaticReloadFunctionGetter);
74 } else if (entry->function() == jsLocationPrototypeFunctionAssign) {
75 slot.setCustom(this, nonCachingStaticAssignFunctionGetter);
80 // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString,
81 // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in
82 // such cases when normally the string form of Location would be the URL.
84 printErrorMessageForFrame(frame, message);
89 bool JSLocation::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
91 Frame* frame = impl()->frame();
93 descriptor.setUndefined();
97 // throw out all cross domain access
98 if (!allowsAccessFromFrame(exec, frame))
101 // Check for the few functions that we allow, even when called cross-domain.
102 const HashEntry* entry = JSLocationPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
104 if (entry && (entry->attributes() & Function)) {
105 if (entry->function() == jsLocationPrototypeFunctionReplace) {
106 slot.setCustom(this, nonCachingStaticReplaceFunctionGetter);
107 descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
109 } else if (entry->function() == jsLocationPrototypeFunctionReload) {
110 slot.setCustom(this, nonCachingStaticReloadFunctionGetter);
111 descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
113 } else if (entry->function() == jsLocationPrototypeFunctionAssign) {
114 slot.setCustom(this, nonCachingStaticAssignFunctionGetter);
115 descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
120 // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString,
121 // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in
122 // such cases when normally the string form of Location would be the URL.
124 descriptor.setUndefined();
128 bool JSLocation::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
130 Frame* frame = impl()->frame();
134 if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
137 bool sameDomainAccess = allowsAccessFromFrame(exec, frame);
139 const HashEntry* entry = JSLocation::s_info.propHashTable(exec)->entry(exec, propertyName);
141 if (sameDomainAccess)
142 JSObject::put(exec, propertyName, value, slot);
146 // Cross-domain access to the location is allowed when assigning the whole location,
147 // but not when assigning the individual pieces, since that might inadvertently
148 // disclose other parts of the original location.
149 if (entry->propertyPutter() != setJSLocationHref && !sameDomainAccess)
155 bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName)
157 // Only allow deleting by frames in the same origin.
158 if (!allowsAccessFromFrame(exec, impl()->frame()))
160 return Base::deleteProperty(exec, propertyName);
163 void JSLocation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
165 // Only allow the location object to enumerated by frames in the same origin.
166 if (!allowsAccessFromFrame(exec, impl()->frame()))
168 Base::getOwnPropertyNames(exec, propertyNames, mode);
171 void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
173 if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
175 Base::defineGetter(exec, propertyName, getterFunction, attributes);
178 void JSLocation::setHref(ExecState* exec, JSValue value)
180 UString href = value.toString(exec);
181 if (exec->hadException())
183 impl()->setHref(ustringToString(href), activeDOMWindow(exec), firstDOMWindow(exec));
186 void JSLocation::setProtocol(ExecState* exec, JSValue value)
188 UString protocol = value.toString(exec);
189 if (exec->hadException())
191 ExceptionCode ec = 0;
192 impl()->setProtocol(ustringToString(protocol), activeDOMWindow(exec), firstDOMWindow(exec), ec);
193 setDOMException(exec, ec);
196 void JSLocation::setHost(ExecState* exec, JSValue value)
198 UString host = value.toString(exec);
199 if (exec->hadException())
201 impl()->setHost(ustringToString(host), activeDOMWindow(exec), firstDOMWindow(exec));
204 void JSLocation::setHostname(ExecState* exec, JSValue value)
206 UString hostname = value.toString(exec);
207 if (exec->hadException())
209 impl()->setHostname(ustringToString(hostname), activeDOMWindow(exec), firstDOMWindow(exec));
212 void JSLocation::setPort(ExecState* exec, JSValue value)
214 UString port = value.toString(exec);
215 if (exec->hadException())
217 impl()->setPort(ustringToString(port), activeDOMWindow(exec), firstDOMWindow(exec));
220 void JSLocation::setPathname(ExecState* exec, JSValue value)
222 UString pathname = value.toString(exec);
223 if (exec->hadException())
225 impl()->setPathname(ustringToString(pathname), activeDOMWindow(exec), firstDOMWindow(exec));
228 void JSLocation::setSearch(ExecState* exec, JSValue value)
230 UString pathname = value.toString(exec);
231 if (exec->hadException())
233 impl()->setSearch(ustringToString(pathname), activeDOMWindow(exec), firstDOMWindow(exec));
236 void JSLocation::setHash(ExecState* exec, JSValue value)
238 UString hash = value.toString(exec);
239 if (exec->hadException())
241 impl()->setHash(ustringToString(hash), activeDOMWindow(exec), firstDOMWindow(exec));
244 JSValue JSLocation::replace(ExecState* exec)
246 UString urlString = exec->argument(0).toString(exec);
247 if (exec->hadException())
248 return jsUndefined();
249 impl()->replace(ustringToString(urlString), activeDOMWindow(exec), firstDOMWindow(exec));
250 return jsUndefined();
253 JSValue JSLocation::reload(ExecState* exec)
255 impl()->reload(activeDOMWindow(exec));
256 return jsUndefined();
259 JSValue JSLocation::assign(ExecState* exec)
261 UString urlString = exec->argument(0).toString(exec);
262 if (exec->hadException())
263 return jsUndefined();
264 impl()->assign(ustringToString(urlString), activeDOMWindow(exec), firstDOMWindow(exec));
265 return jsUndefined();
268 JSValue JSLocation::toStringFunction(ExecState* exec)
270 Frame* frame = impl()->frame();
271 if (!frame || !allowsAccessFromFrame(exec, frame))
272 return jsUndefined();
274 return jsString(exec, impl()->toString());
277 bool JSLocationPrototype::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&)
279 return (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf);
282 void JSLocationPrototype::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
284 if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
286 Base::defineGetter(exec, propertyName, getterFunction, attributes);
289 } // namespace WebCore