Update change log and spec for wrt-plugins-tizen_0.2.84
[framework/web/wrt-plugins-tizen.git] / src / standards / Tizen / LBS / JSLocationServiceProvider.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include "JSLocationServiceProvider.h"
17 #include "LocationServiceProvider.h"
18 #include <Tizen/Common/JSTizenExceptionFactory.h>
19 #include <Tizen/Common/JSTizenException.h>
20 #include <Tizen/Common/SecurityExceptions.h>
21 #include "LBSAce.h"
22 #include "LBSUtil.h"
23 #include "JSLBSPending.h"
24 #include "JSLBS.h"
25
26 #include <dlog.h>
27
28 #undef LOG_TAG
29 #define LOG_TAG "TIZEN_LBS"
30
31 using namespace std;
32 using namespace WrtDeviceApis::CommonsJavaScript;
33 using namespace WrtDeviceApis::Commons;
34
35 namespace TizenApis {
36 namespace Tizen1_0 {
37 namespace LBS {
38
39 struct CallbackData {
40         JSObjectRef onSuccess;
41         JSObjectRef onFail;
42 };
43
44 JSContextRef JSLocationServiceProvider::m_globalContextRef = NULL;
45 JSClassRef JSLocationServiceProvider::m_jsClassRef = NULL;
46
47 JSClassDefinition JSLocationServiceProvider::m_jsClassInfo = {
48         0,
49         kJSClassAttributeNone,
50         "LocationServiceProvider",
51         NULL,
52         NULL,
53         m_function,
54         initialize,
55         finalize,
56         NULL, //hasProperty
57         JSLocationServiceProvider::getProperty, //getProperty
58         NULL, //setProperty
59         NULL, //deleteProperty
60         NULL, //getPropertyNames
61         NULL,
62         NULL, // constructor
63         hasInstance,
64         NULL
65 };
66
67
68 JSStaticFunction JSLocationServiceProvider::m_function[] = {
69         { "setOptions",JSLocationServiceProvider::setOptions,kJSPropertyAttributeNone },
70                 { 0, 0, 0 }
71 };
72
73 const JSClassRef JSLocationServiceProvider::getClassRef()
74 {
75         if (!m_jsClassRef) {
76                 m_jsClassRef = JSClassCreate(&m_jsClassInfo);
77         }
78         return m_jsClassRef;
79 }
80
81 const JSClassDefinition* JSLocationServiceProvider::getClassInfo()
82 {
83         return &m_jsClassInfo;
84 }
85
86 void JSLocationServiceProvider::initialize(JSContextRef ctx, JSObjectRef object)
87 {
88         if( JSLocationServiceProvider::m_globalContextRef == NULL ){
89                 JSLocationServiceProvider::m_globalContextRef = ctx;
90         }
91 }
92
93 void JSLocationServiceProvider::finalize(JSObjectRef object)
94 {
95         LocationServiceProvider * priv = reinterpret_cast<LocationServiceProvider*>(JSObjectGetPrivate(object));
96         if( priv ){
97                 delete priv;
98                 JSObjectSetPrivate(object, NULL);
99         }
100 }
101
102 bool JSLocationServiceProvider::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception) {
103         return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
104 }
105
106 JSValueRef JSLocationServiceProvider::getProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception){
107
108         LocationServiceProvider * priv = reinterpret_cast<LocationServiceProvider*>(JSObjectGetPrivate(object));
109         if( priv == NULL)
110                 return NULL;
111
112         if(JSStringIsEqualToUTF8CString(propertyName, "name")) {
113                 JSStringRef name = JSStringCreateWithUTF8CString(priv->getName().c_str());
114                 JSValueRef jsv = JSValueMakeString(ctx, name);
115                 JSStringRelease(name);
116                 return jsv;
117         }
118         else if(JSStringIsEqualToUTF8CString(propertyName, "metaData")) {
119                 std::vector<std::pair<std::string, std::string>> options = priv->getMetadata();
120                 JSObjectRef metaobject = JSObjectMake(ctx, NULL, NULL);
121                 std::vector<std::pair<std::string, std::string>>::iterator pos;
122                 for( pos = options.begin() ; pos != options.end(); ++pos){
123                         JSStringRef key = JSStringCreateWithUTF8CString(pos->first.c_str());
124                         JSStringRef value = JSStringCreateWithUTF8CString(pos->second.c_str());
125                         JSValueRef valueRef = JSValueMakeString(ctx, value);
126                         JSObjectSetProperty(ctx, metaobject , key , valueRef ,kJSPropertyAttributeReadOnly, NULL );
127                         JSStringRelease(key);
128                         JSStringRelease(value);
129                 }
130                 return metaobject;
131         }
132         else if(JSStringIsEqualToUTF8CString(propertyName, "attribution")) {
133                 JSStringRef attr = JSStringCreateWithUTF8CString(priv->getAttribution().c_str());
134                 JSValueRef jsv = JSValueMakeString(ctx, attr);
135                 JSStringRelease(attr);
136                 return jsv;
137         }
138         else if(JSStringIsEqualToUTF8CString(propertyName, "supportedOptions")) {
139                 std::vector<std::string> supportedOptionVector = priv->getSupportedOptions();
140                 JSValueRef* supportedOptionValues = NULL;
141                 supportedOptionValues = new JSValueRef[supportedOptionVector.size()];
142                 for( unsigned int i=0 ; i < supportedOptionVector.size(); i++){
143                         JSStringRef optionString =  JSStringCreateWithUTF8CString( supportedOptionVector[i].c_str());
144                         supportedOptionValues[i] = JSValueMakeString(ctx, optionString);
145                         JSStringRelease(optionString);
146                 }
147                 JSObjectRef supportedOptionArray = JSObjectMakeArray(ctx, supportedOptionVector.size(), supportedOptionValues, NULL);
148                 delete []supportedOptionValues;
149                 return supportedOptionArray;
150         }
151         else if(JSStringIsEqualToUTF8CString(propertyName, "connectivity")) {
152                 JSStringRef conn = JSStringCreateWithUTF8CString(priv->getConnectivity().c_str());
153                 JSValueRef jsv = JSValueMakeString(ctx, conn);
154                 JSStringRelease(conn);
155                 return jsv;
156         }
157
158         return NULL;
159 }
160
161 void _setOptionCb(int result , void * user_data){
162
163         CallbackData * userdata =  static_cast<CallbackData *>(user_data);
164         if ( userdata == NULL)
165                 return;
166
167         if( result == 0 && userdata->onSuccess ){
168                 JSValueRef args[1] = {NULL};
169                 JSObjectCallAsFunction(JSLBS::getGlobalContext() , userdata->onSuccess , NULL, 1, args, NULL);
170         }
171         else if( result != 0 && userdata->onFail ){
172                 JSObjectRef error = Commons::JSTizenExceptionFactory::makeErrorObject(JSLBS::getGlobalContext(), Commons::JSTizenException::INVALID_VALUES_ERROR , "Fail setOption");
173                 JSValueRef args[1] = {error};
174                 JSObjectCallAsFunction(JSLBS::getGlobalContext() , userdata->onFail , NULL, 1, args, NULL);
175         }
176
177         if( userdata->onSuccess )
178                 JSValueUnprotect(JSLBS::getGlobalContext(), userdata->onSuccess);
179         if( userdata->onFail )
180                 JSValueUnprotect(JSLBS::getGlobalContext(), userdata->onFail);
181
182         delete userdata;
183 }
184
185 JSValueRef JSLocationServiceProvider::setOptions(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
186
187         // Check the access control
188         AceSecurityStatus status = LBS_CHECK_ACCESS(LBS_FUNCTION_CATEGORY_SERVICE_PROVIDER);
189         if( status != AceSecurityStatus::AccessGranted )
190                 return Commons::JSTizenExceptionFactory::postException(ctx,exception, Commons::JSTizenException::PERMISSION_DENIED_ERROR );
191
192         // Check the object type
193         LocationServiceProvider * priv = reinterpret_cast<LocationServiceProvider*>(JSObjectGetPrivate(thisObject));
194         if( priv == NULL){
195                 return Commons::JSTizenExceptionFactory::postException(ctx,exception,  Commons::JSTizenException::TYPE_MISMATCH_ERROR, "The object is not LocationServiceProvider instance");
196         }
197
198         JSValueRef convertedArg[3];
199         JSObjectRef convertedArgObjects[3];
200         for( unsigned int i = 0 ; i < 3; i++ )
201         {
202                 if(i<argumentCount)
203                 {
204                         convertedArg[i] = arguments[i];
205                         convertedArgObjects[i] = JSValueToObject(ctx, arguments[i] , NULL );
206                 }
207                 else
208                 {
209                         convertedArg[i] = JSValueMakeUndefined(ctx);
210                         convertedArgObjects[i] = NULL;
211                 }
212         }
213
214         //Check the first argument
215         if(JSValueIsNull(ctx, convertedArg[0]) || JSValueIsUndefined(ctx, convertedArg[0]) || !JSValueIsObject(ctx, convertedArg[0]))
216         {
217                 return Commons::JSTizenExceptionFactory::postException(ctx,exception,  Commons::JSTizenException::TYPE_MISMATCH_ERROR, "The first argument is invalid (null, undefined or not an object)");
218         }
219
220         JSObjectRef onsuccess;
221         JSObjectRef onfail;
222
223         // The second argument is null or undefined or function object
224         bool isFunctionOnSuccess = false;
225         if(JSValueIsNull(ctx, convertedArg[1]) || JSValueIsUndefined(ctx, convertedArg[1]))
226         {
227                 isFunctionOnSuccess = false;
228                 LOGD("%s - 2rd argument is OK (Either null or undefined) ", __func__);
229         }
230         else if (JSObjectIsFunction(ctx, convertedArgObjects[1]))
231         {
232                 isFunctionOnSuccess = true;
233                 onsuccess = convertedArgObjects[1];
234                 LOGD("%s - 2rd argument is OK (function) ", __func__);
235         }
236         else
237         {
238                 return Commons::JSTizenExceptionFactory::postException(ctx,exception,  Commons::JSTizenException::TYPE_MISMATCH_ERROR, "The second argument must be a function");
239         }
240
241         // The third argument is null or undefined or function object
242         bool isFunctionOnFail = false;
243         if(JSValueIsNull(ctx, convertedArg[2]) || JSValueIsUndefined(ctx, convertedArg[2]))
244         {
245                 isFunctionOnFail = false;
246                 LOGD("%s - 3rd argument is OK (Either null or undefined) ", __func__);
247         }
248         else if (JSObjectIsFunction(ctx, convertedArgObjects[2]))
249         {
250                 isFunctionOnFail = true;
251                 onfail = convertedArgObjects[2];
252                 LOGD("%s - 3rd argument is OK (function) ", __func__);
253         }
254         else
255         {
256                 return Commons::JSTizenExceptionFactory::postException(ctx,exception,  Commons::JSTizenException::TYPE_MISMATCH_ERROR, "The third argument must be a function");
257         }
258
259         // Initialize a CallbackData
260         CallbackData * userdata = NULL;
261         userdata = new CallbackData();
262
263         //set the success callback
264         if(isFunctionOnSuccess)
265         {
266                 userdata->onSuccess = onsuccess;
267                 JSValueProtect(ctx, onsuccess);
268         }
269         else
270         {
271                 userdata->onSuccess = NULL;
272         }
273
274         //set the error callback
275         if(isFunctionOnFail)
276         {
277                 userdata->onFail = onfail;
278                 JSValueProtect(ctx, onfail);
279         }
280         else
281         {
282                 userdata->onFail = NULL;
283         }
284
285         // The first argument is option object
286         JSObjectRef jsOptions = convertedArgObjects[0];
287         if( jsOptions == NULL ){
288                 return Commons::JSTizenExceptionFactory::postException(ctx, exception,  Commons::JSTizenException::TYPE_MISMATCH_ERROR, "The option arguments is not Object");
289         }
290
291         // Convert  Object to vector
292         std::vector<std::pair<std::string, std::string>> options = LBSUtil::convertObject(ctx, jsOptions);
293
294         // Call native setOption function
295         int ret = priv->setOption(options , _setOptionCb , userdata, NULL);
296         LOGD("ret : %d ", ret);
297
298         // Invalid options values
299         if( ret != 0 ){
300                 JSObjectRef error = Commons::JSTizenExceptionFactory::makeErrorObject(JSLBS::getGlobalContext(), Commons::JSTizenException::INVALID_VALUES_ERROR , "invalid option value");
301                 JSValueRef args[1] = {error};
302                 if( userdata->onFail )
303                         JSObjectCallAsFunction(JSLBS::getGlobalContext(), userdata->onFail  , NULL, 1, args, NULL);
304
305                 //remove callback values
306                 if( userdata != NULL ){
307                         if( userdata->onSuccess )
308                                 JSValueUnprotect(ctx, userdata->onSuccess);
309                         if( userdata->onFail )
310                                 JSValueUnprotect(ctx, userdata->onFail);
311                         delete userdata;
312                 }
313         }
314
315         return JSValueMakeUndefined(ctx);
316 }
317
318 } //LBS
319 } // Tizen1_0
320 } // TizenApis
321