tizen beta release
[framework/web/webkit-efl.git] / Source / WebCore / bindings / js / JSDOMBinding.cpp
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4  *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "config.h"
22 #include "JSDOMBinding.h"
23
24 #include "DOMObjectHashTableMap.h"
25 #include "ExceptionCode.h"
26 #include "ExceptionHeaders.h"
27 #include "ExceptionInterfaces.h"
28 #include "Frame.h"
29 #include "JSDOMWindowCustom.h"
30 #include "JSExceptionBase.h"
31 #if ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
32 #include "JSFileException.h"
33 #include "JSOperationNotAllowedException.h"
34 #endif
35 #if ENABLE(TIZEN_INDEXED_DATABASE)
36 #include "JSDOMStringList.h"
37 #include "JSIDBDatabaseException.h"
38 #endif
39 #include "JSRangeException.h"
40 #if ENABLE(SQL_DATABASE)
41 #include "JSSQLException.h"
42 #endif
43 #if ENABLE(SVG)
44 #include "JSSVGException.h"
45 #endif
46 #include "JSXMLHttpRequestException.h"
47 #if ENABLE(XPATH)
48 #include "JSXPathException.h"
49 #endif
50 #include "OperationNotAllowedException.h"
51 #include "RangeException.h"
52 #include "SQLException.h"
53 #include "SVGException.h"
54 #include "ScriptCallStack.h"
55 #include <runtime/DateInstance.h>
56 #include <runtime/Error.h>
57 #include <runtime/ExceptionHelpers.h>
58 #include <runtime/JSFunction.h>
59
60 using namespace JSC;
61
62 namespace WebCore {
63
64 const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable)
65 {
66     return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
67 }
68
69 JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl)
70 {
71     JSString* wrapper = jsString(exec, UString(stringImpl));
72     stringCache.add(stringImpl, Weak<JSString>(exec->globalData(), wrapper, currentWorld(exec)->stringWrapperOwner(), stringImpl));
73     return wrapper;
74 }
75
76 JSValue jsStringOrNull(ExecState* exec, const String& s)
77 {
78     if (s.isNull())
79         return jsNull();
80     return jsString(exec, s);
81 }
82
83 JSValue jsOwnedStringOrNull(ExecState* exec, const String& s)
84 {
85     if (s.isNull())
86         return jsNull();
87     return jsOwnedString(exec, stringToUString(s));
88 }
89
90 JSValue jsStringOrUndefined(ExecState* exec, const String& s)
91 {
92     if (s.isNull())
93         return jsUndefined();
94     return jsString(exec, s);
95 }
96
97 JSValue jsStringOrFalse(ExecState* exec, const String& s)
98 {
99     if (s.isNull())
100         return jsBoolean(false);
101     return jsString(exec, s);
102 }
103
104 JSValue jsString(ExecState* exec, const KURL& url)
105 {
106     return jsString(exec, url.string());
107 }
108
109 JSValue jsStringOrNull(ExecState* exec, const KURL& url)
110 {
111     if (url.isNull())
112         return jsNull();
113     return jsString(exec, url.string());
114 }
115
116 JSValue jsStringOrUndefined(ExecState* exec, const KURL& url)
117 {
118     if (url.isNull())
119         return jsUndefined();
120     return jsString(exec, url.string());
121 }
122
123 JSValue jsStringOrFalse(ExecState* exec, const KURL& url)
124 {
125     if (url.isNull())
126         return jsBoolean(false);
127     return jsString(exec, url.string());
128 }
129
130 AtomicStringImpl* findAtomicString(const Identifier& identifier)
131 {
132     if (identifier.isNull())
133         return 0;
134     StringImpl* impl = identifier.impl();
135     ASSERT(impl->existingHash());
136     return AtomicString::find(impl->characters(), impl->length(), impl->existingHash());
137 }
138
139 String valueToStringWithNullCheck(ExecState* exec, JSValue value)
140 {
141     if (value.isNull())
142         return String();
143     return ustringToString(value.toString(exec));
144 }
145
146 String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
147 {
148     if (value.isUndefinedOrNull())
149         return String();
150     return ustringToString(value.toString(exec));
151 }
152
153 JSValue jsDateOrNull(ExecState* exec, double value)
154 {
155     if (!isfinite(value))
156         return jsNull();
157     return DateInstance::create(exec, exec->lexicalGlobalObject()->dateStructure(), value);
158 }
159
160 double valueToDate(ExecState* exec, JSValue value)
161 {
162     if (value.isNumber())
163         return value.asNumber();
164     if (!value.inherits(&DateInstance::s_info))
165         return std::numeric_limits<double>::quiet_NaN();
166     return static_cast<DateInstance*>(value.toObject(exec))->internalNumber();
167 }
168
169 void reportException(ExecState* exec, JSValue exception)
170 {
171     if (isTerminatedExecutionException(exception))
172         return;
173
174     UString errorMessage = exception.toString(exec);
175     JSObject* exceptionObject = exception.toObject(exec);
176     int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec);
177     UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec);
178     exec->clearException();
179
180     if (ExceptionBase* exceptionBase = toExceptionBase(exception))
181         errorMessage = stringToUString(exceptionBase->message() + ": "  + exceptionBase->description());
182
183     ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();
184     ASSERT(scriptExecutionContext);
185
186     // Crash data indicates null-dereference crashes at this point in the Safari 4 Public Beta.
187     // It's harmless to return here without reporting the exception to the log and the debugger in this case.
188     if (!scriptExecutionContext)
189         return;
190
191     scriptExecutionContext->reportException(ustringToString(errorMessage), lineNumber, ustringToString(exceptionSourceURL), 0);
192 }
193
194 void reportCurrentException(ExecState* exec)
195 {
196     JSValue exception = exec->exception();
197     exec->clearException();
198     reportException(exec, exception);
199 }
200
201 #define TRY_TO_CREATE_EXCEPTION(interfaceName) \
202     case interfaceName##Type: \
203         errorObject = toJS(exec, globalObject, interfaceName::create(description)); \
204         break;
205
206 void setDOMException(ExecState* exec, ExceptionCode ec)
207 {
208     if (!ec || exec->hadException())
209         return;
210
211     // FIXME: All callers to setDOMException need to pass in the right global object
212     // for now, we're going to assume the lexicalGlobalObject.  Which is wrong in cases like this:
213     // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes.
214     JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec);
215
216     ExceptionCodeDescription description(ec);
217
218     JSValue errorObject;
219     switch (description.type) {
220         DOM_EXCEPTION_INTERFACES_FOR_EACH(TRY_TO_CREATE_EXCEPTION)
221     }
222
223     ASSERT(errorObject);
224     throwError(exec, errorObject);
225 }
226
227 #undef TRY_TO_CREATE_EXCEPTION
228
229 DOMWindow* activeDOMWindow(ExecState* exec)
230 {
231     return asJSDOMWindow(exec->lexicalGlobalObject())->impl();
232 }
233
234 DOMWindow* firstDOMWindow(ExecState* exec)
235 {
236     return asJSDOMWindow(exec->dynamicGlobalObject())->impl();
237 }
238
239 bool checkNodeSecurity(ExecState* exec, Node* node)
240 {
241     return node && allowsAccessFromFrame(exec, node->document()->frame());
242 }
243
244 bool allowsAccessFromFrame(ExecState* exec, Frame* frame)
245 {
246     if (!frame)
247         return false;
248     JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec));
249     return window && window->allowsAccessFrom(exec);
250 }
251
252 bool allowsAccessFromFrame(ExecState* exec, Frame* frame, String& message)
253 {
254     if (!frame)
255         return false;
256     JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec));
257     return window && window->allowsAccessFrom(exec, message);
258 }
259
260 void printErrorMessageForFrame(Frame* frame, const String& message)
261 {
262     if (!frame)
263         return;
264     frame->domWindow()->printErrorMessage(message);
265 }
266
267 // FIXME: We should remove or at least deprecate this function. Callers can use firstDOMWindow directly.
268 Frame* toDynamicFrame(ExecState* exec)
269 {
270     return firstDOMWindow(exec)->frame();
271 }
272
273 JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
274 {
275     return JSFunction::create(exec, exec->lexicalGlobalObject(), 0, propertyName, objectProtoFuncToString);
276 }
277
278 Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo)
279 {
280     JSDOMStructureMap& structures = globalObject->structures();
281     return structures.get(classInfo).get();
282 }
283
284 Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, Structure* structure, const ClassInfo* classInfo)
285 {
286     JSDOMStructureMap& structures = globalObject->structures();
287     ASSERT(!structures.contains(classInfo));
288     return structures.set(classInfo, WriteBarrier<Structure>(globalObject->globalData(), globalObject, structure)).first->second.get();
289 }
290
291 JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length)
292 {
293     JSObject* object = value.getObject();
294     if (!object) {
295         throwTypeError(exec);
296         return 0;
297     }
298     JSValue lengthValue = object->get(exec, exec->propertyNames().length);
299     if (exec->hadException())
300         return 0;
301
302     if (lengthValue.isUndefinedOrNull()) {
303         throwTypeError(exec);
304         return 0;
305     }
306
307     length = lengthValue.toUInt32(exec);
308     if (exec->hadException())
309         return 0;
310
311     return object;
312 }
313
314 #if ENABLE(TIZEN_INDEXED_DATABASE)
315 DOMStringList* jsValueToWebCoreDOMStringList(ExecState* exec, JSValue value)
316 {
317     if (value.inherits(&JSArray::s_info)) {
318         RefPtr<DOMStringList> strings = DOMStringList::create();
319         JSArray* jsArray = asArray(value);
320         for (int i = 0; i < jsArray->length(); i++) {
321             String string = valueToStringWithUndefinedOrNullCheck(exec, jsArray->pop());
322             strings->append(string);
323         }
324         return strings.release().leakRef();
325     }
326     return toDOMStringList(value);
327 }
328 #endif // TIZEN_INDEXED_DATABASE
329
330 } // namespace WebCore