Merge branch 'tizen_5.0' into tizen 05/193805/1 accepted/tizen/unified/20181127.073334 accepted/tizen/unified/20181128.144730 submit/tizen/20181126.112620 submit/tizen/20181128.010852
authorLukasz Bardeli <l.bardeli@AMDC967.digital.local>
Mon, 26 Nov 2018 11:19:29 +0000 (12:19 +0100)
committerLukasz Bardeli <l.bardeli@AMDC967.digital.local>
Mon, 26 Nov 2018 11:19:29 +0000 (12:19 +0100)
Change-Id: I7c84d15458fb0b79f5379924c0745dc69e963e9c

packaging/webapi-plugins.spec
src/application/application_manager.cc
src/application/application_manager.h
src/application/application_utils.cc
src/application/application_utils.h
src/archive/filesystem_node.cc
src/common/common.gyp
src/filesystem/js/file.js
src/filesystem/js/file_handle.js
src/ppm/ppm_instance.cc
src/widgetservice/widgetservice_api.js

index 76b7884..15c19d3 100644 (file)
@@ -8,7 +8,7 @@
 %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions}
 
 Name:       webapi-plugins
-Version:    2.34
+Version:    2.35
 Release:    0
 License:    Apache-2.0 and BSD-3-Clause and MIT
 Group:      Development/Libraries
index fc6cf28..1815a80 100644 (file)
@@ -213,7 +213,7 @@ class TerminateHandler {
     return;                                                        \
   }
 
