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