[Verification] Code compiles, TCT pass rate: 57/89.
Change-Id: I1ddb7d67b6cc1b619b5b6a12c31cf907dc17fe9c
####################################################################
%if "%{?profile}" == "mobile"
-%define tizen_feature_account_support 0
+%define tizen_feature_account_support 1
%define tizen_feature_archive_support 0
%define tizen_feature_badge_support 0
%define tizen_feature_bluetooth_support 0
BuildRequires: pkgconfig(capi-appfw-package-manager)
BuildRequires: pkgconfig(wrt-plugins-ipc-message)
+%if 0%{?tizen_feature_account_support}
+BuildRequires: pkgconfig(accounts-svc)
+%endif
+
%if 0%{?tizen_feature_datacontrol_support}
BuildRequires: pkgconfig(capi-data-control)
%endif
--- /dev/null
+{
+ 'includes':[
+ '../common/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'tizen_account',
+ 'type': 'loadable_module',
+ 'sources': [
+ 'account_api.js',
+ 'account_extension.cc',
+ 'account_extension.h',
+ 'account_instance.cc',
+ 'account_instance.h',
+ 'account_manager.cc',
+ 'account_manager.h',
+ ],
+ 'conditions': [
+ ['tizen == 1', {
+ 'variables': {
+ 'packages': [
+ 'capi-appfw-package-manager',
+ 'accounts-svc',
+ ]
+ },
+ }],
+ ],
+ },
+ ],
+}
--- /dev/null
+/* global tizen, xwalk, extension */
+
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+
+var callbackId = 0;
+var callbacks = {};
+
+var lastAccountChangeListenerId = -1;
+var accountChangeListener = {};
+
+function invokeListener(result) {
+ if (result.listener === 'accountChange') {
+ for (var listenerId in accountChangeListener) {
+ console.log("[Account][invokeListener] AccountChangeListenerId: " + listenerId);
+ var listener = callbacks[accountChangeListener[listenerId]];
+ listener(result);
+ }
+ }
+}
+
+extension.setMessageListener(function(json) {
+ var result = JSON.parse(json);
+
+ if (result.hasOwnProperty('listener')) {
+ console.log("[Account][setMessageListener] Call listner");
+ invokeListener(result);
+ } else {
+ console.log("[Account][setMessageListener] Call callback");
+ var callback = callbacks[result.callbackId];
+ callback(result);
+ }
+});
+
+function nextCallbackId() {
+ return callbackId++;
+}
+
+function nextAccountChangeListenerId() {
+ return ++lastAccountChangeListenerId;
+}
+
+function callNative(cmd, args) {
+ var json = {'cmd': cmd, 'args': args};
+ var argjson = JSON.stringify(json);
+ var resultString = extension.internal.sendSyncMessage(argjson);
+ var result = JSON.parse(resultString);
+
+ if (typeof result !== 'object') {
+ throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
+ }
+
+ if (result.status === 'success') {
+ if (result.result) {
+ return result.result;
+ }
+ return true;
+ } else if (result.status === 'error') {
+ var err = result.error;
+ if (err) {
+ throw new tizen.WebAPIException(err.name, err.message);
+ }
+ return false;
+ }
+}
+
+
+function callNativeWithCallback(cmd, args, callback) {
+ if (callback) {
+ var id = nextCallbackId();
+ args.callbackId = id;
+ callbacks[id] = callback;
+ }
+
+ return callNative(cmd, args);
+}
+
+function SetReadOnlyProperty(obj, n, v){
+ if (v)
+ Object.defineProperty(obj, n, {value:v, writable: false, enumerable: true, configurable: true});
+ else
+ Object.defineProperty(obj, n, {writable: false, enumerable: true, configurable: true});
+}
+
+function AccountProvider(providerInfo) {
+ SetReadOnlyProperty(this, 'applicationId', providerInfo.applicationId); // read only property
+ SetReadOnlyProperty(this, 'displayName', providerInfo.displayName); // read only property
+ SetReadOnlyProperty(this, 'iconUri', providerInfo.iconUri); // read only property
+ SetReadOnlyProperty(this, 'smallIconUri', providerInfo.smallIconUri); // read only property
+ SetReadOnlyProperty(this, 'capabilities', providerInfo.capabilities); // read only property
+ SetReadOnlyProperty(this, 'isMultipleAccountSupported', providerInfo.isMultipleAccountSupported); // read only property
+}
+
+function SetAccountId(account, accountId) {
+
+ Object.defineProperty(account, 'id', {writable: true});
+ account.id = accountId;
+ Object.defineProperty(account, 'id', {writable: false});
+
+ return account;
+}
+
+function Account(provider, accountInitDict) {
+ console.log("[Constructor of Account] Enter");
+
+ var args = validator_.validateArgs(arguments, [
+ {'name' : 'provider', 'type' : types_.PLATFORM_OBJECT, 'values' : AccountProvider},
+ {'name' : 'accountInitDict',
+ 'type' : types_.DICTIONARY,
+ 'optional' : true,
+ 'nullable' : true
+ }
+ ]);
+
+ SetReadOnlyProperty(this, 'id', null); // read only property
+ SetReadOnlyProperty(this, 'provider', provider); // read only property
+ if(arguments.length > 1) {
+ this.userName = accountInitDict.userName;
+ this.iconUri = accountInitDict.iconUri;
+ } else {
+ this.userName = null;
+ this.iconUri = null;
+ }
+}
+
+function MakeAccountObject(obj) {
+ console.log("[Account][MakeAccountObject] Enter");
+ var account = new Account(new AccountProvider(obj.provider), obj.accountInitDict);
+ return SetAccountId(account, obj.id);
+}
+
+Account.prototype.setExtendedData = function(key, value) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'key', 'type': types_.STRING},
+ {'name': 'value', 'type': types_.STRING}
+ ]);
+
+ var nativeParam = {
+ 'key': args.key,
+ 'value': args.value
+ };
+
+
+ try {
+ var syncResult = callNative('Account_setExtendedData', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+};
+
+Account.prototype.getExtendedData = function(key) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'key', 'type': types_.STRING}
+ ]);
+
+ var nativeParam = {
+ 'key': args.key
+ };
+
+
+ try {
+ var syncResult = callNative('Account_getExtendedData', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+};
+
+Account.prototype.getExtendedData = function(successCallback, errorCallback) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'successCallback', 'type': types_.LISTENER, 'values': ['onsuccess']},
+ {'name': 'errorCallback', 'type': types_.FUNCTION}
+ ]);
+
+ var nativeParam = {
+ };
+
+
+ try {
+ var syncResult = callNative('Account_getExtendedData', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+};
+
+
+
+function AccountManager() {
+ // constructor of AccountManager
+
+}
+
+
+AccountManager.prototype.add = function(account) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'account', 'type': types_.PLATFORM_OBJECT, 'values': Account}
+ ]);
+
+ var nativeParam = {
+ };
+
+
+ try {
+ var syncResult = callNative('AccountManager_add', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+};
+
+AccountManager.prototype.remove = function(accountId) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'accountId', 'type': types_.LONG}
+ ]);
+
+ var nativeParam = {
+ 'accountId': args.accountId
+ };
+
+
+ try {
+ var syncResult = callNative('AccountManager_remove', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+};
+
+AccountManager.prototype.update = function(account) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'account', 'type': types_.PLATFORM_OBJECT, 'values': Account}
+ ]);
+
+ var nativeParam = {
+ };
+
+
+ try {
+ var syncResult = callNative('AccountManager_update', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+};
+
+AccountManager.prototype.getAccount = function(accountId) {
+ console.log("[AccountManager][getAccount] Enter");
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'accountId', 'type': types_.UNSIGNED_LONG}
+ ]);
+
+ var nativeParam = {
+ 'accountId': args.accountId
+ };
+
+ try {
+ var syncResult = callNative('AccountManager_getAccount', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+ var returnObject = new Account();
+ return returnObject;
+};
+
+AccountManager.prototype.getAccounts = function(successCallback, errorCallback, applicationId) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'successCallback', 'type': types_.LISTENER, 'values': ['onsuccess']},
+ {'name': 'errorCallback', 'type': types_.FUNCTION},
+ {'name': 'applicationId', 'type': types_.STRING}
+ ]);
+
+ var nativeParam = {
+ };
+
+ if (args.applicationId) {
+ nativeParam.applicationId = args.applicationId;
+ }
+
+ try {
+ var syncResult = callNative('AccountManager_getAccounts', nativeParam);
+ // if you need synchronous result from native function using 'syncResult'.
+ } catch (e) {
+ throw e;
+ }
+
+};
+
+AccountManager.prototype.getProvider = function(applicationId) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'applicationId', 'type': types_.STRING}
+ ]);
+
+ var nativeParam = {
+ 'applicationId': args.applicationId
+ };
+
+ try {
+ var syncResult = callNative('AccountManager_getProvider', nativeParam);
+ return new AccountProvider(syncResult);
+ } catch (e) {
+ throw e;
+ }
+};
+
+AccountManager.prototype.getProviders = function(successCallback, errorCallback, capability) {
+ var args = validator_.validateArgs(arguments, [
+ {'name' : 'successCallback', 'type' : types_.FUNCTION},
+ {'name' : 'errorCallback', 'type' : types_.FUNCTION, 'optional' : true, 'nullable' : true},
+ {'name' : 'capability', 'type' : types_.STRING, 'optional' : true, 'nullable' : true}
+ ]);
+
+ var nativeParam = {
+ };
+
+ if (args.capability) {
+ nativeParam.capability = args.capability;
+ }
+
+ try {
+ var syncResult = callNativeWithCallback(
+ 'AccountManager_getProviders',
+ nativeParam,
+ function(param) {
+ if (param.status == 'success') {
+ for (var i = 0; i < param.result.length; i++) {
+ param.result[i] = new AccountProvider(param.result[i]);
+ }
+ args.successCallback(param.result);
+ } else if (param.status == 'error') {
+ var err = param.error;
+ if (err) {
+ args.errorCallback(new tizen.WebAPIError(err.name, err.message));
+ return;
+ }
+ }
+
+ delete callbacks[param.callbackId];
+ });
+ } catch (e) {
+ throw e;
+ }
+};
+
+AccountManager.prototype.addAccountListener = function(callback) {
+ var args = validator_.validateArgs(
+ arguments,
+ [
+ {'name' : 'callback',
+ 'type' : types_.LISTENER,
+ 'values' : ['onadded', 'onremoved', 'onupdated']}
+ ]);
+
+ var nativeParam = {
+ };
+
+ try {
+ var syncResult = callNativeWithCallback(
+ 'AccountManager_addAccountListener',
+ nativeParam,
+ function(param) {
+ if (param.status === 'added') {
+ args.callback.onadded(MakeAccountObject(param.result));
+ } else if (param.status === 'removed') {
+ args.callback.onremoved(param.result);
+ } else if (param.status === 'updated') {
+ args.callback.onupdated(MakeAccountObject(param.result));
+ }
+ });
+
+ console.log("[Account][addAccountListener] callbackId: " + nativeParam.callbackId);
+ var listenerId = nextAccountChangeListenerId();
+ accountChangeListener[listenerId] = nativeParam.callbackId;
+ console.log("[Account][addAccountListener] listenerId: " + listenerId);
+ return listenerId;
+ } catch (e) {
+ throw e;
+ }
+};
+
+AccountManager.prototype.removeAccountListener = function(accountListenerId) {
+ var args = validator_.validateArgs(arguments, [
+ {'name': 'accountListenerId', 'type': types_.LONG}
+ ]);
+
+ var nativeParam = {
+ };
+
+ try {
+ if (args.accountListenerId in accountChangeListener) {
+ delete callbacks[accountChangeListener[args.accountListenerId]];
+ delete accountChangeListener[args.accountListenerId];
+ }
+
+ if (Object.keys(accountChangeListener).length === 0) {
+ console.log("[Account][removeAccountListener] Unscribe native notification");
+ var syncResult = callNative('AccountManager_removeAccountListener', nativeParam);
+ }
+ } catch (e) {
+ throw e;
+ }
+};
+
+tizen.Account = Account;
+
+exports = new AccountManager();
+
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "account/account_extension.h"
+
+#include "account/account_instance.h"
+
+// This will be generated from account_api.js
+extern const char kSource_account_api[];
+
+common::Extension* CreateExtension() {
+ return new AccountExtension;
+}
+
+AccountExtension::AccountExtension() {
+ SetExtensionName("tizen.account");
+ SetJavaScriptAPI(kSource_account_api);
+
+ const char* entry_points[] = {
+ "tizen.Account",
+ NULL
+ };
+ SetExtraJSEntryPoints(entry_points);
+}
+
+AccountExtension::~AccountExtension() {}
+
+common::Instance* AccountExtension::CreateInstance() {
+ return new extension::account::AccountInstance;
+}
\ No newline at end of file
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ACCOUNT_ACCOUNT_EXTENSION_H_
+#define ACCOUNT_ACCOUNT_EXTENSION_H_
+
+#include "common/extension.h"
+
+class AccountExtension : public common::Extension {
+ public:
+ AccountExtension();
+ virtual ~AccountExtension();
+
+ private:
+ virtual common::Instance* CreateInstance();
+};
+
+#endif // ACCOUNT_ACCOUNT_EXTENSION_H_
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "account/account_instance.h"
+
+#include "string.h"
+
+#include <functional>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/task-queue.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace account {
+
+using common::TaskQueue;
+using common::TypeMismatchException;
+using common::UnknownException;
+using common::SecurityException;
+
+namespace {
+// The privileges that required in Account API
+const std::string kPrivilegeAccountRead =
+ "http://tizen.org/privilege/account.read";
+const std::string kPrivilegeAccountWrite =
+ "http://tizen.org/privilege/account.write";
+
+void CheckAccess(const std::string& privilege, picojson::object* out) {
+ LoggerD("Enter");
+
+ /* TODO: Need to check privilege
+ ReportError(
+ SecurityException("This application does not have " \
+ "the privilege to call this method"),
+ out);
+ return;
+ */
+}
+
+} // namespace
+
+#define CHECK_EXIST(args, name, out) \
+ if (!args.contains(name)) {\
+ ReportError(TypeMismatchException(name" is required argument"), out);\
+ return;\
+ }
+
+AccountInstance::AccountInstance() {
+ LoggerD("Enter");
+
+ manager_ = new AccountManager;
+ subscribe_ = NULL;
+
+ using namespace std::placeholders;
+ #define REGISTER_SYNC(c,x) \
+ RegisterSyncHandler(c, std::bind(&AccountInstance::x, this, _1, _2));
+ REGISTER_SYNC("AccountManager_removeAccountListener", AccountManagerRemoveAccountListener);
+ REGISTER_SYNC("AccountManager_update", AccountManagerUpdate);
+ REGISTER_SYNC("AccountManager_remove", AccountManagerRemove);
+// REGISTER_SYNC("Account_constructor", AccountConstructor);
+ REGISTER_SYNC("AccountManager_getAccount", AccountManagerGetAccount);
+ REGISTER_SYNC("AccountManager_getProvider", AccountManagerGetProvider);
+ REGISTER_SYNC("Account_setExtendedData", AccountSetExtendedData);
+ REGISTER_SYNC("AccountManager_addAccountListener", AccountManagerAddAccountListener);
+ REGISTER_SYNC("AccountManager_add", AccountManagerAdd);
+ REGISTER_SYNC("AccountManager_getAccounts", AccountManagerGetAccounts);
+ REGISTER_SYNC("Account_getExtendedData", AccountGetExtendedData);
+ REGISTER_SYNC("AccountManager_getProviders", AccountManagerGetProviders);
+ #undef REGISTER_SYNC
+}
+
+AccountInstance::~AccountInstance() {
+ LoggerD("Enter");
+ delete manager_;
+ if (subscribe_) {
+ account_unsubscribe_notification(subscribe_);
+ }
+}
+
+AccountManager* AccountInstance::GetAccountManager() {
+ LoggerD("Enter");
+ return manager_;
+}
+
+void AccountInstance::AccountSetExtendedData(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountWrite, &out);
+
+ CHECK_EXIST(args, "key", out)
+ CHECK_EXIST(args, "value", out)
+
+ const std::string& key = args.get("key").get<std::string>();
+ const std::string& value = args.get("value").get<std::string>();
+
+ // implement it
+
+ // if success
+ // ReportSuccess(out);
+ // if error
+ // ReportError(out);
+}
+
+void AccountInstance::AccountGetExtendedData(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountRead, &out);
+
+ CHECK_EXIST(args, "key", out)
+
+ const std::string& key = args.get("key").get<std::string>();
+
+ // implement it
+
+ // if success
+ // ReportSuccess(out);
+ // if error
+ // ReportError(out);
+}
+
+void AccountInstance::AccountManagerAdd(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountWrite, &out);
+
+ // implement it
+
+ // if success
+ // ReportSuccess(out);
+ // if error
+ // ReportError(out);
+}
+
+void AccountInstance::AccountManagerRemove(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountWrite, &out);
+
+ // implement it
+
+ // if success
+ // ReportSuccess(out);
+ // if error
+ // ReportError(out);
+}
+
+void AccountInstance::AccountManagerUpdate(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountWrite, &out);
+
+ // implement it
+
+ // if success
+ // ReportSuccess(out);
+ // if error
+ // ReportError(out);
+}
+
+void AccountInstance::AccountManagerGetAccount(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountRead, &out);
+
+ // implement it
+
+ // if success
+ // ReportSuccess(out);
+ // if error
+ // ReportError(out);
+}
+
+void AccountInstance::AccountManagerGetAccounts(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountRead, &out);
+
+ // implement it
+
+ // if success
+ // ReportSuccess(out);
+ // if error
+ // ReportError(out);
+}
+
+void AccountInstance::AccountManagerGetProvider(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountRead, &out);
+
+ std::string application_id = args.get("applicationId").get<std::string>();
+ LoggerD("application_id [%s]", application_id.c_str());
+
+ manager_->GetProviderInfo(application_id, out);
+}
+
+void AccountInstance::AccountManagerGetProviders(const picojson::value& args,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountRead, &out);
+
+ CHECK_EXIST(args, "callbackId", out)
+ int callback_id = static_cast<int>(args.get("callbackId").get<double>());
+
+ const std::string capability = args.contains("capability") ? args.get("capability").get<std::string>() : "";
+
+ LoggerD("capability [%s]", capability.c_str());
+
+ auto get_providers = [this, capability](const std::shared_ptr<picojson::value>& result) {
+ this->manager_->GetProvidersInfo(capability, result->get<picojson::object>());
+ };
+
+ auto get_providers_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+ result->get<picojson::object>()["callbackId"] = picojson::value{static_cast<double>(callback_id)};
+ this->PostMessage(result->serialize().c_str());
+ };
+
+ TaskQueue::GetInstance().Queue<picojson::value>(
+ get_providers,
+ get_providers_result,
+ std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}});
+
+ ReportSuccess(out);
+}
+
+void AccountInstance::InvokeListener(picojson::object& param) {
+ LoggerD("Enter");
+ picojson::value result = picojson::value(param);
+ PostMessage(result.serialize().c_str());
+}
+
+static bool AccountEventCb(const char *event_type, int account_id,
+ void *user_data) {
+ LoggerD("Enter");
+
+ AccountInstance* instance = static_cast<AccountInstance*>(user_data);
+ if (!instance) {
+ LoggerE("instance is NULL");
+ return false;
+ }
+
+ picojson::object result;
+ result["listenerId"] = picojson::value("accountChange");
+ if (!strcmp(event_type, ACCOUNT_NOTI_NAME_INSERT)) {
+ LoggerD("Added");
+ result["status"] = picojson::value("added");
+ picojson::object info;
+ instance->GetAccountManager()->GetAccountInfo(account_id, info);
+ result["result"] = picojson::value(info["result"]);
+ instance->InvokeListener(result);
+ } else if (!strcmp(event_type, ACCOUNT_NOTI_NAME_UPDATE)) {
+ LoggerD("Updated");
+ result["status"] = picojson::value("updated");
+ picojson::object info;
+ instance->GetAccountManager()->GetAccountInfo(account_id, info);
+ result["result"] = picojson::value(info["result"]);
+ instance->InvokeListener(result);
+ } else if (!strcmp(event_type, ACCOUNT_NOTI_NAME_DELETE)) {
+ LoggerD("Deleted");
+ result["status"] = picojson::value("removed");
+ result["result"] = picojson::value("account_id");
+ instance->InvokeListener(result);
+ }
+
+ return true;
+}
+
+void AccountInstance::AccountManagerAddAccountListener(
+ const picojson::value& args, picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountRead, &out);
+
+ int ret = 0;
+ if (!subscribe_) {
+ ret = account_subscribe_create(&subscribe_);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to create account subscribe");
+ ReportError(UnknownException(manager_->GetErrorMsg(ret)), out);
+ return;
+ }
+
+ ret = account_subscribe_notification(subscribe_, AccountEventCb, this);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to subscribe notification");
+ ReportError(UnknownException(manager_->GetErrorMsg(ret)), out);
+ return;
+ }
+ }
+
+ ReportSuccess(out);
+}
+
+void AccountInstance::AccountManagerRemoveAccountListener(
+ const picojson::value& args, picojson::object& out) {
+ LoggerD("Enter");
+
+ CheckAccess(kPrivilegeAccountRead, &out);
+
+ if (subscribe_) {
+ if (account_unsubscribe_notification(subscribe_) != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to unsubscribe notification");
+ }
+ }
+
+ ReportSuccess(out);
+}
+
+#undef CHECK_EXIST
+
+} // namespace account
+} // namespace extension
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ACCOUNT_ACCOUNT_INSTANCE_H_
+#define ACCOUNT_ACCOUNT_INSTANCE_H_
+
+#include <account.h>
+
+#include "account/account_manager.h"
+#include "common/extension.h"
+
+namespace extension {
+namespace account {
+
+class AccountInstance : public common::ParsedInstance {
+ public:
+ AccountInstance();
+ virtual ~AccountInstance();
+
+ AccountManager* GetAccountManager();
+ void InvokeListener(picojson::object& param);
+
+ private:
+ AccountManager* manager_;
+ account_subscribe_h subscribe_;
+
+ void AccountManagerRemoveAccountListener(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerUpdate(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerRemove(
+ const picojson::value& args, picojson::object& out);
+ void AccountConstructor(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerGetAccount(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerGetProvider(
+ const picojson::value& args, picojson::object& out);
+ void AccountSetExtendedData(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerAddAccountListener(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerAdd(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerGetAccounts(
+ const picojson::value& args, picojson::object& out);
+ void AccountGetExtendedData(
+ const picojson::value& args, picojson::object& out);
+ void AccountManagerGetProviders(
+ const picojson::value& args, picojson::object& out);
+};
+
+} // namespace account
+} // namespace extension
+
+#endif // ACCOUNT_ACCOUNT_INSTANCE_H_
--- /dev/null
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "account/account_manager.h"
+
+#include <functional>
+
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+namespace extension {
+namespace account {
+
+using common::ScopeExit;
+using common::UnknownException;
+
+#define REPORT_ERROR(out, exception) \
+ out["status"] = picojson::value("error"); \
+ out["error"] = exception.ToJSON();
+
+namespace {
+
+static bool ProviderCapabilitiesCb(char *app_id, char *key, void *user_data) {
+ LoggerD("Enter");
+
+ picojson::array* array_data = static_cast<picojson::array*>(user_data);
+ if (!array_data) {
+ LoggerE("user_data is NULL");
+ return false;
+ }
+
+ array_data->push_back(picojson::value(key));
+ return true;
+}
+
+static bool AccountProvidersGetCb(account_type_h provider, void *user_data) {
+ LoggerD("Enter");
+
+ picojson::array* array_data = static_cast<picojson::array*>(user_data);
+ if (!array_data) {
+ LoggerE("user_data is NULL");
+ return false;
+ }
+
+ picojson::object object_info;
+ if (AccountManager::ConvertProviderToObject(provider, object_info)) {
+ array_data->push_back(picojson::value(object_info));
+ }
+
+ return true;
+}
+
+static bool GetAccountsCallback(account_h handle, void *user_data) {
+ LoggerD("Enter");
+
+ picojson::array* array_data = static_cast<picojson::array*>(user_data);
+ if (!array_data) {
+ LoggerE("user_data is NULL");
+ return false;
+ }
+
+ picojson::object object_info;
+ if (AccountManager::ConvertAccountToObject(handle, object_info)) {
+ array_data->push_back(picojson::value(object_info));
+ }
+
+ return true;
+}
+
+} // namespace
+
+AccountManager::AccountManager() {
+ if (account_connect() != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to connect account db");
+ }
+}
+
+AccountManager::~AccountManager() {
+ if (account_disconnect() != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to disconnect account db");
+ }
+}
+
+std::string AccountManager::GetErrorMsg(int error) {
+ switch (error) {
+ case ACCOUNT_ERROR_OUT_OF_MEMORY:
+ return "Out of Memory";
+ case ACCOUNT_ERROR_INVALID_PARAMETER:
+ return "Invalid Parameter";
+ case ACCOUNT_ERROR_DUPLICATED:
+ return "Same user name exists in your application";
+ case ACCOUNT_ERROR_NO_DATA:
+ return "Empty data";
+ case ACCOUNT_ERROR_RECORD_NOT_FOUND:
+ return "Related record does not exist";
+ case ACCOUNT_ERROR_DB_FAILED:
+ return "DB operation failed";
+ case ACCOUNT_ERROR_DB_NOT_OPENED:
+ return "DB is not connected";
+ case ACCOUNT_ERROR_QUERY_SYNTAX_ERROR:
+ return "DB query syntax error";
+ case ACCOUNT_ERROR_ITERATOR_END:
+ return "Iterator has reached the end";
+ case ACCOUNT_ERROR_NOTI_FAILED:
+ return "Notification failed";
+ case ACCOUNT_ERROR_PERMISSION_DENIED:
+ return "Permission denied";
+ case ACCOUNT_ERROR_XML_PARSE_FAILED:
+ return "XML parse failed";
+ case ACCOUNT_ERROR_XML_FILE_NOT_FOUND:
+ return "XML file does not exist";
+ case ACCOUNT_ERROR_EVENT_SUBSCRIPTION_FAIL:
+ return "Subscription failed";
+ case ACCOUNT_ERROR_NOT_REGISTERED_PROVIDER:
+ return "Account provider is not registered";
+ case ACCOUNT_ERROR_NOT_ALLOW_MULTIPLE:
+ return "Multiple accounts are not supported";
+ case ACCOUNT_ERROR_DATABASE_BUSY:
+ return "SQLite busy handler expired";
+ default:
+ return "Unknown Error";
+ }
+}
+
+void AccountManager::GetAccountsInfo(const std::string& application_id,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ picojson::array array_data;
+ int ret = ACCOUNT_ERROR_NONE;
+
+ if ("" == application_id) {
+ ret = account_foreach_account_from_db(GetAccountsCallback, &array_data);
+ } else {
+ ret = account_query_account_by_package_name(GetAccountsCallback,
+ application_id.c_str(),
+ &array_data);
+ }
+
+ if (ret == ACCOUNT_ERROR_NONE || ret == ACCOUNT_ERROR_RECORD_NOT_FOUND) {
+ out["status"] = picojson::value("success");
+ out["result"] = picojson::value(array_data);
+ } else {
+ LoggerE("Failed to get accounts information");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ }
+}
+
+bool AccountManager::GetAccountInfo(int account_id, picojson::object& out) {
+ LoggerD("Enter");
+
+ account_h account = NULL;
+ SCOPE_EXIT {
+ account_destroy(account);
+ };
+
+ int ret = account_create(&account);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to create account info");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+
+ ret = account_query_account_by_account_id(account_id, &account);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get account info");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+
+ picojson::object info;
+ if (!ConvertAccountToObject(account, info)) {
+ LoggerE("Failed to convert account_h into object");
+ REPORT_ERROR(out, UnknownException("Unknown error occurs"));
+ return false;
+ }
+
+ out["status"] = picojson::value("success");
+ out["result"] = picojson::value(info);
+
+ return true;
+}
+
+bool AccountManager::GetProviderInfo(const std::string& provider_id,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ account_type_h provider = NULL;
+ SCOPE_EXIT {
+ account_type_destroy(provider);
+ };
+
+ int ret = account_type_create(&provider);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to create provider info");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+
+ ret = account_type_query_by_app_id(provider_id.c_str(), &provider);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get provider info");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+
+ picojson::object info;
+ if (!ConvertProviderToObject(provider, info)) {
+ LoggerE("Failed to convert account_type_h into object");
+ REPORT_ERROR(out, UnknownException("Unknown error occurs"));
+ return false;
+ }
+
+ out["status"] = picojson::value("success");
+ out["result"] = picojson::value(info);
+
+ return true;
+}
+
+bool AccountManager::ConvertAccountToObject(account_h account,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ char* provider_id = NULL;
+ char* icon_path = NULL;
+ char* user_name = NULL;
+
+ SCOPE_EXIT {
+ free(provider_id);
+ free(icon_path);
+ free(user_name);
+ };
+
+ int account_id = -1;
+ int ret = account_get_account_id(account, &account_id);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get account ID");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ out["id"] = picojson::value(static_cast<double>(account_id));
+
+ ret = account_get_package_name(account, &provider_id);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get provider name");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+
+ picojson::object provider_info;
+ if (!GetProviderInfo(provider_id, provider_info)) {
+ LoggerE("Failed to get provider info");
+ return false;
+ }
+ out["provider"] = provider_info["result"];
+
+ picojson::object account_init;
+ ret = account_get_icon_path(account, &icon_path);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get icon path");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ account_init["iconUri"] = picojson::value(icon_path);
+
+ ret = account_get_user_name(account, &user_name);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get user name");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ account_init["userName"] = picojson::value(user_name);
+ out["accountInitDict"] = picojson::value(account_init);
+
+ return true;
+}
+
+bool AccountManager::ConvertProviderToObject(account_type_h provider,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ char* provider_id = NULL;
+ char* display_name = NULL;
+ char* icon_uri = NULL;
+ char* small_icon_uri = NULL;
+ bool is_multiple_account_supported = false;
+ picojson::array capabilities;
+
+ int ret = account_type_get_app_id(provider, &provider_id);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get application id");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ out["applicationId"] = picojson::value(provider_id);
+ free(provider_id);
+
+ // TODO: Which label should be returned?
+ ret = account_type_get_label_by_locale(provider, "default", &display_name);
+ if (ret == ACCOUNT_ERROR_NONE) {
+ out["displayName"] = picojson::value(display_name);
+ free(display_name);
+ } else if (ret == ACCOUNT_ERROR_RECORD_NOT_FOUND) {
+ LoggerD("There is no label");
+ out["displayName"] = picojson::value("");
+ } else {
+ LoggerE("Failed to get label");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+
+ ret = account_type_get_icon_path(provider, &icon_uri);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get icon");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ out["iconUri"] = picojson::value(icon_uri);
+ free(icon_uri);
+
+ ret = account_type_get_small_icon_path(provider, &small_icon_uri);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get small icon");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ out["smallIconUri"] = picojson::value(small_icon_uri);
+ free(small_icon_uri);
+
+ ret = account_type_get_provider_feature_all(provider, ProviderCapabilitiesCb,
+ &capabilities);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get capabilities");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ out["capabilities"] = picojson::value(capabilities);
+
+ int supported = 0;
+ ret = account_type_get_multiple_account_support(provider, &supported);
+ if (ret != ACCOUNT_ERROR_NONE) {
+ LoggerE("Failed to get small icon");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ return false;
+ }
+ is_multiple_account_supported = (supported != 0);
+ out["isMultipleAccountSupported"] = picojson::value(
+ is_multiple_account_supported);
+
+ return true;
+}
+
+void AccountManager::GetProvidersInfo(const std::string& capability,
+ picojson::object& out) {
+ LoggerD("Enter");
+
+ picojson::array array_data;
+ int ret = ACCOUNT_ERROR_NONE;
+
+ if ("" == capability) {
+ ret = account_type_foreach_account_type_from_db(AccountProvidersGetCb,
+ &array_data);
+ } else {
+ ret = account_type_query_by_provider_feature(AccountProvidersGetCb,
+ capability.c_str(),
+ &array_data);
+ }
+
+ if (ret == ACCOUNT_ERROR_NONE || ret == ACCOUNT_ERROR_RECORD_NOT_FOUND) {
+ out["status"] = picojson::value("success");
+ out["result"] = picojson::value(array_data);
+ } else {
+ LoggerE("Failed to get providers information");
+ REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+ }
+}
+
+#undef REPORT_ERROR
+
+} // namespace account
+} // namespace extension
--- /dev/null
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ACCOUNT_ACCOUNT_MANAGER_H_
+#define ACCOUNT_ACCOUNT_MANAGER_H_
+
+#include <account.h>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace account {
+
+class AccountManager {
+ public:
+ AccountManager();
+ virtual ~AccountManager();
+
+ /* out["status"] = "success" or "error"
+ * If status is "success", then the result(picojson::value) will be stored in out["result"].
+ * If status is "error", then the error(picojson::value) will be stored in out["error"].
+ */
+ void GetAccountsInfo(const std::string& application_id, picojson::object& out);
+
+ /* out["status"] = "success" or "error"
+ * If status is "success", then the result(picojson::value) will be stored in out["result"].
+ * If status is "error", then the error(picojson::value) will be stored in out["error"].
+ */
+ bool GetAccountInfo(int account_id, picojson::object& out);
+
+ /* out["status"] = "success" or "error"
+ * If status is "success", then the result(picojson::value) will be stored in out["result"].
+ * If status is "error", then the error(picojson::value) will be stored in out["error"].
+ */
+ void GetProvidersInfo(const std::string& capability, picojson::object& out);
+
+ /* out["status"] = "success" or "error"
+ * If status is "success", then the result(picojson::value) will be stored in out["result"].
+ * If status is "error", then the error(picojson::value) will be stored in out["error"].
+ */
+ static bool GetProviderInfo(const std::string& provider_id, picojson::object& out);
+
+ static bool ConvertAccountToObject(account_h account, picojson::object& out);
+
+ static bool ConvertProviderToObject(account_type_h provider, picojson::object& out);
+
+ static std::string GetErrorMsg(int error);
+};
+
+} // namespace account
+} // namespace extension
+
+#endif // ACCOUNT_ACCOUNT_MANAGER_H_
[
'extension_host_os == "mobile"', {
'dependencies': [
+ 'account/account.gyp:*',
'badge/badge.gyp:*',
'bluetooth/bluetooth.gyp:*',
'callhistory/callhistory.gyp:*',