initial import
[vuplus_webkit] / Source / WebCore / bindings / js / JSLocationCustom.cpp
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 "JSLocationCustom.h"
25
26 #include "Location.h"
27 #include <runtime/JSFunction.h>
28
29 using namespace JSC;
30
31 namespace WebCore {
32
33 static JSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
34 {
35     return JSFunction::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->functionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace);
36 }
37
38 static JSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
39 {
40     return JSFunction::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->functionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload);
41 }
42
43 static JSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
44 {
45     return JSFunction::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->functionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign);
46 }
47
48 bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
49 {
50     Frame* frame = impl()->frame();
51     if (!frame) {
52         slot.setUndefined();
53         return true;
54     }
55
56     // When accessing Location cross-domain, functions are always the native built-in ones.
57     // See JSDOMWindow::getOwnPropertySlotDelegate for additional details.
58
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.
61     String message;
62     if (allowsAccessFromFrame(exec, frame, message))
63         return false;
64
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);
70             return true;
71         } else if (entry->function() == jsLocationPrototypeFunctionReload) {
72             slot.setCustom(this, nonCachingStaticReloadFunctionGetter);
73             return true;
74         } else if (entry->function() == jsLocationPrototypeFunctionAssign) {
75             slot.setCustom(this, nonCachingStaticAssignFunctionGetter);
76             return true;
77         }
78     }
79
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.
83
84     printErrorMessageForFrame(frame, message);
85     slot.setUndefined();
86     return true;
87 }
88
89 bool JSLocation::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
90 {
91     Frame* frame = impl()->frame();
92     if (!frame) {
93         descriptor.setUndefined();
94         return true;
95     }
96     
97     // throw out all cross domain access
98     if (!allowsAccessFromFrame(exec, frame))
99         return true;
100     
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);
103     PropertySlot slot;
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());
108             return true;
109         } else if (entry->function() == jsLocationPrototypeFunctionReload) {
110             slot.setCustom(this, nonCachingStaticReloadFunctionGetter);
111             descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
112             return true;
113         } else if (entry->function() == jsLocationPrototypeFunctionAssign) {
114             slot.setCustom(this, nonCachingStaticAssignFunctionGetter);
115             descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
116             return true;
117         }
118     }
119     
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.
123
124     descriptor.setUndefined();
125     return true;
126 }
127
128 bool JSLocation::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
129 {
130     Frame* frame = impl()->frame();
131     if (!frame)
132         return true;
133
134     if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
135         return true;
136
137     bool sameDomainAccess = allowsAccessFromFrame(exec, frame);
138
139     const HashEntry* entry = JSLocation::s_info.propHashTable(exec)->entry(exec, propertyName);
140     if (!entry) {
141         if (sameDomainAccess)
142             JSObject::put(exec, propertyName, value, slot);
143         return true;
144     }
145
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)
150         return true;
151
152     return false;
153 }
154
155 bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName)
156 {
157     // Only allow deleting by frames in the same origin.
158     if (!allowsAccessFromFrame(exec, impl()->frame()))
159         return false;
160     return Base::deleteProperty(exec, propertyName);
161 }
162
163 void JSLocation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
164 {
165     // Only allow the location object to enumerated by frames in the same origin.
166     if (!allowsAccessFromFrame(exec, impl()->frame()))
167         return;
168     Base::getOwnPropertyNames(exec, propertyNames, mode);
169 }
170
171 void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
172 {
173     if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
174         return;
175     Base::defineGetter(exec, propertyName, getterFunction, attributes);
176 }
177
178 void JSLocation::setHref(ExecState* exec, JSValue value)
179 {
180     UString href = value.toString(exec);
181     if (exec->hadException())
182         return;
183     impl()->setHref(ustringToString(href), activeDOMWindow(exec), firstDOMWindow(exec));
184 }
185
186 void JSLocation::setProtocol(ExecState* exec, JSValue value)
187 {
188     UString protocol = value.toString(exec);
189     if (exec->hadException())
190         return;
191     ExceptionCode ec = 0;
192     impl()->setProtocol(ustringToString(protocol), activeDOMWindow(exec), firstDOMWindow(exec), ec);
193     setDOMException(exec, ec);
194 }
195
196 void JSLocation::setHost(ExecState* exec, JSValue value)
197 {
198     UString host = value.toString(exec);
199     if (exec->hadException())
200         return;
201     impl()->setHost(ustringToString(host), activeDOMWindow(exec), firstDOMWindow(exec));
202 }
203
204 void JSLocation::setHostname(ExecState* exec, JSValue value)
205 {
206     UString hostname = value.toString(exec);
207     if (exec->hadException())
208         return;
209     impl()->setHostname(ustringToString(hostname), activeDOMWindow(exec), firstDOMWindow(exec));
210 }
211
212 void JSLocation::setPort(ExecState* exec, JSValue value)
213 {
214     UString port = value.toString(exec);
215     if (exec->hadException())
216         return;
217     impl()->setPort(ustringToString(port), activeDOMWindow(exec), firstDOMWindow(exec));
218 }
219
220 void JSLocation::setPathname(ExecState* exec, JSValue value)
221 {
222     UString pathname = value.toString(exec);
223     if (exec->hadException())
224         return;
225     impl()->setPathname(ustringToString(pathname), activeDOMWindow(exec), firstDOMWindow(exec));
226 }
227
228 void JSLocation::setSearch(ExecState* exec, JSValue value)
229 {
230     UString pathname = value.toString(exec);
231     if (exec->hadException())
232         return;
233     impl()->setSearch(ustringToString(pathname), activeDOMWindow(exec), firstDOMWindow(exec));
234 }
235
236 void JSLocation::setHash(ExecState* exec, JSValue value)
237 {
238     UString hash = value.toString(exec);
239     if (exec->hadException())
240         return;
241     impl()->setHash(ustringToString(hash), activeDOMWindow(exec), firstDOMWindow(exec));
242 }
243
244 JSValue JSLocation::replace(ExecState* exec)
245 {
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();
251 }
252
253 JSValue JSLocation::reload(ExecState* exec)
254 {
255     impl()->reload(activeDOMWindow(exec));
256     return jsUndefined();
257 }
258
259 JSValue JSLocation::assign(ExecState* exec)
260 {
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();
266 }
267
268 JSValue JSLocation::toStringFunction(ExecState* exec)
269 {
270     Frame* frame = impl()->frame();
271     if (!frame || !allowsAccessFromFrame(exec, frame))
272         return jsUndefined();
273
274     return jsString(exec, impl()->toString());
275 }
276
277 bool JSLocationPrototype::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&)
278 {
279     return (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf);
280 }
281
282 void JSLocationPrototype::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
283 {
284     if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
285         return;
286     Base::defineGetter(exec, propertyName, getterFunction, attributes);
287 }
288
289 } // namespace WebCore