2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file plugin_webkit.h
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of webkit js plugin
21 * accessing routines in EFL
23 #include <javascript_interface.h>
24 #include <dpl/log/secure_log.h>
25 #include <dpl/scoped_array.h>
27 #include <dpl/singleton_impl.h>
29 #include <dpl/foreach.h>
30 #include <dpl/noncopyable.h>
31 #include <JavaScriptCore/JavaScript.h>
32 #include <JavaScriptCore/JSObjectRef.h>
34 IMPLEMENT_SINGLETON(JavaScriptInterface)
36 #define CHECK_JSVALUE_IS_UNDEFINED_RETURN(context, object, ret) \
37 if (JSValueIsUndefined(context, object)) { \
38 _E("Object %s is undefined", #object); \
42 #define CHECK_JSOBJECT_IS_NULL_RETURN(object, ret) \
44 _E("Object %s is NULL", #object); \
50 * Converts JSStringRef to std::string
52 std::string toString(const JSStringRef& arg)
56 size_t jsSize = JSStringGetMaximumUTF8CStringSize(arg);
59 DPL::ScopedArray<char> buffer(new char[jsSize]);
60 size_t written = JSStringGetUTF8CString(arg, buffer.Get(), jsSize);
61 if (written > jsSize) {
62 _E("Conversion could not be fully performed.");
65 result = buffer.Get();
72 * Converts JSValueRef to std::string
74 std::string toString(JSContextRef ctx, JSValueRef value)
78 JSStringRef str = JSValueToStringCopy(ctx, value, NULL);
79 result = toString(str);
84 JSValueRef getProperty(JSContextRef ctx, JSValueRef value, const char* name)
86 Assert(ctx && value && name);
87 JSValueRef result = NULL;
88 JSObjectRef obj = JSValueToObject(ctx, value, NULL);
90 JSStringRef str = JSStringCreateWithUTF8CString(name);
91 result = JSObjectGetProperty(ctx, obj, str, NULL);
97 JSValueRef getPropertyObj(JSContextRef ctx, JSObjectRef obj, const char* name)
99 Assert(ctx && obj && name);
100 JSStringRef str = JSStringCreateWithUTF8CString(name);
101 JSValueRef result = JSObjectGetProperty(ctx, obj, str, NULL);
102 JSStringRelease(str);
106 JSObjectRef getJSGlobalObject(JSGlobalContextRef context)
108 return JSContextGetGlobalObject(context);
112 typedef JSValueRef (*JSCFunction)(
113 JSContextRef context,
115 JSObjectRef thisObject,
116 size_t argumentCount,
117 const JSValueRef arguments[],
118 JSValueRef* exception);
120 void JavaScriptInterface::setObjectProperty(JSGlobalContextRef context,
121 const JSObjectPtr& parentObject,
122 const std::string &propertyName,
123 const JSObjectPtr& propertyObject)
125 _D("JSObjectSetProperty(%p, \"%s\")", context, propertyName.c_str());
128 JSStringRef name = JSStringCreateWithUTF8CString(propertyName.c_str());
131 static_cast<JSGlobalContextRef>(context),
132 static_cast<JSObjectRef>(parentObject->getObject()), name,
133 static_cast<JSObjectRef>(propertyObject->getObject()),
134 kJSPropertyAttributeReadOnly, 0);
136 JSStringRelease(name);
139 void JavaScriptInterface::removeObjectProperty(JSGlobalContextRef context,
140 const JSObjectPtr& parentObject,
141 const std::string &propertyName)
144 //nothing to do -> no context
147 _D("JSObjectDeleteProperty(%p, \"%s\")", context, propertyName.c_str());
149 JSStringRef name = JSStringCreateWithUTF8CString(propertyName.c_str());
150 JSObjectDeleteProperty(
151 static_cast<JSGlobalContextRef>(context),
152 static_cast<JSObjectRef>(parentObject->getObject()), name, 0);
154 JSStringRelease(name);
157 JavaScriptInterface::PropertiesList JavaScriptInterface::
158 getObjectPropertiesList(
159 JSGlobalContextRef context,
160 const JSObjectPtr& object) const
162 PropertiesList result;
163 JSPropertyNameArrayRef properties = JSObjectCopyPropertyNames(
164 static_cast<JSGlobalContextRef>(context),
165 static_cast<JSObjectRef>(object->getObject()));
166 std::size_t count = JSPropertyNameArrayGetCount(properties);
167 result.reserve(count);
168 _D("propesties count %d", count);
169 for (std::size_t i = 0; i < count; ++i) {
170 JSStringRef property = JSPropertyNameArrayGetNameAtIndex(properties, i);
171 result.push_back(toString(property));
173 JSPropertyNameArrayRelease(properties);
177 JSObjectPtr JavaScriptInterface::makeJSFunctionObject(
178 JSGlobalContextRef context,
179 const std::string &name,
180 js_function_impl functionImplementation) const
182 _D("JSObjectMakeFunctionWithCallback(%p, \"%s\")", context, name.c_str());
183 JSStringRef jsFunName = JSStringCreateWithUTF8CString(name.c_str());
185 JSObjectRef object = JSObjectMakeFunctionWithCallback(
188 reinterpret_cast<JSObjectCallAsFunctionCallback>(
189 functionImplementation));
191 JSStringRelease(jsFunName);
192 return JSObjectPtr(new JSObject(static_cast<void*>(object)));
195 JSObjectPtr JavaScriptInterface::makeJSClassObject(
196 JSGlobalContextRef context,
197 JSObjectDeclaration::ConstClassTemplate classTemplate) const
199 _D("JSObjectMake(%p)", context);
200 JSObjectRef object = JSObjectMake(
202 static_cast<JSClassRef>(
203 const_cast<JSObjectDeclaration::ClassTemplate>(classTemplate)),
205 return JSObjectPtr(new JSObject(object));
208 JSObjectPtr JavaScriptInterface::makeJSObjectBasedOnInterface(
209 JSGlobalContextRef context,
210 const std::string &interfaceName) const
212 _D("makeJSObjectBasedOnInterface(%p, \"%s\")", context, interfaceName.c_str());
213 JSObjectPtr jsInterfaceObj = getJSObjectProperty(context,
217 JSObjectRef object = JSObjectCallAsConstructor(context,
218 static_cast<JSObjectRef>(
223 return JSObjectPtr(new JSObject(static_cast<void*>(object)));
226 JSObjectPtr JavaScriptInterface::makeJSInterface(
227 JSGlobalContextRef context,
228 JSObjectDeclaration::ConstClassTemplate classTemplate,
229 JSObjectDeclaration::ConstructorCallback constructorCallback) const
231 _D("makeJSInterface(%p)", context);
232 JSObjectRef object = JSObjectMakeConstructor(context,
233 static_cast<JSClassRef>(
235 JSObjectDeclaration::
239 JSObjectCallAsConstructorCallback>(
242 return JSObjectPtr(new JSObject(static_cast<void*>(object)));
245 JSObjectPtr JavaScriptInterface::createObject(
246 JSGlobalContextRef context,
247 const JSObjectDeclarationPtr&
250 typedef JSObjectDeclaration::Options JO;
252 if (declaration->getOptions()) {
253 switch (declaration->getOptions()->getType()) {
254 case JO::ClassType::Function:
255 return makeJSFunctionObject(
257 declaration->getName(),
258 declaration->getOptions()->getFunctionImpl());
260 case JO::ClassType::Class:
261 if (declaration->getInterfaceName().empty()) {
262 return makeJSClassObject(
264 declaration->getClassTemplate());
266 return makeJSObjectBasedOnInterface(
268 declaration->getInterfaceName());
271 case JO::ClassType::Interface:
272 return makeJSInterface(
274 /* product class template */
275 declaration->getClassTemplate(),
276 declaration->getConstructorCallback());
279 _E("Invalid class type. Making empty JS object.");
280 return JSObjectPtr(new JSObject(
281 JSObjectMake(context, NULL, NULL)));
284 _D("No declaration options");
285 return JSObjectPtr(new JSObject(
288 static_cast<JSClassRef>(
289 const_cast<JSObjectDeclaration::
291 declaration->getClassTemplate())),
296 JSObjectPtr JavaScriptInterface::getGlobalObject(JSGlobalContextRef context)
299 return JSObjectPtr(new JSObject(static_cast<JSObject::RealObject>(
300 JSContextGetGlobalObject(static_cast<
305 JSObjectPtr JavaScriptInterface::copyObjectToIframe(
306 JSGlobalContextRef context,
307 const JSObjectPtr& iframe,
308 const std::string& name)
310 _D("copyObjectToIframe(%s)", name.c_str());
312 JSGlobalContextRef jsGlobalContext =
313 static_cast<JSGlobalContextRef>(context);
315 JSObjectRef globalObject = JSContextGetGlobalObject(jsGlobalContext);
317 JSValueRef requestedObject = getPropertyObj(jsGlobalContext,
320 CHECK_JSVALUE_IS_UNDEFINED_RETURN(jsGlobalContext,
324 JSStringRef requestedObjectStr =
325 JSStringCreateWithUTF8CString(name.c_str());
327 JSObjectSetProperty(jsGlobalContext,
328 static_cast<JSObjectRef>(iframe->getObject()),
331 kJSPropertyAttributeReadOnly,
334 JSStringRelease(requestedObjectStr);
337 new JSObject(const_cast<OpaqueJSValue*>(requestedObject)));
340 JavaScriptInterface::ObjectsListPtr
341 JavaScriptInterface::getIframesList(JSGlobalContextRef ctx) const
343 JSGlobalContextRef context = static_cast<JSGlobalContextRef>(ctx);
344 JSObjectRef globalObject = JSContextGetGlobalObject(context);
345 ObjectsListPtr retList = getIframesList(context, globalObject);
350 JavaScriptInterface::ObjectsListPtr
351 JavaScriptInterface::getIframesList(JSContextRef context,
352 JSObjectRef globalObject) const
354 JSValueRef frames = getPropertyObj(context, globalObject, "frames");
355 CHECK_JSVALUE_IS_UNDEFINED_RETURN(context, frames, ObjectsListPtr());
357 JSObjectRef frames_o = JSValueToObject(context, frames, NULL);
358 CHECK_JSOBJECT_IS_NULL_RETURN(frames_o, ObjectsListPtr());
360 JSValueRef len = getPropertyObj(context, frames_o, "length");
361 CHECK_JSVALUE_IS_UNDEFINED_RETURN(context, len, ObjectsListPtr());
363 size_t count = JSValueToNumber(context, len, NULL);
364 _D("frames_o.length = %%d", count);
366 ObjectsListPtr retList = ObjectsListPtr(new ObjectsList());
368 for (size_t i = 0; i < count; ++i) {
369 std::stringstream ss;
371 JSValueRef frame = getPropertyObj(context,
374 if (JSValueIsUndefined(context, frame)) {
375 _E("Selected frame is null: frame[%d]", i);
378 JSObjectRef frame_obj = JSValueToObject(context, frame, NULL);
380 _E("frame_obj is NULL.");
383 retList->push_back(JSObjectPtr(new JSObject(frame_obj)));
384 ObjectsListPtr childList = getIframesList(context, frame_obj);
386 retList->merge(*childList);
387 _D("Frame Value Pointer: %p", frame);
388 _D("Frame Object Pointer: %p", frame_obj);
394 JSObjectPtr JavaScriptInterface::getJSObjectProperty(JSGlobalContextRef ctx,
395 const JSObjectPtr& frame,
396 const std::string& name)
399 _D("makeJSObjectBasedOnInterface(%p, \"%s\")", ctx, name.c_str());
400 JSObjectRef frame_js = static_cast<JSObjectRef>(frame->getObject());
401 JSValueRef property = getPropertyObj(ctx, frame_js, name.c_str());
402 JSObjectRef objProp = JSValueToObject(ctx, property, NULL);
404 return JSObjectPtr(new JSObject(objProp));
407 void JavaScriptInterface::removeIframes(JSGlobalContextRef context)
409 const char* deleteIframesScript =
410 "frame_set = document.getElementsByTagName('iframe');"
411 "len = frame_set.length;"
412 "for(i=0; i< len; i++)"
413 " frame_set[0].parentNode.removeChild(frame_set[0]); ";
415 JSGlobalContextRef ctx = static_cast<JSGlobalContextRef>(context);
417 JSStringRef script_src = JSStringCreateWithUTF8CString(deleteIframesScript);
419 JSEvaluateScript(ctx, script_src, 0, 0, 0, 0);
421 JSStringRelease(script_src);
424 void JavaScriptInterface::invokeGarbageCollector(JSGlobalContextRef context)
426 LogDebug("Garbage collection");
427 JSGarbageCollect(context);
428 JSGarbageCollect(context);
429 JSGarbageCollect(context);
430 JSGarbageCollect(context);