Fix the double-free issue
[platform/framework/native/appfw.git] / src / app / FApp_AppResourceImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 //
16
17 /**
18  * @file        FApp_AppResourceImpl.cpp
19  * @brief       This is the implementation for the _AppResourceImpl class.
20  */
21
22 #include <unique_ptr.h>
23
24 #include <FBaseResult.h>
25 #include <FBaseSysLog.h>
26 #include <FBaseColHashMap.h>
27 #include <FBaseRt_LibraryImpl.h>
28
29 #include <FAppAppResource.h>
30 #include "FApp_AppManagerImpl.h"
31 #include "FApp_AppResourceString.h"
32 #include "FApp_IAppResourceBitmap.h"
33
34 #include "FApp_AppResourceImpl.h"
35
36
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Collection;
39 using namespace Tizen::Base::Runtime;
40 using namespace Tizen::Graphics;
41 using namespace Tizen::Io;
42
43
44 namespace Tizen { namespace App
45 {
46
47 #define BITMAP_PIXEL_FORMAT_INVALID (BITMAP_PIXEL_FORMAT_MIN)
48
49
50 static _IAppResourceBitmap*(* p_Create_IAppResourceBitmapInstanceN)(int type, const String& value) = null;
51
52 Tizen::Base::Collection::HashMap* _AppResourceImpl::__pContainer = null;
53 Tizen::Base::Runtime::Mutex* _AppResourceImpl::__pLock = null;
54
55 _AppResourceImpl::_AppResourceImpl(void)
56         : __p_AppResourceString(null)
57         , __p_IAppResourceBitmap(null)
58         , __type(APP_RESOURCE_DEFAULT)
59         , __value()
60 {
61 }
62
63 result
64 _AppResourceImpl::ReleaseInstance(const Tizen::Base::String& key)
65 {
66         result ret = E_SUCCESS;
67
68         if (__pContainer != null)
69         {
70                 result r = __pLock->Acquire();
71                 SysTryLog(NID_APP, !IsFailed(r), "Failed to acquire mutex.");
72
73                 ret = __pContainer->Remove(key);
74
75                 r = __pLock->Release();
76                 SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
77         }
78
79         return ret;
80 }
81
82 // Exception: E_OUT_OF_MEMORY, E_SYSTEM, E_INVALID_ARG, E_OBJ_NOT_FOUND, E_APP_NOT_INSTALLED [Get_AppResourceStringN], Get_IAppResourceBitmapN
83 AppResource*
84 _AppResourceImpl::GetInstanceN(AppResourceBy type, const Tizen::Base::String& value)
85 {
86         result r = E_SUCCESS;
87         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
88         if (__pContainer == null)
89         {
90                 ClearLastResult();
91                 pthread_once(&onceBlock, InitSingleton);
92                 r = GetLastResult();
93                 SysTryReturn(NID_APP, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] Creating the container is failed [%s].", GetErrorMessage(r));
94         }
95
96         r = __pLock->Acquire();
97         SysTryLog(NID_APP, !IsFailed(r), "Failed to acquire mutex.");
98
99         bool hasAppResource = false;
100         r = __pContainer->ContainsKey(value, hasAppResource);
101         SysTryCatch(NID_APP, !IsFailed(r), r, r, "[%s] Checking to contain is failed.", GetErrorMessage(r));
102
103         if (hasAppResource)
104         {
105                 r = __pLock->Release();
106                 SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
107
108                 return static_cast<AppResource*> (__pContainer->GetValue(value));
109         }
110         else
111         {
112                 std::unique_ptr< _AppResourceImpl > pAppResourceImpl(new (std::nothrow) _AppResourceImpl());
113                 SysTryCatch(NID_APP, pAppResourceImpl != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,"[E_OUT_OF_MEMORY] Unable to allocate memory for AppResourceImpl.");
114
115                 std::unique_ptr< _AppResourceString > pAppResourceString(_AppResourceString::Get_AppResourceStringN(type, value));
116                 r = GetLastResult();
117                 SysTryCatch(NID_APP, !IsFailed(r), r, r, "[%s] Unable to get _AppResourceString.", GetErrorMessage(r));
118
119                 std::unique_ptr< _IAppResourceBitmap > pAppResourceBitmap(Get_IAppResourceBitmapN(type, value));
120                 r = GetLastResult();
121                 SysTryCatch(NID_APP, !IsFailed(r), r, r, "[%s] Unable to get _IAppResourceBitmap.", GetErrorMessage(r));
122
123                 pAppResourceImpl->__p_AppResourceString = pAppResourceString.release();
124                 pAppResourceImpl->__p_IAppResourceBitmap = pAppResourceBitmap.release();
125                 pAppResourceImpl->__type = type;
126                 pAppResourceImpl->__value = value;
127
128                 std::unique_ptr< String > pStr(new (std::nothrow) String(value));
129                 SysTryCatch(NID_APP, pStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Creating a key is failed.");
130
131                 AppResource* pAppResource = new (std::nothrow) AppResource;
132                 SysTryCatch(NID_APP, pAppResource != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Unable to allocate memory for AppResource");
133
134                 pAppResource->__pAppResourceImpl = pAppResourceImpl.release();
135                 r = __pContainer->Add(*pStr, *pAppResource);
136                 if (IsFailed(r))
137                 {
138                         delete pAppResource;
139                         SysTryCatch(NID_APP, false, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Adding an element to the container is failed.");
140                 }
141
142                 pStr.release();
143
144                 r = __pLock->Release();
145                 SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
146
147                 return pAppResource;
148         }
149
150         // fall thru
151 CATCH:
152         SetLastResult(r);
153
154         r = __pLock->Release();
155         SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
156
157         return null;
158 }
159
160 _IAppResourceBitmap*
161 _AppResourceImpl::Get_IAppResourceBitmapN(AppResourceBy type, const Tizen::Base::String& value)
162 {
163         if (p_Create_IAppResourceBitmapInstanceN == null)
164         {
165                 _LibraryImpl& lib = _AppManagerImpl::GetInstance()->GetUiLibraryImpl();
166                 p_Create_IAppResourceBitmapInstanceN =
167                                 reinterpret_cast<_IAppResourceBitmap*(*)(int, const String&)>(lib.GetProcAddress(L"_Create_IAppResourceBitmapInstanceN"));
168                 SysTryReturn(NID_APP, p_Create_IAppResourceBitmapInstanceN != null,
169                                 null, E_SYSTEM, "[E_SYSTEM] Failed to get Bitmap resource [%s].", GetErrorMessage(E_SYSTEM));
170         }
171
172         std::unique_ptr< _IAppResourceBitmap > pAppResourceBitmap(p_Create_IAppResourceBitmapInstanceN(type, value));
173         SysTryReturn(NID_APP, pAppResourceBitmap != null, null,
174                         E_SYSTEM, "[%s] Unable to get IAppResourceBitmap.", GetErrorMessage(E_SYSTEM));
175
176         return pAppResourceBitmap.release();
177 }
178
179 _AppResourceImpl::~_AppResourceImpl(void)
180 {
181         delete __p_AppResourceString;
182         delete __p_IAppResourceBitmap;
183 }
184
185 result
186 _AppResourceImpl::GetString(const String& resourceId, String& loadedString)
187 {
188         if (__p_AppResourceString == null)
189         {
190                 __p_AppResourceString = _AppResourceString::Get_AppResourceStringN(__type, __value);
191                 SysTryReturnResult(NID_APP, __p_AppResourceString == null, E_FAILURE, "Failed to get String resource.");
192         }
193
194         return __p_AppResourceString->GetString(resourceId, loadedString);
195 }
196
197 Bitmap*
198 _AppResourceImpl::GetBitmapN(const String& imgFilePath, BitmapPixelFormat pixelFormat)
199 {
200         if (__p_IAppResourceBitmap == null)
201         {
202                 __p_IAppResourceBitmap = Get_IAppResourceBitmapN(__type, __value);
203                 SysTryReturn(NID_APP, __p_IAppResourceBitmap == null,
204                                 null, E_SYSTEM, "[%s] Failed to get Bitmap resource.", GetErrorMessage(E_SYSTEM));
205         }
206
207         return __p_IAppResourceBitmap->GetBitmapN(imgFilePath, pixelFormat);
208 }
209
210 Bitmap*
211 _AppResourceImpl::GetBitmapN(const String& imgFilePath)
212 {
213         return GetBitmapN(imgFilePath, BITMAP_PIXEL_FORMAT_INVALID);
214 }
215
216 _AppResourceImpl*
217 _AppResourceImpl::GetInstance(void)
218 {
219         AppResource* pAppResource = AppResource::GetInstance();
220         if (pAppResource)
221         {
222                 return pAppResource->__pAppResourceImpl;
223         }
224         return null;
225 }
226
227 void
228 _AppResourceImpl::Reinitialize(void)
229 {
230         _AppResourceImpl* pThis = _AppResourceImpl::GetInstance();
231         if (pThis == null)
232         {
233                 SysLog(NID_APP, "No _AppResourceImpl instance.");
234                 return;
235         }
236
237         if (__pContainer != null)
238         {
239                 std::unique_ptr< IMapEnumerator > pMapEnum(__pContainer->GetMapEnumeratorN());
240                 if (pMapEnum)
241                 {
242                         while(pMapEnum->MoveNext() == E_SUCCESS)
243                         {
244                                 AppResource* pAppResource = static_cast<AppResource*> (pMapEnum->GetValue());
245                                 if (pAppResource && pAppResource->__pAppResourceImpl)
246                                 {
247                                         _AppResourceImpl* pAppResourceImpl = pAppResource->__pAppResourceImpl;
248                                         delete pAppResourceImpl->__p_AppResourceString;
249                                         pAppResourceImpl->__p_AppResourceString =
250                                                         _AppResourceString::Get_AppResourceStringN(pAppResourceImpl->__type, pAppResourceImpl->__value);
251
252                                         // This function will be called on Language change event
253                                         // Need not to re-initialize Bitmap resource as language change does not affect bitmap resource path
254                                 }
255                         }
256                 }
257         }
258 }
259
260 Bitmap*
261 _AppResourceImpl::GetNonScalingBitmapN(const Tizen::Base::String& imagePath)
262 {
263         _IAppResourceBitmap* pAppResourceBitmap = Tizen::App::_AppResourceImpl::Get_IAppResourceBitmapN(APP_RESOURCE_BITMAP);
264
265         if (pAppResourceBitmap != null)
266         {
267                 return pAppResourceBitmap->GetBitmapN(imagePath, BITMAP_PIXEL_FORMAT_INVALID, false);
268         }
269         else
270         {
271                 SysLog(NID_APP, "Getting pAppResourceBitmap instance is failed");
272                 return null;
273         }
274 }
275
276 void
277 _AppResourceImpl::InitSingleton(void)
278 {
279         std::unique_ptr< HashMap > pContainer(new (std::nothrow) HashMap(SingleObjectDeleter));
280         SysTryReturnVoidResult(NID_APP, pContainer != null, E_OUT_OF_MEMORY, "[%s] Creating the container is failed.");
281
282         result r = pContainer->Construct();
283         SysTryReturnVoidResult(NID_APP, !IsFailed(r), E_SYSTEM, "[E_SYSTEM] Constructing the container is failed.");
284
285         __pContainer = pContainer.release();
286
287         std::unique_ptr< Mutex > pLock(new (std::nothrow) Mutex());
288         SysTryReturnVoidResult(NID_APP, pLock != null, E_OUT_OF_MEMORY, "[%s] Creating the mutex is failed.");
289
290         r = pLock->Create();
291         SysTryReturnVoidResult(NID_APP, !IsFailed(r), E_SYSTEM, "[E_SYSTEM] Constructing the mutex is failed.");
292
293         __pLock = pLock.release();
294
295         //std::atexit(DestroySingleton);
296 }
297
298 void
299 _AppResourceImpl::DestroySingleton(void)
300 {
301         delete __pContainer;
302         delete __pLock;
303 }
304
305 } } // Tizen::App