2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FApp_AppResourceImpl.cpp
20 * @brief This is the implementation file of the _AppResourceImpl class.
25 #include <libxml/tree.h>
26 #include <unique_ptr.h>
28 #include <FBaseString.h>
29 #include <FBaseBoolean.h>
30 #include <FBaseInteger.h>
31 #include <FBaseUtilStringUtil.h>
32 #include <FBaseSysLog.h>
34 #include <FIoDirectory.h>
35 #include <FAppPkgPackageInfo.h>
36 #include <FAppPkgPackageManager.h>
37 #include <FAppIAppSettingEventListener.h>
38 #include <FSec_AccessController.h>
39 #include "FApp_AppSettingImpl.h"
40 #include "FApp_AppInfo.h"
41 #include "FAppPkg_PackageManagerImpl.h"
42 #include "FAppPkg_PackageInfoImpl.h"
45 using namespace Tizen::App::Package;
46 using namespace Tizen::Base;
47 using namespace Tizen::Base::Collection;
48 using namespace Tizen::Io;
49 using namespace Tizen::Security;
50 using namespace Tizen::App;
53 namespace Tizen { namespace App
56 const int APP_ID_LENTH = 10;
57 const int MAX_CONTENT_LEN = 512;
58 const int MAX_LOCAL_BUFSIZE = 128;
59 const char* DBUS_PATH = "/setting/dbus_handler";
60 const char* DBUS_SIGNAL_INTERFACE = "org.tizen.setting.signal";
61 static const wchar_t DBUS_SIGNAL_PREFIX[] = L"Update_";
63 static const wchar_t RESOUCE_FILE_PATH[] = L"setting/";
64 static const wchar_t RESOUCE_FILE_NAME[] = L"setting";
65 static const wchar_t RESOUCE_FILE_EXT[] = L".xml";
67 static _AppSettingImpl* pAppSettingImplInstance = null;
69 _AppSettingImpl::_MutiInstanceManager _AppSettingImpl::__appIdMultiInstanceMgr; // static member
70 DBusConnection* pDBusConnection = null;
79 dbus_connection_close(pDBusConnection);
80 pDBusConnection = null;
84 static _CleanUpDBus cleanUpDBus;
86 _AppSettingImpl::_MutiInstanceManager::_MutiInstanceManager(void)
88 __stringToInstanceMap.Construct();
91 _AppSettingImpl::_MutiInstanceManager::~_MutiInstanceManager(void)
93 __stringToInstanceMap.RemoveAll(true); // Remove instance on exit.
97 _AppSettingImpl::_MutiInstanceManager::GetInstance(const String& version)
100 AppSetting* pAppSettingInstance = null;
101 String* pKeyStr = null;
103 AppSetting* pAppSetting = static_cast<AppSetting*>( __stringToInstanceMap.GetValue(version));
109 // Common creation part
110 std::unique_ptr<_AppSettingImpl> pAppSettingImpl(new (std::nothrow) _AppSettingImpl());
111 SysTryReturn(NID_APP, pAppSettingImpl != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
112 GetErrorMessage(E_OUT_OF_MEMORY));
114 // Get current application context AppId
115 App* pApp = App::GetInstance();
117 SysTryCatch(NID_APP, pApp != null, , E_SYSTEM, "[%s] A system error has been occurred. App::GetInstance() failed",
118 GetErrorMessage(E_SYSTEM));
119 appId = pApp->GetAppId();
121 r = pAppSettingImpl->Construct(appId, version);
122 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
124 pAppSettingInstance = _AppSettingImpl::CreateAppSetting();
125 SysTryCatch(NID_APP, pAppSettingInstance != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
126 GetErrorMessage(E_OUT_OF_MEMORY));
127 _AppSettingImpl::SetImplInstance(*pAppSettingInstance, *pAppSettingImpl.release());
129 pKeyStr = new (std::nothrow) String(version);
130 SysTryCatch(NID_APP, pKeyStr != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
132 r = __stringToInstanceMap.Add(*pKeyStr, *pAppSettingInstance);
133 SysTryCatch(NID_APP, r != E_OUT_OF_MEMORY, , r, "[%s] Memory allocation failed.", GetErrorMessage(r));
134 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
136 return pAppSettingInstance;
139 delete pAppSettingInstance;
144 _AppSettingImpl::_MutiInstanceManager::GetInstanceByAppId(const AppId& appId)
146 result r = E_SUCCESS;
147 AppSetting* pAppSettingInstance = null;
148 String* pKeyStr = null;
150 r = _AccessController::CheckUserPrivilege(_PRV_APPSETTING);
151 SysTryReturn(NID_APP, !IsFailed(r), null, E_PRIVILEGE_DENIED,
152 "[%s] The application does not have the privilege to call this method.", GetErrorMessage(E_PRIVILEGE_DENIED));
154 // Convert AppId to package type id.
156 appId.SubString(0, APP_ID_LENTH, packageId);
158 AppSetting* pAppSetting = static_cast<AppSetting*>( __stringToInstanceMap.GetValue(packageId));
164 _PackageManagerImpl* pPkgMgrImpl = _PackageManagerImpl::GetInstance();
165 SysTryReturn(NID_APP, pPkgMgrImpl != null, null, E_SYSTEM,
166 "[%s] A system error has been occurred. failed to get _PackageMaangerImpl.", GetErrorMessage(E_SYSTEM));
168 PackageInfo* pPackageInfo = null;
169 pPackageInfo = pPkgMgrImpl->GetPackageInfoN(packageId); // !E_SUCCESS for DB fail and query fail
170 SysTryReturn(NID_APP, pPackageInfo != null, null, E_APP_NOT_INSTALLED, "[%s] Propagating.", GetErrorMessage(E_APP_NOT_INSTALLED));
172 const _PackageInfoImpl* pPkgInfoImpl = _PackageInfoImpl::GetInstance(pPackageInfo);
173 SysTryReturn(NID_APP, pPkgInfoImpl != null, null, E_SYSTEM,
174 "[%s] A system error has been occurred. failed to get _PackageInfoImpl.", GetErrorMessage(E_SYSTEM));
176 String rootPath = pPkgInfoImpl->GetAppRootPath();
179 // Common creation part
180 std::unique_ptr<_AppSettingImpl> pAppSettingImpl(new (std::nothrow) _AppSettingImpl());
181 SysTryReturn(NID_APP, pAppSettingImpl != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
182 GetErrorMessage(E_OUT_OF_MEMORY));
184 r = pAppSettingImpl->ConstructByAppPath(packageId, rootPath);
185 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
187 pAppSettingInstance = _AppSettingImpl::CreateAppSetting();
188 SysTryCatch(NID_APP, pAppSettingInstance != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
189 GetErrorMessage(E_OUT_OF_MEMORY));
190 _AppSettingImpl::SetImplInstance(*pAppSettingInstance, *pAppSettingImpl.release());
192 pKeyStr = new (std::nothrow) String(packageId);
193 SysTryCatch(NID_APP, pKeyStr != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
195 r = __stringToInstanceMap.Add(*pKeyStr, *pAppSettingInstance);
196 SysTryCatch(NID_APP, r != E_OUT_OF_MEMORY, , r, "[%s] Memory allocation failed.", GetErrorMessage(r));
197 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
199 return pAppSettingInstance;
202 delete pAppSettingInstance;
208 _AppSettingImpl::_MutiInstanceManager::ReleaseInstanceByAppId(const AppId& appId)
210 result r = _AccessController::CheckUserPrivilege(_PRV_APPSETTING);
211 SysTryReturnResult(NID_APP, !IsFailed(r), E_PRIVILEGE_DENIED,
212 "The application does not have the privilege to call this method.");
214 // Convert AppId to package type id.
216 appId.SubString(0, APP_ID_LENTH, packageId);
218 AppSetting* pAppSetting = static_cast<AppSetting*>(__stringToInstanceMap.GetValue(packageId));
223 _AppSettingImpl* pThisAppSettingImpl = _AppSettingImpl::GetInstance(*pAppSetting);
224 dbus_connection_remove_filter(pDBusConnection, HandleDBusMessage, pThisAppSettingImpl);
226 __stringToInstanceMap.Remove(packageId, true); // Delete item instance and remove item from __stringToInstanceMap
231 return E_OBJ_NOT_FOUND;
236 _AppSettingImpl::_MutiInstanceManager::ReleaseOtherAppInstances(void)
239 { // Iterate all element and remove correspond dbus filter
240 std::unique_ptr<IMapEnumerator> pEnum(__stringToInstanceMap.GetMapEnumeratorN());
243 while (pEnum->MoveNext() == E_SUCCESS)
245 AppSetting* pAppSetting = null;
246 pAppSetting = static_cast<AppSetting*>(pEnum->GetValue());
247 _AppSettingImpl* pThisAppSettingImpl = _AppSettingImpl::GetInstance(*pAppSetting);
248 dbus_connection_remove_filter(pDBusConnection, HandleDBusMessage, pThisAppSettingImpl);
252 __stringToInstanceMap.RemoveAll(true);
260 _SettingItem(Object* pItemValue, int min, int max, xmlNodePtr pItemXmlNode)
261 : __pValue(pItemValue)
264 , __pXmlNode(pItemXmlNode)
270 Object* GetValue(void)
274 const Object* GetValue(void) const
286 xmlNodePtr GetXmlNode(void)
292 _SettingItem(const _SettingItem& rhs);
293 _SettingItem& operator =(const _SettingItem& rhs);
298 xmlNodePtr __pXmlNode;
301 class _ReverseStringComparer
302 : public Tizen::Base::Collection::IComparer
305 _ReverseStringComparer(void) {};
306 virtual ~_ReverseStringComparer(void) {};
307 virtual result Compare(const Tizen::Base::Object& obj1, const Tizen::Base::Object& obj2, int& cmp) const
309 const String& objString1 = static_cast<const String&>(obj1);
310 const String& objString2 = static_cast<const String&>(obj2);
311 cmp = objString2.CompareTo(objString1); // reverse
316 _AppSettingImpl::_AppSettingImpl(void)
317 : __oldVersionInstance(false)
318 , __pEventListener(null)
324 _AppSettingImpl::~_AppSettingImpl(void)
331 __settingContainer.RemoveAll(true);
335 _AppSettingImpl::GetInstance(void)
338 result r = E_SUCCESS;
340 if (pAppSettingImplInstance == null)
342 pAppSettingImplInstance = new (std::nothrow) _AppSettingImpl();
343 SysTryReturn(NID_APP, pAppSettingImplInstance != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
344 GetErrorMessage(E_OUT_OF_MEMORY));
346 // Get current application context AppId
347 App* pApp = App::GetInstance();
348 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] A system error has been occurred. App::GetInstance() failed",
349 GetErrorMessage(E_SYSTEM));
351 appId = pApp->GetAppId();
352 r = pAppSettingImplInstance->Construct(appId);
353 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
355 return pAppSettingImplInstance;
358 delete pAppSettingImplInstance;
359 pAppSettingImplInstance = null;
364 _AppSettingImpl::GetInstance(const Tizen::Base::String& version)
367 //result r = E_SUCCESS;
369 static _MutiInstanceManager multiInstanceManager;
370 AppSetting* pVersionAppSetting = multiInstanceManager.GetInstance(version);
371 SysTryReturn(NID_APP, pVersionAppSetting != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
372 GetErrorMessage(E_OUT_OF_MEMORY));
374 return pVersionAppSetting;
378 _AppSettingImpl::GetInstanceByAppId(const AppId& appId)
382 AppSetting* pAppSettingByAppId = __appIdMultiInstanceMgr.GetInstanceByAppId(appId);
383 return pAppSettingByAppId;
387 _AppSettingImpl::ReleaseInstanceByAppId(const AppId& appId)
389 return __appIdMultiInstanceMgr.ReleaseInstanceByAppId(appId);
393 _AppSettingImpl::ReleaseOtherAppInstances(void)
395 return __appIdMultiInstanceMgr.ReleaseOtherAppInstances();
398 Tizen::Base::Collection::IList*
399 _AppSettingImpl::GetAppSettingVersionListN(void)
401 result r = E_SUCCESS;
402 ArrayList* pVersionList = new (std::nothrow) ArrayList;
403 SysTryReturn(NID_APP, pVersionList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
404 GetErrorMessage(E_OUT_OF_MEMORY));
405 r = pVersionList->Construct();
406 SysTryReturn(NID_APP, !IsFailed(r), null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
407 GetErrorMessage(E_OUT_OF_MEMORY));
409 // Iterate file and add to list
410 String dirPath = _AppInfo::GetAppRootPath() + RESOUCE_FILE_PATH;
412 r = dir.Construct(dirPath);
413 SysTryReturn(NID_APP, !IsFailed(r), null, E_SYSTEM, "[%s] A system error has been occurred. Directory construction failed.",
414 GetErrorMessage(E_SYSTEM));
416 std::unique_ptr<DirEnumerator> pDirEnum(dir.ReadN());
417 SysTryReturn(NID_APP, pDirEnum != null, null, E_SYSTEM,
418 "[%s] A system error has been occurred. Directory enumerator getting failed.", GetErrorMessage(E_SYSTEM));
420 String settingName(RESOUCE_FILE_NAME);
421 String settingExt(RESOUCE_FILE_EXT);
422 while (pDirEnum->MoveNext() == E_SUCCESS)
424 DirEntry dirEntry = pDirEnum->GetCurrentDirEntry();
425 if (!dirEntry.IsDirectory())
427 String fullName = dirEntry.GetName();
428 // Check name and extension to getting valid one
431 const int extLength = settingExt.GetLength();
432 const int posStart = settingName.GetLength();
433 const int posEnd = fullName.GetLength() - extLength;
434 if (posStart >= posEnd)
438 fullName.SubString(0, posStart, name);
439 fullName.SubString(posEnd, ext);
440 if ((name == settingName) && (ext == settingExt))
443 if (E_SUCCESS == fullName.SubString(posStart, posEnd-posStart, version))
445 String* pVersionStr = new (std::nothrow) String(version);
446 SysTryReturn(NID_APP, pVersionStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
447 GetErrorMessage(E_OUT_OF_MEMORY));
448 pVersionList->Add(*pVersionStr);
454 if (pVersionList->GetCount())
456 static _ReverseStringComparer strComparator;
457 pVersionList->Sort(strComparator);
458 pVersionList->RemoveAt(0); // remove latest version from list.
465 _AppSettingImpl::GetValue(const Tizen::Base::String& id, bool& value) const
467 const Object* pObject = __settingContainer.GetValue(id);
468 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
469 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
470 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
471 const Boolean* pBoolean = dynamic_cast<const Boolean*>(pItem->GetValue());
472 SysTryReturnResult(NID_APP, pBoolean != null, E_TYPE_MISMATCH,
473 "Type mismatch between requested type bool and object type of %ls.", id.GetPointer());
474 value = pBoolean->ToBool();
480 _AppSettingImpl::GetValue(const Tizen::Base::String& id, int& value) const
482 const Object* pObject = __settingContainer.GetValue(id);
483 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
484 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
485 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
486 const Integer* pInteger = dynamic_cast<const Integer*>(pItem->GetValue());
487 SysTryReturnResult(NID_APP, pInteger != null, E_TYPE_MISMATCH,
488 "Type mismatch between requested type int and object type of %ls.", id.GetPointer());
489 value = pInteger->ToInt();
495 _AppSettingImpl::GetValue(const Tizen::Base::String& id, Tizen::Base::String& value) const
497 const Object* pObject = __settingContainer.GetValue(id);
498 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
499 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
500 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
501 const String* pString = dynamic_cast<const String*>(pItem->GetValue());
502 SysTryReturnResult(NID_APP, pString != null, E_TYPE_MISMATCH,
503 "Type mismatch between requested type String and object type of %ls.", id.GetPointer());
510 _AppSettingImpl::SetValue(const Tizen::Base::String& id, bool value, bool save)
512 Object* pObject = __settingContainer.GetValue(id);
513 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
514 _SettingItem* pItem = dynamic_cast<_SettingItem*>(pObject);
515 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
516 Boolean* pBoolean = dynamic_cast<Boolean*>(pItem->GetValue());
517 SysTryReturnResult(NID_APP, pBoolean != null, E_TYPE_MISMATCH,
518 "Type mismatch between requested type bool and object type of %ls.", id.GetPointer());
521 static const String strTrue(L"true");
522 static const String strFalse(L"false");
523 const String& strValue = value ? strTrue : strFalse;
524 UpdateProperty(pItem->GetXmlNode(), strValue);
528 static const String strIntTrue(L"1");
529 static const String strIntFalse(L"0");
530 SendMessage(id, value ? strIntTrue : strIntFalse, true);
532 if (__pEventListener)
534 __pEventListener->OnAppSettingChanged(id);
541 _AppSettingImpl::SetValue(const Tizen::Base::String& id, int value, bool save)
543 Object* pObject = __settingContainer.GetValue(id);
544 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
545 _SettingItem* pItem = dynamic_cast<_SettingItem*>(pObject);
546 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
547 Integer* pInteger = dynamic_cast<Integer*>(pItem->GetValue());
548 SysTryReturnResult(NID_APP, pInteger != null, E_TYPE_MISMATCH,
549 "Type mismatch between requested type int and object type of %ls.", id.GetPointer());
551 SysTryReturnResult(NID_APP, (pItem->GetMin() <= value), E_OUT_OF_RANGE, "value(%d) is less than minimum range(%d).",
552 value, pItem->GetMin());
553 SysTryReturnResult(NID_APP, (pItem->GetMax() >= value), E_OUT_OF_RANGE, "value(%d) is greater than maximum range(%d).",
554 value, pItem->GetMax());
557 String strValue = pInteger->ToString();
558 UpdateProperty(pItem->GetXmlNode(), strValue);
562 SendMessage(id, strValue, true);
564 if (__pEventListener)
566 __pEventListener->OnAppSettingChanged(id);
573 _AppSettingImpl::SetValue(const Tizen::Base::String& id, const Tizen::Base::String& value, bool save)
575 Object* pObject = __settingContainer.GetValue(id);
576 SysTryReturnResult(NID_APP, pObject != null, E_OBJ_NOT_FOUND, "Specified id is not found in the application setting");
577 _SettingItem* pItem = dynamic_cast<_SettingItem*>(pObject);
578 SysTryReturnResult(NID_APP, pItem != null, E_TYPE_MISMATCH, "Type mismatch for instance of id.");
579 String* pString = dynamic_cast<String*>(pItem->GetValue());
580 SysTryReturnResult(NID_APP, pString != null, E_TYPE_MISMATCH,
581 "Type mismatch between requested type String and object type of %ls.", id.GetPointer());
583 SysTryReturnResult(NID_APP, pItem->GetMin() <= value.GetLength(), E_OUT_OF_RANGE,
584 "value length(%d) less than minimum length(%d).", value.GetLength(), pItem->GetMin());
585 SysTryReturnResult(NID_APP, pItem->GetMax() >= value.GetLength(), E_OUT_OF_RANGE,
586 "value length(%d) greater than maximum range(%d).", value.GetLength(), pItem->GetMax());
589 UpdateProperty(pItem->GetXmlNode(), *pString);
593 SendMessage(id, *pString, false);
595 if (__pEventListener)
597 __pEventListener->OnAppSettingChanged(id);
604 _AppSettingImpl::SetAppSettingEventListener(IAppSettingEventListener* pListener)
606 __pEventListener = pListener;
611 _AppSettingImpl::GetInstance(AppSetting& appSetting)
613 return appSetting.__pAppSettingImpl;
616 const _AppSettingImpl*
617 _AppSettingImpl::GetInstance(const AppSetting& appSetting)
619 return appSetting.__pAppSettingImpl;
623 _AppSettingImpl::Construct(const AppId& correspondAppId, const String& version)
625 result r = E_SUCCESS;
626 if (version.GetLength() > 0)
628 __oldVersionInstance = true;
630 correspondAppId.SubString(0, APP_ID_LENTH, __correspondAppId); // Use 10 char id value.
632 __filePath = _AppInfo::GetAppRootPath() + RESOUCE_FILE_PATH;
633 __filePath += RESOUCE_FILE_NAME;
634 if (version.GetLength())
636 __filePath += version;
638 __filePath += RESOUCE_FILE_EXT;
640 r = __settingContainer.Construct();
641 SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
642 if (!__oldVersionInstance)
644 SysTryReturnResult(NID_APP, InitizlizeDBus(), E_SYSTEM, "A system error has been occurred. DBus initialization failed.");
647 SysTryReturnResult(NID_APP, !IsFailed(r), E_SYSTEM, "A system error has been occurred. Loading procedure failed.");
652 _AppSettingImpl::ConstructByAppPath(const AppId& correspondAppId, const Tizen::Base::String& appRootPath)
654 result r = E_SUCCESS;
655 SysTryReturn(NID_APP, !appRootPath.IsEmpty(), E_INVALID_ARG, E_INVALID_ARG,
656 "[%s] Invalid argument is used. appRootPath length is 0.", GetErrorMessage(E_INVALID_ARG));
658 correspondAppId.SubString(0, APP_ID_LENTH, __correspondAppId); // Use 10 char id value.
659 __filePath = appRootPath + RESOUCE_FILE_PATH;
660 __filePath += RESOUCE_FILE_NAME;
661 __filePath += RESOUCE_FILE_EXT;
663 r = __settingContainer.Construct();
664 SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
665 SysTryReturnResult(NID_APP, InitizlizeDBus(), E_SYSTEM, "A system error has been occurred. DBus initialization failed.");
667 SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
673 _AppSettingImpl::Load(void)
675 SysTryReturnResult(NID_APP, File::IsFileExist(__filePath), E_OBJ_NOT_FOUND,
676 "The instance of specified AppId does not have setting information.");
678 result r = E_SUCCESS;
679 std::unique_ptr<ByteBuffer> pfilePath(Tizen::Base::Utility::StringUtil::StringToUtf8N(__filePath));
680 SysTryReturnResult(NID_APP, pfilePath != null, E_OUT_OF_MEMORY, "Memory allocation failed. File path conversion failed.");
682 __pDoc = xmlParseFile(reinterpret_cast<const char*>(pfilePath->GetPointer()));
683 SysTryReturnResult(NID_APP, __pDoc != null, E_SYSTEM,
684 "A system error has been occurred. Can not parse xml file: %ls", __filePath.GetPointer());
686 xmlNodePtr rootNodePtr = xmlDocGetRootElement(__pDoc);
687 SysTryReturnResult(NID_APP, rootNodePtr != null, E_SYSTEM, "A system error has been occurred. Can not find root node");
689 VisitNode(rootNodePtr);
695 _AppSettingImpl::Save(void)
697 static const int XML_SAVE_FAILED = -1;
698 static const int XML_SAVE_FORMAT = 1;
700 SysTryReturnResult(NID_APP, __pDoc != null, E_SYSTEM,
701 "A system error has been occurred. XML Document not valid so can not save it.");
702 std::unique_ptr<ByteBuffer> pfilePath(Tizen::Base::Utility::StringUtil::StringToUtf8N(__filePath));
703 SysTryReturnResult(NID_APP, pfilePath != null, E_OUT_OF_MEMORY, "Memory allocation failed. File path conversion failed.");
705 int result = xmlSaveFormatFile(reinterpret_cast<const char*>(pfilePath->GetPointer()), __pDoc, XML_SAVE_FORMAT);
706 SysTryReturnResult(NID_APP, result != XML_SAVE_FAILED, E_SYSTEM, "A system error has been occurred. Document saving failed.");
712 _AppSettingImpl::VisitNode(xmlNodePtr pCurrentNode)
714 for (xmlNodePtr nodePtr = pCurrentNode; nodePtr != null; nodePtr = nodePtr->next) // Visit sibling node
716 // Check node name and add to collection.
717 if (nodePtr->type == XML_ELEMENT_NODE)
719 CheckNodeNameAndAddToCollection(nodePtr);
722 VisitNode(nodePtr->children);
727 _AppSettingImpl::CheckNodeNameAndAddToCollection(xmlNodePtr pNode)
729 static const char* pPropId = "id";
730 static const char* pPropValue = "value";
732 // 1. Get type (bool, integer, string, expandlist)
733 _ElementType detectedType = GetElementType(pNode);
735 // Make item and add to collection.
736 if (detectedType != ELEMENT_INVALID)
739 xmlChar* pId = xmlGetProp(pNode, reinterpret_cast<const xmlChar*>(pPropId));
745 std::unique_ptr<String> pStrId(new (std::nothrow) String(reinterpret_cast<char*>(pId)));
746 SysTryReturnVoidResult(NID_APP, pStrId, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
747 GetErrorMessage(E_OUT_OF_MEMORY));
752 { // 3. Get min(length), max(length) value
753 if ((detectedType == ELEMENT_INTEGER) || (detectedType == ELEMENT_STRING))
755 GetMinMaxValue(pNode, detectedType, min, max);
759 bool validValue = false;
760 xmlChar* pValue = xmlGetProp(pNode, reinterpret_cast<const xmlChar*>(pPropValue));
763 strValue = String(reinterpret_cast<char*>(pValue));
768 // 5. Create value object from value
769 Object* pValueObject = GetValueObjectN(detectedType, strValue, validValue);
772 _SettingItem* pSettingItem = new (std::nothrow) _SettingItem(pValueObject, min, max, pNode);
773 SysTryReturnVoidResult(NID_APP, pSettingItem, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
774 GetErrorMessage(E_OUT_OF_MEMORY));
776 { // 6. Add item to container
777 SysLog(NID_APP, "AppSetting item adding: ID=%ls min=%d max=%d Value=%ls",
778 pStrId->GetPointer(), min, max, strValue.GetPointer());
779 __settingContainer.Add(*pStrId.release(), *pSettingItem);
783 SysLog(NID_APP, "Failed create new _SettingItem");
792 _AppSettingImpl::GetElementType(xmlNodePtr pNode)
794 const xmlChar* pElementBool = reinterpret_cast<const xmlChar*>("bool");
795 const xmlChar* pElementInteger = reinterpret_cast<const xmlChar*>("integer");
796 const xmlChar* pElementString = reinterpret_cast<const xmlChar*>("string");
797 const xmlChar* pElementExpandlist = reinterpret_cast<const xmlChar*>("expandlist");
799 _ElementType type = ELEMENT_INVALID;
800 if (xmlStrcmp(pNode->name, pElementBool) == 0)
805 if (xmlStrcmp(pNode->name, pElementInteger) == 0)
807 type = ELEMENT_INTEGER;
810 if (xmlStrcmp(pNode->name, pElementString) == 0)
812 type = ELEMENT_STRING;
815 if (xmlStrcmp(pNode->name, pElementExpandlist) == 0)
817 type = ELEMENT_EXPANDLIST;
824 _AppSettingImpl::GetMinMaxValue(xmlNodePtr pNode, _ElementType type, int& min, int& max)
826 const xmlChar* pPropMin = reinterpret_cast<const xmlChar*>("min");
827 const xmlChar* pPropMax = reinterpret_cast<const xmlChar*>("max");
828 const xmlChar* pPropMinLength = reinterpret_cast<const xmlChar*>("minlength");
829 const xmlChar* pPropMaxLength = reinterpret_cast<const xmlChar*>("maxlength");
831 if (type == ELEMENT_INTEGER)
833 xmlChar* pStrMin = xmlGetProp(pNode, pPropMin);
836 Integer::Parse(reinterpret_cast<char*>(pStrMin), min);
841 SysLog(NID_APP, "Failed to get 'min' value.");
844 xmlChar* pStrMax = xmlGetProp(pNode, pPropMax);
847 Integer::Parse(reinterpret_cast<char*>(pStrMax), max);
852 SysLog(NID_APP, "Failed to get 'max' value.");
856 if (type == ELEMENT_STRING)
858 xmlChar* pStrMin = xmlGetProp(pNode, pPropMinLength);
861 Integer::Parse(reinterpret_cast<char*>(pStrMin), min);
866 SysLog(NID_APP, "Failed to get 'minlength' value.");
869 xmlChar* pStrMax = xmlGetProp(pNode, pPropMaxLength);
872 Integer::Parse(reinterpret_cast<char*>(pStrMax), max);
877 SysLog(NID_APP, "Failed to get 'maxlength' value.");
882 SysLog(NID_APP, "Invalid element type.");
887 _AppSettingImpl::GetValueObjectN(_ElementType type, String& strValue, bool validValue)
889 const String strTrue(L"true");
890 Object* pValueObject = null;
896 bool valueBool = false;
899 if (strValue == strTrue)
904 pValueObject = new (std::nothrow) Boolean(valueBool);
905 SysTryReturn(NID_APP, pValueObject != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
906 GetErrorMessage(E_OUT_OF_MEMORY));
910 case ELEMENT_INTEGER:
912 int valueInteger = 0;
915 Integer::Parse(strValue, valueInteger);
917 pValueObject = new (std::nothrow) Integer(valueInteger);
918 SysTryReturn(NID_APP, pValueObject != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
919 GetErrorMessage(E_OUT_OF_MEMORY));
924 case ELEMENT_EXPANDLIST:
926 String* pStringObject = new (std::nothrow) String;
927 SysTryReturn(NID_APP, pStringObject != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
928 GetErrorMessage(E_OUT_OF_MEMORY));
929 if (pStringObject && validValue)
931 *pStringObject = strValue;
933 pValueObject = pStringObject;
937 case ELEMENT_INVALID:
938 // It already validate by caller;
939 SysLog(NID_APP, "Invalid element type.");
947 _AppSettingImpl::UpdateProperty(xmlNodePtr pNode, const String& value)
949 const xmlChar* pPropValue = reinterpret_cast<const xmlChar*>("value");
953 const xmlChar* pZeroLength = reinterpret_cast<const xmlChar*>("");
954 xmlAttrPtr attrPtr = xmlSetProp(pNode, pPropValue, pZeroLength);
962 std::unique_ptr<ByteBuffer> pBuf(Tizen::Base::Utility::StringUtil::StringToUtf8N(value));
965 xmlAttrPtr attrPtr = xmlSetProp(pNode, pPropValue, reinterpret_cast<const xmlChar*>(pBuf->GetPointer()));
973 SysLog(NID_APP, "StringToUtf8N is failed.");
980 _AppSettingImpl::InitizlizeDBus(void)
983 dbus_error_init(&error);
985 if (pDBusConnection == null)
987 char rule[MAX_LOCAL_BUFSIZE];
988 pDBusConnection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
989 if (pDBusConnection == null)
991 SysLog(NID_APP, "Fail to connect to the D-BUS daemon: %s", error.message);
992 dbus_error_free(&error);
995 dbus_connection_setup_with_g_main(pDBusConnection, null);
997 snprintf(rule, MAX_LOCAL_BUFSIZE, "path='%s',type='signal',interface='%s'", DBUS_PATH, DBUS_SIGNAL_INTERFACE);
998 dbus_bus_add_match(pDBusConnection, rule, &error);
999 if (dbus_error_is_set(&error))
1001 SysLog(NID_APP, "Fail to add match : %s", error.message);
1002 dbus_error_free(&error);
1007 // this value is vary by AppSetting instance for proper handling.
1008 // Should be explicit remove filter on ReleaseInstanceByAppId.
1009 if (dbus_connection_add_filter(pDBusConnection, HandleDBusMessage, this, NULL) == FALSE)
1011 SysLog(NID_APP, "Fail to add filter : %s", error.message);
1012 dbus_error_free(&error);
1019 _AppSettingImpl::HandleDBusMessage(DBusConnection* connection, DBusMessage* message, void* user_data)
1021 int my_pid = getpid();
1024 char* pValue = NULL;
1027 dbus_error_init(&error);
1029 _AppSettingImpl* pAppSettingImpl = static_cast<_AppSettingImpl*>(user_data);
1030 SysTryLogReturn(NID_APP, pAppSettingImpl != null, DBUS_HANDLER_RESULT_HANDLED,
1031 "Not valid pAppSettingImpl from user_data");
1032 String signalString(DBUS_SIGNAL_PREFIX);
1033 signalString += pAppSettingImpl->__correspondAppId;
1034 std::unique_ptr<ByteBuffer> pBufferSignal(Tizen::Base::Utility::StringUtil::StringToUtf8N(signalString));
1035 SysTryLogReturn(NID_APP, pBufferSignal != null, DBUS_HANDLER_RESULT_HANDLED, "pBufferSignal is not valid");
1036 const char* pCharBufferSignal = reinterpret_cast<const char*>(pBufferSignal->GetPointer());
1038 if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE, pCharBufferSignal))
1040 if (dbus_message_get_args(message, &error,
1041 DBUS_TYPE_UINT32, &sender_pid,
1042 DBUS_TYPE_STRING, &pId,
1043 DBUS_TYPE_STRING, &pValue,
1044 DBUS_TYPE_INVALID) == FALSE)
1046 SysLog(NID_APP, "Fail to get data : %s", error.message);
1047 dbus_error_free(&error);
1048 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1051 if (sender_pid != 0 && my_pid != sender_pid)
1053 pAppSettingImpl->SetValueFromDBusData(pId, pValue);
1055 return DBUS_HANDLER_RESULT_HANDLED;
1059 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1064 _AppSettingImpl::SetValueFromDBusData(const char* pId, const char* pValue)
1066 const String delimiter(L"|");
1069 int indexOfDelimiter = 0;
1071 // Native Setting module send the key as "id|title" so need to get id part before the '|' character.
1072 // Value is "INT|value" for check box and slider Or "STRING|value" so need to get right side value string.
1075 result r = strOrg.IndexOf(delimiter, 0, indexOfDelimiter);
1076 SysTryReturnVoidResult(NID_APP, !IsFailed(r), r, "[%s] Propagating. Bus data parsing failed", GetErrorMessage(r));
1077 strOrg.SubString(0, indexOfDelimiter, strId); // Get left string of '|'
1081 r = strOrg.IndexOf(delimiter, 0, indexOfDelimiter);
1082 SysTryReturnVoidResult(NID_APP, !IsFailed(r), r, "[%s] Propagating. Bus data parsing failed", GetErrorMessage(r));
1083 strOrg.SubString(indexOfDelimiter+1, strValue); // Get right string of '|'
1085 const Object* pObject = __settingContainer.GetValue(strId);
1088 const _SettingItem* pItem = dynamic_cast<const _SettingItem*>(pObject);
1089 SysTryReturnVoidResult(NID_APP, pItem != null, E_SYSTEM, "[%s] A system error has been occurred. Casting failed to item.",
1090 GetErrorMessage(E_SYSTEM));
1091 const Boolean* pBoolean = dynamic_cast<const Boolean*>(pItem->GetValue());
1094 static const String strFalse(L"0");
1095 bool valueBool = true;
1097 if (strValue == strFalse)
1101 SetValue(strId, valueBool, false);
1104 const Integer* pInteger = dynamic_cast<const Integer*>(pItem->GetValue());
1107 int valueInteger = 0;
1108 Integer::Parse(strValue, valueInteger);
1109 SetValue(strId, valueInteger, false);
1112 const String* pString = dynamic_cast<const String*>(pItem->GetValue());
1115 SetValue(strId, strValue, false);
1118 SysLog(NID_APP, "Failed determin value type for id=%s", pId);
1122 SysLog(NID_APP, "Failed find value for id=%s", pId);
1127 _AppSettingImpl::SendMessage(const String& id, const String& value, bool intType)
1129 if (__oldVersionInstance)
1131 return true; // NOP for old version instance.
1134 if (!pDBusConnection)
1136 SysLog(NID_APP, "DBus connection invalid");
1141 const String strRightOfId(L"|N/A");
1142 const String strLeftOfValueIntType(L"INT|");
1143 const String strLeftOfValueStrType(L"STRING|");
1145 String strId = id + strRightOfId;
1149 strValue = strLeftOfValueIntType;
1153 strValue = strLeftOfValueStrType;
1156 String signalString(DBUS_SIGNAL_PREFIX);
1157 signalString += __correspondAppId;
1159 std::unique_ptr<ByteBuffer> pBufferId(Tizen::Base::Utility::StringUtil::StringToUtf8N(strId));
1160 std::unique_ptr<ByteBuffer> pBufferValue(Tizen::Base::Utility::StringUtil::StringToUtf8N(strValue));
1161 std::unique_ptr<ByteBuffer> pBufferSignal(Tizen::Base::Utility::StringUtil::StringToUtf8N(signalString));
1162 if (pBufferId && pBufferValue && pBufferSignal)
1164 int sender_pid = getpid();
1165 const char* pCharBufferId = reinterpret_cast<const char*>(pBufferId->GetPointer());
1166 const char* pCharBufferValue = reinterpret_cast<const char*>(pBufferValue->GetPointer());
1167 const char* pCharBufferSignal = reinterpret_cast<const char*>(pBufferSignal->GetPointer());
1169 DBusMessage* pMessageWihtAppId = dbus_message_new_signal(DBUS_PATH, DBUS_SIGNAL_INTERFACE, pCharBufferSignal);
1170 if (dbus_message_append_args(pMessageWihtAppId,
1171 DBUS_TYPE_UINT32, &sender_pid,
1172 DBUS_TYPE_STRING, &pCharBufferId,
1173 DBUS_TYPE_STRING, &pCharBufferValue,
1174 DBUS_TYPE_INVALID) == FALSE)
1176 SysLog(NID_APP, "DBus connection invalid");
1180 if (dbus_connection_send(pDBusConnection, pMessageWihtAppId, NULL) == FALSE)
1182 SysLog(NID_APP, "Fail to send message");
1186 dbus_connection_flush(pDBusConnection);
1187 dbus_message_unref(pMessageWihtAppId);
1191 SysLog(NID_APP, "System error: memory full ?");
1198 _AppSettingImpl::CreateAppSetting(void)
1200 AppSetting* pAppSetting = new (std::nothrow) AppSetting;
1201 SysTryReturn(NID_APP, pAppSetting != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1202 GetErrorMessage(E_OUT_OF_MEMORY));
1208 _AppSettingImpl::SetImplInstance(AppSetting& appSetting, _AppSettingImpl& impl)
1210 appSetting.__pAppSettingImpl = &impl;