1 // Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "runtime/web_application.h"
9 #include <ewk_chromium.h>
16 #include "common/logger.h"
17 #include "common/constants.h"
18 #include "common/command_line.h"
19 #include "common/string_utils.h"
20 #include "runtime/native_window.h"
21 #include "runtime/web_view.h"
22 #include "runtime/vibration_manager.h"
23 #include "common/app_control.h"
24 #include "common/locale_manager.h"
25 #include "common/application_data.h"
26 #include "common/resource_manager.h"
27 #include "common/app_db.h"
28 #include "runtime/notification_manager.h"
29 #include "runtime/popup.h"
30 #include "runtime/popup_string.h"
35 // TODO(sngn.lee) : It should be declare in common header
36 const char* kKeyNameBack = "back";
38 const char* kConsoleLogEnableKey = "WRT_CONSOLE_LOG_ENABLE";
39 const char* kConsoleMessageLogTag = "ConsoleMessage";
41 const char* kDebugKey = "debug";
42 const char* kPortKey = "port";
44 // TODO(wy80.choi): consider 64bits system.
45 const char* kInjectedBundlePath = "/usr/lib/libwrt-injected-bundle.so";
46 const char* kDBusIntrospectionXML =
48 " <interface name='org.tizen.wrt.Application'>"
49 " <method name='NotifyEPCreated'>"
50 " <arg name='status' type='s' direction='in'/>"
52 " <method name='GetRuntimeVariable'>"
53 " <arg name='key' type='s' direction='in' />"
54 " <arg name='value' type='s' direction='out' />"
58 const char* kAppControlEventScript = \
60 "var __event = document.createEvent(\"CustomEvent\");\n"
61 "__event.initCustomEvent(\"appcontrol\", true, true);\n"
62 "document.dispatchEvent(__event);\n"
64 "for (var i=0; i < window.frames.length; i++)\n"
65 "{ window.frames[i].document.dispatchEvent(__event); }"
67 const char* kBackKeyEventScript = \
69 "var __event = document.createEvent(\"CustomEvent\");\n"
70 "__event.initCustomEvent(\"tizenhwkey\", true, true);\n"
71 "__event.keyName = \"back\";\n"
72 "document.dispatchEvent(__event);\n"
74 "for (var i=0; i < window.frames.length; i++)\n"
75 "{ window.frames[i].document.dispatchEvent(__event); }"
77 const char* kFullscreenPrivilege = "http://tizen.org/privilege/fullscreen";
78 const char* kFullscreenFeature = "fullscreen";
79 const char* kNotificationPrivilege =
80 "http://tizen.org/privilege/notification";
81 const char* kLocationPrivilege =
82 "http://tizen.org/privilege/location";
83 const char* kStoragePrivilege =
84 "http://tizen.org/privilege/unlimitedstorage";
85 const char* kNotiIconFile = "noti_icon.png";
87 const char* kVisibilitySuspendFeature = "visibility,suspend";
88 const char* kMediastreamRecordFeature = "mediastream,record";
89 const char* kEncryptedDatabaseFeature = "encrypted,database";
90 const char* kRotationLockFeature = "rotation,lock";
91 const char* kBackgroundMusicFeature = "background,music";
92 const char* kSoundModeFeature = "sound,mode";
93 const char* kBackgroundVibrationFeature = "background,vibration";
94 const char* kGeolocationPermissionPrefix = "__WRT_GEOPERM_";
95 const char* kNotificationPermissionPrefix = "__WRT_NOTIPERM_";
96 const char* kQuotaPermissionPrefix = "__WRT_QUOTAPERM_";
97 const char* kCertificateAllowPrefix = "__WRT_CERTIPERM_";
98 const char* kDBPrivateSection = "private";
101 bool FindPrivilege(wrt::ApplicationData* app_data,
102 const std::string& privilege) {
103 if (app_data->permissions_info().get() == NULL)
105 auto it = app_data->permissions_info()->GetAPIPermissions().begin();
106 auto end = app_data->permissions_info()->GetAPIPermissions().end();
107 for ( ; it != end; ++it) {
108 if (*it == privilege)
114 void ExecExtensionProcess(const std::string& uuid) {
116 if ((pid = fork()) < 0) {
117 LOGGER(ERROR) << "Failed to fork child process for extension process.";
120 CommandLine* cmd = CommandLine::ForCurrentProcess();
121 std::string switch_ext("--");
122 switch_ext.append(kSwitchExtensionServer);
123 execl(cmd->program().c_str(),
124 cmd->program().c_str(), switch_ext.c_str(), uuid.c_str(), NULL);
128 static void SendDownloadRequest(const std::string& url) {
129 wrt::AppControl request;
130 request.set_operation(APP_CONTROL_OPERATION_DOWNLOAD);
131 request.set_uri(url);
132 request.LaunchRequest();
135 static void InitializeNotificationCallback(Ewk_Context* ewk_context,
136 WebApplication* app) {
137 auto show = [](Ewk_Context*,
138 Ewk_Notification* noti,
140 WebApplication* self = static_cast<WebApplication*>(user_data);
143 uint64_t id = ewk_notification_id_get(noti);
144 std::string title(ewk_notification_title_get(noti) ?
145 ewk_notification_title_get(noti) : "");
146 std::string body(ewk_notification_body_get(noti) ?
147 ewk_notification_body_get(noti) : "");
148 std::string icon_path = self->data_path() + "/" + kNotiIconFile;
149 if (!ewk_notification_icon_save_as_png(noti, icon_path.c_str())) {
152 if (NotificationManager::GetInstance()->Show(id, title, body, icon_path))
153 ewk_notification_showed(id);
155 auto hide = [](Ewk_Context*,
158 NotificationManager::GetInstance()->Hide(noti_id);
159 ewk_notification_closed(noti_id, EINA_FALSE);
161 ewk_context_notification_callbacks_set(ewk_context,
167 static Eina_Bool ExitAppIdlerCallback(void* /*data*/) {
169 return ECORE_CALLBACK_CANCEL;
174 WebApplication::WebApplication(
175 NativeWindow* window, std::unique_ptr<ApplicationData> app_data)
178 ewk_context_(ewk_context_new_with_injected_bundle_path(
179 kInjectedBundlePath)),
181 appid_(app_data->app_id()),
182 app_uuid_(utils::GenerateUUID()),
183 locale_manager_(new LocaleManager()),
184 app_data_(std::move(app_data)),
186 std::unique_ptr<char, decltype(std::free)*>
187 path {app_get_data_path(), std::free};
188 app_data_path_ = path.get();
190 resource_manager_.reset(
191 new ResourceManager(app_data_.get(), locale_manager_.get()));
192 resource_manager_->set_base_resource_path(
193 app_data_->application_path());
197 WebApplication::~WebApplication() {
199 ewk_context_delete(ewk_context_);
202 bool WebApplication::Initialize() {
204 ewk_context_cache_model_set(ewk_context_, EWK_CACHE_MODEL_DOCUMENT_BROWSER);
207 auto cookie_manager = ewk_context_cookie_manager_get(ewk_context_);
208 ewk_cookie_manager_accept_policy_set(cookie_manager,
209 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
211 // set persistent storage path
212 std::string cookie_path = data_path() + ".cookie";
213 ewk_cookie_manager_persistent_storage_set(
214 cookie_manager, cookie_path.c_str(),
215 EWK_COOKIE_PERSISTENT_STORAGE_SQLITE);
217 // vibration callback
218 auto vibration_start_callback = [](uint64_t ms, void*) {
219 platform::VibrationManager::GetInstance()->Start(static_cast<int>(ms));
221 auto vibration_stop_callback = [](void* /*user_data*/) {
222 platform::VibrationManager::GetInstance()->Stop();
224 ewk_context_vibration_client_callbacks_set(ewk_context_,
225 vibration_start_callback,
226 vibration_stop_callback,
229 auto download_callback = [](const char* downloadUrl, void* /*data*/) {
230 SendDownloadRequest(downloadUrl);
232 ewk_context_did_start_download_callback_set(ewk_context_,
235 InitializeNotificationCallback(ewk_context_, this);
237 if (FindPrivilege(app_data_.get(), kFullscreenPrivilege)) {
238 ewk_context_tizen_extensible_api_string_set(ewk_context_,
243 if (app_data_->setting_info() != NULL &&
244 app_data_->setting_info()->background_support_enabled()) {
245 ewk_context_tizen_extensible_api_string_set(ewk_context_,
246 kVisibilitySuspendFeature,
248 ewk_context_tizen_extensible_api_string_set(ewk_context_,
249 kBackgroundMusicFeature,
252 ewk_context_tizen_extensible_api_string_set(ewk_context_,
253 kMediastreamRecordFeature,
255 ewk_context_tizen_extensible_api_string_set(ewk_context_,
256 kEncryptedDatabaseFeature,
258 if (app_data_->setting_info() != NULL &&
259 app_data_->setting_info()->screen_orientation()
260 == wgt::parse::SettingInfo::ScreenOrientation::AUTO) {
261 ewk_context_tizen_extensible_api_string_set(ewk_context_,
262 kRotationLockFeature,
266 if (app_data_->setting_info() != NULL &&
267 app_data_->setting_info()->sound_mode()
268 == wgt::parse::SettingInfo::SoundMode::EXCLUSIVE) {
269 ewk_context_tizen_extensible_api_string_set(ewk_context_,
274 if (app_data_->setting_info() != NULL &&
275 app_data_->setting_info()->background_vibration()) {
276 ewk_context_tizen_extensible_api_string_set(ewk_context_,
277 kBackgroundVibrationFeature,
281 if (app_data_->widget_info() != NULL &&
282 !app_data_->widget_info()->default_locale().empty()) {
283 locale_manager_->SetDefaultLocale(
284 app_data_->widget_info()->default_locale());
287 // TODO(sngn.lee): Find the path of certificate file
288 // ewk_context_certificate_file_set(ewk_context_, .... );
290 // TODO(sngn.lee): find the proxy url
291 // ewk_context_proxy_uri_set(ewk_context_, ... );
294 // TODO(sngn.lee): check csp element in config.xml and enable - "csp"
299 void WebApplication::Launch(std::unique_ptr<wrt::AppControl> appcontrol) {
300 // Start DBus Server for Runtime
301 // TODO(wy80.choi): Should I add PeerCredentials checker?
302 using std::placeholders::_1;
303 using std::placeholders::_2;
304 using std::placeholders::_3;
305 using std::placeholders::_4;
306 dbus_server_.SetIntrospectionXML(kDBusIntrospectionXML);
307 dbus_server_.SetMethodCallback(kDBusInterfaceNameForApplication,
308 std::bind(&WebApplication::HandleDBusMethod, this, _1, _2, _3, _4));
309 dbus_server_.Start(app_uuid_ +
310 "." + std::string(kDBusNameForApplication));
312 // Execute ExtensionProcess
313 ExecExtensionProcess(app_uuid_);
316 WebView* view = new WebView(window_, ewk_context_);
319 // send widget info to injected bundle
320 // TODO(wy80.choi): ewk_send_widget_info should be fixed to receive uuid of
321 // application instead of widget_id.
322 // Currently, uuid is passed as encoded_bundle argument temporarily.
323 ewk_send_widget_info(ewk_context_, appid_.c_str(),
324 elm_config_scale_get(),
328 std::unique_ptr<ResourceManager::Resource> res =
329 resource_manager_->GetStartResource(appcontrol.get());
330 // TODO(wy80.choi): temporary comment for test, remove it later.
331 // view->LoadUrl("file:///home/owner/apps_rw/33CFo0eFJe/"
332 // "33CFo0eFJe.annex/index.html");
333 view->LoadUrl(res->uri());
334 view_stack_.push_front(view);
335 window_->SetContent(view->evas_object());
337 // TODO(sngn.lee): below code only debug code
338 auto callback = [](void*, Evas*, Evas_Object* obj,
341 evas_object_geometry_get(obj, &x, &y, &w, &h);
342 LOGGER(DEBUG) << "resize ! ("
343 << x << ", " << y << ", " << w << ", " << h << ")";
345 evas_object_event_callback_add(view->evas_object(),
346 EVAS_CALLBACK_RESIZE,
349 if (appcontrol->data(kDebugKey) == "true") {
351 LaunchInspector(appcontrol.get());
354 // TODO(sngn.lee): check the below code location.
355 // in Wearable, webkit can render contents before show window
356 // but Mobile, webkit can't render contents before show window
360 received_appcontrol_ = std::move(appcontrol);
363 void WebApplication::AppControl(std::unique_ptr<wrt::AppControl> appcontrol) {
364 std::unique_ptr<ResourceManager::Resource> res =
365 resource_manager_->GetStartResource(appcontrol.get());
366 if (res->should_reset()) {
369 WebView* view = new WebView(window_, ewk_context_);
372 view->LoadUrl(res->uri());
373 view_stack_.push_front(view);
374 window_->SetContent(view->evas_object());
377 SendAppControlEvent();
380 if (!debug_mode_ && appcontrol->data(kDebugKey) == "true") {
382 LaunchInspector(appcontrol.get());
385 received_appcontrol_ = std::move(appcontrol);
388 void WebApplication::SendAppControlEvent() {
389 auto it = view_stack_.begin();
390 while (it != view_stack_.end()) {
391 (*it)->EvalJavascript(kAppControlEventScript);
395 void WebApplication::ClearViewStack() {
396 window_->SetContent(NULL);
397 auto it = view_stack_.begin();
398 for ( ; it != view_stack_.end(); ++it) {
405 void WebApplication::Resume() {
406 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
407 view_stack_.front()->SetVisibility(true);
409 if (app_data_->setting_info() != NULL &&
410 app_data_->setting_info()->background_support_enabled()) {
414 auto it = view_stack_.begin();
415 for ( ; it != view_stack_.end(); ++it) {
420 void WebApplication::Suspend() {
421 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
422 view_stack_.front()->SetVisibility(false);
424 if (app_data_->setting_info() != NULL &&
425 app_data_->setting_info()->background_support_enabled()) {
426 LOGGER(DEBUG) << "gone background (backgroud support enabed)";
430 auto it = view_stack_.begin();
431 for ( ; it != view_stack_.end(); ++it) {
436 void WebApplication::OnCreatedNewWebView(WebView* /*view*/, WebView* new_view) {
437 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
438 view_stack_.front()->SetVisibility(false);
440 SetupWebView(new_view);
441 view_stack_.push_front(new_view);
442 window_->SetContent(new_view->evas_object());
445 void WebApplication::OnClosedWebView(WebView * view) {
446 if (view_stack_.size() == 0)
449 WebView* current = view_stack_.front();
450 if (current == view) {
451 view_stack_.pop_front();
453 auto found = std::find(view_stack_.begin(), view_stack_.end(), view);
454 if (found != view_stack_.end()) {
455 view_stack_.erase(found);
459 if (view_stack_.size() == 0) {
460 if (terminator_ != NULL) {
463 } else if (current != view_stack_.front()) {
464 view_stack_.front()->SetVisibility(true);
465 window_->SetContent(view_stack_.front()->evas_object());
468 // Delete after the callback context(for ewk view) was not used
469 ecore_idler_add([](void* view) {
470 WebView* obj = static_cast<WebView*>(view);
476 void WebApplication::OnReceivedWrtMessage(
478 Ewk_IPC_Wrt_Message_Data* msg) {
480 Eina_Stringshare* msg_id = ewk_ipc_wrt_message_data_id_get(msg);
481 Eina_Stringshare* msg_ref_id = ewk_ipc_wrt_message_data_reference_id_get(msg);
482 Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(msg);
483 Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg);
485 LOGGER(DEBUG) << "RecvMsg: id = " << msg_id;
486 LOGGER(DEBUG) << "RecvMsg: refid = " << msg_ref_id;
487 LOGGER(DEBUG) << "RecvMsg: type = " << msg_type;
488 LOGGER(DEBUG) << "RecvMsg: value = " << msg_value;
490 #define TYPE_IS(x) (!strcmp(msg_type, x))
491 if (TYPE_IS("tizen://hide")) {
494 } else if (TYPE_IS("tizen://exit")) {
496 ecore_idler_add(ExitAppIdlerCallback, NULL);
497 } else if (TYPE_IS("tizen://changeUA")) {
499 // Change UserAgent of current WebView
501 if (view_stack_.size() > 0 && view_stack_.front() != NULL) {
502 ret = view_stack_.front()->SetUserAgent(std::string(msg_value));
505 Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new();
506 ewk_ipc_wrt_message_data_type_set(ans, msg_type);
507 ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id);
509 ewk_ipc_wrt_message_data_value_set(ans, "success");
511 ewk_ipc_wrt_message_data_value_set(ans, "failed");
512 if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) {
513 LOGGER(ERROR) << "Failed to send response";
515 ewk_ipc_wrt_message_data_del(ans);
516 } else if (TYPE_IS("tizen://test-sync")) {
517 // TODO(wy80.choi): this type should be removed after finish test
518 ewk_ipc_wrt_message_data_value_set(msg, "Reply!!");
519 } else if (TYPE_IS("tizen://test-async")) {
520 // TODO(wy80.choi): this type should be removed after finish test
521 Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new();
522 ewk_ipc_wrt_message_data_type_set(ans, msg_type);
523 ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id);
524 ewk_ipc_wrt_message_data_value_set(ans, "Aync Reply!!");
525 if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) {
526 LOGGER(ERROR) << "Failed to send response";
528 ewk_ipc_wrt_message_data_del(ans);
532 eina_stringshare_del(msg_value);
533 eina_stringshare_del(msg_type);
534 eina_stringshare_del(msg_ref_id);
535 eina_stringshare_del(msg_id);
538 void WebApplication::OnOrientationLock(WebView* view,
540 int preferred_rotation) {
541 if (view_stack_.size() == 0)
544 // Only top-most view can set the orientation relate operation
545 if (view_stack_.front() != view)
548 auto orientaion_setting = app_data_->setting_info() != NULL ?
549 app_data_->setting_info()->screen_orientation() :
550 // TODO(sngn.lee): check default value
551 wgt::parse::SettingInfo::ScreenOrientation::AUTO;
552 if (orientaion_setting != wgt::parse::SettingInfo::ScreenOrientation::AUTO) {
557 window_->SetRotationLock(preferred_rotation);
559 window_->SetAutoRotation();
563 void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) {
564 bool enabled = app_data_->setting_info() != NULL ?
565 app_data_->setting_info()->hwkey_enabled() :
567 if (enabled && kKeyNameBack == keyname) {
568 view->EvalJavascript(kBackKeyEventScript);
572 void WebApplication::OnLanguageChanged() {
573 locale_manager_->UpdateSystemLocale();
574 ewk_context_cache_clear(ewk_context_);
575 auto it = view_stack_.begin();
576 for ( ; it != view_stack_.end(); ++it) {
581 void WebApplication::OnConsoleMessage(const std::string& msg, int level) {
582 static bool enabled = (getenv(kConsoleLogEnableKey) != NULL);
584 if (debug_mode_ || enabled) {
585 int dlog_level = DLOG_DEBUG;
587 case EWK_CONSOLE_MESSAGE_LEVEL_WARNING:
588 dlog_level = DLOG_WARN;
590 case EWK_CONSOLE_MESSAGE_LEVEL_ERROR:
591 dlog_level = DLOG_ERROR;
594 dlog_level = DLOG_DEBUG;
597 LOG_(LOG_ID_MAIN, dlog_level, kConsoleMessageLogTag, "%s", msg.c_str());
601 void WebApplication::OnLowMemory() {
602 ewk_context_cache_clear(ewk_context_);
603 ewk_context_notify_low_memory(ewk_context_);
606 bool WebApplication::OnContextMenuDisabled(WebView* /*view*/) {
607 return !(app_data_->setting_info() != NULL ?
608 app_data_->setting_info()->context_menu_enabled() :
612 void WebApplication::OnLoadStart(WebView* /*view*/) {
613 LOGGER(DEBUG) << "LoadStart";
615 void WebApplication::OnLoadFinished(WebView* /*view*/) {
616 LOGGER(DEBUG) << "LoadFinished";
618 void WebApplication::OnRendered(WebView* /*view*/) {
619 LOGGER(DEBUG) << "Rendered";
622 void WebApplication::LaunchInspector(wrt::AppControl* appcontrol) {
624 ewk_context_inspector_server_start(ewk_context_, 0);
625 std::stringstream ss;
627 std::map<std::string, std::vector<std::string>> data;
628 data[kPortKey] = { ss.str() };
629 appcontrol->Reply(data);
632 void WebApplication::SetupWebView(WebView* view) {
633 view->SetEventListener(this);
634 // TODO(sngn.lee): set UserAgent to WebView
635 // TODO(sngn.lee): set CSP
638 bool WebApplication::OnDidNavigation(WebView* /*view*/,
639 const std::string& /*url*/) {
640 // TODO(sngn.lee): scheme handling
641 // except(file , http, https, app) pass to appcontrol and return false
645 void WebApplication::OnNotificationPermissionRequest(
647 const std::string& url,
648 std::function<void(bool)> result_handler) {
649 auto db = AppDB::GetInstance();
650 std::string reminder = db->Get(kDBPrivateSection,
651 kNotificationPermissionPrefix + url);
652 if (reminder == "allowed") {
653 result_handler(true);
654 } else if (reminder == "denied") {
655 result_handler(false);
658 // Local Domain: Grant permission if defined, otherwise Popup user prompt.
659 // Remote Domain: Popup user prompt.
660 if (utils::StartsWith(url, "file://") &&
661 FindPrivilege(app_data_.get(), kNotificationPrivilege)) {
662 result_handler(true);
666 Popup* popup = Popup::CreatePopup(window_);
667 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
668 popup->SetTitle(popup_string::kPopupTitleWebNotification);
669 popup->SetBody(popup_string::kPopupBodyWebNotification);
670 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
671 popup->SetResultHandler(
672 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
673 bool result = popup->GetButtonResult();
674 bool remember = popup->GetCheckBoxResult();
676 db->Set(kDBPrivateSection, kNotificationPermissionPrefix + url,
677 result ? "allowed" : "denied");
679 result_handler(result);
684 void WebApplication::OnGeolocationPermissionRequest(
686 const std::string& url,
687 std::function<void(bool)> result_handler) {
688 auto db = AppDB::GetInstance();
689 std::string reminder = db->Get(kDBPrivateSection,
690 kGeolocationPermissionPrefix + url);
691 if (reminder == "allowed") {
692 result_handler(true);
693 } else if (reminder == "denied") {
694 result_handler(false);
697 // Local Domain: Grant permission if defined, otherwise block execution.
698 // Remote Domain: Popup user prompt if defined, otherwise block execution.
699 if (!FindPrivilege(app_data_.get(), kLocationPrivilege)) {
700 result_handler(false);
704 if (utils::StartsWith(url, "file://")) {
705 result_handler(true);
709 Popup* popup = Popup::CreatePopup(window_);
710 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
711 popup->SetTitle(popup_string::kPopupTitleGeoLocation);
712 popup->SetBody(popup_string::kPopupBodyGeoLocation);
713 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
714 popup->SetResultHandler(
715 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
716 bool result = popup->GetButtonResult();
717 bool remember = popup->GetCheckBoxResult();
719 db->Set(kDBPrivateSection, kGeolocationPermissionPrefix + url,
720 result ? "allowed" : "denied");
722 result_handler(result);
728 void WebApplication::OnQuotaExceed(
730 const std::string& url,
731 std::function<void(bool)> result_handler) {
732 auto db = AppDB::GetInstance();
733 std::string reminder = db->Get(kDBPrivateSection,
734 kQuotaPermissionPrefix + url);
735 if (reminder == "allowed") {
736 result_handler(true);
737 } else if (reminder == "denied") {
738 result_handler(false);
741 // Local Domain: Grant permission if defined, otherwise Popup user prompt.
742 // Remote Domain: Popup user prompt.
743 if (utils::StartsWith(url, "file://") &&
744 FindPrivilege(app_data_.get(), kStoragePrivilege)) {
745 result_handler(true);
749 Popup* popup = Popup::CreatePopup(window_);
750 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
751 popup->SetTitle(popup_string::kPopupTitleWebStorage);
752 popup->SetBody(popup_string::kPopupBodyWebStorage);
753 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
754 popup->SetResultHandler(
755 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
756 bool result = popup->GetButtonResult();
757 bool remember = popup->GetCheckBoxResult();
759 db->Set(kDBPrivateSection, kQuotaPermissionPrefix + url,
760 result ? "allowed" : "denied");
762 result_handler(result);
767 void WebApplication::OnAuthenticationRequest(
769 const std::string& /*url*/,
770 const std::string& /*message*/,
771 std::function<void(bool submit,
772 const std::string& id,
773 const std::string& password)
775 Popup* popup = Popup::CreatePopup(window_);
776 popup->SetButtonType(Popup::ButtonType::LoginCancelButton);
777 popup->SetFirstEntry(popup_string::kPopupLabelAuthusername,
778 Popup::EntryType::Edit);
779 popup->SetSecondEntry(popup_string::kPopupLabelPassword,
780 Popup::EntryType::PwEdit);
781 popup->SetTitle(popup_string::kPopupTitleAuthRequest);
782 popup->SetBody(popup_string::kPopupBodyAuthRequest);
783 popup->SetResultHandler(
784 [result_handler](Popup* popup, void* /*user_data*/) {
785 bool result = popup->GetButtonResult();
786 std::string id = popup->GetFirstEntryResult();
787 std::string passwd = popup->GetSecondEntryResult();
788 result_handler(result, id, passwd);
793 void WebApplication::OnCertificateAllowRequest(
795 const std::string& /*url*/,
796 const std::string& pem,
797 std::function<void(bool allow)> result_handler) {
798 auto db = AppDB::GetInstance();
799 std::string reminder = db->Get(kDBPrivateSection,
800 kCertificateAllowPrefix + pem);
801 if (reminder == "allowed") {
802 result_handler(true);
803 } else if (reminder == "denied") {
804 result_handler(false);
807 Popup* popup = Popup::CreatePopup(window_);
808 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
809 popup->SetTitle(popup_string::kPopupTitleCert);
810 popup->SetBody(popup_string::kPopupBodyCert);
811 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
812 popup->SetResultHandler(
813 [db, result_handler, pem](Popup* popup, void* /*user_data*/) {
814 bool result = popup->GetButtonResult();
815 bool remember = popup->GetCheckBoxResult();
817 db->Set(kDBPrivateSection, kCertificateAllowPrefix + pem,
818 result ? "allowed" : "denied");
820 result_handler(result);
826 void WebApplication::HandleDBusMethod(GDBusConnection* /*connection*/,
827 const std::string& method_name,
828 GVariant* parameters,
829 GDBusMethodInvocation* invocation) {
830 if (method_name == kMethodNotifyEPCreated) {
831 LOGGER(DEBUG) << "Received 'NotifyEPCreated' from ExtensionServer.";
832 } else if (method_name == kMethodGetRuntimeVariable) {
835 g_variant_get(parameters, "(&s)", &key);
836 if (g_strcmp0(key, "runtime_name") == 0) {
837 value = std::string("wrt");
838 } else if (g_strcmp0(key, "app_id") == 0) {
839 // TODO(wy80.choi): TEC requries double quotes,
840 // but webapi-plugins doesn't. It should be fixed.
841 value = "\"" + appid_ + "\"";
842 } else if (g_strcmp0(key, "encoded_bundle") == 0) {
843 value = received_appcontrol_->encoded_bundle();
845 g_dbus_method_invocation_return_value(
846 invocation, g_variant_new("(s)", value.c_str()));