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.
18 #include "runtime/web_application.h"
22 #include <ewk_chromium.h>
29 #include "common/logger.h"
30 #include "common/constants.h"
31 #include "common/command_line.h"
32 #include "common/string_utils.h"
33 #include "runtime/native_window.h"
34 #include "runtime/web_view.h"
35 #include "runtime/vibration_manager.h"
36 #include "common/app_control.h"
37 #include "common/locale_manager.h"
38 #include "common/application_data.h"
39 #include "common/resource_manager.h"
40 #include "common/app_db.h"
41 #include "runtime/notification_manager.h"
42 #include "runtime/popup.h"
43 #include "runtime/popup_string.h"
48 // TODO(sngn.lee) : It should be declare in common header
49 const char* kKeyNameBack = "back";
51 const char* kConsoleLogEnableKey = "WRT_CONSOLE_LOG_ENABLE";
52 const char* kConsoleMessageLogTag = "ConsoleMessage";
54 const char* kDebugKey = "debug";
55 const char* kPortKey = "port";
57 // TODO(wy80.choi): consider 64bits system.
58 const char* kInjectedBundlePath = "/usr/lib/libwrt-injected-bundle.so";
59 const char* kDBusIntrospectionXML =
61 " <interface name='org.tizen.wrt.Application'>"
62 " <method name='NotifyEPCreated'>"
63 " <arg name='status' type='s' direction='in'/>"
65 " <method name='GetRuntimeVariable'>"
66 " <arg name='key' type='s' direction='in' />"
67 " <arg name='value' type='s' direction='out' />"
71 const char* kAppControlEventScript = \
73 "var __event = document.createEvent(\"CustomEvent\");\n"
74 "__event.initCustomEvent(\"appcontrol\", true, true);\n"
75 "document.dispatchEvent(__event);\n"
77 "for (var i=0; i < window.frames.length; i++)\n"
78 "{ window.frames[i].document.dispatchEvent(__event); }"
80 const char* kBackKeyEventScript = \
82 "var __event = document.createEvent(\"CustomEvent\");\n"
83 "__event.initCustomEvent(\"tizenhwkey\", true, true);\n"
84 "__event.keyName = \"back\";\n"
85 "document.dispatchEvent(__event);\n"
87 "for (var i=0; i < window.frames.length; i++)\n"
88 "{ window.frames[i].document.dispatchEvent(__event); }"
90 const char* kFullscreenPrivilege = "http://tizen.org/privilege/fullscreen";
91 const char* kFullscreenFeature = "fullscreen";
92 const char* kNotificationPrivilege =
93 "http://tizen.org/privilege/notification";
94 const char* kLocationPrivilege =
95 "http://tizen.org/privilege/location";
96 const char* kStoragePrivilege =
97 "http://tizen.org/privilege/unlimitedstorage";
98 const char* kNotiIconFile = "noti_icon.png";
100 const char* kVisibilitySuspendFeature = "visibility,suspend";
101 const char* kMediastreamRecordFeature = "mediastream,record";
102 const char* kEncryptedDatabaseFeature = "encrypted,database";
103 const char* kRotationLockFeature = "rotation,lock";
104 const char* kBackgroundMusicFeature = "background,music";
105 const char* kSoundModeFeature = "sound,mode";
106 const char* kBackgroundVibrationFeature = "background,vibration";
107 const char* kGeolocationPermissionPrefix = "__WRT_GEOPERM_";
108 const char* kNotificationPermissionPrefix = "__WRT_NOTIPERM_";
109 const char* kQuotaPermissionPrefix = "__WRT_QUOTAPERM_";
110 const char* kCertificateAllowPrefix = "__WRT_CERTIPERM_";
111 const char* kDBPrivateSection = "private";
114 bool FindPrivilege(wrt::ApplicationData* app_data,
115 const std::string& privilege) {
116 if (app_data->permissions_info().get() == NULL)
118 auto it = app_data->permissions_info()->GetAPIPermissions().begin();
119 auto end = app_data->permissions_info()->GetAPIPermissions().end();
120 for ( ; it != end; ++it) {
121 if (*it == privilege)
127 void ExecExtensionProcess(const std::string& uuid) {
129 if ((pid = fork()) < 0) {
130 LOGGER(ERROR) << "Failed to fork child process for extension process.";
133 CommandLine* cmd = CommandLine::ForCurrentProcess();
134 std::string switch_ext("--");
135 switch_ext.append(kSwitchExtensionServer);
136 execl(cmd->program().c_str(),
137 cmd->program().c_str(), switch_ext.c_str(), uuid.c_str(), NULL);
141 static void SendDownloadRequest(const std::string& url) {
142 wrt::AppControl request;
143 request.set_operation(APP_CONTROL_OPERATION_DOWNLOAD);
144 request.set_uri(url);
145 request.LaunchRequest();
148 static void InitializeNotificationCallback(Ewk_Context* ewk_context,
149 WebApplication* app) {
150 auto show = [](Ewk_Context*,
151 Ewk_Notification* noti,
153 WebApplication* self = static_cast<WebApplication*>(user_data);
156 uint64_t id = ewk_notification_id_get(noti);
157 std::string title(ewk_notification_title_get(noti) ?
158 ewk_notification_title_get(noti) : "");
159 std::string body(ewk_notification_body_get(noti) ?
160 ewk_notification_body_get(noti) : "");
161 std::string icon_path = self->data_path() + "/" + kNotiIconFile;
162 if (!ewk_notification_icon_save_as_png(noti, icon_path.c_str())) {
165 if (NotificationManager::GetInstance()->Show(id, title, body, icon_path))
166 ewk_notification_showed(id);
168 auto hide = [](Ewk_Context*,
171 NotificationManager::GetInstance()->Hide(noti_id);
172 ewk_notification_closed(noti_id, EINA_FALSE);
174 ewk_context_notification_callbacks_set(ewk_context,
180 static Eina_Bool ExitAppIdlerCallback(void* /*data*/) {
182 return ECORE_CALLBACK_CANCEL;
187 WebApplication::WebApplication(
188 NativeWindow* window, std::unique_ptr<ApplicationData> app_data)
191 ewk_context_(ewk_context_new_with_injected_bundle_path(
192 kInjectedBundlePath)),
194 appid_(app_data->app_id()),
195 app_uuid_(utils::GenerateUUID()),
196 locale_manager_(new LocaleManager()),
197 app_data_(std::move(app_data)),
199 std::unique_ptr<char, decltype(std::free)*>
200 path {app_get_data_path(), std::free};
201 app_data_path_ = path.get();
203 resource_manager_.reset(
204 new ResourceManager(app_data_.get(), locale_manager_.get()));
205 resource_manager_->set_base_resource_path(
206 app_data_->application_path());
210 WebApplication::~WebApplication() {
212 ewk_context_delete(ewk_context_);
215 bool WebApplication::Initialize() {
217 ewk_context_cache_model_set(ewk_context_, EWK_CACHE_MODEL_DOCUMENT_BROWSER);
220 auto cookie_manager = ewk_context_cookie_manager_get(ewk_context_);
221 ewk_cookie_manager_accept_policy_set(cookie_manager,
222 EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
224 // set persistent storage path
225 std::string cookie_path = data_path() + ".cookie";
226 ewk_cookie_manager_persistent_storage_set(
227 cookie_manager, cookie_path.c_str(),
228 EWK_COOKIE_PERSISTENT_STORAGE_SQLITE);
230 // vibration callback
231 auto vibration_start_callback = [](uint64_t ms, void*) {
232 platform::VibrationManager::GetInstance()->Start(static_cast<int>(ms));
234 auto vibration_stop_callback = [](void* /*user_data*/) {
235 platform::VibrationManager::GetInstance()->Stop();
237 ewk_context_vibration_client_callbacks_set(ewk_context_,
238 vibration_start_callback,
239 vibration_stop_callback,
242 auto download_callback = [](const char* downloadUrl, void* /*data*/) {
243 SendDownloadRequest(downloadUrl);
245 ewk_context_did_start_download_callback_set(ewk_context_,
248 InitializeNotificationCallback(ewk_context_, this);
250 if (FindPrivilege(app_data_.get(), kFullscreenPrivilege)) {
251 ewk_context_tizen_extensible_api_string_set(ewk_context_,
256 if (app_data_->setting_info() != NULL &&
257 app_data_->setting_info()->background_support_enabled()) {
258 ewk_context_tizen_extensible_api_string_set(ewk_context_,
259 kVisibilitySuspendFeature,
261 ewk_context_tizen_extensible_api_string_set(ewk_context_,
262 kBackgroundMusicFeature,
265 ewk_context_tizen_extensible_api_string_set(ewk_context_,
266 kMediastreamRecordFeature,
268 ewk_context_tizen_extensible_api_string_set(ewk_context_,
269 kEncryptedDatabaseFeature,
271 if (app_data_->setting_info() != NULL &&
272 app_data_->setting_info()->screen_orientation()
273 == wgt::parse::SettingInfo::ScreenOrientation::AUTO) {
274 ewk_context_tizen_extensible_api_string_set(ewk_context_,
275 kRotationLockFeature,
279 if (app_data_->setting_info() != NULL &&
280 app_data_->setting_info()->sound_mode()
281 == wgt::parse::SettingInfo::SoundMode::EXCLUSIVE) {
282 ewk_context_tizen_extensible_api_string_set(ewk_context_,
287 if (app_data_->setting_info() != NULL &&
288 app_data_->setting_info()->background_vibration()) {
289 ewk_context_tizen_extensible_api_string_set(ewk_context_,
290 kBackgroundVibrationFeature,
294 if (app_data_->widget_info() != NULL &&
295 !app_data_->widget_info()->default_locale().empty()) {
296 locale_manager_->SetDefaultLocale(
297 app_data_->widget_info()->default_locale());
300 // TODO(sngn.lee): Find the path of certificate file
301 // ewk_context_certificate_file_set(ewk_context_, .... );
303 // TODO(sngn.lee): find the proxy url
304 // ewk_context_proxy_uri_set(ewk_context_, ... );
307 // TODO(sngn.lee): check csp element in config.xml and enable - "csp"
312 void WebApplication::Launch(std::unique_ptr<wrt::AppControl> appcontrol) {
313 // Start DBus Server for Runtime
314 // TODO(wy80.choi): Should I add PeerCredentials checker?
315 using std::placeholders::_1;
316 using std::placeholders::_2;
317 using std::placeholders::_3;
318 using std::placeholders::_4;
319 dbus_server_.SetIntrospectionXML(kDBusIntrospectionXML);
320 dbus_server_.SetMethodCallback(kDBusInterfaceNameForApplication,
321 std::bind(&WebApplication::HandleDBusMethod, this, _1, _2, _3, _4));
322 dbus_server_.Start(app_uuid_ +
323 "." + std::string(kDBusNameForApplication));
325 // Execute ExtensionProcess
326 ExecExtensionProcess(app_uuid_);
329 WebView* view = new WebView(window_, ewk_context_);
332 // send widget info to injected bundle
333 // TODO(wy80.choi): ewk_send_widget_info should be fixed to receive uuid of
334 // application instead of widget_id.
335 // Currently, uuid is passed as encoded_bundle argument temporarily.
336 ewk_send_widget_info(ewk_context_, appid_.c_str(),
337 elm_config_scale_get(),
341 std::unique_ptr<ResourceManager::Resource> res =
342 resource_manager_->GetStartResource(appcontrol.get());
343 // TODO(wy80.choi): temporary comment for test, remove it later.
344 // view->LoadUrl("file:///home/owner/apps_rw/33CFo0eFJe/"
345 // "33CFo0eFJe.annex/index.html");
346 view->LoadUrl(res->uri());
347 view_stack_.push_front(view);
348 window_->SetContent(view->evas_object());
350 // TODO(sngn.lee): below code only debug code
351 auto callback = [](void*, Evas*, Evas_Object* obj,
354 evas_object_geometry_get(obj, &x, &y, &w, &h);
355 LOGGER(DEBUG) << "resize ! ("
356 << x << ", " << y << ", " << w << ", " << h << ")";
358 evas_object_event_callback_add(view->evas_object(),
359 EVAS_CALLBACK_RESIZE,
362 if (appcontrol->data(kDebugKey) == "true") {
364 LaunchInspector(appcontrol.get());
367 // TODO(sngn.lee): check the below code location.
368 // in Wearable, webkit can render contents before show window
369 // but Mobile, webkit can't render contents before show window
373 received_appcontrol_ = std::move(appcontrol);
376 void WebApplication::AppControl(std::unique_ptr<wrt::AppControl> appcontrol) {
377 std::unique_ptr<ResourceManager::Resource> res =
378 resource_manager_->GetStartResource(appcontrol.get());
379 if (res->should_reset()) {
382 WebView* view = new WebView(window_, ewk_context_);
385 view->LoadUrl(res->uri());
386 view_stack_.push_front(view);
387 window_->SetContent(view->evas_object());
390 SendAppControlEvent();
393 if (!debug_mode_ && appcontrol->data(kDebugKey) == "true") {
395 LaunchInspector(appcontrol.get());
398 received_appcontrol_ = std::move(appcontrol);
401 void WebApplication::SendAppControlEvent() {
402 auto it = view_stack_.begin();
403 while (it != view_stack_.end()) {
404 (*it)->EvalJavascript(kAppControlEventScript);
408 void WebApplication::ClearViewStack() {
409 window_->SetContent(NULL);
410 auto it = view_stack_.begin();
411 for ( ; it != view_stack_.end(); ++it) {
418 void WebApplication::Resume() {
419 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
420 view_stack_.front()->SetVisibility(true);
422 if (app_data_->setting_info() != NULL &&
423 app_data_->setting_info()->background_support_enabled()) {
427 auto it = view_stack_.begin();
428 for ( ; it != view_stack_.end(); ++it) {
433 void WebApplication::Suspend() {
434 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
435 view_stack_.front()->SetVisibility(false);
437 if (app_data_->setting_info() != NULL &&
438 app_data_->setting_info()->background_support_enabled()) {
439 LOGGER(DEBUG) << "gone background (backgroud support enabed)";
443 auto it = view_stack_.begin();
444 for ( ; it != view_stack_.end(); ++it) {
449 void WebApplication::OnCreatedNewWebView(WebView* /*view*/, WebView* new_view) {
450 if (view_stack_.size() > 0 && view_stack_.front() != NULL)
451 view_stack_.front()->SetVisibility(false);
453 SetupWebView(new_view);
454 view_stack_.push_front(new_view);
455 window_->SetContent(new_view->evas_object());
458 void WebApplication::OnClosedWebView(WebView * view) {
459 if (view_stack_.size() == 0)
462 WebView* current = view_stack_.front();
463 if (current == view) {
464 view_stack_.pop_front();
466 auto found = std::find(view_stack_.begin(), view_stack_.end(), view);
467 if (found != view_stack_.end()) {
468 view_stack_.erase(found);
472 if (view_stack_.size() == 0) {
473 if (terminator_ != NULL) {
476 } else if (current != view_stack_.front()) {
477 view_stack_.front()->SetVisibility(true);
478 window_->SetContent(view_stack_.front()->evas_object());
481 // Delete after the callback context(for ewk view) was not used
482 ecore_idler_add([](void* view) {
483 WebView* obj = static_cast<WebView*>(view);
489 void WebApplication::OnReceivedWrtMessage(
491 Ewk_IPC_Wrt_Message_Data* msg) {
493 Eina_Stringshare* msg_id = ewk_ipc_wrt_message_data_id_get(msg);
494 Eina_Stringshare* msg_ref_id = ewk_ipc_wrt_message_data_reference_id_get(msg);
495 Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(msg);
496 Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg);
498 LOGGER(DEBUG) << "RecvMsg: id = " << msg_id;
499 LOGGER(DEBUG) << "RecvMsg: refid = " << msg_ref_id;
500 LOGGER(DEBUG) << "RecvMsg: type = " << msg_type;
501 LOGGER(DEBUG) << "RecvMsg: value = " << msg_value;
503 #define TYPE_IS(x) (!strcmp(msg_type, x))
504 if (TYPE_IS("tizen://hide")) {
507 } else if (TYPE_IS("tizen://exit")) {
509 ecore_idler_add(ExitAppIdlerCallback, NULL);
510 } else if (TYPE_IS("tizen://changeUA")) {
512 // Change UserAgent of current WebView
514 if (view_stack_.size() > 0 && view_stack_.front() != NULL) {
515 ret = view_stack_.front()->SetUserAgent(std::string(msg_value));
518 Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new();
519 ewk_ipc_wrt_message_data_type_set(ans, msg_type);
520 ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id);
522 ewk_ipc_wrt_message_data_value_set(ans, "success");
524 ewk_ipc_wrt_message_data_value_set(ans, "failed");
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);
529 } else if (TYPE_IS("tizen://test-sync")) {
530 // TODO(wy80.choi): this type should be removed after finish test
531 ewk_ipc_wrt_message_data_value_set(msg, "Reply!!");
532 } else if (TYPE_IS("tizen://test-async")) {
533 // TODO(wy80.choi): this type should be removed after finish test
534 Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new();
535 ewk_ipc_wrt_message_data_type_set(ans, msg_type);
536 ewk_ipc_wrt_message_data_reference_id_set(ans, msg_id);
537 ewk_ipc_wrt_message_data_value_set(ans, "Aync Reply!!");
538 if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) {
539 LOGGER(ERROR) << "Failed to send response";
541 ewk_ipc_wrt_message_data_del(ans);
545 eina_stringshare_del(msg_value);
546 eina_stringshare_del(msg_type);
547 eina_stringshare_del(msg_ref_id);
548 eina_stringshare_del(msg_id);
551 void WebApplication::OnOrientationLock(WebView* view,
553 int preferred_rotation) {
554 if (view_stack_.size() == 0)
557 // Only top-most view can set the orientation relate operation
558 if (view_stack_.front() != view)
561 auto orientaion_setting = app_data_->setting_info() != NULL ?
562 app_data_->setting_info()->screen_orientation() :
563 // TODO(sngn.lee): check default value
564 wgt::parse::SettingInfo::ScreenOrientation::AUTO;
565 if (orientaion_setting != wgt::parse::SettingInfo::ScreenOrientation::AUTO) {
570 window_->SetRotationLock(preferred_rotation);
572 window_->SetAutoRotation();
576 void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) {
577 bool enabled = app_data_->setting_info() != NULL ?
578 app_data_->setting_info()->hwkey_enabled() :
580 if (enabled && kKeyNameBack == keyname) {
581 view->EvalJavascript(kBackKeyEventScript);
585 void WebApplication::OnLanguageChanged() {
586 locale_manager_->UpdateSystemLocale();
587 ewk_context_cache_clear(ewk_context_);
588 auto it = view_stack_.begin();
589 for ( ; it != view_stack_.end(); ++it) {
594 void WebApplication::OnConsoleMessage(const std::string& msg, int level) {
595 static bool enabled = (getenv(kConsoleLogEnableKey) != NULL);
597 if (debug_mode_ || enabled) {
598 int dlog_level = DLOG_DEBUG;
600 case EWK_CONSOLE_MESSAGE_LEVEL_WARNING:
601 dlog_level = DLOG_WARN;
603 case EWK_CONSOLE_MESSAGE_LEVEL_ERROR:
604 dlog_level = DLOG_ERROR;
607 dlog_level = DLOG_DEBUG;
610 LOG_(LOG_ID_MAIN, dlog_level, kConsoleMessageLogTag, "%s", msg.c_str());
614 void WebApplication::OnLowMemory() {
615 ewk_context_cache_clear(ewk_context_);
616 ewk_context_notify_low_memory(ewk_context_);
619 bool WebApplication::OnContextMenuDisabled(WebView* /*view*/) {
620 return !(app_data_->setting_info() != NULL ?
621 app_data_->setting_info()->context_menu_enabled() :
625 void WebApplication::OnLoadStart(WebView* /*view*/) {
626 LOGGER(DEBUG) << "LoadStart";
628 void WebApplication::OnLoadFinished(WebView* /*view*/) {
629 LOGGER(DEBUG) << "LoadFinished";
631 void WebApplication::OnRendered(WebView* /*view*/) {
632 LOGGER(DEBUG) << "Rendered";
635 void WebApplication::LaunchInspector(wrt::AppControl* appcontrol) {
637 ewk_context_inspector_server_start(ewk_context_, 0);
638 std::stringstream ss;
640 std::map<std::string, std::vector<std::string>> data;
641 data[kPortKey] = { ss.str() };
642 appcontrol->Reply(data);
645 void WebApplication::SetupWebView(WebView* view) {
646 view->SetEventListener(this);
647 // TODO(sngn.lee): set UserAgent to WebView
648 // TODO(sngn.lee): set CSP
651 bool WebApplication::OnDidNavigation(WebView* /*view*/,
652 const std::string& /*url*/) {
653 // TODO(sngn.lee): scheme handling
654 // except(file , http, https, app) pass to appcontrol and return false
658 void WebApplication::OnNotificationPermissionRequest(
660 const std::string& url,
661 std::function<void(bool)> result_handler) {
662 auto db = AppDB::GetInstance();
663 std::string reminder = db->Get(kDBPrivateSection,
664 kNotificationPermissionPrefix + url);
665 if (reminder == "allowed") {
666 result_handler(true);
667 } else if (reminder == "denied") {
668 result_handler(false);
671 // Local Domain: Grant permission if defined, otherwise Popup user prompt.
672 // Remote Domain: Popup user prompt.
673 if (utils::StartsWith(url, "file://") &&
674 FindPrivilege(app_data_.get(), kNotificationPrivilege)) {
675 result_handler(true);
679 Popup* popup = Popup::CreatePopup(window_);
680 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
681 popup->SetTitle(popup_string::kPopupTitleWebNotification);
682 popup->SetBody(popup_string::kPopupBodyWebNotification);
683 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
684 popup->SetResultHandler(
685 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
686 bool result = popup->GetButtonResult();
687 bool remember = popup->GetCheckBoxResult();
689 db->Set(kDBPrivateSection, kNotificationPermissionPrefix + url,
690 result ? "allowed" : "denied");
692 result_handler(result);
697 void WebApplication::OnGeolocationPermissionRequest(
699 const std::string& url,
700 std::function<void(bool)> result_handler) {
701 auto db = AppDB::GetInstance();
702 std::string reminder = db->Get(kDBPrivateSection,
703 kGeolocationPermissionPrefix + url);
704 if (reminder == "allowed") {
705 result_handler(true);
706 } else if (reminder == "denied") {
707 result_handler(false);
710 // Local Domain: Grant permission if defined, otherwise block execution.
711 // Remote Domain: Popup user prompt if defined, otherwise block execution.
712 if (!FindPrivilege(app_data_.get(), kLocationPrivilege)) {
713 result_handler(false);
717 if (utils::StartsWith(url, "file://")) {
718 result_handler(true);
722 Popup* popup = Popup::CreatePopup(window_);
723 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
724 popup->SetTitle(popup_string::kPopupTitleGeoLocation);
725 popup->SetBody(popup_string::kPopupBodyGeoLocation);
726 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
727 popup->SetResultHandler(
728 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
729 bool result = popup->GetButtonResult();
730 bool remember = popup->GetCheckBoxResult();
732 db->Set(kDBPrivateSection, kGeolocationPermissionPrefix + url,
733 result ? "allowed" : "denied");
735 result_handler(result);
741 void WebApplication::OnQuotaExceed(
743 const std::string& url,
744 std::function<void(bool)> result_handler) {
745 auto db = AppDB::GetInstance();
746 std::string reminder = db->Get(kDBPrivateSection,
747 kQuotaPermissionPrefix + url);
748 if (reminder == "allowed") {
749 result_handler(true);
750 } else if (reminder == "denied") {
751 result_handler(false);
754 // Local Domain: Grant permission if defined, otherwise Popup user prompt.
755 // Remote Domain: Popup user prompt.
756 if (utils::StartsWith(url, "file://") &&
757 FindPrivilege(app_data_.get(), kStoragePrivilege)) {
758 result_handler(true);
762 Popup* popup = Popup::CreatePopup(window_);
763 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
764 popup->SetTitle(popup_string::kPopupTitleWebStorage);
765 popup->SetBody(popup_string::kPopupBodyWebStorage);
766 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
767 popup->SetResultHandler(
768 [db, result_handler, url](Popup* popup, void* /*user_data*/) {
769 bool result = popup->GetButtonResult();
770 bool remember = popup->GetCheckBoxResult();
772 db->Set(kDBPrivateSection, kQuotaPermissionPrefix + url,
773 result ? "allowed" : "denied");
775 result_handler(result);
780 void WebApplication::OnAuthenticationRequest(
782 const std::string& /*url*/,
783 const std::string& /*message*/,
784 std::function<void(bool submit,
785 const std::string& id,
786 const std::string& password)
788 Popup* popup = Popup::CreatePopup(window_);
789 popup->SetButtonType(Popup::ButtonType::LoginCancelButton);
790 popup->SetFirstEntry(popup_string::kPopupLabelAuthusername,
791 Popup::EntryType::Edit);
792 popup->SetSecondEntry(popup_string::kPopupLabelPassword,
793 Popup::EntryType::PwEdit);
794 popup->SetTitle(popup_string::kPopupTitleAuthRequest);
795 popup->SetBody(popup_string::kPopupBodyAuthRequest);
796 popup->SetResultHandler(
797 [result_handler](Popup* popup, void* /*user_data*/) {
798 bool result = popup->GetButtonResult();
799 std::string id = popup->GetFirstEntryResult();
800 std::string passwd = popup->GetSecondEntryResult();
801 result_handler(result, id, passwd);
806 void WebApplication::OnCertificateAllowRequest(
808 const std::string& /*url*/,
809 const std::string& pem,
810 std::function<void(bool allow)> result_handler) {
811 auto db = AppDB::GetInstance();
812 std::string reminder = db->Get(kDBPrivateSection,
813 kCertificateAllowPrefix + pem);
814 if (reminder == "allowed") {
815 result_handler(true);
816 } else if (reminder == "denied") {
817 result_handler(false);
820 Popup* popup = Popup::CreatePopup(window_);
821 popup->SetButtonType(Popup::ButtonType::AllowDenyButton);
822 popup->SetTitle(popup_string::kPopupTitleCert);
823 popup->SetBody(popup_string::kPopupBodyCert);
824 popup->SetCheckBox(popup_string::kPopupCheckRememberPreference);
825 popup->SetResultHandler(
826 [db, result_handler, pem](Popup* popup, void* /*user_data*/) {
827 bool result = popup->GetButtonResult();
828 bool remember = popup->GetCheckBoxResult();
830 db->Set(kDBPrivateSection, kCertificateAllowPrefix + pem,
831 result ? "allowed" : "denied");
833 result_handler(result);
839 void WebApplication::HandleDBusMethod(GDBusConnection* /*connection*/,
840 const std::string& method_name,
841 GVariant* parameters,
842 GDBusMethodInvocation* invocation) {
843 if (method_name == kMethodNotifyEPCreated) {
844 LOGGER(DEBUG) << "Received 'NotifyEPCreated' from ExtensionServer.";
845 } else if (method_name == kMethodGetRuntimeVariable) {
848 g_variant_get(parameters, "(&s)", &key);
849 if (g_strcmp0(key, "runtime_name") == 0) {
850 value = std::string("wrt");
851 } else if (g_strcmp0(key, "app_id") == 0) {
852 // TODO(wy80.choi): TEC requries double quotes,
853 // but webapi-plugins doesn't. It should be fixed.
854 value = "\"" + appid_ + "\"";
855 } else if (g_strcmp0(key, "encoded_bundle") == 0) {
856 value = received_appcontrol_->encoded_bundle();
858 g_dbus_method_invocation_return_value(
859 invocation, g_variant_new("(s)", value.c_str()));