2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 * @file FApp_AppResourceImpl.cpp
19 * @brief This is the implementation file of the _AppResourceImpl class.
24 #include <libxml/tree.h>
25 #include <unique_ptr.h>
27 #include <FBaseString.h>
28 #include <FBaseBoolean.h>
29 #include <FBaseInteger.h>
30 #include <FBaseUtilStringUtil.h>
31 #include <FBaseSysLog.h>
33 #include <FIoDirectory.h>
34 #include <FAppPkgPackageInfo.h>
35 #include <FAppPkgPackageManager.h>
36 #include <FAppIAppSettingEventListener.h>
37 #include <FSec_AccessController.h>
38 #include "FApp_AppSettingImpl.h"
39 #include "FApp_AppInfo.h"
40 #include "FAppPkg_PackageManagerImpl.h"
41 #include "FAppPkg_PackageInfoImpl.h"
44 using namespace Tizen::App::Package;
45 using namespace Tizen::Base;
46 using namespace Tizen::Base::Collection;
47 using namespace Tizen::Io;
48 using namespace Tizen::Security;
49 using namespace Tizen::App;
52 namespace Tizen { namespace App
55 const int APP_ID_LENTH = 10;
56 const int MAX_CONTENT_LEN = 512;
57 const int MAX_LOCAL_BUFSIZE = 128;
58 const char* DBUS_PATH = "/setting/dbus_handler";
59 const char* DBUS_SIGNAL_INTERFACE = "org.tizen.setting.signal";
60 static const wchar_t DBUS_SIGNAL_PREFIX[] = L"Update_";
62 static const wchar_t RESOUCE_FILE_PATH[] = L"setting/";
63 static const wchar_t RESOUCE_FILE_NAME[] = L"setting";
64 static const wchar_t RESOUCE_FILE_EXT[] = L".xml";
66 static _AppSettingImpl* pAppSettingImplInstance = null;
68 _AppSettingImpl::_MutiInstanceManager _AppSettingImpl::__appIdMultiInstanceMgr; // static member
69 DBusConnection* pDBusConnection = null;
78 dbus_connection_close(pDBusConnection);
79 pDBusConnection = null;
83 static _CleanUpDBus cleanUpDBus;
85 _AppSettingImpl::_MutiInstanceManager::_MutiInstanceManager(void)
87 __stringToInstanceMap.Construct();
90 _AppSettingImpl::_MutiInstanceManager::~_MutiInstanceManager(void)
92 __stringToInstanceMap.RemoveAll(true); // Remove instance on exit.
96 _AppSettingImpl::_MutiInstanceManager::GetInstance(const String& version)
99 AppSetting* pAppSettingInstance = null;
100 String* pKeyStr = null;
102 AppSetting* pAppSetting = static_cast<AppSetting*>( __stringToInstanceMap.GetValue(version));
108 // Common creation part
109 std::unique_ptr<_AppSettingImpl> pAppSettingImpl(new (std::nothrow) _AppSettingImpl());
110 SysTryReturn(NID_APP, pAppSettingImpl != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
111 GetErrorMessage(E_OUT_OF_MEMORY));
113 // Get current application context AppId
114 App* pApp = App::GetInstance();
116 SysTryCatch(NID_APP, pApp != null, , E_SYSTEM, "[%s] A system error has been occurred. App::GetInstance() failed",
117 GetErrorMessage(E_SYSTEM));
118 appId = pApp->GetAppId();
120 r = pAppSettingImpl->Construct(appId, version);
121 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
123 pAppSettingInstance = _AppSettingImpl::CreateAppSetting();
124 SysTryCatch(NID_APP, pAppSettingInstance != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
125 GetErrorMessage(E_OUT_OF_MEMORY));
126 _AppSettingImpl::SetImplInstance(*pAppSettingInstance, *pAppSettingImpl.release());
128 pKeyStr = new (std::nothrow) String(version);
129 SysTryCatch(NID_APP, pKeyStr != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
131 r = __stringToInstanceMap.Add(*pKeyStr, *pAppSettingInstance);
132 SysTryCatch(NID_APP, r != E_OUT_OF_MEMORY, , r, "[%s] Memory allocation failed.", GetErrorMessage(r));
133 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
135 return pAppSettingInstance;
138 delete pAppSettingInstance;
143 _AppSettingImpl::_MutiInstanceManager::GetInstanceByAppId(const AppId& appId)
145 result r = E_SUCCESS;
146 AppSetting* pAppSettingInstance = null;
147 String* pKeyStr = null;
149 r = _AccessController::CheckUserPrivilege(_PRV_APPSETTING);
150 SysTryReturn(NID_APP, !IsFailed(r), null, E_PRIVILEGE_DENIED,
151 "[%s] The application does not have the privilege to call this method.", GetErrorMessage(E_PRIVILEGE_DENIED));
153 // Convert AppId to package type id.
155 appId.SubString(0, APP_ID_LENTH, packageId);
157 AppSetting* pAppSetting = static_cast<AppSetting*>( __stringToInstanceMap.GetValue(packageId));
163 _PackageManagerImpl* pPkgMgrImpl = _PackageManagerImpl::GetInstance();
164 SysTryReturn(NID_APP, pPkgMgrImpl != null, null, E_SYSTEM,
165 "[%s] A system error has been occurred. failed to get _PackageMaangerImpl.", GetErrorMessage(E_SYSTEM));
167 std::unique_ptr<PackageInfo> pPackageInfo(pPkgMgrImpl->GetPackageInfoN(packageId)); // !E_SUCCESS for DB fail and query fail
168 SysTryReturn(NID_APP, pPackageInfo != null, null, E_APP_NOT_INSTALLED, "[%s] Propagating.", GetErrorMessage(E_APP_NOT_INSTALLED));
170 const _PackageInfoImpl* pPkgInfoImpl = _PackageInfoImpl::GetInstance(pPackageInfo.get());
171 SysTryReturn(NID_APP, pPkgInfoImpl != null, null, E_SYSTEM,
172 "[%s] A system error has been occurred. failed to get _PackageInfoImpl.", GetErrorMessage(E_SYSTEM));
174 String rootPath = pPkgInfoImpl->GetAppRootPath();
177 // Common creation part
178 std::unique_ptr<_AppSettingImpl> pAppSettingImpl(new (std::nothrow) _AppSettingImpl());
179 SysTryReturn(NID_APP, pAppSettingImpl != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
180 GetErrorMessage(E_OUT_OF_MEMORY));
182 r = pAppSettingImpl->ConstructByAppPath(packageId, rootPath);
183 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
185 pAppSettingInstance = _AppSettingImpl::CreateAppSetting();
186 SysTryCatch(NID_APP, pAppSettingInstance != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
187 GetErrorMessage(E_OUT_OF_MEMORY));
188 _AppSettingImpl::SetImplInstance(*pAppSettingInstance, *pAppSettingImpl.release());
190 pKeyStr = new (std::nothrow) String(packageId);
191 SysTryCatch(NID_APP, pKeyStr != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
193 r = __stringToInstanceMap.Add(*pKeyStr, *pAppSettingInstance);
194 SysTryCatch(NID_APP, r != E_OUT_OF_MEMORY, , r, "[%s] Memory allocation failed.", GetErrorMessage(r));
195 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
197 return pAppSettingInstance;
200 delete pAppSettingInstance;
205 _AppSettingImpl::_MutiInstanceManager::ReleaseInstanceByAppId(const AppId& appId)
207 result r = _AccessController::CheckUserPrivilege(_PRV_APPSETTING);
208 SysTryReturnResult(NID_APP, !IsFailed(r), E_PRIVILEGE_DENIED,
209 "The application does not have the privilege to call this method.");
211 // Convert AppId to package type id.
213 appId.SubString(0, APP_ID_LENTH, packageId);
215 AppSetting* pAppSetting = static_cast<AppSetting*>(__stringToInstanceMap.GetValue(packageId));
220 _AppSettingImpl* pThisAppSettingImpl = _AppSettingImpl::GetInstance(*pAppSetting);
221 dbus_connection_remove_filter(pDBusConnection, HandleDBusMessage, pThisAppSettingImpl);
223 __stringToInstanceMap.Remove(packageId, true); // Delete item instance and remove item from __stringToInstanceMap
228 return E_OBJ_NOT_FOUND;
233 _AppSettingImpl::_MutiInstanceManager::ReleaseOtherAppInstances(void)
236 { // Iterate all element and remove correspond dbus filter
237 std::unique_ptr<IMapEnumerator> pEnum(__stringToInstanceMap.GetMapEnumeratorN());
240 while (pEnum->MoveNext() == E_SUCCESS)
242 AppSetting* pAppSetting = null;
243 pAppSetting = static_cast<AppSetting*>(pEnum->GetValue());
244 _AppSettingImpl* pThisAppSettingImpl = _AppSettingImpl::GetInstance(*pAppSetting);
245 dbus_connection_remove_filter(pDBusConnection, HandleDBusMessage, pThisAppSettingImpl);
249 __stringToInstanceMap.RemoveAll(true);
257 _SettingItem(Object* pItemValue, int min, int max, xmlNodePtr pItemXmlNode)
258 : __pValue(pItemValue)
261 , __pXmlNode(pItemXmlNode)
267 Object* GetValue(void)
271 const Object* GetValue(void) const
283 xmlNodePtr GetXmlNode(void)
289 _SettingItem(const _SettingItem& rhs);
290 _SettingItem& operator =(const _SettingItem& rhs);
295 xmlNodePtr __pXmlNode;
298 class _ReverseStringComparer
299 : public Tizen::Base::Collection::IComparer
302 _ReverseStringComparer(void) {};
303 virtual ~_ReverseStringComparer(void) {};
304 virtual result Compare(const Tizen::Base::Object& obj1, const Tizen::Base::Object& obj2, int& cmp) const
306 const String& objString1 = static_cast<const String&>(obj1);
307 const String& objString2 = static_cast<const String&>(obj2);
308 cmp = objString2.CompareTo(objString1); // reverse
313 _AppSettingImpl::_AppSettingImpl(void)
314 : __oldVersionInstance(false)
315 , __pEventListener(null)
321 _AppSettingImpl::~_AppSettingImpl(void)
328 __settingContainer.RemoveAll(true);
332 _AppSettingImpl::GetInstance(void)
335 result r = E_SUCCESS;
337 if (pAppSettingImplInstance == null)
339 pAppSettingImplInstance = new (std::nothrow) _AppSettingImpl();
340 SysTryReturn(NID_APP, pAppSettingImplInstance != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
341 GetErrorMessage(E_OUT_OF_MEMORY));
343 // Get current application context AppId
344 App* pApp = App::GetInstance();
345 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] A system error has been occurred. App::GetInstance() failed",
346 GetErrorMessage(E_SYSTEM));
348 appId = pApp->GetAppId();
349 r = pAppSettingImplInstance->Construct(appId);
350 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
352 return pAppSettingImplInstance;
355 delete pAppSettingImplInstance;
356 pAppSettingImplInstance = null;
361 _AppSettingImpl::GetInstance(const Tizen::Base::String& version)
364 //result r = E_SUCCESS;
366 static _MutiInstanceManager multiInstanceManager;
367 AppSetting* pVersionAppSetting = multiInstanceManager.GetInstance(version);
368 SysTryReturn(NID_APP, pVersionAppSetting != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
369 GetErrorMessage(E_OUT_OF_MEMORY));
371 return pVersionAppSetting;
375 _AppSettingImpl::GetInstanceByAppId(const AppId& appId)
379 AppSetting* pAppSettingByAppId = __appIdMultiInstanceMgr.GetInstanceByAppId(appId);
380 return pAppSettingByAppId;
384 _AppSettingImpl::ReleaseInstanceByAppId(const AppId& appId)
386 return __appIdMultiInstanceMgr.ReleaseInstanceByAppId(appId);
390 _AppSettingImpl::ReleaseOtherAppInstances(void)
392 return __appIdMultiInstanceMgr.ReleaseOtherAppInstances();
395 Tizen::Base::Collection::IList*
396 _AppSettingImpl::GetAppSettingVersionListN(void)
398 result r = E_SUCCESS;
399 ArrayList* pVersionList = new (std::nothrow) ArrayList;
400 SysTryReturn(NID_APP, pVersionList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
401 GetErrorMessage(E_OUT_OF_MEMORY));
402 r = pVersionList->Construct();
403 SysTryReturn(NID_APP, !IsFailed(r), null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
404 GetErrorMessage(E_OUT_OF_MEMORY));
406 // Iterate file and add to list
407 String dirPath = _AppInfo::GetAppRootPath() + RESOUCE_FILE_PATH;
409 r = dir.Construct(dirPath);
410 SysTryReturn(NID_APP, !IsFailed(r), null, E_SYSTEM, "[%s] A system error has been occurred. Directory construction failed.",
411 GetErrorMessage(E_SYSTEM));
413 std::unique_ptr<DirEnumerator> pDirEnum(dir.ReadN());
414 SysTryReturn(NID_APP, pDirEnum != null, null, E_SYSTEM,
415 "[%s] A system error has been occurred. Directory enumerator getting failed.", GetErrorMessage(E_SYSTEM));
417 String settingName(RESOUCE_FILE_NAME);
418 String settingExt(RESOUCE_FILE_EXT);
419 while (pDirEnum->MoveNext() == E_SUCCESS)
421 DirEntry dirEntry = pDirEnum->GetCurrentDirEntry();
422 if (!dirEntry.IsDirectory())
424 String fullName = dirEntry.GetName();
425 // Check name and extension to getting valid one
428 const int extLength = settingExt.GetLength();
429 const int posStart = settingName.GetLength();
430 const int posEnd = fullName.GetLength() - extLength;
431 if (posStart >= posEnd)
435 fullName.SubString(0, posStart, name);
436 fullName.SubString(posEnd, ext);
437 if ((name == settingName) && (ext == settingExt))
440 if (E_SUCCESS == fullName.SubString(posStart, posEnd-posStart, version))
442 String* pVersionStr = new (std::nothrow) String(version);
443 SysTryReturn(NID_APP, pVersionStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
444 GetErrorMessage(E_OUT_OF_MEMORY));
445 pVersionList->Add(*pVersionStr);
451 if (pVersionList->GetCount())
453 static _ReverseStringComparer strComparator;
454 pVersionList->Sort(strComparator);
455 pVersionList->RemoveAt(0); // remove latest version from list.
462 _AppSettingImpl::GetValue(const Tizen::Base::String& id, bool& value) const
464 const Object* pObject = __settingContainer.GetValue(id);
465 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
466 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
467 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
468 const Boolean* pBoolean = dynamic_cast<const Boolean*>(pItem->GetValue());
469 SysTryReturnResult(NID_APP, pBoolean != null, E_TYPE_MISMATCH, "Type mismatch between requested type bool and object type.");
470 value = pBoolean->ToBool();
476 _AppSettingImpl::GetValue(const Tizen::Base::String& id, int& value) const
478 const Object* pObject = __settingContainer.GetValue(id);
479 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
480 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
481 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
482 const Integer* pInteger = dynamic_cast<const Integer*>(pItem->GetValue());
483 SysTryReturnResult(NID_APP, pInteger != null, E_TYPE_MISMATCH, "Type mismatch between requested type int and object type.");
484 value = pInteger->ToInt();
490 _AppSettingImpl::GetValue(const Tizen::Base::String& id, Tizen::Base::String& value) const
492 const Object* pObject = __settingContainer.GetValue(id);
493 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
494 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
495 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
496 const String* pString = dynamic_cast<const String*>(pItem->GetValue());
497 SysTryReturnResult(NID_APP, pString != null, E_TYPE_MISMATCH, "Type mismatch between requested type String and object type.");
504 _AppSettingImpl::SetValue(const Tizen::Base::String& id, bool value, bool save)
506 Object* pObject = __settingContainer.GetValue(id);
507 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
508 _SettingItem* pItem = dynamic_cast<_SettingItem*>(pObject);
509 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
510 Boolean* pBoolean = dynamic_cast<Boolean*>(pItem->GetValue());
511 SysTryReturnResult(NID_APP, pBoolean != null, E_TYPE_MISMATCH, "Type mismatch between requested type bool and object type.");
514 static const String strTrue(L"true");
515 static const String strFalse(L"false");
516 const String& strValue = value ? strTrue : strFalse;
517 UpdateProperty(pItem->GetXmlNode(), strValue);
521 static const String strIntTrue(L"1");
522 static const String strIntFalse(L"0");
523 SendMessage(id, value ? strIntTrue : strIntFalse, true);
525 if (__pEventListener)
527 __pEventListener->OnAppSettingChanged(id);
534 _AppSettingImpl::SetValue(const Tizen::Base::String& id, int value, bool save)
536 Object* pObject = __settingContainer.GetValue(id);
537 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
538 _SettingItem* pItem = dynamic_cast<_SettingItem*>(pObject);
539 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
540 Integer* pInteger = dynamic_cast<Integer*>(pItem->GetValue());
541 SysTryReturnResult(NID_APP, pInteger != null, E_TYPE_MISMATCH, "Type mismatch between requested type int and object type.");
543 SysTryReturnResult(NID_APP, (pItem->GetMin() <= value), E_OUT_OF_RANGE, "value(%d) is less than minimum range(%d).",
544 value, pItem->GetMin());
545 SysTryReturnResult(NID_APP, (pItem->GetMax() >= value), E_OUT_OF_RANGE, "value(%d) is greater than maximum range(%d).",
546 value, pItem->GetMax());
549 String strValue = pInteger->ToString();
550 UpdateProperty(pItem->GetXmlNode(), strValue);
554 SendMessage(id, strValue, true);
556 if (__pEventListener)
558 __pEventListener->OnAppSettingChanged(id);
565 _AppSettingImpl::SetValue(const Tizen::Base::String& id, const Tizen::Base::String& value, bool save)
567 Object* pObject = __settingContainer.GetValue(id);
568 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
569 _SettingItem* pItem = dynamic_cast<_SettingItem*>(pObject);
570 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
571 String* pString = dynamic_cast<String*>(pItem->GetValue());
572 SysTryReturnResult(NID_APP, pString != null, E_TYPE_MISMATCH, "Type mismatch between requested type String and object type.");
574 SysTryReturnResult(NID_APP, pItem->GetMin() <= value.GetLength(), E_OUT_OF_RANGE,
575 "value length(%d) less than minimum length(%d).", value.GetLength(), pItem->GetMin());
576 SysTryReturnResult(NID_APP, pItem->GetMax() >= value.GetLength(), E_OUT_OF_RANGE,
577 "value length(%d) greater than maximum range(%d).", value.GetLength(), pItem->GetMax());
580 UpdateProperty(pItem->GetXmlNode(), *pString);
584 SendMessage(id, *pString, false);
586 if (__pEventListener)
588 __pEventListener->OnAppSettingChanged(id);
595 _AppSettingImpl::SetAppSettingEventListener(IAppSettingEventListener* pListener)
597 __pEventListener = pListener;
602 _AppSettingImpl::GetInstance(AppSetting& appSetting)
604 return appSetting.__pAppSettingImpl;
607 const _AppSettingImpl*
608 _AppSettingImpl::GetInstance(const AppSetting& appSetting)
610 return appSetting.__pAppSettingImpl;
614 _AppSettingImpl::Construct(const AppId& correspondAppId, const String& version)
616 result r = E_SUCCESS;
617 if (version.GetLength() > 0)
619 __oldVersionInstance = true;
621 correspondAppId.SubString(0, APP_ID_LENTH, __correspondAppId); // Use 10 char id value.
623 __filePath = _AppInfo::GetAppRootPath() + RESOUCE_FILE_PATH;
624 __filePath += RESOUCE_FILE_NAME;
625 if (version.GetLength())
627 __filePath += version;
629 __filePath += RESOUCE_FILE_EXT;
631 r = __settingContainer.Construct();
632 SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
633 if (!__oldVersionInstance)
635 SysTryReturnResult(NID_APP, InitizlizeDBus(), E_SYSTEM, "A system error has been occurred. DBus initialization failed.");
638 SysTryReturnResult(NID_APP, !IsFailed(r), E_SYSTEM, "A system error has been occurred. Loading procedure failed.");
643 _AppSettingImpl::ConstructByAppPath(const AppId& correspondAppId, const Tizen::Base::String& appRootPath)
645 result r = E_SUCCESS;
646 SysTryReturn(NID_APP, !appRootPath.IsEmpty(), E_INVALID_ARG, E_INVALID_ARG,
647 "[%s] Invalid argument is used. appRootPath length is 0.", GetErrorMessage(E_INVALID_ARG));
649 correspondAppId.SubString(0, APP_ID_LENTH, __correspondAppId); // Use 10 char id value.
650 __filePath = appRootPath + RESOUCE_FILE_PATH;
651 __filePath += RESOUCE_FILE_NAME;
652 __filePath += RESOUCE_FILE_EXT;
654 r = __settingContainer.Construct();
655 SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
656 SysTryReturnResult(NID_APP, InitizlizeDBus(), E_SYSTEM, "A system error has been occurred. DBus initialization failed.");
658 SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
664 _AppSettingImpl::Load(void)
666 SysTryReturnResult(NID_APP, File::IsFileExist(__filePath), E_OBJ_NOT_FOUND,
667 "The instance of specified AppId does not have setting information.");
669 result r = E_SUCCESS;
670 std::unique_ptr<ByteBuffer> pfilePath(Tizen::Base::Utility::StringUtil::StringToUtf8N(__filePath));
671 SysTryReturnResult(NID_APP, pfilePath != null, E_OUT_OF_MEMORY, "Memory allocation failed. File path conversion failed.");
673 __pDoc = xmlParseFile(reinterpret_cast<const char*>(pfilePath->GetPointer()));
674 SysTryReturnResult(NID_APP, __pDoc != null, E_SYSTEM,
675 "A system error has been occurred. Can not parse xml file: %ls", __filePath.GetPointer());
677 xmlNodePtr rootNodePtr = xmlDocGetRootElement(__pDoc);
678 SysTryReturnResult(NID_APP, rootNodePtr != null, E_SYSTEM, "A system error has been occurred. Can not find root node");
680 VisitNode(rootNodePtr);
686 _AppSettingImpl::Save(void)
688 static const int XML_SAVE_FAILED = -1;
689 static const int XML_SAVE_FORMAT = 1;
691 SysTryReturnResult(NID_APP, __pDoc != null, E_SYSTEM,
692 "A system error has been occurred. XML Document not valid so can not save it.");
693 std::unique_ptr<ByteBuffer> pfilePath(Tizen::Base::Utility::StringUtil::StringToUtf8N(__filePath));
694 SysTryReturnResult(NID_APP, pfilePath != null, E_OUT_OF_MEMORY, "Memory allocation failed. File path conversion failed.");
696 int result = xmlSaveFormatFile(reinterpret_cast<const char*>(pfilePath->GetPointer()), __pDoc, XML_SAVE_FORMAT);
697 SysTryReturnResult(NID_APP, result != XML_SAVE_FAILED, E_SYSTEM, "A system error has been occurred. Document saving failed.");
703 _AppSettingImpl::VisitNode(xmlNodePtr pCurrentNode)
705 for (xmlNodePtr nodePtr = pCurrentNode; nodePtr != null; nodePtr = nodePtr->next) // Visit sibling node
707 // Check node name and add to collection.
708 if (nodePtr->type == XML_ELEMENT_NODE)
710 CheckNodeNameAndAddToCollection(nodePtr);
713 VisitNode(nodePtr->children);
718 _AppSettingImpl::CheckNodeNameAndAddToCollection(xmlNodePtr pNode)
720 static const char* pPropId = "id";
721 static const char* pPropValue = "value";
723 // 1. Get type (bool, integer, string, expandlist)
724 _ElementType detectedType = GetElementType(pNode);
726 // Make item and add to collection.
727 if (detectedType != ELEMENT_INVALID)
730 xmlChar* pId = xmlGetProp(pNode, reinterpret_cast<const xmlChar*>(pPropId));
736 std::unique_ptr<String> pStrId(new (std::nothrow) String(reinterpret_cast<char*>(pId)));
737 SysTryReturnVoidResult(NID_APP, pStrId, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
738 GetErrorMessage(E_OUT_OF_MEMORY));
743 { // 3. Get min(length), max(length) value
744 if ((detectedType == ELEMENT_INTEGER) || (detectedType == ELEMENT_STRING))
746 GetMinMaxValue(pNode, detectedType, min, max);
750 bool validValue = false;
751 xmlChar* pValue = xmlGetProp(pNode, reinterpret_cast<const xmlChar*>(pPropValue));
754 strValue = String(reinterpret_cast<char*>(pValue));
759 // 5. Create value object from value
760 Object* pValueObject = GetValueObjectN(detectedType, strValue, validValue);
763 _SettingItem* pSettingItem = new (std::nothrow) _SettingItem(pValueObject, min, max, pNode);
764 SysTryReturnVoidResult(NID_APP, pSettingItem, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
765 GetErrorMessage(E_OUT_OF_MEMORY));
767 { // 6. Add item to container
768 SysLog(NID_APP, "AppSetting item adding: ID=%ls min=%d max=%d Value=%ls",
769 pStrId->GetPointer(), min, max, strValue.GetPointer());
770 __settingContainer.Add(*pStrId.release(), *pSettingItem);
774 SysLog(NID_APP, "Failed create new _SettingItem");
783 _AppSettingImpl::GetElementType(xmlNodePtr pNode)
785 const xmlChar* pElementBool = reinterpret_cast<const xmlChar*>("bool");
786 const xmlChar* pElementInteger = reinterpret_cast<const xmlChar*>("integer");
787 const xmlChar* pElementString = reinterpret_cast<const xmlChar*>("string");
788 const xmlChar* pElementExpandlist = reinterpret_cast<const xmlChar*>("expandlist");
790 _ElementType type = ELEMENT_INVALID;
791 if (xmlStrcmp(pNode->name, pElementBool) == 0)
796 if (xmlStrcmp(pNode->name, pElementInteger) == 0)
798 type = ELEMENT_INTEGER;
801 if (xmlStrcmp(pNode->name, pElementString) == 0)
803 type = ELEMENT_STRING;
806 if (xmlStrcmp(pNode->name, pElementExpandlist) == 0)
808 type = ELEMENT_EXPANDLIST;
815 _AppSettingImpl::GetMinMaxValue(xmlNodePtr pNode, _ElementType type, int& min, int& max)
817 const xmlChar* pPropMin = reinterpret_cast<const xmlChar*>("min");
818 const xmlChar* pPropMax = reinterpret_cast<const xmlChar*>("max");
819 const xmlChar* pPropMinLength = reinterpret_cast<const xmlChar*>("minlength");
820 const xmlChar* pPropMaxLength = reinterpret_cast<const xmlChar*>("maxlength");
822 if (type == ELEMENT_INTEGER)
824 xmlChar* pStrMin = xmlGetProp(pNode, pPropMin);
827 Integer::Parse(reinterpret_cast<char*>(pStrMin), min);
832 SysLog(NID_APP, "Failed to get 'min' value.");
835 xmlChar* pStrMax = xmlGetProp(pNode, pPropMax);
838 Integer::Parse(reinterpret_cast<char*>(pStrMax), max);
843 SysLog(NID_APP, "Failed to get 'max' value.");
847 if (type == ELEMENT_STRING)
849 xmlChar* pStrMin = xmlGetProp(pNode, pPropMinLength);
852 Integer::Parse(reinterpret_cast<char*>(pStrMin), min);
857 SysLog(NID_APP, "Failed to get 'minlength' value.");
860 xmlChar* pStrMax = xmlGetProp(pNode, pPropMaxLength);
863 Integer::Parse(reinterpret_cast<char*>(pStrMax), max);
868 SysLog(NID_APP, "Failed to get 'maxlength' value.");
873 SysLog(NID_APP, "Invalid element type.");
878 _AppSettingImpl::GetValueObjectN(_ElementType type, String& strValue, bool validValue)
880 const String strTrue(L"true");
881 Object* pValueObject = null;
887 bool valueBool = false;
890 if (strValue == strTrue)
895 pValueObject = new (std::nothrow) Boolean(valueBool);
896 SysTryReturn(NID_APP, pValueObject != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
897 GetErrorMessage(E_OUT_OF_MEMORY));
901 case ELEMENT_INTEGER:
903 int valueInteger = 0;
906 Integer::Parse(strValue, valueInteger);
908 pValueObject = new (std::nothrow) Integer(valueInteger);
909 SysTryReturn(NID_APP, pValueObject != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
910 GetErrorMessage(E_OUT_OF_MEMORY));
915 case ELEMENT_EXPANDLIST:
917 String* pStringObject = new (std::nothrow) String;
918 SysTryReturn(NID_APP, pStringObject != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
919 GetErrorMessage(E_OUT_OF_MEMORY));
920 if (pStringObject && validValue)
922 *pStringObject = strValue;
924 pValueObject = pStringObject;
928 case ELEMENT_INVALID:
929 // It already validate by caller;
930 SysLog(NID_APP, "Invalid element type.");
938 _AppSettingImpl::UpdateProperty(xmlNodePtr pNode, const String& value)
940 const xmlChar* pPropValue = reinterpret_cast<const xmlChar*>("value");
944 const xmlChar* pZeroLength = reinterpret_cast<const xmlChar*>("");
945 xmlAttrPtr attrPtr = xmlSetProp(pNode, pPropValue, pZeroLength);
953 std::unique_ptr<ByteBuffer> pBuf(Tizen::Base::Utility::StringUtil::StringToUtf8N(value));
956 xmlAttrPtr attrPtr = xmlSetProp(pNode, pPropValue, reinterpret_cast<const xmlChar*>(pBuf->GetPointer()));
964 SysLog(NID_APP, "StringToUtf8N is failed.");
971 _AppSettingImpl::InitizlizeDBus(void)
974 dbus_error_init(&error);
976 if (pDBusConnection == null)
978 char rule[MAX_LOCAL_BUFSIZE];
979 pDBusConnection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
980 if (pDBusConnection == null)
982 SysLog(NID_APP, "Fail to connect to the D-BUS daemon: %s", error.message);
983 dbus_error_free(&error);
986 dbus_connection_setup_with_g_main(pDBusConnection, null);
988 snprintf(rule, MAX_LOCAL_BUFSIZE, "path='%s',type='signal',interface='%s'", DBUS_PATH, DBUS_SIGNAL_INTERFACE);
989 dbus_bus_add_match(pDBusConnection, rule, &error);
990 if (dbus_error_is_set(&error))
992 SysLog(NID_APP, "Fail to add match : %s", error.message);
993 dbus_error_free(&error);
998 // this value is vary by AppSetting instance for proper handling.
999 // Should be explicit remove filter on ReleaseInstanceByAppId.
1000 if (dbus_connection_add_filter(pDBusConnection, HandleDBusMessage, this, NULL) == FALSE)
1002 SysLog(NID_APP, "Fail to add filter : %s", error.message);
1003 dbus_error_free(&error);
1010 _AppSettingImpl::HandleDBusMessage(DBusConnection* connection, DBusMessage* message, void* user_data)
1012 int my_pid = getpid();
1015 char* pValue = NULL;
1018 dbus_error_init(&error);
1020 _AppSettingImpl* pAppSettingImpl = static_cast<_AppSettingImpl*>(user_data);
1021 SysTryLogReturn(NID_APP, pAppSettingImpl != null, DBUS_HANDLER_RESULT_HANDLED,
1022 "Not valid pAppSettingImpl from user_data");
1023 String signalString(DBUS_SIGNAL_PREFIX);
1024 signalString += pAppSettingImpl->__correspondAppId;
1025 std::unique_ptr<ByteBuffer> pBufferSignal(Tizen::Base::Utility::StringUtil::StringToUtf8N(signalString));
1026 SysTryLogReturn(NID_APP, pBufferSignal != null, DBUS_HANDLER_RESULT_HANDLED, "pBufferSignal is not valid");
1027 const char* pCharBufferSignal = reinterpret_cast<const char*>(pBufferSignal->GetPointer());
1029 if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE, pCharBufferSignal))
1031 if (dbus_message_get_args(message, &error,
1032 DBUS_TYPE_UINT32, &sender_pid,
1033 DBUS_TYPE_STRING, &pId,
1034 DBUS_TYPE_STRING, &pValue,
1035 DBUS_TYPE_INVALID) == FALSE)
1037 SysLog(NID_APP, "Fail to get data : %s", error.message);
1038 dbus_error_free(&error);
1039 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1042 if (sender_pid != 0 && my_pid != sender_pid)
1044 pAppSettingImpl->SetValueFromDBusData(pId, pValue);
1046 return DBUS_HANDLER_RESULT_HANDLED;
1050 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1055 _AppSettingImpl::SetValueFromDBusData(const char* pId, const char* pValue)
1057 const String delimiter(L"|");
1060 int indexOfDelimiter = 0;
1062 // Native Setting module send the key as "id|title" so need to get id part before the '|' character.
1063 // Value is "INT|value" for check box and slider Or "STRING|value" so need to get right side value string.
1066 result r = strOrg.IndexOf(delimiter, 0, indexOfDelimiter);
1067 SysTryReturnVoidResult(NID_APP, !IsFailed(r), r, "[%s] Propagating. Bus data parsing failed", GetErrorMessage(r));
1068 strOrg.SubString(0, indexOfDelimiter, strId); // Get left string of '|'
1072 r = strOrg.IndexOf(delimiter, 0, indexOfDelimiter);
1073 SysTryReturnVoidResult(NID_APP, !IsFailed(r), r, "[%s] Propagating. Bus data parsing failed", GetErrorMessage(r));
1074 strOrg.SubString(indexOfDelimiter+1, strValue); // Get right string of '|'
1076 const Object* pObject = __settingContainer.GetValue(strId);
1079 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
1080 SysTryReturnVoidResult(NID_APP, pItem != null, E_SYSTEM, "[%s] A system error has been occurred. Casting failed to item.",
1081 GetErrorMessage(E_SYSTEM));
1082 const Boolean* pBoolean = dynamic_cast<const Boolean*>(pItem->GetValue());
1085 static const String strFalse(L"0");
1086 bool valueBool = true;
1088 if (strValue == strFalse)
1092 SetValue(strId, valueBool, false);
1095 const Integer* pInteger = dynamic_cast<const Integer*>(pItem->GetValue());
1098 int valueInteger = 0;
1099 Integer::Parse(strValue, valueInteger);
1100 SetValue(strId, valueInteger, false);
1103 const String* pString = dynamic_cast<const String*>(pItem->GetValue());
1106 SetValue(strId, strValue, false);
1109 SysSecureLog(NID_APP, "Failed determine value type for id= %s", pId);
1113 SysSecureLog(NID_APP, "Failed find value for id= %s", pId);
1118 _AppSettingImpl::SendMessage(const String& id, const String& value, bool intType)
1120 if (__oldVersionInstance)
1122 return true; // NOP for old version instance.
1125 if (!pDBusConnection)
1127 SysLog(NID_APP, "DBus connection invalid");
1132 const String strRightOfId(L"|N/A");
1133 const String strLeftOfValueIntType(L"INT|");
1134 const String strLeftOfValueStrType(L"STRING|");
1136 String strId = id + strRightOfId;
1140 strValue = strLeftOfValueIntType;
1144 strValue = strLeftOfValueStrType;
1147 String signalString(DBUS_SIGNAL_PREFIX);
1148 signalString += __correspondAppId;
1150 std::unique_ptr<ByteBuffer> pBufferId(Tizen::Base::Utility::StringUtil::StringToUtf8N(strId));
1151 std::unique_ptr<ByteBuffer> pBufferValue(Tizen::Base::Utility::StringUtil::StringToUtf8N(strValue));
1152 std::unique_ptr<ByteBuffer> pBufferSignal(Tizen::Base::Utility::StringUtil::StringToUtf8N(signalString));
1153 if (pBufferId && pBufferValue && pBufferSignal)
1155 int sender_pid = getpid();
1156 const char* pCharBufferId = reinterpret_cast<const char*>(pBufferId->GetPointer());
1157 const char* pCharBufferValue = reinterpret_cast<const char*>(pBufferValue->GetPointer());
1158 const char* pCharBufferSignal = reinterpret_cast<const char*>(pBufferSignal->GetPointer());
1160 DBusMessage* pMessageWihtAppId = dbus_message_new_signal(DBUS_PATH, DBUS_SIGNAL_INTERFACE, pCharBufferSignal);
1161 if (dbus_message_append_args(pMessageWihtAppId,
1162 DBUS_TYPE_UINT32, &sender_pid,
1163 DBUS_TYPE_STRING, &pCharBufferId,
1164 DBUS_TYPE_STRING, &pCharBufferValue,
1165 DBUS_TYPE_INVALID) == FALSE)
1167 SysLog(NID_APP, "DBus connection invalid");
1171 if (dbus_connection_send(pDBusConnection, pMessageWihtAppId, NULL) == FALSE)
1173 SysLog(NID_APP, "Fail to send message");
1177 dbus_connection_flush(pDBusConnection);
1178 dbus_message_unref(pMessageWihtAppId);
1182 SysLog(NID_APP, "System error: memory full ?");
1189 _AppSettingImpl::CreateAppSetting(void)
1191 AppSetting* pAppSetting = new (std::nothrow) AppSetting;
1192 SysTryReturn(NID_APP, pAppSetting != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1193 GetErrorMessage(E_OUT_OF_MEMORY));
1199 _AppSettingImpl::SetImplInstance(AppSetting& appSetting, _AppSettingImpl& impl)
1201 appSetting.__pAppSettingImpl = &impl;