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"
24 #include <dpl/log/log.h>
25 #include <dpl/string.h>
26 #include <wrt-commons/security-origin-dao/security_origin_dao_types.h>
27 #include <wrt-commons/security-origin-dao/security_origin_dao.h>
28 #include <common/view_logic_security_origin_support.h>
30 #include <notification.h>
33 #include <curl/curl.h>
34 #include <widget_model.h>
38 const char* PATTERN_CHECK_EXTERNAL = "^http(s)?://\\w+.*$";
39 const char* const WEB_NOTIFICATION_ASK_BODY_PREFIX = "Do you want to allow ";
40 const char* const WEB_NOTIFICATION_ASK_BODY_POSTFIX =
41 " to use web notificaion?";
42 const char* const WEB_NOTIFICATION_ASK_CHECK = "Don't ask again";
46 namespace ViewModule {
47 namespace WebNotification {
49 using namespace SecurityOriginDB;
50 using namespace ViewModule::SecurityOriginSupportUtil;
52 class WebNotificationPermissionData
53 : public ViewModule::SecurityOriginSupportUtil::PermissionData
56 Ewk_Context* m_ewkContext;
58 WebNotificationPermissionData(
59 SecurityOriginDB::SecurityOriginDAO* originDao,
60 SecurityOriginDB::SecurityOriginData originData,
61 Ewk_Context* ewkContext,
63 ViewModule::SecurityOriginSupportUtil::PermissionData(
67 m_ewkContext(ewkContext)
72 bool notificationShow(WebNotificationDataPtr notiData);
73 bool notificationHide(WebNotificationDataPtr notiData);
74 bool isExternalUri(const std::string &pattern, const std::string &uri);
75 bool downloadImage(WebNotificationDataPtr notiData);
76 size_t curlWriteData(void *ptr, size_t size, size_t nmemb, FILE *stream);
77 void askUserForWebNotificationPermission(
79 WebNotificationPermissionData* data);
80 static void popupCallback(void* data, Evas_Object* obj, void* eventInfo);
82 WebNotificationData::WebNotificationData(WidgetModel* widgetModel,
84 m_widgetModel(widgetModel),
87 Assert(m_widgetModel);
90 WebNotificationData::~WebNotificationData()
94 void webNotificationPermissionRequest(
96 SecurityOriginDAO* securityOriginDAO,
97 Ewk_Context* ewkContext,
100 LogDebug("permissionRequest called");
101 Assert(securityOriginDAO);
103 Ewk_Notification_Permission_Request* request =
104 static_cast<Ewk_Notification_Permission_Request*>(data);
105 const Ewk_Security_Origin* ewkOrigin =
106 ewk_notification_permission_request_origin_get(request);
109 SecurityOriginData securityOriginData(
110 FEATURE_WEB_NOTIFICATION,
112 DPL::FromUTF8String(ewk_security_origin_protocol_get(ewkOrigin)),
113 DPL::FromUTF8String(ewk_security_origin_host_get(ewkOrigin)),
114 ewk_security_origin_port_get(ewkOrigin)));
116 // check cache database
117 Result result = securityOriginDAO->getResult(securityOriginData);
118 if (RESULT_ALLOW_ONCE == result || RESULT_ALLOW_ALWAYS == result) {
120 ewk_notification_permission_request_response(ewkContext,
124 } else if (RESULT_DENY_ONCE == result || RESULT_DENY_ALWAYS == result) {
126 ewk_notification_permission_request_response(ewkContext,
133 WebNotificationPermissionData* permissionData =
134 new WebNotificationPermissionData(securityOriginDAO,
139 // suspend notification
140 ewk_notification_permission_request_suspend(request);
141 askUserForWebNotificationPermission(window, permissionData);
145 bool showWebNotification(WebNotificationDataPtr notiData)
147 LogInfo("showWebNotification called");
149 /* TODO : register notification to database */
150 return notificationShow(notiData);
153 bool notificationShow(WebNotificationDataPtr notiData)
155 LogDebug("notificationShow called");
157 notification_h noti_h = NULL;
158 notification_error_e error = NOTIFICATION_ERROR_NONE;
161 // create notification
162 noti_h = notification_new(
163 NOTIFICATION_TYPE_NOTI, NOTIFICATION_GROUP_ID_NONE, notiData->m_id);
165 LogError("Fail to notification_new");
169 // set notification title
170 error = notification_set_text(
172 NOTIFICATION_TEXT_TYPE_TITLE,
173 notiData->m_title.c_str(),
175 NOTIFICATION_VARIABLE_TYPE_NONE);
176 if (error != NOTIFICATION_ERROR_NONE) {
177 ThrowMsg(Exception::NotificationShowError, "Fail to set title");
180 // set notification content
181 error = notification_set_text(
183 NOTIFICATION_TEXT_TYPE_CONTENT,
184 notiData->m_body.c_str(),
186 NOTIFICATION_VARIABLE_TYPE_NONE);
187 if (error != NOTIFICATION_ERROR_NONE) {
188 ThrowMsg(Exception::NotificationShowError,
189 "Fail to set content:" << error);
192 //check uri is "http", https" or not
193 bool validIconURL = true;
194 LogInfo("url path is " << notiData->m_iconURL);
195 if (isExternalUri(PATTERN_CHECK_EXTERNAL, notiData->m_iconURL)) {
196 //download image from url
197 validIconURL = downloadImage(notiData);
201 // If fail to download external image, skip to set image.
202 // In this case, set to default package image.
203 if (true == validIconURL) {
204 error = notification_set_image(
206 NOTIFICATION_IMAGE_TYPE_ICON,
207 notiData->m_iconURL.c_str());
208 if (error != NOTIFICATION_ERROR_NONE) {
209 ThrowMsg(Exception::NotificationShowError,
210 "Fail to free notification: " << error);
214 // insert notification
215 int priv_id = NOTIFICATION_PRIV_ID_NONE;
216 error = notification_insert(noti_h, &priv_id);
217 if (error != NOTIFICATION_ERROR_NONE) {
218 ThrowMsg(Exception::NotificationShowError,
219 "Fail to insert notification: " << error);
222 LogInfo("Notification is inserted!");
223 LogInfo("noti id =[" << notiData->m_id << "] " <<
224 "priv_id =[" << priv_id << "]");
227 error = notification_free(noti_h);
228 if (error != NOTIFICATION_ERROR_NONE) {
229 ThrowMsg(Exception::NotificationShowError,
230 "Fail to free notification: " << error);
235 } Catch(Exception::NotificationShowError) {
236 LogError(_rethrown_exception.GetMessage());
237 notification_free(noti_h);
240 } Catch(DPL::Exception) {
241 LogError(_rethrown_exception.GetMessage());
246 bool notificationHide(WebNotificationDataPtr notiData)
248 LogInfo("notificationHide called");
254 bool isExternalUri(const std::string &pattern, const std::string &uri)
256 LogInfo("isExternalUri called");
258 pcrecpp::RE_Options pcreOpt;
259 pcreOpt.set_caseless(true);
260 pcrecpp::RE re(pattern, pcreOpt);
262 return re.FullMatch(uri);
265 bool downloadImage(WebNotificationDataPtr notiData)
267 LogInfo("downloadImage called");
271 // /opt/apps/tizen_id/data + '/' + filename
272 std::string downloadPath =
274 notiData->m_widgetModel->PersistentStoragePath.Get()) + "/";
275 LogDebug("downloadPath " << downloadPath);
277 // Make valid filename
278 // If there is already exist filename, rename to "filename_%d"
279 std::string fileName =
280 notiData->m_iconURL.substr(notiData->m_iconURL.rfind('/') + 1);
281 LogDebug("fileName from URL: " << fileName);
282 std::string rename = fileName;
283 unsigned int renameSuffixNb = 0;
284 while (0 == access((downloadPath + rename).c_str(), F_OK)) {
285 std::ostringstream suffixOstr;
287 suffixOstr << fileName << "_" << renameSuffixNb++;
290 rename.insert(rename.find('.'), suffixOstr.str());
293 downloadPath += rename;
294 LogDebug("Valid file path : " << downloadPath);
296 // Download image by curl
301 curl = curl_easy_init();
303 ThrowMsg(Exception::InitError, "fail to curl_easy_init");
306 fp = fopen(downloadPath.c_str(), "wb");
308 ThrowMsg(Exception::InitError, "fail to open");
311 curl_easy_setopt(curl, CURLOPT_URL, notiData->m_iconURL.c_str());
312 curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
313 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curlWriteData);
315 CURLcode err = curl_easy_perform(curl);
317 ThrowMsg(Exception::DownloadImageError,
318 "fail to curl_easy_perform: " << err);
321 curl_easy_cleanup(curl);
322 } Catch (DPL::Exception) {
323 LogError(_rethrown_exception.GetMessage());
325 curl_easy_cleanup(curl);
329 LogDebug("Download success.. downloadedImgPath: " << downloadPath);
330 notiData->m_iconURL = downloadPath;
334 size_t curlWriteData(void *ptr, size_t size, size_t nmemb, FILE *stream)
336 size_t written = fwrite(ptr, size, nmemb, stream);
340 void askUserForWebNotificationPermission(
342 WebNotificationPermissionData* data)
344 LogDebug("askUserForWebNotificationPermission called");
346 WEB_NOTIFICATION_ASK_BODY_PREFIX +
347 DPL::ToUTF8String(data->m_originData.origin.host) +
348 WEB_NOTIFICATION_ASK_BODY_POSTFIX;
349 Evas_Object* popup = createPopup(window,
351 WEB_NOTIFICATION_ASK_CHECK,
355 LogError("Fail to create popup object");
359 evas_object_show(popup);
363 void popupCallback(void* data, Evas_Object* obj, void* /*eventInfo*/)
365 LogDebug("popupCallback");
367 WebNotificationPermissionData* permData =
368 static_cast<WebNotificationPermissionData*>(data);
369 Ewk_Notification_Permission_Request* request =
370 static_cast<Ewk_Notification_Permission_Request*>(permData->m_data);
372 Evas_Object* popup = getPopup(obj);
373 Result result = getResult(obj);
375 if (result != RESULT_UNKNOWN) {
376 permData->m_originDao->setSecurityOriginData(permData->m_originData, result);
379 (result == RESULT_ALLOW_ALWAYS || result == RESULT_ALLOW_ONCE) ?
380 EINA_TRUE : EINA_FALSE;
381 ewk_notification_permission_request_response(permData->m_ewkContext,
385 evas_object_hide(popup);
386 evas_object_del(popup);
390 } // namespace WebNotification
391 } //namespace ViewModule