2 * Copyright (c) 2015 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 #include "runtime/browser/web_application.h"
21 #include <ewk_chromium.h>
28 #include "common/logger.h"
29 #include "common/command_line.h"
30 #include "common/string_utils.h"
31 #include "common/app_control.h"
32 #include "common/locale_manager.h"
33 #include "common/application_data.h"
34 #include "common/resource_manager.h"
35 #include "common/app_db.h"
36 #include "common/profiler.h"
38 #include "runtime/browser/native_window.h"
39 #include "runtime/browser/web_view.h"
40 #include "runtime/browser/vibration_manager.h"
41 #include "runtime/browser/notification_manager.h"
42 #include "runtime/browser/popup.h"
43 #include "runtime/browser/popup_string.h"
45 #ifndef INJECTED_BUNDLE_PATH
46 #error INJECTED_BUNDLE_PATH is not set.
52 // TODO(sngn.lee) : It should be declare in common header
53 const char* kKeyNameBack = "back";
54 const char* kKeyNameMenu = "menu";
56 const char* kConsoleLogEnableKey = "WRT_CONSOLE_LOG_ENABLE";
57 const char* kConsoleMessageLogTag = "ConsoleMessage";
59 const char* kDebugKey = "debug";
60 const char* kPortKey = "port";
62 const char* kAppControlEventScript = \
64 "var __event = document.createEvent(\"CustomEvent\");\n"
65 "__event.initCustomEvent(\"appcontrol\", true, true);\n"
66 "document.dispatchEvent(__event);\n"
68 "for (var i=0; i < window.frames.length; i++)\n"
69 "{ window.frames[i].document.dispatchEvent(__event); }"
71 const char* kBackKeyEventScript = \
73 "var __event = document.createEvent(\"CustomEvent\");\n"
74 "__event.initCustomEvent(\"tizenhwkey\", true, true);\n"
75 "__event.keyName = \"back\";\n"
76 "document.dispatchEvent(__event);\n"
78 "for (var i=0; i < window.frames.length; i++)\n"
79 "{ window.frames[i].document.dispatchEvent(__event); }"
81 const char* kMenuKeyEventScript = \
83 "var __event = document.createEvent(\"CustomEvent\");\n"
84 "__event.initCustomEvent(\"tizenhwkey\", true, true);\n"
85 "__event.keyName = \"menu\";\n"
86 "document.dispatchEvent(__event);\n"
88 "for (var i=0; i < window.frames.length; i++)\n"
89 "{ window.frames[i].document.dispatchEvent(__event); }"
91 const char* kFullscreenPrivilege = "http://tizen.org/privilege/fullscreen";
92 const char* kFullscreenFeature = "fullscreen";
93 const char* kNotificationPrivilege =
94 "http://tizen.org/privilege/notification";
95 const char* kLocationPrivilege =
96 "http://tizen.org/privilege/location";
97 const char* kStoragePrivilege =
98 "http://tizen.org/privilege/unlimitedstorage";
99 const char* kUsermediaPrivilege =
100 "http://tizen.org/privilege/mediacapture";
101 const char* kNotiIconFile = "noti_icon.png";
103 const char* kVisibilitySuspendFeature = "visibility,suspend";
104 const char* kMediastreamRecordFeature = "mediastream,record";
105 const char* kEncryptedDatabaseFeature = "encrypted,database";
106 const char* kRotationLockFeature = "rotation,lock";
107 const char* kBackgroundMusicFeature = "background,music";
108 const char* kSoundModeFeature = "sound,mode";
109 const char* kBackgroundVibrationFeature = "background,vibration";
110 const char* kCSPFeature = "csp";
112 const char* kGeolocationPermissionPrefix = "__WRT_GEOPERM_";
113 const char* kNotificationPermissionPrefix = "__WRT_NOTIPERM_";
114 const char* kQuotaPermissionPrefix = "__WRT_QUOTAPERM_";
115 const char* kCertificateAllowPrefix = "__WRT_CERTIPERM_";
116 const char* kUsermediaPermissionPrefix = "__WRT_USERMEDIAPERM_";
117 const char* kDBPrivateSection = "private";
119 const char* kDefaultCSPRule =
120 "default-src *; script-src 'self'; style-src 'self'; object-src 'none';";
122 bool FindPrivilege(common::ApplicationData* app_data,
123 const std::string& privilege) {
124 if (app_data->permissions_info().get() == NULL)
126 auto it = app_data->permissions_info()->GetAPIPermissions().begin();
127 auto end = app_data->permissions_info()->GetAPIPermissions().end();
128 for ( ; it != end; ++it) {
129 if (*it == privilege)
135 static void SendDownloadRequest(const std::string& url) {
136 common::AppControl request;
137 request.set_operation(APP_CONTROL_OPERATION_DOWNLOAD);
138 request.set_uri(url);
139 request.LaunchRequest();
142 static void InitializeNotificationCallback(Ewk_Context* ewk_context,
143 WebApplication* app) {
144 auto show = [](Ewk_Context*,
145 Ewk_Notification* noti,
147 WebApplication* self = static_cast<WebApplication*>(user_data);
150 uint64_t id = ewk_notification_id_get(noti);
151 std::string title(ewk_notification_title_get(noti) ?
152 ewk_notification_title_get(noti) : "");
153 std::string body(ewk_notification_body_get(noti) ?
154 ewk_notification_body_get(noti) : "");
155 std::string icon_path = self->data_path() + "/" + kNotiIconFile;
156 if (!ewk_notification_icon_save_as_png(noti, icon_path.c_str())) {
159 if (NotificationManager::GetInstance()->Show(id, title, body, icon_path))
160 ewk_notification_showed(id);
162 auto hide = [](Ewk_Context*,
165 NotificationManager::GetInstance()->Hide(noti_id);
166 ewk_notification_closed(noti_id, EINA_FALSE);
168 ewk_context_notification_callbacks_set(ewk_context,
174 static Eina_Bool ExitAppIdlerCallback(void* /*data*/) {
176 return ECORE_CALLBACK_CANCEL;
179 static bool ClearCookie(Ewk_Context* ewk_context) {
180 Ewk_Cookie_Manager* cookie_manager =
181 ewk_context_cookie_manager_get(ewk_context);
182 if (!cookie_manager) {
183 LOGGER(ERROR) << "Fail to get cookie manager";
186 ewk_cookie_manager_cookies_clear(cookie_manager);
190 static bool ProcessWellKnownScheme(const std::string& url) {
191 if (utils::StartsWith(url, "file:") ||
192 utils::StartsWith(url, "app:") ||
193 utils::StartsWith(url, "data:") ||
194 utils::StartsWith(url, "http:") ||
195 utils::StartsWith(url, "https:") ||
196 utils::StartsWith(url, "widget:") ||
197 utils::StartsWith(url, "about:") ||
198 utils::StartsWith(url, "blob:")) {
202 std::unique_ptr<AppControl> request(AppControl::MakeAppcontrolFromURL(url));
203 if (request.get() == NULL || !request->LaunchRequest()) {
204 LOGGER(ERROR) << "Fail to send appcontrol request";
205 SLoggerE("Fail to send appcontrol request [%s]", url.c_str());
208 // Should return true, to stop the WebEngine progress step about this URL
214 WebApplication::WebApplication(
215 NativeWindow* window, std::unique_ptr<common::ApplicationData> app_data)
218 ewk_context_(ewk_context_new_with_injected_bundle_path(
219 INJECTED_BUNDLE_PATH)),
221 appid_(app_data->app_id()),
222 locale_manager_(new common::LocaleManager()),
223 app_data_(std::move(app_data)),
225 std::unique_ptr<char, decltype(std::free)*>
226 path {app_get_data_path(), std::free};
227 app_data_path_ = path.get();
229 resource_manager_.reset(
230 new common::ResourceManager(app_data_.get(), locale_manager_.get()));
231 resource_manager_->set_base_resource_path(
232 app_data_->application_path());
236 WebApplication::~WebApplication() {
238 ewk_context_delete(ewk_context_);
241 bool WebApplication::Initialize() {
244 ewk_context_cache_model_set(ewk_context_, EWK_CACHE_MODEL_DOCUMENT_BROWSER);
247 auto cookie_manager = ewk_context_cookie_manager_get(ewk_context_);
248 ewk_cookie_manager_accept_policy_set(cookie_manager,
249 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
251 // set persistent storage path
252 std::string cookie_path = data_path() + ".cookie";
253 ewk_cookie_manager_persistent_storage_set(
254 cookie_manager, cookie_path.c_str(),
255 EWK_COOKIE_PERSISTENT_STORAGE_SQLITE);
257 // vibration callback
258 auto vibration_start_callback = [](uint64_t ms, void*) {
259 platform::VibrationManager::GetInstance()->Start(static_cast<int>(ms));
261 auto vibration_stop_callback = [](void* /*user_data*/) {
262 platform::VibrationManager::GetInstance()->Stop();
264 ewk_context_vibration_client_callbacks_set(ewk_context_,
265 vibration_start_callback,
266 vibration_stop_callback,
269 auto download_callback = [](const char* downloadUrl, void* /*data*/) {
270 SendDownloadRequest(downloadUrl);
272 ewk_context_did_start_download_callback_set(ewk_context_,
275 InitializeNotificationCallback(ewk_context_, this);
277 if (FindPrivilege(app_data_.get(), kFullscreenPrivilege)) {
278 ewk_context_tizen_extensible_api_string_set(ewk_context_,
283 if (app_data_->setting_info() != NULL &&
284 app_data_->setting_info()->background_support_enabled()) {
285 ewk_context_tizen_extensible_api_string_set(ewk_context_,
286 kVisibilitySuspendFeature,
288 ewk_context_tizen_extensible_api_string_set(ewk_context_,
289 kBackgroundMusicFeature,
292 ewk_context_tizen_extensible_api_string_set(ewk_context_,
293 kMediastreamRecordFeature,
295 ewk_context_tizen_extensible_api_string_set(ewk_context_,
296 kEncryptedDatabaseFeature,
298 if (app_data_->setting_info() != NULL &&
299 app_data_->setting_info()->screen_orientation()
300 == wgt::parse::SettingInfo::ScreenOrientation::AUTO) {
301 ewk_context_tizen_extensible_api_string_set(ewk_context_,
302 kRotationLockFeature,
304 } else if (app_data_->setting_info() != NULL &&
305 app_data_->setting_info()->screen_orientation()
306 == wgt::parse::SettingInfo::ScreenOrientation::PORTRAIT) {
307 window_->SetRotationLock(
308 NativeWindow::ScreenOrientation::PORTRAIT_PRIMARY);
309 } else if (app_data_->setting_info() != NULL &&
310 app_data_->setting_info()->screen_orientation()
311 == wgt::parse::SettingInfo::ScreenOrientation::LANDSCAPE) {
312 window_->SetRotationLock(
313 NativeWindow::ScreenOrientation::LANDSCAPE_PRIMARY);
316 if (app_data_->setting_info() != NULL &&
317 app_data_->setting_info()->sound_mode()
318 == wgt::parse::SettingInfo::SoundMode::EXCLUSIVE) {
319 ewk_context_tizen_extensible_api_string_set(ewk_context_,
324 if (app_data_->setting_info() != NULL &&
325 app_data_->setting_info()->background_vibration()) {
326 ewk_context_tizen_extensible_api_string_set(ewk_context_,
327 kBackgroundVibrationFeature,
331 if (app_data_->widget_info() != NULL &&
332 !app_data_->widget_info()->default_locale().empty()) {
333 locale_manager_->SetDefaultLocale(
334 app_data_->widget_info()->default_locale());
337 // TODO(sngn.lee): Find the path of certificate file
338 // ewk_context_certificate_file_set(ewk_context_, .... );
340 // TODO(sngn.lee): find the proxy url
341 // ewk_context_proxy_uri_set(ewk_context_, ... );
343 if (app_data_->csp_info() != NULL ||
344 app_data_->csp_report_info() != NULL ||
345 app_data_->allowed_navigation_info() != NULL) {
346 security_model_version_ = 2;
347 if (app_data_->csp_info() == NULL ||
348 app_data_->csp_info()->security_rules().empty()) {
349 csp_rule_ = kDefaultCSPRule;
351 csp_rule_ = app_data_->csp_info()->security_rules();
353 if (app_data_->csp_report_info() != NULL &&
354 !app_data_->csp_report_info()->security_rules().empty()) {
355 csp_report_rule_ = app_data_->csp_report_info()->security_rules();
357 ewk_context_tizen_extensible_api_string_set(ewk_context_,
361 security_model_version_ = 1;
367 void WebApplication::Launch(std::unique_ptr<common::AppControl> appcontrol) {
369 WebView* view = new WebView(window_, ewk_context_);
372 // send widget info to injected bundle
373 ewk_send_widget_info(ewk_context_, appid_.c_str(),
374 elm_config_scale_get(),
378 std::unique_ptr<common::ResourceManager::Resource> res =
379 resource_manager_->GetStartResource(appcontrol.get());
380 view->SetDefaultEncoding(res->encoding());
382 STEP_PROFILE_END("OnCreate -> URL Set");
383 STEP_PROFILE_START("URL Set -> Rendered");
385 view->LoadUrl(res->uri(), res->mime());
386 view_stack_.push_front(view);
387 window_->SetContent(view->evas_object());
389 if (appcontrol->data(kDebugKey) == "true") {
391 LaunchInspector(appcontrol.get());
394 // TODO(sngn.lee): check the below code location.
395 // in Wearable, webkit can render contents before show window
396 // but Mobile, webkit can't render contents before show window
400 received_appcontrol_ = std::move(appcontrol);
403 void WebApplication::AppControl(
404 std::unique_ptr<common::AppControl> appcontrol) {
405 std::unique_ptr<common::ResourceManager::Resource> res =
406 resource_manager_->GetStartResource(appcontrol.get());
407 if (res->should_reset()) {
410 WebView* view = new WebView(window_, ewk_context_);
412 view->SetDefaultEncoding(res->encoding());
413 view->LoadUrl(res->uri(), res->mime());
414 view_stack_.push_front(view);
415 window_->SetContent(view->evas_object());
418 SendAppControlEvent();
421 if (!debug_mode_ && appcontrol->data(kDebugKey) == "true") {
423 LaunchInspector(appcontrol.get());
426 received_appcontrol_ = std::move(appcontrol);
429 void WebApplication::SendAppControlEvent() {
430 auto it = view_stack_.begin();
431 while (it != view_stack_.end()) {
432 (*it)->EvalJavascript(kAppControlEventScript);
436 void WebApplication::ClearViewStack() {
437 window_->SetContent(NULL);
438 auto it = view_stack_.begin();
439 for ( ; it != view_stack_.end(); ++it) {
446 void WebApplication::Resume() {
447 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
448 view_stack_.front()->SetVisibility(true);
450 if (app_data_->setting_info() != NULL &&
451 app_data_->setting_info()->background_support_enabled()) {
455 auto it = view_stack_.begin();
456 for ( ; it != view_stack_.end(); ++it) {
461 void WebApplication::Suspend() {
462 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
463 view_stack_.front()->SetVisibility(false);
465 if (app_data_->setting_info() != NULL &&
466 app_data_->setting_info()->background_support_enabled()) {
467 LOGGER(DEBUG) << "gone background (backgroud support enabed)";
471 auto it = view_stack_.begin();
472 for ( ; it != view_stack_.end(); ++it) {
477 void WebApplication::OnCreatedNewWebView(WebView* /*view*/, WebView* new_view) {
478 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
479 view_stack_.front()->SetVisibility(false);
481 SetupWebView(new_view);
482 view_stack_.push_front(new_view);
483 window_->SetContent(new_view->evas_object());
486 void WebApplication::OnClosedWebView(WebView * view) {
487 if (view_stack_.size() == 0)
490 WebView* current = view_stack_.front();
491 if (current == view) {
492 view_stack_.pop_front();
494 auto found = std::find(view_stack_.begin(), view_stack_.end(), view);
495 if (found != view_stack_.end()) {
496 view_stack_.erase(found);
500 if (view_stack_.size() == 0) {
501 if (terminator_ != NULL) {
504 } else if (current != view_stack_.front()) {
505 view_stack_.front()->SetVisibility(true);
506 window_->SetContent(view_stack_.front()->evas_object());
509 // Delete after the callback context(for ewk view) was not used
510 ecore_idler_add([](void* view) {
511 WebView* obj = static_cast<WebView*>(view);
517 void WebApplication::OnReceivedWrtMessage(
519 Ewk_IPC_Wrt_Message_Data* msg) {
521 Eina_Stringshare* msg_id = ewk_ipc_wrt_message_data_id_get(msg);
522 Eina_Stringshare* msg_ref_id = ewk_ipc_wrt_message_data_reference_id_get(msg);
523 Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(msg);
524 Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg);
526 LOGGER(DEBUG) << "RecvMsg: id = " << msg_id;
527 LOGGER(DEBUG) << "RecvMsg: refid = " << msg_ref_id;
528 LOGGER(DEBUG) << "RecvMsg: type = " << msg_type;
529 LOGGER(DEBUG) << "RecvMsg: value = " << msg_value;
531 #define TYPE_IS(x) (!strcmp(msg_type, x))
532 if (TYPE_IS("tizen://hide")) {
535 } else if (TYPE_IS("tizen://exit")) {
537 ecore_idler_add(ExitAppIdlerCallback, NULL);
538 } else if (TYPE_IS("tizen://changeUA")) {
540 // Change UserAgent of current WebView
542 if (view_stack_.size() > 0 && view_stack_.front() != NULL) {
543 ret = view_stack_.front()->SetUserAgent(std::string(msg_value));
546 Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new();
547 ewk_ipc_wrt_message_data_type_set(ans, msg_type);
548 ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id);
550 ewk_ipc_wrt_message_data_value_set(ans, "success");
552 ewk_ipc_wrt_message_data_value_set(ans, "failed");
553 if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) {
554 LOGGER(ERROR) << "Failed to send response";
556 ewk_ipc_wrt_message_data_del(ans);
557 } else if (TYPE_IS("tizen://deleteAllCookies")) {
558 Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new();
559 ewk_ipc_wrt_message_data_type_set(ans, msg_type);
560 ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id);
561 if (ClearCookie(ewk_context_))
562 ewk_ipc_wrt_message_data_value_set(ans, "success");
564 ewk_ipc_wrt_message_data_value_set(ans, "failed");
565 if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) {
566 LOGGER(ERROR) << "Failed to send response";
568 ewk_ipc_wrt_message_data_del(ans);
572 eina_stringshare_del(msg_value);
573 eina_stringshare_del(msg_type);
574 eina_stringshare_del(msg_ref_id);
575 eina_stringshare_del(msg_id);
578 void WebApplication::OnOrientationLock(
581 NativeWindow::ScreenOrientation preferred_rotation) {
582 if (view_stack_.size() == 0)
585 // Only top-most view can set the orientation relate operation
586 if (view_stack_.front() != view)
589 auto orientaion_setting = app_data_->setting_info() != NULL ?
590 app_data_->setting_info()->screen_orientation() :
591 // TODO(sngn.lee): check default value
592 wgt::parse::SettingInfo::ScreenOrientation::AUTO;
593 if (orientaion_setting != wgt::parse::SettingInfo::ScreenOrientation::AUTO) {
598 window_->SetRotationLock(preferred_rotation);
600 window_->SetAutoRotation();
604 void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) {
605 bool enabled = app_data_->setting_info() != NULL ?
606 app_data_->setting_info()->hwkey_enabled() :
608 if (enabled && kKeyNameBack == keyname) {
609 view->EvalJavascript(kBackKeyEventScript);
610 } else if (enabled && kKeyNameMenu == keyname) {
611 view->EvalJavascript(kMenuKeyEventScript);
615 void WebApplication::OnLanguageChanged() {
616 locale_manager_->UpdateSystemLocale();
617 ewk_context_cache_clear(ewk_context_);
618 auto it = view_stack_.begin();
619 for ( ; it != view_stack_.end(); ++it) {
624 void WebApplication::OnConsoleMessage(const std::string& msg, int level) {
625 static bool enabled = (getenv(kConsoleLogEnableKey) != NULL);
628 if (debug_mode_ || enabled) {
629 int dlog_level = DLOG_DEBUG;
631 case EWK_CONSOLE_MESSAGE_LEVEL_WARNING:
632 dlog_level = DLOG_WARN;
634 case EWK_CONSOLE_MESSAGE_LEVEL_ERROR:
635 dlog_level = DLOG_ERROR;
638 dlog_level = DLOG_DEBUG;
641 LOGGER_RAW(dlog_level, kConsoleMessageLogTag) << msg;
645 void WebApplication::OnLowMemory() {
646 ewk_context_cache_clear(ewk_context_);
647 ewk_context_notify_low_memory(ewk_context_);
650 bool WebApplication::OnContextMenuDisabled(WebView* /*view*/) {
651 return !(app_data_->setting_info() != NULL ?
652 app_data_->setting_info()->context_menu_enabled() :
656 void WebApplication::OnLoadStart(WebView* /*view*/) {
657 LOGGER(DEBUG) << "LoadStart";
659 void WebApplication::OnLoadFinished(WebView* /*view*/) {
660 LOGGER(DEBUG) << "LoadFinished";
662 void WebApplication::OnRendered(WebView* /*view*/) {
663 STEP_PROFILE_END("URL Set -> Rendered");
664 STEP_PROFILE_END("Start -> Launch Completed");
665 LOGGER(DEBUG) << "Rendered";
668 void WebApplication::LaunchInspector(common::AppControl* appcontrol) {
670 ewk_context_inspector_server_start(ewk_context_, 0);
671 std::stringstream ss;
673 std::map<std::string, std::vector<std::string>> data;
674 data[kPortKey] = { ss.str() };
675 appcontrol->Reply(data);
678 void WebApplication::SetupWebView(WebView* view) {
679 view->SetEventListener(this);
682 if (security_model_version_ == 2) {
683 view->SetCSPRule(csp_rule_, false);
684 if (!csp_report_rule_.empty()) {
685 view->SetCSPRule(csp_report_rule_, true);
689 // TODO(sngn.lee): set UserAgent to WebView
692 bool WebApplication::OnDidNavigation(WebView* /*view*/,
693 const std::string& url) {
695 // except(file , http, https, app) pass to appcontrol and return false
696 if (ProcessWellKnownScheme(url)) {
699 return resource_manager_->AllowNavigation(url);
702 void WebApplication::OnNotificationPermissionRequest(
704 const std::string& url,
705 std::function<void(bool)> result_handler) {
706 auto db = common::AppDB::GetInstance();
707 std::string reminder = db->Get(kDBPrivateSection,
708 kNotificationPermissionPrefix + url);
709 if (reminder == "allowed") {
710 result_handler(true);
712 } else if (reminder == "denied") {
713 result_handler(false);
717 // Local Domain: Grant permission if defined, otherwise Popup user prompt.
718 // Remote Domain: Popup user prompt.
719 if (common::utils::StartsWith(url, "file://") &&
720 FindPrivilege(app_data_.get(), kNotificationPrivilege)) {
721 result_handler(true);
725 Popup* popup = Popup::CreatePopup(window_);
726 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
727 popup->SetTitle(popup_string::kPopupTitleWebNotification);
728 popup->SetBody(popup_string::kPopupBodyWebNotification);
729 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
730 popup->SetResultHandler(
731 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
732 bool result = popup->GetButtonResult();
733 bool remember = popup->GetCheckBoxResult();
735 db->Set(kDBPrivateSection, kNotificationPermissionPrefix + url,
736 result ? "allowed" : "denied");
738 result_handler(result);
743 void WebApplication::OnGeolocationPermissionRequest(
745 const std::string& url,
746 std::function<void(bool)> result_handler) {
747 auto db = common::AppDB::GetInstance();
748 std::string reminder = db->Get(kDBPrivateSection,
749 kGeolocationPermissionPrefix + url);
750 if (reminder == "allowed") {
751 result_handler(true);
753 } else if (reminder == "denied") {
754 result_handler(false);
758 // Local Domain: Grant permission if defined, otherwise block execution.
759 // Remote Domain: Popup user prompt if defined, otherwise block execution.
760 if (!FindPrivilege(app_data_.get(), kLocationPrivilege)) {
761 result_handler(false);
765 if (common::utils::StartsWith(url, "file://")) {
766 result_handler(true);
770 Popup* popup = Popup::CreatePopup(window_);
771 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
772 popup->SetTitle(popup_string::kPopupTitleGeoLocation);
773 popup->SetBody(popup_string::kPopupBodyGeoLocation);
774 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
775 popup->SetResultHandler(
776 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
777 bool result = popup->GetButtonResult();
778 bool remember = popup->GetCheckBoxResult();
780 db->Set(kDBPrivateSection, kGeolocationPermissionPrefix + url,
781 result ? "allowed" : "denied");
783 result_handler(result);
789 void WebApplication::OnQuotaExceed(
791 const std::string& url,
792 std::function<void(bool)> result_handler) {
793 auto db = common::AppDB::GetInstance();
794 std::string reminder = db->Get(kDBPrivateSection,
795 kQuotaPermissionPrefix + url);
796 if (reminder == "allowed") {
797 result_handler(true);
799 } else if (reminder == "denied") {
800 result_handler(false);
804 // Local Domain: Grant permission if defined, otherwise Popup user prompt.
805 // Remote Domain: Popup user prompt.
806 if (common::utils::StartsWith(url, "file://") &&
807 FindPrivilege(app_data_.get(), kStoragePrivilege)) {
808 result_handler(true);
812 Popup* popup = Popup::CreatePopup(window_);
813 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
814 popup->SetTitle(popup_string::kPopupTitleWebStorage);
815 popup->SetBody(popup_string::kPopupBodyWebStorage);
816 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
817 popup->SetResultHandler(
818 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
819 bool result = popup->GetButtonResult();
820 bool remember = popup->GetCheckBoxResult();
822 db->Set(kDBPrivateSection, kQuotaPermissionPrefix + url,
823 result ? "allowed" : "denied");
825 result_handler(result);
830 void WebApplication::OnAuthenticationRequest(
832 const std::string& /*url*/,
833 const std::string& /*message*/,
834 std::function<void(bool submit,
835 const std::string& id,
836 const std::string& password)
838 Popup* popup = Popup::CreatePopup(window_);
839 popup->SetButtonType(Popup::ButtonType::LoginCancelButton);
840 popup->SetFirstEntry(popup_string::kPopupLabelAuthusername,
841 Popup::EntryType::Edit);
842 popup->SetSecondEntry(popup_string::kPopupLabelPassword,
843 Popup::EntryType::PwEdit);
844 popup->SetTitle(popup_string::kPopupTitleAuthRequest);
845 popup->SetBody(popup_string::kPopupBodyAuthRequest);
846 popup->SetResultHandler(
847 [result_handler](Popup* popup, void* /*user_data*/) {
848 bool result = popup->GetButtonResult();
849 std::string id = popup->GetFirstEntryResult();
850 std::string passwd = popup->GetSecondEntryResult();
851 result_handler(result, id, passwd);
856 void WebApplication::OnCertificateAllowRequest(
858 const std::string& /*url*/,
859 const std::string& pem,
860 std::function<void(bool allow)> result_handler) {
861 auto db = common::AppDB::GetInstance();
862 std::string reminder = db->Get(kDBPrivateSection,
863 kCertificateAllowPrefix + pem);
864 if (reminder == "allowed") {
865 result_handler(true);
867 } else if (reminder == "denied") {
868 result_handler(false);
872 Popup* popup = Popup::CreatePopup(window_);
873 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
874 popup->SetTitle(popup_string::kPopupTitleCert);
875 popup->SetBody(popup_string::kPopupBodyCert);
876 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
877 popup->SetResultHandler(
878 [db, result_handler, pem](Popup* popup, void* /*user_data*/) {
879 bool result = popup->GetButtonResult();
880 bool remember = popup->GetCheckBoxResult();
882 db->Set(kDBPrivateSection, kCertificateAllowPrefix + pem,
883 result ? "allowed" : "denied");
885 result_handler(result);
890 void WebApplication::OnUsermediaPermissionRequest(
892 const std::string& url,
893 std::function<void(bool)> result_handler) {
894 auto db = common::AppDB::GetInstance();
895 std::string reminder = db->Get(kDBPrivateSection,
896 kUsermediaPermissionPrefix + url);
897 if (reminder == "allowed") {
898 result_handler(true);
900 } else if (reminder == "denied") {
901 result_handler(false);
905 // Local Domain: Grant permission if defined, otherwise block execution.
906 // Remote Domain: Popup user prompt if defined, otherwise block execution.
907 if (!FindPrivilege(app_data_.get(), kUsermediaPrivilege)) {
908 result_handler(false);
912 if (common::utils::StartsWith(url, "file://")) {
913 result_handler(true);
917 Popup* popup = Popup::CreatePopup(window_);
918 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
919 popup->SetTitle(popup_string::kPopupTitleUserMedia);
920 popup->SetBody(popup_string::kPopupBodyUserMedia);
921 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
922 popup->SetResultHandler(
923 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
924 bool result = popup->GetButtonResult();
925 bool remember = popup->GetCheckBoxResult();
927 db->Set(kDBPrivateSection, kUsermediaPermissionPrefix + url,
928 result ? "allowed" : "denied");
930 result_handler(result);
935 } // namespace runtime