2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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.
17 * @file view_logic_web_notification_support.cpp
18 * @author Jihoon Chung (jihoon.chung@samsung.com)
19 * @brief Implementation file of web Notification API used by ViewLogic
22 #include "view_logic_web_notification_support.h"
23 #include "view_logic_web_notification_data.h"
29 #include <dpl/log/secure_log.h>
30 #include <dpl/assert.h>
31 #include <dpl/exception.h>
32 #include <dpl/wrt-dao-ro/widget_config.h>
34 #include <notification.h>
37 #include <curl/curl.h>
39 namespace ViewModule {
41 const char* PATTERN_CHECK_EXTERNAL = "^http(s)?://\\w+.*$";
44 bool isExternalUri(const std::string &uri);
45 size_t curlWriteData(void* ptr, size_t size, size_t nmemb, FILE* stream);
47 bool isExternalUri(const std::string &uri)
49 pcrecpp::RE_Options pcreOpt;
50 pcreOpt.set_caseless(true);
51 pcrecpp::RE re(PATTERN_CHECK_EXTERNAL, pcreOpt);
53 return re.FullMatch(uri);
56 size_t curlWriteData(void* ptr, size_t size, size_t nmemb, FILE* stream)
58 size_t written = fwrite(ptr, size, nmemb, stream);
61 } // anonymous namespace
63 // Implementation class
64 class WebNotificationSupportImplementation
70 DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
71 DECLARE_EXCEPTION_TYPE(Base, InitError)
72 DECLARE_EXCEPTION_TYPE(Base, NotificationShowError)
73 DECLARE_EXCEPTION_TYPE(Base, DownloadImageError)
77 std::string m_persistentPath;
79 typedef std::map<uint64_t, WebNotificationDataPtr> NotiMap;
80 typedef std::map<uint64_t, WebNotificationDataPtr>::iterator NotiMapIt;
81 NotiMap m_notiDataMap;
83 std::string createDownloadPath(const std::string& iconUrl)
85 // Make valid filename
86 // If there is already exist filename, rename to "filename_%d"
88 std::string downloadPath = m_persistentPath;
89 std::string fileName = iconUrl.substr(iconUrl.rfind('/') + 1);
90 _D("fileName from URL: %s", fileName.c_str());
91 std::string rename = fileName;
92 unsigned int renameSuffixNb = 0;
93 while (0 == access((m_persistentPath + rename).c_str(), F_OK)) {
94 std::ostringstream suffixOstr;
96 suffixOstr << fileName << "_" << renameSuffixNb++;
99 rename.insert(rename.find('.'), suffixOstr.str());
102 downloadPath += rename;
103 _D("Valid file path : %s", downloadPath.c_str());
107 std::string downloadImage(const std::string& iconUrl)
109 if (iconUrl.empty()) {
110 _W("Icon url is empty");
111 return std::string();
113 std::string downloadPath = createDownloadPath(iconUrl);
115 // Download image by curl
120 curl = curl_easy_init();
122 _W("fail to curl_easy_init");
123 Throw(Exception::InitError);
125 fp = fopen(downloadPath.c_str(), "wb");
128 Throw(Exception::InitError);
131 curl_easy_setopt(curl, CURLOPT_URL, iconUrl.c_str());
132 curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
133 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curlWriteData);
135 CURLcode err = curl_easy_perform(curl);
137 _W("fail to curl_easy_perform: %d", err);
138 Throw(Exception::DownloadImageError);
141 curl_easy_cleanup(curl);
142 } Catch(DPL::Exception) {
144 curl_easy_cleanup(curl);
145 return std::string();
147 _D("Download success");
151 int showNotification(WebNotificationDataPtr notiData)
154 notification_h noti_h = NULL;
155 notification_error_e error = NOTIFICATION_ERROR_NONE;
158 // create notification
159 noti_h = notification_new(
160 NOTIFICATION_TYPE_NOTI,
161 NOTIFICATION_GROUP_ID_DEFAULT,
162 NOTIFICATION_PRIV_ID_NONE);
164 _E("Fail to notification_new");
165 Throw(Exception::NotificationShowError);
168 // set notification title
169 error = notification_set_text(
171 NOTIFICATION_TEXT_TYPE_TITLE,
172 notiData->getTitle(),
174 NOTIFICATION_VARIABLE_TYPE_NONE);
175 if (error != NOTIFICATION_ERROR_NONE) {
176 _E("Fail to set title");
177 Throw(Exception::NotificationShowError);
180 // set notification content
181 error = notification_set_text(
183 NOTIFICATION_TEXT_TYPE_CONTENT,
186 NOTIFICATION_VARIABLE_TYPE_NONE);
187 if (error != NOTIFICATION_ERROR_NONE) {
188 _E("Fail to set content: %d", error);
189 Throw(Exception::NotificationShowError);
192 //check uri is "http", https" or not
193 if (notiData->getIconUrl()) {
194 std::string iconPath;
195 if (isExternalUri(notiData->getIconUrl())) {
196 //download image from url
197 iconPath = downloadImage(notiData->getIconUrl());
201 // If fail to download external image, skip to set image.
202 // In this case, set to default package image.
203 if (!iconPath.empty()) {
204 error = notification_set_image(
206 NOTIFICATION_IMAGE_TYPE_ICON,
208 if (error != NOTIFICATION_ERROR_NONE) {
209 _E("Fail to free notification: %d", error);
210 Throw(Exception::NotificationShowError);
215 // insert notification
216 int privId = NOTIFICATION_PRIV_ID_NONE;
217 error = notification_insert(noti_h, &privId);
218 if (error != NOTIFICATION_ERROR_NONE) {
219 _E("Fail to insert notification : %d", error);
220 Throw(Exception::NotificationShowError);
222 _D("ewkId=[%u], notiId=[%d]", notiData->getEwkNotiId(), privId);
225 error = notification_free(noti_h);
226 if (error != NOTIFICATION_ERROR_NONE) {
227 _E("Fail to free notification : %d", error);
228 Throw(Exception::NotificationShowError);
232 notiData->setNotiId(privId);
233 } Catch(Exception::NotificationShowError) {
234 notification_free(noti_h);
237 } Catch(DPL::Exception) {
238 _E("Fail to show notification");
244 bool hideNotification(uint64_t ewkNotiId)
246 notification_error_e error = NOTIFICATION_ERROR_NONE;
247 NotiMapIt it = m_notiDataMap.find(ewkNotiId);
249 notification_delete_by_priv_id(NULL,
250 NOTIFICATION_TYPE_NOTI,
251 it->second->getNotiId());
252 if (error == NOTIFICATION_ERROR_NONE) {
253 _D("Success to hide");
255 } else if (error == NOTIFICATION_ERROR_NOT_EXIST_ID) {
256 _D("Success to hide. Not exist noti");
259 _W("Error to hide : %d", error);
265 bool isExistData(uint64_t ewkNotiId)
267 if (m_notiDataMap.find(ewkNotiId) == m_notiDataMap.end()) {
273 void insertData(WebNotificationDataPtr notiData)
275 m_notiDataMap[notiData->getEwkNotiId()] = notiData;
278 void removeData(uint64_t ewkNotiId)
280 m_notiDataMap.erase(ewkNotiId);
283 WebNotificationDataPtr getData(uint64_t ewkNotiId)
285 return m_notiDataMap.find(ewkNotiId)->second;
289 WebNotificationSupportImplementation() :
294 void initialize(WrtDB::TizenPkgId pkgId)
296 // icon download path
297 // /opt/apps/tizen_id/data + '/' + filename
299 WrtDB::WidgetConfig::GetWidgetPersistentStoragePath(pkgId) + '/';
300 _D("path %s", m_persistentPath.c_str());
301 m_initialized = true;
304 void deinitialize(void)
307 m_initialized = false;
310 bool show(WebNotificationDataPtr notiData)
312 Assert(m_initialized);
313 if (isExistData(notiData->getEwkNotiId())) {
314 // Web Notifications (http://www.w3.org/TR/notifications/)
315 // 4.7 Replacing a notification
316 // 3. If old is in the list of pending notifications, queue a
317 // task to replace old with new, in the same position, in the
318 // list of pending notifications, and fire an event named
320 // 4. Otherwise, queue a task to replace old with new, in the
321 // same position, in the list of active notifications, fire
322 // an event named close on old, and fire an event named show
324 hideNotification(notiData->getEwkNotiId());
325 removeData(notiData->getEwkNotiId());
327 if (showNotification(notiData)) {
328 insertData(notiData);
334 void* hide(uint64_t ewkNotiId)
336 Assert(m_initialized);
337 if (!isExistData(ewkNotiId)) {
338 _W("Noti isn't exist");
341 if (!hideNotification(ewkNotiId)) {
344 WebNotificationDataPtr data = getData(ewkNotiId);
345 removeData(ewkNotiId);
346 return static_cast<void*>(data->getData());
350 WebNotificationSupport::WebNotificationSupport() :
351 m_impl(new WebNotificationSupportImplementation())
355 WebNotificationSupport::~WebNotificationSupport()
359 void WebNotificationSupport::initialize(WrtDB::TizenAppId appId)
361 m_impl->initialize(appId);
364 void WebNotificationSupport::deinitialize(void)
366 m_impl->deinitialize();
369 bool WebNotificationSupport::show(WebNotificationDataPtr notiData)
371 return m_impl->show(notiData);
374 void* WebNotificationSupport::hide(uint64_t ewkNotiId)
376 return m_impl->hide(ewkNotiId);
378 } //namespace ViewModule