Fix invalid licenses
[platform/framework/web/crosswalk-tizen.git] / src / extension / widget / widget.cc
1 /*
2  * Copyright (c) 2015 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 "extension/widget/widget.h"
17
18 #include <list>
19 #include <memory>
20 #include <map>
21 #include <vector>
22
23 #include "extension/xwalk/XW_Extension.h"
24 #include "extension/xwalk/XW_Extension_EntryPoints.h"
25 #include "extension/xwalk/XW_Extension_Permissions.h"
26 #include "extension/xwalk/XW_Extension_Runtime.h"
27 #include "extension/xwalk/XW_Extension_SyncMessage.h"
28
29 #include "extension/widget/picojson.h"
30 #include "common/logger.h"
31 #include "common/app_db.h"
32 #include "common/application_data.h"
33 #include "common/locale_manager.h"
34 #include "common/string_utils.h"
35
36 XW_Extension g_xw_extension = 0;
37 std::string g_appid;
38 std::unique_ptr<wrt::ApplicationData> g_appdata;
39 const XW_CoreInterface* g_core = NULL;
40 const XW_MessagingInterface* g_messaging = NULL;
41 const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL;
42 const XW_Internal_EntryPointsInterface* g_entry_points = NULL;
43 const XW_Internal_RuntimeInterface* g_runtime = NULL;
44 extern const char kSource_widget_api[];
45
46 typedef void (*CmdHandler)(const picojson::value& args, picojson::object* out);
47
48 static void InitHandler(const picojson::value& args, picojson::object* out);
49 static void KeyHandler(const picojson::value& args, picojson::object* out);
50 static void GetItemHandler(const picojson::value& args,
51                            picojson::object* out);
52 static void LengthHandler(const picojson::value& args,
53                            picojson::object* out);
54 static void ClearHandler(const picojson::value& args,
55                            picojson::object* out);
56 static void SetItemHandler(const picojson::value& args,
57                            picojson::object* out);
58 static void RemoveHandler(const picojson::value& args,
59                            picojson::object* out);
60
61 std::map<std::string, CmdHandler> g_handler = {
62   {"init", InitHandler},
63   {"key", KeyHandler},
64   {"length", LengthHandler},
65   {"clear", ClearHandler},
66   {"getItem", GetItemHandler},
67   {"setItem", SetItemHandler},
68   {"removeItem", RemoveHandler},
69 };
70
71
72 static void HandleMessage(XW_Instance instance,
73                           const char* message,
74                           bool sync);
75
76 extern "C" int32_t XW_Initialize(XW_Extension extension,
77                                  XW_GetInterface get_interface) {
78   g_xw_extension = extension;
79   g_core = reinterpret_cast<const XW_CoreInterface*>(
80       get_interface(XW_CORE_INTERFACE));
81   if (!g_core) {
82     LOGGER(ERROR)
83         << "Can't initialize extension: error getting Core interface.";
84     return XW_ERROR;
85   }
86
87   g_messaging = reinterpret_cast<const XW_MessagingInterface*>(
88       get_interface(XW_MESSAGING_INTERFACE));
89   if (!g_messaging) {
90     LOGGER(ERROR)
91         << "Can't initialize extension: error getting Messaging interface.";
92     return XW_ERROR;
93   }
94
95   g_sync_messaging =
96       reinterpret_cast<const XW_Internal_SyncMessagingInterface*>(
97           get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE));
98   if (!g_sync_messaging) {
99     LOGGER(ERROR)
100         << "Can't initialize extension: "
101         << "error getting SyncMessaging interface.";
102     return XW_ERROR;
103   }
104
105   g_entry_points = reinterpret_cast<const XW_Internal_EntryPointsInterface*>(
106       get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
107   if (!g_entry_points) {
108     LOGGER(ERROR)
109         << "NOTE: Entry points interface not available in this version "
110         << "of Crosswalk, ignoring entry point data for extensions.\n";
111     return XW_ERROR;
112   }
113
114   g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
115       get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
116   if (!g_runtime) {
117     LOGGER(ERROR)
118         << "NOTE: runtime interface not available in this version "
119         << "of Crosswalk, ignoring runtime variables for extensions.\n";
120     return XW_ERROR;
121   }
122
123   std::vector<char> res(256, 0);
124   g_runtime->GetRuntimeVariableString(extension, "app_id", &res[0], 256);
125   g_appid = std::string(res.begin(), res.end());
126   if (g_appid.at(0) == '"') {
127     g_appid = g_appid.substr(1, g_appid.size()-2);
128   }
129
130   g_core->RegisterInstanceCallbacks(
131       g_xw_extension,
132       [](XW_Instance /*instance*/){
133         if (g_appdata.get() == NULL) {
134           g_appdata.reset(new wrt::ApplicationData(g_appid));
135         }
136         wrt::Widget::GetInstance()->Initialize(g_appdata.get());
137       },
138       NULL);
139
140   g_messaging->Register(g_xw_extension, [](XW_Instance instance,
141                                            const char* message) {
142     HandleMessage(instance, message, false);
143   });
144   g_sync_messaging->Register(g_xw_extension, [](XW_Instance instance,
145                                                 const char* message) {
146     HandleMessage(instance, message, true);
147   });
148
149   g_core->SetExtensionName(g_xw_extension, "Widget");
150   const char* entry_points[] = {"widget", NULL};
151   g_entry_points->SetExtraJSEntryPoints(g_xw_extension, entry_points);
152   g_core->SetJavaScriptAPI(g_xw_extension, kSource_widget_api);
153
154   return XW_OK;
155 }
156
157 static void InitHandler(const picojson::value& /*args*/,
158                         picojson::object* out) {
159   picojson::value result = picojson::value(picojson::object());
160   picojson::object& obj = result.get<picojson::object>();
161
162   auto widget_info = g_appdata->widget_info();
163   if (widget_info.get() == NULL) {
164     out->insert(std::make_pair("status", picojson::value("error")));
165     return;
166   }
167   out->insert(std::make_pair("status", picojson::value("success")));
168
169   wrt::LocaleManager locale_manager;
170   if (!widget_info->default_locale().empty()) {
171     locale_manager.SetDefaultLocale(widget_info->default_locale());
172   }
173
174   // TODO(sngn.lee): should be returned localized string
175   obj["author"] = picojson::value(widget_info->author());
176   obj["description"] = picojson::value(
177       locale_manager.GetLocalizedString(widget_info->description_set()));
178   obj["name"] = picojson::value(
179       locale_manager.GetLocalizedString(widget_info->name_set()));
180   obj["shortName"] = picojson::value(
181       locale_manager.GetLocalizedString(widget_info->short_name_set()));
182   obj["version"] = picojson::value(widget_info->version());
183   obj["id"] = picojson::value(widget_info->id());
184   obj["authorEmail"] = picojson::value(widget_info->author_email());
185   obj["authorHref"] = picojson::value(widget_info->author_href());
186   obj["height"] = picojson::value(static_cast<double>(widget_info->height()));
187   obj["width"] = picojson::value(static_cast<double>(widget_info->width()));
188
189   out->insert(std::make_pair("result", result));
190 }
191
192 static void KeyHandler(const picojson::value& args, picojson::object* out) {
193   int idx = static_cast<int>(args.get("idx").get<double>());
194   std::string key;
195   if (!wrt::Widget::GetInstance()->Key(idx, &key)) {
196     out->insert(std::make_pair("status", picojson::value("error")));
197     return;
198   }
199   out->insert(std::make_pair("status", picojson::value("success")));
200   out->insert(std::make_pair("result", picojson::value(key)));
201 }
202
203 static void GetItemHandler(const picojson::value& args,
204                            picojson::object* out) {
205   const std::string& key = args.get("key").get<std::string>();
206   std::string value;
207   if (!wrt::Widget::GetInstance()->GetItem(key, &value)) {
208     out->insert(std::make_pair("status", picojson::value("error")));
209     return;
210   }
211   out->insert(std::make_pair("status", picojson::value("success")));
212   out->insert(std::make_pair("result", picojson::value(value)));
213 }
214
215 static void LengthHandler(const picojson::value& /*args*/,
216                            picojson::object* out) {
217   int length = wrt::Widget::GetInstance()->Length();
218   out->insert(std::make_pair("status", picojson::value("success")));
219   out->insert(
220       std::make_pair("result", picojson::value(static_cast<double>(length))));
221 }
222
223 static void ClearHandler(const picojson::value& /*args*/,
224                            picojson::object* out) {
225   wrt::Widget::GetInstance()->Clear();
226   out->insert(std::make_pair("status", picojson::value("success")));
227 }
228
229 static void SetItemHandler(const picojson::value& args,
230                            picojson::object* out) {
231   const std::string& key = args.get("key").get<std::string>();
232   const std::string& value = args.get("value").get<std::string>();
233   std::string oldvalue;
234   if (wrt::Widget::GetInstance()->GetItem(key, &oldvalue)) {
235     out->insert(std::make_pair("result", picojson::value(oldvalue)));
236   } else {
237     out->insert(std::make_pair("result", picojson::value()));
238   }
239   wrt::Widget::GetInstance()->SetItem(key, value);
240   out->insert(std::make_pair("status", picojson::value("success")));
241 }
242
243 static void RemoveHandler(const picojson::value& args,
244                            picojson::object* out) {
245   const std::string& key = args.get("key").get<std::string>();
246   std::string oldvalue;
247   if (wrt::Widget::GetInstance()->GetItem(key, &oldvalue)) {
248     out->insert(std::make_pair("result", picojson::value(oldvalue)));
249   } else {
250     out->insert(std::make_pair("result", picojson::value()));
251   }
252   wrt::Widget::GetInstance()->RemoveItem(key);
253   out->insert(std::make_pair("status", picojson::value("success")));
254 }
255
256
257 static void HandleMessage(XW_Instance instance,
258                           const char* message,
259                           bool sync) {
260   picojson::value value;
261   std::string err;
262   picojson::parse(value, message, message + strlen(message), &err);
263   if (!err.empty()) {
264     LOGGER(ERROR) << "Ignoring message. " << err;
265     return;
266   }
267
268   if (!value.is<picojson::object>()) {
269     LOGGER(ERROR) << "Ignoring message. It is not an object.";
270     return;
271   }
272
273   std::string cmd = value.get("cmd").to_str();
274   // check for args in JSON message
275   const picojson::value& args = value.get("args");
276   picojson::value result = picojson::value(picojson::object());
277
278   auto handler = g_handler.find(cmd);
279   if (handler != g_handler.end()) {
280     handler->second(args, &result.get<picojson::object>());
281   } else {
282     result.get<picojson::object>().insert(
283         std::make_pair("status", picojson::value("error")));
284   }
285
286   if (sync) {
287     g_sync_messaging->SetSyncReply(instance, result.serialize().c_str());
288   }
289 }
290
291 namespace wrt {
292
293 namespace {
294   const char* kDbInitedCheckKey = "__WRT_DB_INITED__";
295   const char* kDBPublicSection = "public";
296   const char* kDBPrivateSection = "private";
297 }  // namespace
298
299
300 Widget* Widget::GetInstance() {
301   static Widget instance;
302   return &instance;
303 }
304
305 Widget::Widget() {
306 }
307 Widget::~Widget() {
308 }
309
310 void Widget::Initialize(const ApplicationData* appdata) {
311   AppDB* db = AppDB::GetInstance();
312   if (db->HasKey(kDBPrivateSection, kDbInitedCheckKey))
313     return;
314   if (appdata->widget_info() == NULL)
315     return;
316
317   auto preferences = appdata->widget_info()->preferences();
318   auto it = preferences.begin();
319   for ( ; it != preferences.end(); ++it) {
320     db->Set(kDBPublicSection,
321             (*it)->Name(),
322             (*it)->Value());
323   }
324   db->Set(kDBPrivateSection, kDbInitedCheckKey, "true");
325 }
326
327 int Widget::Length() {
328   AppDB* db = AppDB::GetInstance();
329   std::list<std::string> list;
330   db->GetKeys(kDBPublicSection, &list);
331   return list.size();
332 }
333
334 bool Widget::Key(int idx, std::string* key) {
335   AppDB* db = AppDB::GetInstance();
336   std::list<std::string> list;
337   db->GetKeys(kDBPublicSection, &list);
338
339   auto it = list.begin();
340   for ( ; it != list.end() && idx >= 0; ++it) {
341     if (idx == 0) {
342       *key = *it;
343       return true;
344     }
345     idx--;
346   }
347   return false;
348 }
349
350 bool Widget::GetItem(const std::string& key, std::string* value) {
351   AppDB* db = AppDB::GetInstance();
352   if (!db->HasKey(kDBPublicSection, key))
353     return false;
354   *value = db->Get(kDBPublicSection, key);
355   return true;
356 }
357
358 bool Widget::SetItem(const std::string& key, const std::string& value) {
359   AppDB* db = AppDB::GetInstance();
360   db->Set(kDBPublicSection, key, value);
361   return true;
362 }
363
364 bool Widget::RemoveItem(const std::string& key) {
365   AppDB* db = AppDB::GetInstance();
366   if (!db->HasKey(kDBPublicSection, key))
367     return false;
368   db->Remove(kDBPublicSection, key);
369   return true;
370 }
371
372 void Widget::Clear() {
373   AppDB* db = AppDB::GetInstance();
374   std::list<std::string> list;
375   db->GetKeys(kDBPublicSection, &list);
376   auto it = list.begin();
377   for ( ; it != list.end(); ++it) {
378     db->Remove(kDBPublicSection, *it);
379   }
380 }
381
382 }  // namespace wrt