[Common] Fixed invalid parsing of decimal values
[platform/core/api/webapi-plugins.git] / src / common / extension.cc
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5
6 #include "common/extension.h"
7
8 #include <iostream>
9 #include <map>
10 #include <string>
11 #include <vector>
12
13 #include "common/assert.h"
14 #include "common/logger.h"
15 #include "common/tools.h"
16
17 // This function is hidden, because each plugin needs to have own implementation.
18 __attribute__((visibility("hidden"))) common::Extension* CreateExtension() {
19   common::Extension* e = new common::Extension();
20   e->SetExtensionName("common");
21   return e;
22 }
23
24 namespace {
25
26 // this variable is valid only during Extension::XW_Initialize() call
27 // do not use !!!
28 // it's here, so we don't have to modify the interface of CreateExtension(), Extension(), etc.
29 XW_Extension g_xw_extension_ = 0;
30
31 const XW_CoreInterface* g_core = NULL;
32 const XW_MessagingInterface* g_messaging = NULL;
33 const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL;
34 const XW_Internal_EntryPointsInterface* g_entry_points = NULL;
35 const XW_Internal_RuntimeInterface* g_runtime = NULL;
36 const XW_Internal_PermissionsInterface* g_permission = NULL;
37
38 bool InitializeInterfaces(XW_GetInterface get_interface) {
39   ScopeLogger();
40   static bool initialized = false;
41
42   if (!initialized) {
43     g_core = reinterpret_cast<const XW_CoreInterface*>(get_interface(XW_CORE_INTERFACE));
44     if (!g_core) {
45       LoggerE("Can't initialize extension: error getting Core interface.");
46       return false;
47     }
48
49     g_messaging =
50         reinterpret_cast<const XW_MessagingInterface*>(get_interface(XW_MESSAGING_INTERFACE));
51     if (!g_messaging) {
52       LoggerE("Can't initialize extension: error getting Messaging interface.");
53       return false;
54     }
55
56     g_sync_messaging = reinterpret_cast<const XW_Internal_SyncMessagingInterface*>(
57         get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE));
58     if (!g_sync_messaging) {
59       LoggerE("Can't initialize extension: error getting SyncMessaging interface.");
60       return false;
61     }
62
63     g_entry_points = reinterpret_cast<const XW_Internal_EntryPointsInterface*>(
64         get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
65     if (!g_entry_points) {
66       LoggerE(
67           "NOTE: Entry points interface not available in this version "
68           "of runtime, ignoring entry point data for extensions.");
69     }
70
71     g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
72         get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
73     if (!g_runtime) {
74       LoggerE(
75           "NOTE: runtime interface not available in this version "
76           "of runtime, ignoring runtime variables for extensions.");
77     }
78
79     g_permission = reinterpret_cast<const XW_Internal_PermissionsInterface*>(
80         get_interface(XW_INTERNAL_PERMISSIONS_INTERFACE));
81     if (!g_permission) {
82       LoggerE(
83           "NOTE: permission interface not available in this version "
84           "of runtime, ignoring permission for extensions.");
85     }
86
87     initialized = true;
88   }
89
90   return true;
91 }
92
93 }  // namespace
94
95 namespace common {
96
97 Extension::Extension() : xw_extension_(g_xw_extension_) {
98   ScopeLogger();
99 }
100
101 Extension::~Extension() {
102   ScopeLogger();
103 }
104
105 void Extension::SetExtensionName(const char* name) {
106   ScopeLogger();
107   g_core->SetExtensionName(xw_extension_, name);
108 }
109
110 void Extension::SetJavaScriptAPI(const char* api) {
111   ScopeLogger();
112   g_core->SetJavaScriptAPI(xw_extension_, api);
113 }
114
115 void Extension::SetExtraJSEntryPoints(const char** entry_points) {
116   ScopeLogger();
117   if (g_entry_points) g_entry_points->SetExtraJSEntryPoints(xw_extension_, entry_points);
118 }
119
120 bool Extension::RegisterPermissions(const char* perm_table) {
121   ScopeLogger();
122   if (g_permission) return g_permission->RegisterPermissions(xw_extension_, perm_table);
123   return false;
124 }
125
126 bool Extension::CheckAPIAccessControl(const char* api_name) {
127   ScopeLogger();
128   if (g_permission) return g_permission->CheckAPIAccessControl(xw_extension_, api_name);
129   return false;
130 }
131
132 Instance* Extension::CreateInstance() {
133   ScopeLogger();
134   return NULL;
135 }
136
137 std::string Extension::GetRuntimeVariable(const char* var_name, unsigned len) {
138   ScopeLogger();
139   if (!g_runtime) return "";
140
141   std::vector<char> res(len + 1, 0);
142   g_runtime->GetRuntimeVariableString(xw_extension_, var_name, &res[0], len);
143   // crosswalk has used the double quote for the app_id from the first.
144   // the n-wrt (new wrt) is using the double quote also.
145   // but that's wrt and wrt-service's bug.
146   // To keep compatibilities, two case of formats should be considered in webapi-plugins.
147   // removing double quote to keep compatibilities with new and old wrt
148   std::string value = std::string(res.data());
149   if (0 == strncmp(var_name, "app_id", 6) && value.find('"', 0) != std::string::npos &&
150       value.find('"', value.size() - 1) != std::string::npos) {
151     value = value.erase(0, 1);
152     value = value.erase(value.size() - 1, 1);
153   }
154
155   return value;
156 }
157
158 // static
159 void Extension::OnInstanceCreated(XW_Instance xw_instance, Instance* instance) {
160   ScopeLogger();
161   Assert(!g_core->GetInstanceData(xw_instance));
162   if (!instance) return;
163   instance->xw_instance_ = xw_instance;
164   g_core->SetInstanceData(xw_instance, instance);
165   instance->Initialize();
166 }
167
168 // static
169 void Extension::OnInstanceDestroyed(XW_Instance xw_instance) {
170   ScopeLogger();
171   Instance* instance = reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
172   if (!instance) return;
173   instance->xw_instance_ = 0;
174   delete instance;
175 }
176
177 // static
178 void Extension::HandleMessage(XW_Instance xw_instance, const char* msg) {
179   ScopeLogger();
180   Instance* instance = reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
181   if (!instance) return;
182   instance->HandleMessage(msg);
183 }
184
185 // static
186 void Extension::HandleSyncMessage(XW_Instance xw_instance, const char* msg) {
187   ScopeLogger();
188   Instance* instance = reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
189   if (!instance) return;
190   instance->HandleSyncMessage(msg);
191 }
192
193 // static
194 int32_t Extension::XW_Initialize(XW_Extension extension, XW_GetInterface get_interface,
195                                  XW_Initialize_Func initialize,
196                                  XW_CreatedInstanceCallback created_instance,
197                                  XW_ShutdownCallback shutdown) {
198   ScopeLogger();
199   Assert(extension);
200
201   if (!InitializeInterfaces(get_interface)) {
202     return XW_ERROR;
203   }
204
205   g_xw_extension_ = extension;
206
207   if (XW_ERROR == initialize(extension, get_interface)) {
208     return XW_ERROR;
209   }
210
211   g_xw_extension_ = 0;
212
213   using common::Extension;
214   g_core->RegisterShutdownCallback(extension, shutdown);
215   g_core->RegisterInstanceCallbacks(extension, created_instance, Extension::OnInstanceDestroyed);
216   g_messaging->Register(extension, Extension::HandleMessage);
217   g_sync_messaging->Register(extension, Extension::HandleSyncMessage);
218   return XW_OK;
219 }
220
221 std::mutex Instance::instances_mutex_;
222 std::unordered_set<Instance*> Instance::all_instances_;
223
224 Instance::Instance() : xw_instance_(0) {
225   ScopeLogger();
226   {
227     std::lock_guard<std::mutex> lock{instances_mutex_};
228     all_instances_.insert(this);
229   }
230 }
231
232 Instance::~Instance() {
233   ScopeLogger();
234   {
235     std::lock_guard<std::mutex> lock{instances_mutex_};
236     all_instances_.erase(this);
237   }
238   Assert(xw_instance_ == 0);
239 }
240
241 void Instance::PostMessage(Instance* that, const char* msg) {
242   ScopeLogger();
243   if (nullptr != that) {
244     std::lock_guard<std::mutex> lock{instances_mutex_};
245     if (all_instances_.end() != all_instances_.find(that)) {
246       that->PostMessage(msg);
247       return;
248     }
249   }
250   LoggerE("Trying to post message to non-existing instance: [%p], ignoring", that);
251 }
252
253 void Instance::PostMessage(const char* msg) {
254   ScopeLogger();
255   if (!xw_instance_) {
256     LoggerE(
257         "Ignoring PostMessage() in the constructor or after the "
258         "instance was destroyed.");
259     return;
260   }
261   g_messaging->PostMessage(xw_instance_, msg);
262 }
263
264 void Instance::SendSyncReply(const char* reply) {
265   ScopeLogger();
266   if (!xw_instance_) {
267     LoggerE(
268         "Ignoring SendSyncReply() in the constructor or after the "
269         "instance was destroyed.");
270     return;
271   }
272   g_sync_messaging->SetSyncReply(xw_instance_, reply);
273 }
274
275 ParsedInstance::ParsedInstance() {
276   ScopeLogger();
277 }
278
279 ParsedInstance::~ParsedInstance() {
280   ScopeLogger();
281 }
282
283 void ParsedInstance::RegisterHandler(const std::string& name, const NativeHandler& func) {
284   ScopeLogger();
285   handler_map_.insert(std::make_pair(name, func));
286 }
287
288 void ParsedInstance::RegisterSyncHandler(const std::string& name, const NativeHandler& func) {
289   ScopeLogger();
290   handler_map_.insert(std::make_pair("#SYNC#" + name, func));
291 }
292
293 void ParsedInstance::ReportSuccess(picojson::object& out) {
294   ScopeLogger();
295   tools::ReportSuccess(out);
296 }
297
298 void ParsedInstance::ReportSuccess(const picojson::value& result, picojson::object& out) {
299   ScopeLogger();
300   tools::ReportSuccess(result, out);
301 }
302
303 void ParsedInstance::ReportError(picojson::object& out) {
304   ScopeLogger();
305   tools::ReportError(out);
306 }
307
308 void ParsedInstance::ReportError(const PlatformException& ex, picojson::object& out) {
309   ScopeLogger();
310   tools::ReportError(ex, out);
311 }
312
313 void ParsedInstance::ReportError(const PlatformResult& error, picojson::object* out) {
314   ScopeLogger();
315   tools::ReportError(error, out);
316 }
317
318 void ParsedInstance::HandleMessage(const char* msg) {
319   ScopeLogger();
320   HandleMessage(msg, false);
321 }
322
323 void ParsedInstance::HandleSyncMessage(const char* msg) {
324   ScopeLogger();
325   HandleMessage(msg, true);
326 }
327
328 void ParsedInstance::HandleMessage(const char* msg, bool is_sync) {
329   ScopeLogger();
330   try {
331     picojson::value value;
332     std::string err;
333     picojson::parse(value, msg, msg + strlen(msg), &err);
334     if (!err.empty()) {
335       LoggerE("Ignoring message:\"%s\", error: %s", msg, err.c_str());
336       return;
337     }
338
339     if (!value.is<picojson::object>()) {
340       LoggerE("Ignoring message. It is not an object.");
341       return;
342     }
343
344     std::string cmd = (is_sync ? "#SYNC#" : "") + value.get("cmd").to_str();
345
346     auto it = handler_map_.find(cmd);
347     if (handler_map_.end() == it) {
348       LoggerE("Unknown command: %s", cmd.c_str());
349       throw UnknownException("Unknown command.");
350     }
351
352     NativeHandler func = it->second;
353
354     // check for args in JSON message
355     const picojson::value& args = value.get("args");
356     if (!args.is<picojson::object>()) {
357       throw InvalidValuesException("No \"args\" field in message");
358     }
359
360     picojson::value result = picojson::value(picojson::object());
361     func(args, result.get<picojson::object>());
362
363     if (is_sync) SendSyncReply(result.serialize().c_str());
364   } catch (const PlatformException& e) {
365     return HandleException(e);
366   } catch (const PlatformException* e) {
367     return HandleException(*e);
368   } catch (...) {
369     return HandleException(UnknownException("Unknown exception"));
370   }
371 }
372
373 void ParsedInstance::HandleException(const PlatformException& ex) {
374   ScopeLogger();
375   LoggerE("Exception: %s", ex.message().c_str());
376   picojson::value result = picojson::value(picojson::object());
377   ReportError(ex, result.get<picojson::object>());
378   SendSyncReply(result.serialize().c_str());
379 }
380
381 void ParsedInstance::HandleError(const PlatformResult& e) {
382   LoggerE("Error: %d", static_cast<int>(e.error_code()));
383   picojson::value result = picojson::value(picojson::object());
384   ReportError(e, &result.get<picojson::object>());
385   SendSyncReply(result.serialize().c_str());
386 }
387
388 }  // namespace common