-void ApplicationManager::AsyncResponse(PlatformResult& result,
+void ApplicationManager::AsyncResponse(const PlatformResult& result,
                                        std::shared_ptr<picojson::value>* response) {
   ScopeLogger();
   LogAndReportError(result, &(*response)->get<picojson::object>());
@@ -375,82 +375,52 @@ void ApplicationManager::Kill(const picojson::value& args) {
   kill();
 }
 
-void ApplicationManager::Launch(const picojson::value& args) {
+namespace {
+
+PlatformResult PrepareAppControlForLaunchAppControl(const picojson::value& args,
+                                                    app_control_h* app_control) {
   ScopeLogger();
 
-  int callback_id = -1;
-  const auto& callback = args.get(kCallbackId);
-  if (callback.is<double>()) {
-    callback_id = static_cast<int>(callback.get<double>());
+  const auto& control = args.get("appControl");
+  if (!control.is<picojson::object>()) {
+    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
   }
+  const picojson::object& app_control_obj = control.get<picojson::object>();
 
-  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
-  picojson::object& obj = response->get<picojson::object>();
-  obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+  app_control_h tmp_app_control = nullptr;
+  auto result = ApplicationUtils::ApplicationControlToService(app_control_obj, &tmp_app_control);
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
+      app_control_ptr(tmp_app_control, &app_control_destroy);
 
-  const auto& app_id = args.get("id");
-  if (!app_id.is<std::string>()) {
-    PlatformResult ret =
-        LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
-    AsyncResponse(ret, &response);
-    return;
+  if (result.IsError()) {
+    LoggerE("Application control to service failed.");
+    return result;
   }
-  const std::string& id = app_id.get<std::string>();
 
-  auto launch = [id](const std::shared_ptr<picojson::value>& response) -> void {
-    ScopeLogger("launch");
-    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
-    const char* app_id = id.c_str();
-    const int retry_count = 3;
+  std::string app_id;
+  const auto& id = args.get("id");
+  if (id.is<std::string>()) {
+    app_id = id.get<std::string>();
+  }
 
-    int retry = 0;
-    int ret = 0;
+  if (!app_id.empty()) {
+    LoggerD("app_id: %s", app_id.c_str());
 
-    while (retry < retry_count) {
-      ret = aul_open_app(app_id);
+    int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
 
-      if (ret >= 0) {
-        break;
-      }
-
-      // delay 300ms for each retry
-      struct timespec sleep_time = {0, 300L * 1000L * 1000L};
-      nanosleep(&sleep_time, nullptr);
-      ++retry;
-
-      LoggerD("Retry launch request: %d", retry);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
     }
+  }
 
-    if (ret < 0) {
-      result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error has occurred.");
-
-      LoggerD("Aul open return: %d (%s)", ret, get_error_message(ret));
-      switch (ret) {
-        case AUL_R_EINVAL:
-        case AUL_R_ERROR:
-        case AUL_R_ENOAPP:
-          result =
-              LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Launchpad returns not found error.",
-                                 ("aul_open_app returns Not Found error"));
-          break;
-
-        case AUL_R_ECOMM:
-          result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Internal IPC error has occurred.",
-                                      ("aul_open_app returns internal IPC error"));
-          break;
-      }
-
-      LogAndReportError(result, &response->get<picojson::object>());
-    } else {
-      LoggerD("Launch request success");
-      ReportSuccess(response->get<picojson::object>());
-    }
-  };
+  *app_control = app_control_ptr.release();
 
-  launch(response);
-  Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+}  // namespace
+
 void ApplicationManager::LaunchAppControl(const picojson::value& args) {
   ScopeLogger();
 
@@ -465,180 +435,226 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) {
   response_obj.insert(
       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
 
-  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
-  const auto& control = args.get("appControl");
-  if (!control.is<picojson::object>()) {
-    result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
-    AsyncResponse(result, &response);
-    return;
-  }
-  const picojson::object& app_control_obj = control.get<picojson::object>();
-
-  std::string launch_mode_str;
-  const auto& launch_mode = control.get("launchMode");
-  if (launch_mode.is<std::string>()) {
-    launch_mode_str = launch_mode.get<std::string>();
-  }
-
   app_control_h app_control = nullptr;
-  result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
-  std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
-      app_control, &app_control_destroy);  // automatically release the memory
-
-  if (result.IsError()) {
-    LoggerE("Application control to service failed.");
-    AsyncResponse(result, &response);
+  auto prepare_app_control_result = PrepareAppControlForLaunchAppControl(args, &app_control);
+  if (prepare_app_control_result.IsError()) {
+    AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
     return;
   }
 
-  std::string app_id;
-  const auto& id = args.get("id");
-  if (id.is<std::string>()) {
-    app_id = id.get<std::string>();
-  }
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
+      app_control_ptr(app_control, &app_control_destroy);
 
-  std::string reply_callback;
+  std::string reply_callback_id;
   const auto& reply = args.get("replyCallback");
   if (reply.is<std::string>()) {
-    reply_callback = reply.get<std::string>();
+    reply_callback_id = reply.get<std::string>();
   }
 
-  auto launch = [this, app_control_ptr, app_id, launch_mode_str,
-                 reply_callback](const std::shared_ptr<picojson::value>& response) -> void {
-    ScopeLogger("Entered into asynchronous function, launch");
+  struct LaunchAppControlCallbackData {
+    ApplicationInstance* instance;
+    std::shared_ptr<picojson::value> response;
+    std::string reply_callback_id;
+  }* launch_app_user_data = new (std::nothrow)
+      LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id};
 
-    if (!app_id.empty()) {
-      LoggerD("app_id: %s", app_id.c_str());
+  if (!launch_app_user_data) {
+    LoggerE("Memory allocation fail!");
+    AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response);
+    return;
+  }
 
-      int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
+  app_control_reply_cb reply_callback = nullptr;
+  if (!reply_callback_id.empty()) {
+    launch_app_user_data->reply_callback_id = reply_callback_id;
 
-      if (APP_CONTROL_ERROR_NONE != ret) {
-        LogAndReportError(
-            PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
-            &response->get<picojson::object>(),
-            ("Failed to set app id: %d (%s)", ret, get_error_message(ret)));
-        return;
-      }
-    }
+    reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
+                        void* user_data) {
+      ScopeLogger("reply_callback");
 
-    if (!launch_mode_str.empty()) {
-      app_control_launch_mode_e launch_mode;
-
-      if ("SINGLE" == launch_mode_str) {
-        launch_mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
-      } else if ("GROUP" == launch_mode_str) {
-        launch_mode = APP_CONTROL_LAUNCH_MODE_GROUP;
-      } else {
-        ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
-                    &response->get<picojson::object>());
+      LaunchAppControlCallbackData* callback_data =
+          static_cast<LaunchAppControlCallbackData*>(user_data);
+      if (!callback_data) {
+        LoggerD("reply_callback failed: user_data is nullptr");
         return;
       }
 
-      int ret = app_control_set_launch_mode(app_control_ptr.get(), launch_mode);
-      if (APP_CONTROL_ERROR_NONE != ret) {
-        LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Setting launch mode failed."),
-                          &response->get<picojson::object>(),
-                          ("Setting launch mode failed: %d (%s)", ret, get_error_message(ret)));
-        return;
+      picojson::value return_value = picojson::value(picojson::object());
+      picojson::object& return_value_obj = return_value.get<picojson::object>();
+      return_value_obj.insert(
+          std::make_pair(kListenerId, picojson::value(callback_data->reply_callback_id)));
+
+      if (APP_CONTROL_RESULT_SUCCEEDED == result) {
+        LoggerD("App started");
+        return_value_obj.insert(std::make_pair("data", picojson::value(picojson::array())));
+        if (!ApplicationUtils::ServiceToApplicationControlDataArray(
+                reply, &return_value_obj.find("data")->second.get<picojson::array>())) {
+          return_value_obj.erase("data");
+        }
+        ReportSuccess(return_value_obj);
+      } else {
+        ReportError(return_value_obj);
       }
-    }
 
-    app_control_reply_cb callback = nullptr;
-    struct ReplayCallbackData {
-      ApplicationInstance* app_instance;
-      std::string reply_callback;
+      Instance::PostMessage(callback_data->instance, return_value.serialize().c_str());
+      delete callback_data;
     };
+  }
 
-    ReplayCallbackData* user_data = nullptr;
+  app_control_result_cb result_callback = [](app_control_h launch_request,
+                                             app_control_error_e launch_result, void* user_data) {
+    ScopeLogger("LaunchAppControl result_callback");
 
-    if (!reply_callback.empty()) {
-      user_data = new ReplayCallbackData();
-      user_data->app_instance = &this->instance_;
-      user_data->reply_callback = reply_callback;
+    LaunchAppControlCallbackData* callback_data =
+        static_cast<LaunchAppControlCallbackData*>(user_data);
 
-      callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
-                    void* user_data) {
-        LoggerD("send_launch_request callback");
+    auto result = ApplicationUtils::TranslateAppControlError(launch_result);
 
-        picojson::value return_value = picojson::value(picojson::object());
-        picojson::object& return_value_obj = return_value.get<picojson::object>();
-        ReplayCallbackData* reply_callback = static_cast<ReplayCallbackData*>(user_data);
+    if (result.IsError()) {
+      LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
+    } else {
+      ReportSuccess(callback_data->response->get<picojson::object>());
+    }
 
-        if (APP_CONTROL_RESULT_SUCCEEDED == result) {
-          const std::string data = "data";
-          return_value_obj.insert(std::make_pair(data, picojson::value(picojson::array())));
-          if (!ApplicationUtils::ServiceToApplicationControlDataArray(
-                  reply, &return_value_obj.find(data)->second.get<picojson::array>())) {
-            return_value_obj.erase(data);
-          }
-          ReportSuccess(return_value_obj);
-        } else {
-          ReportError(return_value_obj);
-        }
+    Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
 
-        return_value_obj.insert(
-            std::make_pair("listenerId", picojson::value(reply_callback->reply_callback)));
-        Instance::PostMessage(reply_callback->app_instance, return_value.serialize().c_str());
-        delete reply_callback;
-      };
+    if (result.IsError() || (callback_data->reply_callback_id).empty()) {
+      delete callback_data;
     }
+  };
 
-    const int retry_count = 3;
+  /*
+   * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
+   * Previous implementation, using synchronous app_control_send_launch_request,
+   * tries to launch the application 3 times, before reporting an error.
+   * New implementation, using app_control_send_launch_request_async makes only one attempt.
+   * If problems, such as failed application start occur, multiple attempts may solve the problem.
+   */
+  auto launch_result =
+      ApplicationUtils::TranslateAppControlError(static_cast<app_control_error_e>(app_control_send_launch_request_async(
+          app_control_ptr.get(), result_callback, reply_callback, launch_app_user_data)));
+
+  if (launch_result.IsError()) {
+    delete launch_app_user_data;
+    AsyncResponse(launch_result, &response);
+  } else {
+    LoggerD("App launched");
+  }
+}
 
-    int retry = 0;
-    int ret = 0;
+namespace {
 
-    while (retry < retry_count) {
-      LoggerD("Calling launch request. Attempt number: %d", retry);
+PlatformResult TranslateLaunchError(app_control_error_e return_code) {
+  ScopeLogger();
 
-      ret = app_control_send_launch_request(app_control_ptr.get(), callback, user_data);
-      LoggerD("App control launch request returned: %d, %s", ret, get_error_message(ret));
-      if (APP_CONTROL_ERROR_NONE == ret) {
-        break;
-      }
+  auto result = ApplicationUtils::TranslateAppControlError(return_code);
+  if (ErrorCode::SECURITY_ERR == result.error_code()) {
+    result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
+  }
 
-      // delay 300ms for each retry
-      struct timespec sleep_time = {0, 300L * 1000L * 1000L};
-      nanosleep(&sleep_time, nullptr);
-      ++retry;
-    }
+  return result;
+}
+
+PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) {
+  ScopeLogger();
+
+  const auto& app_id = args.get("id");
+  if (!app_id.is<std::string>()) {
+    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+  }
+  const auto app_id_str = app_id.get<std::string>();
+
+  app_control_h tmp_app_control = nullptr;
+  int result = app_control_create(&tmp_app_control);
+  if (APP_CONTROL_ERROR_NONE != result) {
+    LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result));
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
+  }
+
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
+      app_control_ptr(tmp_app_control, &app_control_destroy);
+
+  if (!app_id_str.empty()) {
+    LoggerD("app_id: %s", app_id_str.c_str());
+
+    int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
 
     if (APP_CONTROL_ERROR_NONE != ret) {
-      delete user_data;
-
-      switch (ret) {
-        case APP_CONTROL_ERROR_INVALID_PARAMETER:
-          LogAndReportError(
-              PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter returned."),
-              &response->get<picojson::object>(),
-              ("app_control_send_launch_request returns APP_CONTROL_ERROR_INVALID_PARAMETER"));
-          return;
-        case APP_CONTROL_ERROR_OUT_OF_MEMORY:
-          LogAndReportError(
-              PlatformResult(ErrorCode::UNKNOWN_ERR, "Out of memory."),
-              &response->get<picojson::object>(),
-              ("app_control_send_launch_request returns APP_CONTROL_ERROR_OUT_OF_MEMORY"));
-          return;
-        case APP_CONTROL_ERROR_LAUNCH_REJECTED:
-        case APP_CONTROL_ERROR_APP_NOT_FOUND:
-          LogAndReportError(
-              PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found."),
-              &response->get<picojson::object>(),
-              ("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND"));
-          return;
-        default:
-          LogAndReportError(
-              PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."),
-              &response->get<picojson::object>(),
-              ("app_control_send_launch_request returns: %d (%s)", ret, get_error_message(ret)));
-          return;
-      }
+      LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
     }
-    ReportSuccess(response->get<picojson::object>());
+  }
+
+  *app_control = app_control_ptr.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace
+void ApplicationManager::Launch(const picojson::value& args) {
+  ScopeLogger();
+
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
+  picojson::object& response_obj = response->get<picojson::object>();
+  response_obj.insert(
+      std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+
+  app_control_h app_control = nullptr;
+  auto prepare_app_control_result = PrepareAppControlForLaunch(args, &app_control);
+  if (prepare_app_control_result.IsError()) {
+    AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
+    return;
+  }
+
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
+      app_control_ptr(app_control, &app_control_destroy);
+
+  struct LaunchCallbackData {
+    ApplicationInstance* instance;
+    std::shared_ptr<picojson::value> response;
+  }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
+
+  app_control_result_cb result_callback = [](app_control_h launch_request,
+                                             app_control_error_e launch_result, void* user_data) {
+    ScopeLogger("Launch result_callback");
+
+    LaunchCallbackData* callback_data = static_cast<LaunchCallbackData*>(user_data);
+
+    auto result = TranslateLaunchError(launch_result);
+
+    if (result.IsError()) {
+      LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
+    } else {
+      ReportSuccess(callback_data->response->get<picojson::object>());
+    }
+
+    Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
+
+    delete callback_data;
   };
 
-  launch(response);
-  Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  /*
+   * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
+   * Previous implementation, using synchronous app_control_send_launch_request,
+   * tries to launch the application 3 times, before reporting an error.
+   * New implementation, using app_control_send_launch_request_async makes only one attempt.
+   * If problems, such as failed application start occur, multiple attempts may solve the problem.
+   */
+  auto launch_result = TranslateLaunchError(static_cast<app_control_error_e>(app_control_send_launch_request_async(
+      app_control_ptr.get(), result_callback, nullptr, launch_user_data)));
+
+  if (launch_result.IsError()) {
+    delete launch_user_data;
+    AsyncResponse(launch_result, &response);
+  } else {
+    LoggerD("App launched");
+  }
 }
 
 // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
index c1fa8ad..be0ebbf 100644 (file)
@@ -64,7 +64,8 @@ class ApplicationManager {
   void StartAppInfoEventListener(picojson::object* out);
   void StopAppInfoEventListener();
   void GetApplicationInformationSize(const picojson::value& args, picojson::object* out);
-  void AsyncResponse(common::PlatformResult& result, std::shared_ptr<picojson::value>* response);
+  void AsyncResponse(const common::PlatformResult& result,
+                     std::shared_ptr<picojson::value>* response);
 
   void BroadcastEventHelper(const picojson::value& args, picojson::object& out, bool trusted);
   common::PlatformResult StartEventListener(const std::string& event_name,
index 596d292..5b46388 100644 (file)
@@ -183,64 +183,182 @@ void ApplicationUtils::CreateApplicationMetaData(const char* key, const char* va
   app_meta_data->insert(std::make_pair("value", picojson::value(value)));
 }
 
+namespace {
+
+const std::string kOperationAppControlField = "operation";
+const std::string kURIAppControlField = "uri";
+const std::string kMIMEAppControlField = "mime";
+const std::string kCategoryAppControlField = "category";
+const std::string kLaunchModeAppControlField = "launchMode";
+const std::string kDataAppControlField = "data";
+
+const std::string kGroupLaunchMode = "GROUP";
+const std::string kSingleLaunchMode = "SINGLE";
+
+using AppControlTextFieldSetter = std::function<int(app_control_h, const char*)>;
+// clang-format off
+const std::map<std::string, AppControlTextFieldSetter> AppControlTextFieldSetters = {
+  { kOperationAppControlField, app_control_set_operation },
+  { kURIAppControlField, app_control_set_uri },
+  { kMIMEAppControlField, app_control_set_mime },
+  { kCategoryAppControlField, app_control_set_category }
+};  // clang-format on
+
+PlatformResult SetAppControlTextField(app_control_h app_control, const std::string& field_name,
+                                      const std::string& value) {
+  ScopeLogger("Field: %s, value: %s", field_name.c_str(), value.c_str());
+
+  auto setter_it = AppControlTextFieldSetters.find(field_name);
+  if (AppControlTextFieldSetters.end() == setter_it) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
+  }
+  auto setter = setter_it->second;
+
+  auto result = setter(app_control, value.c_str());
+  auto result_translated =
+      ApplicationUtils::TranslateAppControlError(static_cast<app_control_error_e>(result));
+
+  if (result_translated.IsError()) {
+    LoggerD("Setting app_control's %s field failed: %s", field_name.c_str(),
+            result_translated.message().c_str());
+  }
+
+  return result_translated;
+}
+
+app_control_launch_mode_e LaunchModeStringToEnum(const std::string& launch_mode) {
+  ScopeLogger();
+
+  return launch_mode == kGroupLaunchMode ? APP_CONTROL_LAUNCH_MODE_GROUP
+                                         : APP_CONTROL_LAUNCH_MODE_SINGLE;
+}
+
+bool LaunchModeIsInvalid(const std::string& launch_mode) {
+  ScopeLogger();
+
+  auto is_valid = launch_mode == kSingleLaunchMode || launch_mode == kGroupLaunchMode;
+  LoggerD("Launch mode: %s (%s)", launch_mode.c_str(), is_valid ? "valid" : "invalid");
+
+  return !is_valid;
+}
+
+PlatformResult SetAppControlLaunchModeField(app_control_h app_control,
+                                            const std::string& launch_mode_str) {
+  ScopeLogger();
+
+  if (LaunchModeIsInvalid(launch_mode_str)) {
+    LoggerD("Invalid launchMode value: %s", launch_mode_str.c_str());
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid launchMode value: " + launch_mode_str);
+  }
+
+  auto result = app_control_set_launch_mode(app_control, LaunchModeStringToEnum(launch_mode_str));
+  return ApplicationUtils::TranslateAppControlError(static_cast<app_control_error_e>(result));
+}
+
+PlatformResult SetAppControlDataField(app_control_h app_control, const picojson::array& data) {
+  ScopeLogger();
+
+  for (auto iter = data.begin(); iter != data.end(); ++iter) {
+    if (iter->is<picojson::object>()) {
+      PlatformResult ret = ApplicationUtils::ApplicationControlDataToServiceExtraData(
+          iter->get<picojson::object>(), app_control);
+      if (ret.IsError()) {
+        return ret;
+      }
+    } else {
+      LoggerD("Invalid data value: not an object");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid data type: not an object");
+    }
+  }
+
+  return PlatformResult{ErrorCode::NO_ERROR};
+}
+
+PlatformResult SetAppControlFieldIfValueSpecified(
+    app_control_h app_control, const std::string& field_name,
+    const picojson::object::const_iterator& iterator) {
+  ScopeLogger();
+
+  if (iterator->second.is<std::string>()) {
+    if (field_name != kLaunchModeAppControlField) {
+      return SetAppControlTextField(app_control, field_name, iterator->second.get<std::string>());
+    }
+    return SetAppControlLaunchModeField(app_control, iterator->second.get<std::string>());
+  } else if (iterator->second.is<picojson::array>() && kDataAppControlField == field_name) {
+    return SetAppControlDataField(app_control, iterator->second.get<picojson::array>());
+  }
+
+  return PlatformResult{ErrorCode::NO_ERROR};
+}
+
+}  // namespace
+
 PlatformResult ApplicationUtils::ApplicationControlToService(
     const picojson::object& app_control_obj, app_control_h* app_control) {
   ScopeLogger();
-  const auto it_operation = app_control_obj.find("operation");
-  const auto it_uri = app_control_obj.find("uri");
-  const auto it_mime = app_control_obj.find("mime");
-  const auto it_category = app_control_obj.find("category");
-  const auto it_data = app_control_obj.find("data");
+
+  const auto it_operation = app_control_obj.find(kOperationAppControlField);
+  const auto it_uri = app_control_obj.find(kURIAppControlField);
+  const auto it_mime = app_control_obj.find(kMIMEAppControlField);
+  const auto it_category = app_control_obj.find(kCategoryAppControlField);
+  const auto it_data = app_control_obj.find(kDataAppControlField);
+  const auto it_launch_mode = app_control_obj.find(kLaunchModeAppControlField);
   const auto it_app_control_end = app_control_obj.end();
 
   if (it_operation == it_app_control_end || it_uri == it_app_control_end ||
       it_mime == it_app_control_end || it_category == it_app_control_end ||
       it_data == it_app_control_end || !it_operation->second.is<std::string>() ||
-      !it_data->second.is<picojson::array>()) {
+      !it_data->second.is<picojson::array>() || it_launch_mode == it_app_control_end) {
     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed.");
   }
 
   app_control_h app_control_tmp = nullptr;
   int result = app_control_create(&app_control_tmp);
-
   if (APP_CONTROL_ERROR_NONE != result) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creation AppControl failed.",
-                              ("Problem with create handle."));
+    LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result));
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
   }
 
   std::unique_ptr<std::remove_pointer<app_control_h>::type, int (*)(app_control_h)> app_control_ptr(
       app_control_tmp, &app_control_destroy);
 
-  // operation
-  app_control_set_operation(app_control_tmp, it_operation->second.get<std::string>().c_str());
+  auto set_field_result = PlatformResult(ErrorCode::UNKNOWN_ERR);
 
-  // uri
-  if (it_uri->second.is<std::string>()) {
-    app_control_set_uri(app_control_tmp, it_uri->second.get<std::string>().c_str());
+  set_field_result =
+      SetAppControlFieldIfValueSpecified(app_control_tmp, kOperationAppControlField, it_operation);
+  if (set_field_result.IsError()) {
+    return set_field_result;
   }
 
-  // mime
-  if (it_mime->second.is<std::string>()) {
-    app_control_set_mime(app_control_tmp, it_mime->second.get<std::string>().c_str());
+  set_field_result =
+      SetAppControlFieldIfValueSpecified(app_control_tmp, kURIAppControlField, it_uri);
+  if (set_field_result.IsError()) {
+    return set_field_result;
   }
 
-  // category
-  if (it_category->second.is<std::string>()) {
-    app_control_set_category(app_control_tmp, it_category->second.get<std::string>().c_str());
+  set_field_result =
+      SetAppControlFieldIfValueSpecified(app_control_tmp, kMIMEAppControlField, it_mime);
+  if (set_field_result.IsError()) {
+    return set_field_result;
   }
 
-  // ApplicationControlData
-  const picojson::array& data = it_data->second.get<picojson::array>();
+  set_field_result =
+      SetAppControlFieldIfValueSpecified(app_control_tmp, kCategoryAppControlField, it_category);
+  if (set_field_result.IsError()) {
+    return set_field_result;
+  }
 
-  for (auto iter = data.begin(); iter != data.end(); ++iter) {
-    if (iter->is<picojson::object>()) {
-      PlatformResult ret =
-          ApplicationControlDataToServiceExtraData(iter->get<picojson::object>(), app_control_tmp);
-      if (ret.IsError()) {
-        LoggerE("Failed ApplicationControlDataToServiceExtraData()");
-        return ret;
-      }
-    }
+  set_field_result = SetAppControlFieldIfValueSpecified(app_control_tmp, kLaunchModeAppControlField,
+                                                        it_launch_mode);
+  if (set_field_result.IsError()) {
+    return set_field_result;
+  }
+
+  set_field_result =
+      SetAppControlFieldIfValueSpecified(app_control_tmp, kDataAppControlField, it_data);
+  if (set_field_result.IsError()) {
+    return set_field_result;
   }
 
   *app_control = app_control_ptr.release();
@@ -259,27 +377,34 @@ PlatformResult ApplicationUtils::ApplicationControlDataToServiceExtraData(
   if (it_key == it_app_control_data_end || it_value == it_app_control_data_end ||
       !it_key->second.is<std::string>() || !it_value->second.is<picojson::array>()) {
     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed.",
-                              ("Problem with key or value."));
+                              ("Invalid key or value."));
   }
 
   const std::string& key = it_key->second.get<std::string>();
   const picojson::array& value = it_value->second.get<picojson::array>();
 
-  const size_t size = value.size();
-  const char** arr = new const char*[size];
-  size_t i = 0;
+  std::vector<const char*> value_data;
 
-  for (auto iter = value.begin(); iter != value.end(); ++iter, ++i) {
-    arr[i] = iter->get<std::string>().c_str();
+  for (auto& v : value) {
+    value_data.push_back(v.get<std::string>().c_str());
   }
 
-  if (1 == size) {
-    app_control_add_extra_data(app_control, key.c_str(), arr[0]);
-  } else {
-    app_control_add_extra_data_array(app_control, key.c_str(), arr, size);
+  auto result = app_control_add_extra_data_array(app_control, key.c_str(), value_data.data(),
+                                                 value_data.size());
+  if (APP_CONTROL_ERROR_INVALID_PARAMETER == result) {
+    if (0 == key.length()) {
+      LoggerD("app_control_add_extra_data_array failed: zero-length key");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Invalid AppControlData key: key length is 0.");
+    }
+    LoggerD("app_control_add_extra_data_array failed: invalid parameter passed");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid AppControlData value, associated with key: " + key);
+  } else if (APP_CONTROL_ERROR_KEY_REJECTED == result) {
+    LoggerD("app_control_add_extra_data_array failed: key rejected");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid AppControlData's key: " + key);
   }
 
-  delete[] arr;
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
@@ -295,42 +420,68 @@ void ApplicationUtils::ServiceToApplicationControl(app_control_h app_control,
   };
 
   ret = app_control_get_operation(app_control, &tmp_str);
-  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Get operation failed: %d (%s)", ret, get_error_message(ret));
+  } else if (tmp_str) {
     LoggerD("operation: %s", tmp_str);
-    app_control_obj->insert(std::make_pair("operation", picojson::value(std::string(tmp_str))));
+    app_control_obj->insert(
+        std::make_pair(kOperationAppControlField, picojson::value(std::string(tmp_str))));
   } else {
-    LoggerE("Get operation failed: %d (%s)", ret, get_error_message(ret));
+    LoggerD("operation field is empty");
   }
   clear(tmp_str);
 
   ret = app_control_get_uri(app_control, &tmp_str);
-  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Get URI failed: %d (%s)", ret, get_error_message(ret));
+  } else if (tmp_str) {
     LoggerD("URI: %s", tmp_str);
-    app_control_obj->insert(std::make_pair("uri", picojson::value(std::string(tmp_str))));
+    app_control_obj->insert(
+        std::make_pair(kURIAppControlField, picojson::value(std::string(tmp_str))));
+  } else {
+    LoggerD("URI field is empty");
   }
   clear(tmp_str);
 
   ret = app_control_get_mime(app_control, &tmp_str);
-  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Get MIME failed: %d (%s)", ret, get_error_message(ret));
+  } else if (tmp_str) {
     LoggerD("MIME: %s", tmp_str);
-    app_control_obj->insert(std::make_pair("mime", picojson::value(std::string(tmp_str))));
+    app_control_obj->insert(
+        std::make_pair(kMIMEAppControlField, picojson::value(std::string(tmp_str))));
   } else {
-    LoggerE("Get mime failed: %d (%s)", ret, get_error_message(ret));
+    LoggerD("MIME field is empty");
   }
   clear(tmp_str);
 
   ret = app_control_get_category(app_control, &tmp_str);
-  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Get category failed: %d (%s)", ret, get_error_message(ret));
+  } else if (tmp_str) {
     LoggerD("category: %s", tmp_str);
-    app_control_obj->insert(std::make_pair("category", picojson::value(std::string(tmp_str))));
+    app_control_obj->insert(
+        std::make_pair(kCategoryAppControlField, picojson::value(std::string(tmp_str))));
   } else {
-    LoggerE("Get category failed: %d (%s)", ret, get_error_message(ret));
+    LoggerD("category field is empty");
   }
   clear(tmp_str);
 
-  app_control_obj->insert(std::make_pair("data", picojson::value(picojson::array())));
+  app_control_launch_mode_e launch_mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
+  ret = app_control_get_launch_mode(app_control, &launch_mode);
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Get launch mode failed: %d (%s)", ret, get_error_message(ret));
+  } else {
+    std::string launch_mode_str =
+        launch_mode == APP_CONTROL_LAUNCH_MODE_SINGLE ? kSingleLaunchMode : kGroupLaunchMode;
+    LoggerD("launch mode: %s", launch_mode_str.c_str());
+    app_control_obj->insert(
+        std::make_pair(kLaunchModeAppControlField, picojson::value(launch_mode_str)));
+  }
+
+  app_control_obj->insert(std::make_pair(kDataAppControlField, picojson::value(picojson::array())));
   ServiceToApplicationControlDataArray(
-      app_control, &app_control_obj->find("data")->second.get<picojson::array>());
+      app_control, &app_control_obj->find(kDataAppControlField)->second.get<picojson::array>());
 }
 
 void ApplicationUtils::ServiceExtraDataToApplicationControlData(
@@ -391,6 +542,36 @@ bool ApplicationUtils::ServiceToApplicationControlDataArray(app_control_h app_co
   return APP_CONTROL_ERROR_NONE == ret;
 }
 
+PlatformResult ApplicationUtils::TranslateAppControlError(app_control_error_e return_code) {
+  ScopeLogger("Return code: %d (%s)", static_cast<int>(return_code),
+              get_error_message(static_cast<int>(return_code)));
+
+  switch (return_code) {
+    case APP_CONTROL_ERROR_NONE:
+      return PlatformResult(ErrorCode::NO_ERROR);
+
+    case APP_CONTROL_ERROR_INVALID_PARAMETER:
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+
+    case APP_CONTROL_ERROR_APP_NOT_FOUND:
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found.");
+
+    case APP_CONTROL_ERROR_PERMISSION_DENIED:
+      return PlatformResult(ErrorCode::SECURITY_ERR, "Permission denied.");
+
+    case APP_CONTROL_ERROR_OUT_OF_MEMORY:
+    case APP_CONTROL_ERROR_KEY_NOT_FOUND:
+    case APP_CONTROL_ERROR_KEY_REJECTED:
+    case APP_CONTROL_ERROR_INVALID_DATA_TYPE:
+    case APP_CONTROL_ERROR_LAUNCH_REJECTED:
+    case APP_CONTROL_ERROR_LAUNCH_FAILED:
+    case APP_CONTROL_ERROR_TIMED_OUT:
+    case APP_CONTROL_ERROR_IO_ERROR:
+    default:
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
+  }
+}
+
 bool ApplicationUtils::ServiceExtraDataCallback(app_control_h app_control, const char* key,
                                                 void* user_data) {
   ScopeLogger();
index 455f197..308827b 100644 (file)
@@ -59,6 +59,8 @@ class ApplicationUtils {
   static bool ServiceToApplicationControlDataArray(app_control_h app_control,
                                                    picojson::array* data);
 
+  static common::PlatformResult TranslateAppControlError(app_control_error_e error_code);
+
  private:
   static bool ServiceExtraDataCallback(app_control_h app_control, const char* key, void* user_data);
 };
index 9ba9400..1d8048c 100644 (file)
@@ -115,9 +115,10 @@ PlatformResult Node::resolve(const PathPtr& path, NodePtr* node) {
   struct stat syminfo;
 
   if (lstat(path->getFullPath().c_str(), &info) != 0) {
-    LoggerE("File:[%s] error no:%d", path->getFullPath().c_str(), errno);
+    int tmp_errno = errno;
+    LoggerE("File: [%s] error no: %d", path->getFullPath().c_str(), tmp_errno);
 
-    switch (errno) {
+    switch (tmp_errno) {
       case EACCES:
         SLoggerE("File: [%s]", path->getFullPath().c_str());
         return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Node access denied");
index 51537c0..89f99a8 100644 (file)
           ],
         },
       },
+      'defines': ['PICOJSON_USE_RVALUE_REFERENCE'],
     },
   ],
-  'defines': ['PICOJSON_USE_RVALUE_REFERENCE'],
 }
