da8e5a048e6df557ef9facc614cc4a388d725ddb
[platform/framework/web/wrt-plugins-tizen.git] / src / NFC / JSNdefMessage.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include "JSNdefMessage.h"
19 #include "JSNdefRecord.h"
20 #include "JSNdefRecordText.h"
21 #include "JSNdefRecordURI.h"
22 #include "JSNdefRecordMedia.h"
23 #include "NFCConverter.h"
24 #include <GlobalContextManager.h>
25 #include <ArgumentValidator.h>
26 #include <Commons/Exception.h>
27 #include <CommonsJavaScript/PrivateObject.h>
28 #include <CommonsJavaScript/JSUtils.h>
29 #include <JSWebAPIErrorFactory.h>
30 #include <SecurityExceptions.h>
31 #include <PlatformException.h>
32
33 #include "NFCFactory.h"
34 #include "plugin_config.h"
35 #include <Logger.h>
36
37 using namespace DeviceAPI::Common;
38 using namespace WrtDeviceApis::Commons;
39 using namespace WrtDeviceApis::CommonsJavaScript;
40
41 namespace DeviceAPI {
42 namespace NFC {
43
44  JSClassDefinition JSNdefMessage::m_classInfo =
45 {
46     0,
47     kJSClassAttributeNone,
48     TIZEN_NDEFMESSAGE_ATTRIBUTENAME,
49     0,
50     m_property,
51     m_function,
52     initialize,
53     finalize,
54     NULL, //hasProperty,
55     NULL,
56     NULL, //setProperty,
57     NULL, //DeleteProperty,
58     NULL, //GetPropertyNames,
59     NULL, //CallAsFunction,
60     NULL, //CallAsConstructor,
61     NULL, //HasInstance,
62     NULL  //ConvertToType
63 };
64
65 JSStaticValue JSNdefMessage::m_property[] =
66 {
67     //NdefMessageProperties
68     { TIZEN_NDEFMESSAGE_RECORDCOUNT, getProperty,
69             NULL, kJSPropertyAttributeReadOnly},
70      { TIZEN_NDEFMESSAGE_RECORDS, getProperty,
71             setProperty, kJSPropertyAttributeNone},
72     { 0, 0, 0, 0 }
73 };
74
75 JSStaticFunction JSNdefMessage::m_function[] = {
76     {"toByte", JSNdefMessage::toByte, kJSPropertyAttributeNone},
77     { 0, 0, 0}
78 };
79
80 JSClassRef JSNdefMessage::m_jsClassRef = JSClassCreate(JSNdefMessage::getClassInfo());
81
82 JSObjectRef JSNdefMessage::createJSObject(JSContextRef context, void *messageHandle) {
83         LoggerD("entered");
84
85         INdefMessagePtr ndefMessage = NFCFactory::getInstance().createNDEFMessageObject();
86         std::vector<NdefRecordData> records = ndefMessage->toNDEFRecords(messageHandle);
87         JSValueRef recordArray = NULL;
88         if (records.size() > 0) {
89                 JSValueRef valueArray[records.size()];
90                 NFCConverter convert(context);
91                 for (std::size_t i = 0; i < records.size(); ++i) {
92                         valueArray[i] = convert.toJSValueRef(records[i]);
93                 }
94                 recordArray = JSCreateArrayObject(context, records.size(), valueArray);
95         } else
96                 recordArray = JSCreateArrayObject(context, 0, NULL);
97         return createJSObject(context, ndefMessage, recordArray);
98 }
99
100 /*
101 JSObjectRef JSNdefMessage::createJSObject(JSContextRef context, std::vector<void *> ndefRcords) {
102         LoggerD("entered");
103
104         INdefMessagePtr ndefMessage = NFCFactory::getInstance().createNDEFMessageObject(ndefRcords);
105         return createJSObject(context, ndefMessage);
106 }*/
107
108 JSObjectRef JSNdefMessage::createJSObject(JSContextRef context, std::vector<unsigned char> rawdata) {
109         LoggerD("entered");
110
111         INdefMessagePtr ndefMessage = NFCFactory::getInstance().createNDEFMessageObject();
112         NFCConverter convert(context);
113         std::vector<NdefRecordData> records = ndefMessage->toNDEFRecords(rawdata);
114         JSValueRef recordArray = NULL;
115         if (records.size() > 0) {
116                 JSValueRef valueArray[records.size()];
117                 NFCConverter convert(context);
118                 for (std::size_t i = 0; i < records.size(); ++i) {
119                         valueArray[i] = convert.toJSValueRef(records[i]);
120                 }
121                 recordArray = JSCreateArrayObject(context, records.size(), valueArray);
122         } else
123                 recordArray = JSCreateArrayObject(context, 0, NULL);
124         return createJSObject(context, ndefMessage, recordArray);
125 }
126
127 JSObjectRef JSNdefMessage::createJSObject(JSContextRef context, INdefMessagePtr message, JSValueRef recordArray) {
128         LoggerD("entered");
129
130         if ((message->mLocalProperty).setArrayProperty(context, TIZEN_NDEFMESSAGE_RECORDS, recordArray) == false)
131                 LoggerE("Can't set property");
132
133         NdefMessagePrivObject *priv = new NdefMessagePrivObject(context, message);
134         JSObjectRef obj = JSObjectMake(context, getClassRef(), priv);
135         return obj;
136 }
137 void JSNdefMessage::initialize(JSContextRef context, JSObjectRef object)
138 {
139         LoggerD("entered");
140 }
141
142 void JSNdefMessage::finalize(JSObjectRef object)
143 {
144         LoggerD( "entered" );
145         NdefMessagePrivObject *priv = static_cast<NdefMessagePrivObject*>(JSObjectGetPrivate(object));
146         if (priv) {
147                 INdefMessagePtr ndefMessage(priv->getObject());
148                 JSObjectSetPrivate(object, NULL);
149                 LoggerD("Deleting NdefMessage object");
150                 delete priv;
151         }
152 }
153
154
155 const JSClassRef JSNdefMessage::getClassRef()
156 {
157         if (!m_jsClassRef) {
158                 m_jsClassRef = JSClassCreate(&m_classInfo);
159         }
160         return m_jsClassRef;
161 }
162
163 const JSClassDefinition* JSNdefMessage::getClassInfo()
164 {
165         return &m_classInfo;
166 }
167
168 JSObjectRef JSNdefMessage::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
169 {
170         LoggerD("entered");
171
172         ArgumentValidator validator(ctx, argumentCount, arguments);
173     JSObjectRef objArg = NULL;
174         try {
175                 if (argumentCount > 0)
176                         objArg = validator.toArrayObject(0);
177         } catch(...) {
178                 LoggerE("First parameter is not an array");
179         }
180         JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(ctx);
181
182         JSObjectRef result = NULL;
183         Try {
184                 if (objArg != NULL) {
185                         NFCConverter convert(global_context);
186                         unsigned int arrayLen = JSGetArrayLength(ctx, objArg);
187                         if (arrayLen > 0) {
188                                 bool isRecordArray = false;
189                                 bool isByteArray = false;
190                                 JSValueRef valueArray[arrayLen];
191                                 
192                                 for (unsigned int i = 0; i < arrayLen; ++i) {
193                                         valueArray[i] = JSGetArrayElement(ctx, objArg, i);
194                                         bool bNdefRecord = convert.isNdefRecord(valueArray[i]);
195                                         LoggerD("isNdefRecord : " << bNdefRecord);
196                                         if (bNdefRecord)
197                                                 isRecordArray = true;
198                                         else
199                                                 isByteArray = true;
200                                         if (isRecordArray && isByteArray)
201                                                 break;
202                                 }
203                                 if (!isRecordArray && isByteArray) {
204                                         result = createJSObject(global_context, convert.toVectorOfOctets(arguments[0]));
205                                 } else {
206                                         INdefMessagePtr ndefMessage = NFCFactory::getInstance().createNDEFMessageObject();
207                                         JSValueRef recordArray = JSCreateArrayObject(global_context, arrayLen, valueArray);
208                                         result = createJSObject(global_context, ndefMessage, recordArray);
209                                 }
210                         }
211                 }
212         } Catch(WrtDeviceApis::Commons::Exception) {
213                 LoggerE(_rethrown_exception.GetClassName() << ": " << _rethrown_exception.GetMessage());
214         } Catch(BasePlatformException) {
215                 LoggerE(_rethrown_exception.getName() << ": " << _rethrown_exception.getMessage());
216         }
217
218         if (result == NULL)
219                 result = createJSObject(global_context);
220
221         if (result) {
222                 JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
223             JSObjectSetProperty(global_context, result, ctorName, constructor,
224                 kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
225         JSStringRelease(ctorName);
226         }
227         return result;
228
229 }
230
231 JSValueRef JSNdefMessage::getProperty(JSContextRef context, JSObjectRef object,
232         JSStringRef propertyName, JSValueRef* exception)
233 {
234         LoggerD("Enter");
235
236         Try     {
237                 NdefMessagePrivObject* privateObject = static_cast<NdefMessagePrivObject*>(JSObjectGetPrivate(object));
238                 if (!privateObject) {
239                         LoggerE("Private object is not set.");
240                         ThrowMsg(NullPointerException, "Private object not initialized");
241                 }
242
243                 INdefMessagePtr ndefMessage(privateObject->getObject());
244
245                 NFCConverter convert(context);
246                 JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
247                 JSValueRef recordsValue = (ndefMessage->mLocalProperty).getProperty(global_context, TIZEN_NDEFMESSAGE_RECORDS);
248         
249                 LoggerD("propertyName : " << convert.toString(propertyName));
250                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NDEFMESSAGE_RECORDCOUNT)) {
251                 if (JSValueIsNull(global_context, recordsValue) || JSValueIsUndefined(global_context, recordsValue)) {
252                                 ThrowMsg(ConversionException,
253                                          "NdefRecordArray is JS null or JS undefined.");
254                     }
255
256                     if (!JSIsArrayValue(global_context, recordsValue)) {
257                         ThrowMsg(ConversionException, "Argument is not an JS array.");
258                     }
259
260                         JSObjectRef obj = convert.toJSObjectRef(recordsValue);
261                         
262                         if (!obj) {
263                                 LoggerE("Object is null");
264                                 ThrowMsg(ConversionException, "Object is null");
265                         }
266                         long count = 0;
267                         for (std::size_t i = 0; i < JSGetArrayLength(global_context, obj); ++i) {
268                                 JSValueRef element = JSGetArrayElement(global_context, obj, i);
269                                 if (convert.isNdefRecord(element))
270                                         count++;
271                         }
272                         return convert.toJSValueRefLong(count);
273                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NDEFMESSAGE_RECORDS)) {
274                         return recordsValue;
275                 }
276         } Catch (ConversionException) {
277                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
278         } Catch (NullPointerException) {
279                 LoggerE("NullPointerException: " << _rethrown_exception.GetMessage());
280         } Catch (WrtDeviceApis::Commons::UnknownException) {
281                 LoggerE("UnknownExceptionException: " << _rethrown_exception.GetMessage());
282         } Catch (PlatformException) {
283                 LoggerE("PlatformExceptionException: " << _rethrown_exception.GetMessage());
284         } Catch (WrtDeviceApis::Commons::Exception) {
285                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
286         }
287         return JSValueMakeUndefined(context);
288 }
289
290 bool JSNdefMessage::setProperty(JSContextRef context, JSObjectRef object,
291         JSStringRef propertyName, JSValueRef value,  JSValueRef* exception)
292 {
293         LoggerD("Enter");
294
295         Try     {
296                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_NDEFMESSAGE_RECORDS)) {
297                         NdefMessagePrivObject* privateObject = static_cast<NdefMessagePrivObject*>(JSObjectGetPrivate(object));
298                         if (!privateObject) {
299                                 LoggerE("Private object is not set.");
300                                 ThrowMsg(NullPointerException, "Private object not initialized");
301                         }
302
303                         NFCConverter convert(context);
304
305                         if (JSValueIsNull(context, value) || JSValueIsUndefined(context, value) || !JSIsArrayValue(context, value)) {
306                                 LoggerE("value is invald.");
307                                 ThrowMsg(ConversionException, "value is invald.");
308                         }
309                         INdefMessagePtr ndefMessage(privateObject->getObject());
310                         JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
311
312                         JSObjectRef obj = convert.toJSObjectRef(value);
313                         
314                         if (!obj) {
315                                 LoggerE("Object is null");
316                                 ThrowMsg(ConversionException, "Object is null");
317                         }
318                         unsigned int arrayLen = JSGetArrayLength(global_context, obj);
319                         JSValueRef valueArray[arrayLen];
320                         for (std::size_t i = 0; i < arrayLen; ++i) {
321                                 JSValueRef element = JSGetArrayElement(global_context, obj, i);
322                                 valueArray[i] = element;
323                         }
324                         JSValueRef recordsArray = JSCreateArrayObject(global_context, arrayLen, valueArray);            
325                         return (ndefMessage->mLocalProperty).setArrayProperty(global_context, TIZEN_NDEFMESSAGE_RECORDS, recordsArray);
326                  }
327         } Catch (NullPointerException) {
328                 LoggerE("NullPointerException: " << _rethrown_exception.GetMessage());
329         } Catch (ConversionException) {
330                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
331         } Catch (InvalidArgumentException) {
332                 LoggerE("InvalidArgumentException: " << _rethrown_exception.GetMessage());
333         } Catch (PlatformException) {
334                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
335         } Catch (WrtDeviceApis::Commons::UnknownException) {
336                 LoggerE("PlatformException: " << _rethrown_exception.GetMessage());
337         } Catch (WrtDeviceApis::Commons::Exception) {
338                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
339         }
340         return false;
341
342 }
343
344 JSValueRef JSNdefMessage::toByte(JSContextRef context,
345         JSObjectRef object,
346         JSObjectRef thisObject,
347         size_t argumentCount,
348         const JSValueRef arguments[],
349         JSValueRef* exception)
350 {
351         LoggerD("Entered ");
352         Try {
353                 NdefMessagePrivObject* privateObject = static_cast<NdefMessagePrivObject*>(JSObjectGetPrivate(thisObject));
354                 if (NULL == privateObject) {
355                         LoggerE("private object is null");
356                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
357                 }
358
359                 INdefMessagePtr ndefMessage(privateObject->getObject());
360                 NFCConverter convert(context);
361
362                 JSContextRef global_context = GlobalContextManager::getInstance()->getGlobalContext(context);
363                 std::vector<void *> records;
364                 try {
365                         JSValueRef recordsValue = (ndefMessage->mLocalProperty).getProperty(global_context, TIZEN_NDEFMESSAGE_RECORDS);
366                         records = convert.toVectorOfRecordHandles(recordsValue);
367                 } catch (WrtDeviceApis::Commons::Exception& err) {
368                         LoggerE(err.GetClassName() << ":"<<err.GetMessage());
369                         ThrowMsg(InvalidArgumentException, "Invalid NDEF Message");
370                 }
371                 return convert.toJSValueRef(ndefMessage->toByte(records));
372         } Catch (ConversionException) {
373                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
374                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
375         } Catch(NullPointerException) {
376                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
377                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
378         } Catch(InvalidArgumentException) {
379                 LoggerE("InvalidArgumentException: " << _rethrown_exception.GetMessage());
380                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
381         } Catch (WrtDeviceApis::Commons::UnknownException) {
382                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
383                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
384         } Catch (WrtDeviceApis::Commons::Exception) {
385                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
386                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
387         }
388 }
389
390 }
391 }