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.
6 #include "common/extension.h"
13 #include "common/assert.h"
14 #include "common/logger.h"
15 #include "common/tools.h"
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");
26 // this variable is valid only during Extension::XW_Initialize() call
28 // it's here, so we don't have to modify the interface of CreateExtension(), Extension(), etc.
29 XW_Extension g_xw_extension_ = 0;
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;
38 bool InitializeInterfaces(XW_GetInterface get_interface) {
40 static bool initialized = false;
43 g_core = reinterpret_cast<const XW_CoreInterface*>(get_interface(XW_CORE_INTERFACE));
45 LoggerE("Can't initialize extension: error getting Core interface.");
50 reinterpret_cast<const XW_MessagingInterface*>(get_interface(XW_MESSAGING_INTERFACE));
52 LoggerE("Can't initialize extension: error getting Messaging interface.");
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.");
63 g_entry_points = reinterpret_cast<const XW_Internal_EntryPointsInterface*>(
64 get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
65 if (!g_entry_points) {
67 "NOTE: Entry points interface not available in this version "
68 "of runtime, ignoring entry point data for extensions.");
71 g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
72 get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
75 "NOTE: runtime interface not available in this version "
76 "of runtime, ignoring runtime variables for extensions.");
79 g_permission = reinterpret_cast<const XW_Internal_PermissionsInterface*>(
80 get_interface(XW_INTERNAL_PERMISSIONS_INTERFACE));
83 "NOTE: permission interface not available in this version "
84 "of runtime, ignoring permission for extensions.");
97 Extension::Extension() : xw_extension_(g_xw_extension_) {
101 Extension::~Extension() {
105 void Extension::SetExtensionName(const char* name) {
107 g_core->SetExtensionName(xw_extension_, name);
110 void Extension::SetJavaScriptAPI(const char* api) {
112 g_core->SetJavaScriptAPI(xw_extension_, api);
115 void Extension::SetExtraJSEntryPoints(const char** entry_points) {
117 if (g_entry_points) g_entry_points->SetExtraJSEntryPoints(xw_extension_, entry_points);
120 bool Extension::RegisterPermissions(const char* perm_table) {
122 if (g_permission) return g_permission->RegisterPermissions(xw_extension_, perm_table);
126 bool Extension::CheckAPIAccessControl(const char* api_name) {
128 if (g_permission) return g_permission->CheckAPIAccessControl(xw_extension_, api_name);
132 Instance* Extension::CreateInstance() {
137 std::string Extension::GetRuntimeVariable(const char* var_name, unsigned len) {
139 if (!g_runtime) return "";
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);
159 void Extension::OnInstanceCreated(XW_Instance xw_instance, Instance* instance) {
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();
169 void Extension::OnInstanceDestroyed(XW_Instance xw_instance) {
171 Instance* instance = reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
172 if (!instance) return;
173 instance->xw_instance_ = 0;
178 void Extension::HandleMessage(XW_Instance xw_instance, const char* msg) {
180 Instance* instance = reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
181 if (!instance) return;
182 instance->HandleMessage(msg);
186 void Extension::HandleSyncMessage(XW_Instance xw_instance, const char* msg) {
188 Instance* instance = reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
189 if (!instance) return;
190 instance->HandleSyncMessage(msg);
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) {
201 if (!InitializeInterfaces(get_interface)) {
205 g_xw_extension_ = extension;
207 if (XW_ERROR == initialize(extension, get_interface)) {
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);
221 std::mutex Instance::instances_mutex_;
222 std::unordered_set<Instance*> Instance::all_instances_;
224 Instance::Instance() : xw_instance_(0) {
227 std::lock_guard<std::mutex> lock{instances_mutex_};
228 all_instances_.insert(this);
232 Instance::~Instance() {
235 std::lock_guard<std::mutex> lock{instances_mutex_};
236 all_instances_.erase(this);
238 Assert(xw_instance_ == 0);
241 void Instance::PostMessage(Instance* that, const char* msg) {
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);
250 LoggerE("Trying to post message to non-existing instance: [%p], ignoring", that);
253 void Instance::PostMessage(const char* msg) {
257 "Ignoring PostMessage() in the constructor or after the "
258 "instance was destroyed.");
261 g_messaging->PostMessage(xw_instance_, msg);
264 void Instance::SendSyncReply(const char* reply) {
268 "Ignoring SendSyncReply() in the constructor or after the "
269 "instance was destroyed.");
272 g_sync_messaging->SetSyncReply(xw_instance_, reply);
275 ParsedInstance::ParsedInstance() {
279 ParsedInstance::~ParsedInstance() {
283 void ParsedInstance::RegisterHandler(const std::string& name, const NativeHandler& func) {
285 handler_map_.insert(std::make_pair(name, func));
288 void ParsedInstance::RegisterSyncHandler(const std::string& name, const NativeHandler& func) {
290 handler_map_.insert(std::make_pair("#SYNC#" + name, func));
293 void ParsedInstance::ReportSuccess(picojson::object& out) {
295 tools::ReportSuccess(out);
298 void ParsedInstance::ReportSuccess(const picojson::value& result, picojson::object& out) {
300 tools::ReportSuccess(result, out);
303 void ParsedInstance::ReportError(picojson::object& out) {
305 tools::ReportError(out);
308 void ParsedInstance::ReportError(const PlatformException& ex, picojson::object& out) {
310 tools::ReportError(ex, out);
313 void ParsedInstance::ReportError(const PlatformResult& error, picojson::object* out) {
315 tools::ReportError(error, out);
318 void ParsedInstance::HandleMessage(const char* msg) {
320 HandleMessage(msg, false);
323 void ParsedInstance::HandleSyncMessage(const char* msg) {
325 HandleMessage(msg, true);
328 void ParsedInstance::HandleMessage(const char* msg, bool is_sync) {
331 picojson::value value;
333 picojson::parse(value, msg, msg + strlen(msg), &err);
335 LoggerE("Ignoring message:\"%s\", error: %s", msg, err.c_str());
339 if (!value.is<picojson::object>()) {
340 LoggerE("Ignoring message. It is not an object.");
344 std::string cmd = (is_sync ? "#SYNC#" : "") + value.get("cmd").to_str();
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.");
352 NativeHandler func = it->second;
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");
360 picojson::value result = picojson::value(picojson::object());
361 func(args, result.get<picojson::object>());
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);
369 return HandleException(UnknownException("Unknown exception"));
373 void ParsedInstance::HandleException(const PlatformException& ex) {
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());
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());
388 } // namespace common