index 990e428..0885dea 100644 (file)
@@ -74,7 +74,7 @@ File.prototype.toURI = function() {
 function stringToRegex(str) {
   var _regString = '^';
   if (str === '') {
-    return new RegExp(_regString, 'i');
+    return new RegExp(_regString + "$", 'i');
   }
   // single '\' sign is not visible in JS string, escaping % wildcard need to be done by '\\%'
   str = str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
index d45a1d1..3d9a2ed 100644 (file)
@@ -68,6 +68,7 @@ FileHandle.prototype.seekNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
   var data = {id: this.id, offset: args.offset, blocking: false};
   if (undefined === args.whence) {
@@ -128,6 +129,7 @@ FileHandle.prototype.readStringNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
   if ((this.mode === 'w') || (this.mode === 'a')) {
     setTimeout(function() {
@@ -135,6 +137,7 @@ FileHandle.prototype.readStringNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle state is write-only'));
     }, 0);
+    return;
   }
   var data = {id: this.id, encoding: args.inputEncoding, blocking: false};
   if (!type_.isNullOrUndefined(args.count)) {
@@ -196,6 +199,7 @@ FileHandle.prototype.writeStringNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
   if ('r' === this.mode) {
     setTimeout(function() {
@@ -203,6 +207,7 @@ FileHandle.prototype.writeStringNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle state is read-only'));
     }, 0);
+    return;
   }
   var data =
       {id: this.id, string: args.string, encoding: args.outputEncoding, blocking: false};
@@ -265,6 +270,7 @@ FileHandle.prototype.readBlobNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
 
   var data = {id: this.id, blocking: false};
@@ -339,12 +345,14 @@ FileHandle.prototype.writeBlobNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   } else if (this.mode === 'r') {
     setTimeout(function() {
       native_.callIfPossible(
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle state is read-only'));
     }, 0);
+    return;
   }
 
   var encodedData = ArrayToString(blobToUint8Array(args.blob));
@@ -365,6 +373,7 @@ FileHandle.prototype.writeBlobNonBlocking = function() {
     setTimeout(function() {
       native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
     }, 0);
+    return;
   }
 };
 
@@ -403,6 +412,7 @@ FileHandle.prototype.readDataNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
   if ((this.mode === 'w') || (this.mode === 'a')) {
     setTimeout(function() {
@@ -410,6 +420,7 @@ FileHandle.prototype.readDataNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle state is write-only'));
     }, 0);
+    return;
   }
 
   var data = {id: this.id, blocking: false};
@@ -470,12 +481,14 @@ FileHandle.prototype.writeDataNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   } else if (this.mode === 'r') {
     setTimeout(function() {
       native_.callIfPossible(
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle state is read-only'));
     }, 0);
+    return;
   }
 
   var encodedData = ArrayToString(args.data);
@@ -527,6 +540,7 @@ FileHandle.prototype.flushNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
   if (this.mode === 'r') {
     setTimeout(function() {
@@ -534,6 +548,7 @@ FileHandle.prototype.flushNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle state is read-only'));
     }, 0);
+    return;
   }
   var data = {id: this.id, blocking: false};
 
@@ -583,6 +598,7 @@ FileHandle.prototype.syncNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
   if (this.mode === 'r') {
     setTimeout(function() {
@@ -590,6 +606,7 @@ FileHandle.prototype.syncNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle state is read-only'));
     }, 0);
+    return;
   }
   var data = {id: this.id, blocking: false};
 
@@ -635,6 +652,7 @@ FileHandle.prototype.closeNonBlocking = function() {
           args.errorCallback,
           new WebAPIException(WebAPIException.IO_ERR, 'FileHandle is not opened'));
     }, 0);
+    return;
   }
 
   var data = {id: this.id, blocking: false};
