1 // Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #include "extension/widget/widget.h"
11 #include "extension/xwalk/XW_Extension.h"
12 #include "extension/xwalk/XW_Extension_EntryPoints.h"
13 #include "extension/xwalk/XW_Extension_Permissions.h"
14 #include "extension/xwalk/XW_Extension_Runtime.h"
15 #include "extension/xwalk/XW_Extension_SyncMessage.h"
17 #include "extension/widget/picojson.h"
18 #include "common/logger.h"
19 #include "common/app_db.h"
20 #include "common/application_data.h"
21 #include "common/locale_manager.h"
22 #include "common/string_utils.h"
24 XW_Extension g_xw_extension = 0;
26 std::unique_ptr<wrt::ApplicationData> g_appdata;
27 const XW_CoreInterface* g_core = NULL;
28 const XW_MessagingInterface* g_messaging = NULL;
29 const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL;
30 const XW_Internal_EntryPointsInterface* g_entry_points = NULL;
31 const XW_Internal_RuntimeInterface* g_runtime = NULL;
32 extern const char kSource_widget_api[];
34 typedef void (*CmdHandler)(const picojson::value& args, picojson::object* out);
36 static void InitHandler(const picojson::value& args, picojson::object* out);
37 static void KeyHandler(const picojson::value& args, picojson::object* out);
38 static void GetItemHandler(const picojson::value& args,
39 picojson::object* out);
40 static void LengthHandler(const picojson::value& args,
41 picojson::object* out);
42 static void ClearHandler(const picojson::value& args,
43 picojson::object* out);
44 static void SetItemHandler(const picojson::value& args,
45 picojson::object* out);
46 static void RemoveHandler(const picojson::value& args,
47 picojson::object* out);
49 std::map<std::string, CmdHandler> g_handler = {
50 {"init", InitHandler},
52 {"length", LengthHandler},
53 {"clear", ClearHandler},
54 {"getItem", GetItemHandler},
55 {"setItem", SetItemHandler},
56 {"removeItem", RemoveHandler},
60 static void HandleMessage(XW_Instance instance,
64 extern "C" int32_t XW_Initialize(XW_Extension extension,
65 XW_GetInterface get_interface) {
66 g_xw_extension = extension;
67 g_core = reinterpret_cast<const XW_CoreInterface*>(
68 get_interface(XW_CORE_INTERFACE));
71 << "Can't initialize extension: error getting Core interface.";
75 g_messaging = reinterpret_cast<const XW_MessagingInterface*>(
76 get_interface(XW_MESSAGING_INTERFACE));
79 << "Can't initialize extension: error getting Messaging interface.";
84 reinterpret_cast<const XW_Internal_SyncMessagingInterface*>(
85 get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE));
86 if (!g_sync_messaging) {
88 << "Can't initialize extension: "
89 << "error getting SyncMessaging interface.";
93 g_entry_points = reinterpret_cast<const XW_Internal_EntryPointsInterface*>(
94 get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
95 if (!g_entry_points) {
97 << "NOTE: Entry points interface not available in this version "
98 << "of Crosswalk, ignoring entry point data for extensions.\n";
102 g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
103 get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
106 << "NOTE: runtime interface not available in this version "
107 << "of Crosswalk, ignoring runtime variables for extensions.\n";
111 std::vector<char> res(256, 0);
112 g_runtime->GetRuntimeVariableString(extension, "app_id", &res[0], 256);
113 g_appid = std::string(res.begin(), res.end());
114 if (g_appid.at(0) == '"') {
115 g_appid = g_appid.substr(1, g_appid.size()-2);
118 g_core->RegisterInstanceCallbacks(
120 [](XW_Instance /*instance*/){
121 if (g_appdata.get() == NULL) {
122 g_appdata.reset(new wrt::ApplicationData(g_appid));
124 wrt::Widget::GetInstance()->Initialize(g_appdata.get());
128 g_messaging->Register(g_xw_extension, [](XW_Instance instance,
129 const char* message) {
130 HandleMessage(instance, message, false);
132 g_sync_messaging->Register(g_xw_extension, [](XW_Instance instance,
133 const char* message) {
134 HandleMessage(instance, message, true);
137 g_core->SetExtensionName(g_xw_extension, "Widget");
138 const char* entry_points[] = {"widget", NULL};
139 g_entry_points->SetExtraJSEntryPoints(g_xw_extension, entry_points);
140 g_core->SetJavaScriptAPI(g_xw_extension, kSource_widget_api);
145 static void InitHandler(const picojson::value& /*args*/,
146 picojson::object* out) {
147 picojson::value result = picojson::value(picojson::object());
148 picojson::object& obj = result.get<picojson::object>();
150 auto widget_info = g_appdata->widget_info();
151 if (widget_info.get() == NULL) {
152 out->insert(std::make_pair("status", picojson::value("error")));
155 out->insert(std::make_pair("status", picojson::value("success")));
157 wrt::LocaleManager locale_manager;
158 if (!widget_info->default_locale().empty()) {
159 locale_manager.SetDefaultLocale(widget_info->default_locale());
162 // TODO(sngn.lee): should be returned localized string
163 obj["author"] = picojson::value(widget_info->author());
164 obj["description"] = picojson::value(
165 locale_manager.GetLocalizedString(widget_info->description_set()));
166 obj["name"] = picojson::value(
167 locale_manager.GetLocalizedString(widget_info->name_set()));
168 obj["shortName"] = picojson::value(
169 locale_manager.GetLocalizedString(widget_info->short_name_set()));
170 obj["version"] = picojson::value(widget_info->version());
171 obj["id"] = picojson::value(widget_info->id());
172 obj["authorEmail"] = picojson::value(widget_info->author_email());
173 obj["authorHref"] = picojson::value(widget_info->author_href());
174 obj["height"] = picojson::value(static_cast<double>(widget_info->height()));
175 obj["width"] = picojson::value(static_cast<double>(widget_info->width()));
177 out->insert(std::make_pair("result", result));
180 static void KeyHandler(const picojson::value& args, picojson::object* out) {
181 int idx = static_cast<int>(args.get("idx").get<double>());
183 if (!wrt::Widget::GetInstance()->Key(idx, &key)) {
184 out->insert(std::make_pair("status", picojson::value("error")));
187 out->insert(std::make_pair("status", picojson::value("success")));
188 out->insert(std::make_pair("result", picojson::value(key)));
191 static void GetItemHandler(const picojson::value& args,
192 picojson::object* out) {
193 const std::string& key = args.get("key").get<std::string>();
195 if (!wrt::Widget::GetInstance()->GetItem(key, &value)) {
196 out->insert(std::make_pair("status", picojson::value("error")));
199 out->insert(std::make_pair("status", picojson::value("success")));
200 out->insert(std::make_pair("result", picojson::value(value)));
203 static void LengthHandler(const picojson::value& /*args*/,
204 picojson::object* out) {
205 int length = wrt::Widget::GetInstance()->Length();
206 out->insert(std::make_pair("status", picojson::value("success")));
208 std::make_pair("result", picojson::value(static_cast<double>(length))));
211 static void ClearHandler(const picojson::value& /*args*/,
212 picojson::object* out) {
213 wrt::Widget::GetInstance()->Clear();
214 out->insert(std::make_pair("status", picojson::value("success")));
217 static void SetItemHandler(const picojson::value& args,
218 picojson::object* out) {
219 const std::string& key = args.get("key").get<std::string>();
220 const std::string& value = args.get("value").get<std::string>();
221 std::string oldvalue;
222 if (wrt::Widget::GetInstance()->GetItem(key, &oldvalue)) {
223 out->insert(std::make_pair("result", picojson::value(oldvalue)));
225 out->insert(std::make_pair("result", picojson::value()));
227 wrt::Widget::GetInstance()->SetItem(key, value);
228 out->insert(std::make_pair("status", picojson::value("success")));
231 static void RemoveHandler(const picojson::value& args,
232 picojson::object* out) {
233 const std::string& key = args.get("key").get<std::string>();
234 std::string oldvalue;
235 if (wrt::Widget::GetInstance()->GetItem(key, &oldvalue)) {
236 out->insert(std::make_pair("result", picojson::value(oldvalue)));
238 out->insert(std::make_pair("result", picojson::value()));
240 wrt::Widget::GetInstance()->RemoveItem(key);
241 out->insert(std::make_pair("status", picojson::value("success")));
245 static void HandleMessage(XW_Instance instance,
248 picojson::value value;
250 picojson::parse(value, message, message + strlen(message), &err);
252 LOGGER(ERROR) << "Ignoring message. " << err;
256 if (!value.is<picojson::object>()) {
257 LOGGER(ERROR) << "Ignoring message. It is not an object.";
261 std::string cmd = value.get("cmd").to_str();
262 // check for args in JSON message
263 const picojson::value& args = value.get("args");
264 picojson::value result = picojson::value(picojson::object());
266 auto handler = g_handler.find(cmd);
267 if (handler != g_handler.end()) {
268 handler->second(args, &result.get<picojson::object>());
270 result.get<picojson::object>().insert(
271 std::make_pair("status", picojson::value("error")));
275 g_sync_messaging->SetSyncReply(instance, result.serialize().c_str());
282 const char* kDbInitedCheckKey = "__WRT_DB_INITED__";
283 const char* kDBPublicSection = "public";
284 const char* kDBPrivateSection = "private";
288 Widget* Widget::GetInstance() {
289 static Widget instance;
298 void Widget::Initialize(const ApplicationData* appdata) {
299 AppDB* db = AppDB::GetInstance();
300 if (db->HasKey(kDBPrivateSection, kDbInitedCheckKey))
302 if (appdata->widget_info() == NULL)
305 auto preferences = appdata->widget_info()->preferences();
306 auto it = preferences.begin();
307 for ( ; it != preferences.end(); ++it) {
308 db->Set(kDBPublicSection,
312 db->Set(kDBPrivateSection, kDbInitedCheckKey, "true");
315 int Widget::Length() {
316 AppDB* db = AppDB::GetInstance();
317 std::list<std::string> list;
318 db->GetKeys(kDBPublicSection, &list);
322 bool Widget::Key(int idx, std::string* key) {
323 AppDB* db = AppDB::GetInstance();
324 std::list<std::string> list;
325 db->GetKeys(kDBPublicSection, &list);
327 auto it = list.begin();
328 for ( ; it != list.end() && idx >= 0; ++it) {
338 bool Widget::GetItem(const std::string& key, std::string* value) {
339 AppDB* db = AppDB::GetInstance();
340 if (!db->HasKey(kDBPublicSection, key))
342 *value = db->Get(kDBPublicSection, key);
346 bool Widget::SetItem(const std::string& key, const std::string& value) {
347 AppDB* db = AppDB::GetInstance();
348 db->Set(kDBPublicSection, key, value);
352 bool Widget::RemoveItem(const std::string& key) {
353 AppDB* db = AppDB::GetInstance();
354 if (!db->HasKey(kDBPublicSection, key))
356 db->Remove(kDBPublicSection, key);
360 void Widget::Clear() {
361 AppDB* db = AppDB::GetInstance();
362 std::list<std::string> list;
363 db->GetKeys(kDBPublicSection, &list);
364 auto it = list.begin();
365 for ( ; it != list.end(); ++it) {
366 db->Remove(kDBPublicSection, *it);