index be7d415..039e430 100644 (file)
@@ -117,11 +117,11 @@ void PPMInstance::ResponseCallback(ppm_call_cause_e cause, ppm_request_result_e
   picojson::value event = picojson::value(picojson::object());
   picojson::object& obj = event.get<picojson::object>();
 
-  obj.insert(std::make_pair("callbackId", picojson::value(data->callbackId)));
+  obj.emplace(std::make_pair("callbackId", picojson::value(data->callbackId)));
 
   if (PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER == cause) {
-    obj.insert(std::make_pair("result", picojson::value(CheckRequestResultToString(result))));
-    obj.insert(std::make_pair("privilege", picojson::value(privilege)));
+    obj.emplace(std::make_pair("result", picojson::value(CheckRequestResultToString(result))));
+    obj.emplace(std::make_pair("privilege", picojson::value(privilege)));
   } else {
     LogAndReportError(
         common::PlatformResult(common::ErrorCode::ABORT_ERR, "Get callback data failed"), &obj);
@@ -140,20 +140,21 @@ void PPMInstance::ResponseMultipleCallback(ppm_call_cause_e cause,
   picojson::value event = picojson::value(picojson::object());
   picojson::object& obj = event.get<picojson::object>();
 
-  obj.insert(std::make_pair("callbackId", picojson::value(data->callbackId)));
+  obj.emplace(std::make_pair("callbackId", picojson::value(data->callbackId)));
 
   if (PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER == cause) {
     picojson::value result_array = picojson::value(picojson::array());
     picojson::array& array_obj = result_array.get<picojson::array>();
+    array_obj.reserve(privileges_count);
 
     for (size_t i = 0; i < privileges_count; i++) {
       picojson::value result_elem = picojson::value(picojson::object());
       picojson::object& obj = result_elem.get<picojson::object>();
       obj["privilege"] = picojson::value(privileges[i]);
       obj["result"] = picojson::value(CheckRequestResultToString(result[i]));
-      array_obj.push_back(result_elem);
+      array_obj.push_back(std::move(result_elem));
     }
-    obj.insert(std::make_pair("result", result_array));
+    obj.emplace(std::make_pair("result", result_array));
   } else {
     LogAndReportError(
         common::PlatformResult(common::ErrorCode::ABORT_ERR, "Get callback data failed"), &obj);
@@ -184,17 +185,15 @@ void PPMInstance::checkPermissions(const picojson::value& args, picojson::object
   ScopeLogger();
 
   const picojson::array& privileges = args.get("privileges").get<picojson::array>();
-  unsigned int size = static_cast<int>(privileges.size());
-
   std::vector<const char*> privilege_array;
-  size_t i = 0;
+  privilege_array.reserve(privileges.size());
 
-  for (auto iter = privileges.begin(); iter != privileges.end(); ++iter, ++i) {
+  for (auto iter = privileges.begin(); iter != privileges.end(); ++iter) {
     privilege_array.push_back(iter->get<std::string>().c_str());
   }
 
-  std::vector<ppm_check_result_e> results(size);
-  int ret = ppm_check_permissions(privilege_array.data(), size, results.data());
+  std::vector<ppm_check_result_e> results(privileges.size());
+  int ret = ppm_check_permissions(privilege_array.data(), privileges.size(), results.data());
 
   if (PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE != ret) {
     LogAndReportError(convertError(ret), &out,
@@ -205,15 +204,16 @@ void PPMInstance::checkPermissions(const picojson::value& args, picojson::object
 
   picojson::value result_array = picojson::value(picojson::array());
   picojson::array& array_obj = result_array.get<picojson::array>();
+  array_obj.reserve(privileges.size());
 
-  for (size_t i = 0; i < size; i++) {
+  for (size_t i = 0; i < privileges.size(); i++) {
     picojson::value result_elem = picojson::value(picojson::object());
     picojson::object& obj = result_elem.get<picojson::object>();
 
     obj["privilege"] = picojson::value(privilege_array[i]);
     obj["type"] = picojson::value(CheckResultToString(results[i]));
 
-    array_obj.push_back(result_elem);
+    array_obj.push_back(std::move(result_elem));
   }
 
   ReportSuccess(result_array, out);
@@ -247,14 +247,11 @@ void PPMInstance::requestPermissions(const picojson::value& args, picojson::obje
   ScopeLogger();
 
   const double callback_id = args.get("callbackId").get<double>();
-
   const picojson::array& privileges = args.get("privileges").get<picojson::array>();
-  unsigned int size = static_cast<int>(privileges.size());
-
   std::vector<const char*> privilege_array;
-  size_t i = 0;
+  privilege_array.reserve(privileges.size());
 
-  for (auto iter = privileges.begin(); iter != privileges.end(); ++iter, ++i) {
+  for (auto iter = privileges.begin(); iter != privileges.end(); ++iter) {
     privilege_array.push_back(iter->get<std::string>().c_str());
   }
 
@@ -262,10 +259,11 @@ void PPMInstance::requestPermissions(const picojson::value& args, picojson::obje
   user_data->_instance = this;
   user_data->callbackId = callback_id;
 
-  int ret = ppm_request_permissions(privilege_array.data(), size, ResponseMultipleCallback,
-                                    static_cast<void*>(user_data));
+  int ret = ppm_request_permissions(privilege_array.data(), privileges.size(),
+                                    ResponseMultipleCallback, static_cast<void*>(user_data));
 
   if (PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE != ret) {
+    delete user_data;
     LogAndReportError(convertError(ret), &out,
                       ("checkPermission error: %d (%s)", ret, get_error_message(ret)));
     return;
index a534fd2..e09d3fb 100644 (file)
@@ -344,10 +344,6 @@ ListenerManager.prototype.addListener = function(callback) {
 };
 
 ListenerManager.prototype.removeListener = function(watchId) {
-  if (this.listeners[watchId] === null || this.listeners[watchId] === undefined) {
-    return;
-  }
-
   if (this.listeners.hasOwnProperty(watchId)) {
     delete this.listeners[watchId];
   }