BuildRequires: bison, edje-tools, expat-devel, flex, gettext, gperf, libcap-devel
BuildRequires: libjpeg-turbo-devel, ninja, perl, python3, python3-xml, which
BuildRequires: pkgconfig(capi-appfw-application)
+BuildRequires: pkgconfig(capi-appfw-app-manager)
BuildRequires: pkgconfig(capi-location-manager)
BuildRequires: pkgconfig(capi-media-audio-io)
BuildRequires: pkgconfig(capi-media-camera)
BuildRequires: pkgconfig(libxslt)
BuildRequires: pkgconfig(minizip)
BuildRequires: pkgconfig(mm-player)
+BuildRequires: pkgconfig(notification)
BuildRequires: pkgconfig(nspr)
BuildRequires: pkgconfig(nss)
BuildRequires: pkgconfig(scim)
}
}
+config("capi-appfw-app-manager") {
+ if (is_tizen) {
+ ldflags = [ "-lcapi-appfw-app-manager" ]
+ }
+}
+
+tizen_pkg_config("libcapi-appfw-app-manager") {
+ packages = []
+ if (is_tizen) {
+ packages = [ "capi-appfw-app-manager" ]
+ }
+}
+
config("capi-location-manager") {
if (is_tizen) {
ldflags = [ "-lcapi-location-manager" ]
}
}
+config("notification") {
+ if (is_tizen) {
+ ldflags = [ "-lnotification" ]
+ }
+}
+
+tizen_pkg_config("libnotification") {
+ packages = []
+ if (is_tizen) {
+ packages = [ "notification" ]
+ }
+}
+
config("security-manager") {
if (is_tizen) {
ldflags = [ "-lsecurity-manager-client" ]
#if defined(OS_TIZEN)
#include <appfw/app.h>
+#include <dlfcn.h>
#include <tzplatform_config.h>
+
+#include "base/logging.h"
#endif
namespace {
+
#if defined(OS_TIZEN)
const base::FilePath::CharType kDataPath[] = FILE_PATH_LITERAL(DATA_DIR);
const base::FilePath::CharType kExePath[] = FILE_PATH_LITERAL(EXE_DIR);
const base::FilePath::CharType kApplicationDataDir[] = FILE_PATH_LITERAL("data");
const base::FilePath::CharType kApplicationCacheDir[] = FILE_PATH_LITERAL("cache");
+const base::FilePath::CharType kChromiumLibPath[] =
+ FILE_PATH_LITERAL("lib/" CHROMIUM_IMPL_LIB_FILE);
+const base::FilePath::CharType kNotificationIconDir[] = FILE_PATH_LITERAL("noti");
#endif
+
#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
// FIXME: EWK_BRINGUP definition should be removed.
const base::FilePath::CharType kLocalePath[] = FILE_PATH_LITERAL(LOCALE_DIR);
#endif // !defined(EWK_BRINGUP)
+
const base::FilePath::CharType kEdjePath[] = FILE_PATH_LITERAL(EDJE_DIR);
const base::FilePath::CharType kApplicationName[] = FILE_PATH_LITERAL("chromium-efl");
const base::FilePath::CharType kApplicationDataBaseDir[] = FILE_PATH_LITERAL("db");
return true;
}
+bool GetDirSharedDataTizen(base::FilePath& result) {
+ char* buffer = app_get_shared_data_path();
+
+ if (!buffer) {
+ LOG(ERROR) << "Failed to get shared/data path. "
+ << get_error_message(get_last_result());
+ return false;
+ }
+
+ result = base::FilePath(buffer);
+ free(buffer);
+ return true;
+}
+
bool GetDirChromiumPrivateTizen(base::FilePath& result) {
std::unique_ptr<char, base::FreeDeleter> data_path(app_get_data_path());
if (data_path) {
return false;
cur = cur.Append(kApplicationDataBaseDir);
break;
+#if defined(OS_TIZEN)
+ case DIR_SHARED:
+ if (!GetDirSharedDataTizen(cur))
+ return false;
+ break;
+ case DIR_SHARED_NOTI_ICON:
+ if (!base::PathService::Get(DIR_SHARED, &cur))
+ return false;
+ cur = cur.Append(kNotificationIconDir);
+ break;
+#endif
default:
return false;
}
DIR_DOWNLOADS,
DIR_DOWNLOAD_IMAGE,
DIR_LOCALE,
+ DIR_SHARED,
+ DIR_SHARED_NOTI_ICON,
PATH_END
};
configs += [ "//tizen_src/build:ui-gadget" ]
configs += [ "//tizen_src/build:libui-gadget" ]
public_configs += [ "//tizen_src/build:ui-gadget-public" ]
+ configs += [ "//tizen_src/build:notification" ]
+ configs += [ "//tizen_src/build:libnotification" ]
deps = [
"//base/:base_static",
"//components/autofill/content/browser",
"browser/sound_effect.h",
]
deps += [ "//cc:cc" ]
+ configs += [ "//tizen_src/build:capi-appfw-app-manager" ]
+ configs += [ "//tizen_src/build:libcapi-appfw-app-manager" ]
} else {
if (use_gio) {
configs += [ "//build/linux:gio_config" ]
public_configs += [ "../../build:capi-system-device-public" ]
}
- sources = [
- "browser/notification/notification_controller_efl.cc",
- "browser/notification/notification_controller_efl.h",
- ]
-
if (tizen_autofill_support) {
defines = [ "TIZEN_AUTOFILL_SUPPORT=true" ]
}
libs = [ "atomic" ]
}
- sources += [
+ sources = [
"authentication_challenge_popup.cc",
"authentication_challenge_popup.h",
"autofill_popup_view_efl.cc",
"browser/inputpicker/InputPicker.h",
"browser/inputpicker/color_chooser_efl.cc",
"browser/inputpicker/color_chooser_efl.h",
+ "browser/notification/notification_controller_efl.cc",
+ "browser/notification/notification_controller_efl.h",
+ "browser/notification/notification_helper.cc",
+ "browser/notification/notification_helper.h",
"browser/password_manager/password_manager_client_efl.cc",
"browser/password_manager/password_manager_client_efl.h",
"browser/password_manager/password_store_factory.cc",
#include "browser/notification/notification_controller_efl.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "common/web_contents_utils.h"
+#include "content/common/paths_efl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/persistent_notification_status.h"
#include "eweb_view.h"
+#include "private/ewk_context_private.h"
#include "private/ewk_notification_private.h"
+#include "public/ewk_context.h"
+#include "public/ewk_context_internal.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "ui/gfx/codec/png_codec.h"
+
+#if defined(OS_TIZEN)
+#include <app_control_internal.h>
+#include <app_manager.h>
+#include <notification_internal.h>
+#endif
using web_contents_utils::WebViewFromWebContents;
-using namespace blink::mojom;
+using blink::mojom::PermissionStatus;
namespace content {
-NotificationControllerEfl::NotificationControllerEfl()
- : notification_show_callback_(nullptr)
- , notification_cancel_callback_(nullptr)
- , notification_callback_user_data_(nullptr)
- , weak_factory_(this)
-{
+static const char kPermissionDatabaseName[] = "permissions_db";
+
+#if defined(OS_TIZEN)
+bool SetNotificationImage(notification_h noti,
+ notification_image_type_e type,
+ const SkBitmap& bitmap,
+ const base::FilePath& path) {
+ std::vector<unsigned char> data;
+ if (!gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data)) {
+ LOG(ERROR) << "Bitmap color type " << bitmap.colorType();
+ return false;
+ }
+
+ FILE* f = base::OpenFile(path, "wb");
+ if (!f)
+ return false;
+
+ size_t written = fwrite(&*data.begin(), 1, data.size(), f);
+ base::CloseFile(f);
+ if (written == data.size()) {
+ if (notification_set_image(noti, type, path.value().data()) ==
+ NOTIFICATION_ERROR_NONE) {
+ return true;
+ }
+ LOG(ERROR) << "Failed to set notification image." << path.value();
+ } else {
+ LOG(ERROR) << "Failed to write image file. " << path.value()
+ << ", written size:" << written << "/" << data.size();
+ }
+ base::DeleteFile(path);
+ return false;
}
-NotificationControllerEfl::~NotificationControllerEfl() {
- // notifications_map_.Clear();
+void RemoveImageFiles(const std::string& tag) {
+ base::FilePath image_path;
+ if (!base::PathService::Get(PathsEfl::DIR_SHARED_NOTI_ICON, &image_path)) {
+ LOG(ERROR) << "Failed to retrieve the notification resource path";
+ return;
+ }
+
+ if (tag.empty()) {
+ // Remove all unused icons.
+ base::FileEnumerator enumerator(image_path, false,
+ base::FileEnumerator::FILES);
+ for (base::FilePath file = enumerator.Next(); !file.empty();
+ file = enumerator.Next()) {
+ const std::string file_str = file.BaseName().value();
+ size_t dot_at = file_str.find_last_of('.');
+ if (dot_at != std::string::npos) {
+ notification_h noti =
+ notification_load_by_tag(file_str.substr(0, dot_at).c_str());
+ if (noti)
+ notification_free(noti);
+ else if (!base::DeleteFile(file))
+ LOG(ERROR) << "Failed to delete icon. " << file_str;
+ }
+ }
+ return;
+ }
+
+ if (!base::DeleteFile(image_path.AppendASCII(tag + ".icon"))) {
+ LOG(ERROR) << "Failed to delete icon. "
+ << image_path.AppendASCII(tag).value();
+ }
+ if (!base::DeleteFile(image_path.AppendASCII(tag + ".badge"))) {
+ LOG(ERROR) << "Failed to delete badge. "
+ << image_path.AppendASCII(tag).value();
+ }
}
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
-void NotificationControllerEfl::NotificationAdd(
- uint64_t notification_id,
- const GURL& origin,
- const std::u16string& replace_id,
- std::unique_ptr<DesktopNotificationDelegate> delegate) {
- NotificationData* new_notification(
- new NotificationData(origin, replace_id, std::move(delegate)));
- notifications_map_.AddWithID(new_notification, notification_id);
+
+static void NotificationEventCallback(notification_h noti,
+ int event_type,
+ void* userdata) {
+ auto thiz = static_cast<NotificationControllerEfl*>(userdata);
+ int notification_priv_id = NOTIFICATION_PRIV_ID_NONE;
+ int notification_ret_val = NOTIFICATION_ERROR_NONE;
+
+ notification_ret_val =
+ notification_get_id(noti, nullptr, ¬ification_priv_id);
+ if (notification_ret_val != NOTIFICATION_ERROR_NONE) {
+ LOG(ERROR) << " Can't get notification ID " << notification_ret_val;
+ return;
+ }
+
+ uint64_t notification_id =
+ thiz->default_callback()->FindNotificationID(notification_priv_id);
+ bool ret = false;
+ if (notification_id) {
+ if (event_type == NOTIFICATION_EVENT_TYPE_PRESSED) {
+ ret = thiz->notification_helper()->NotificationClicked(notification_id);
+ } else {
+ ret = thiz->notification_helper()->NotificationClosed(
+ notification_id,
+ event_type != NOTIFICATION_EVENT_TYPE_HIDDEN_BY_TIMEOUT);
+ }
+ }
+
+ const char* tag = nullptr;
+ notification_ret_val = notification_get_tag(noti, &tag);
+ if (tag && notification_ret_val == NOTIFICATION_ERROR_NONE)
+ RemoveImageFiles(tag);
+
+ // TODO: Need to check the invalid case.
+ if (!ret) {
+ LOG(ERROR) << "Failed to handle notification, id:" << notification_id
+ << ", event_type:" << event_type;
+ }
}
-bool NotificationControllerEfl::NotificationClosed(uint64_t notification_id,
- bool by_user) {
+#endif // defined(OS_TIZEN)
+
+PermissionHandler::PermissionHandler() {}
- NotificationData* saved_data = notifications_map_.Lookup(notification_id);
- if (!saved_data)
+PermissionHandler::~PermissionHandler() {}
+
+bool PermissionHandler::InitializePermissionDatabase(bool clear) {
+ if (permissions_db_)
+ return true;
+
+ base::FilePath db_path;
+ if (!base::PathService::Get(PathsEfl::WEB_DATABASE_DIR, &db_path)) {
+ LOG(ERROR) << "Could not get web database directory.";
return false;
+ }
- saved_data->notification_delegate->NotificationClosed();
- notifications_map_.Remove(notification_id);
- return true;
+ db_path = db_path.Append(FILE_PATH_LITERAL(kPermissionDatabaseName));
+ if (clear)
+ base::DeletePathRecursively(db_path);
+
+ leveldb::DB* db;
+ leveldb::Options options;
+ options.create_if_missing = true;
+ leveldb::Status status =
+ leveldb::DB::Open(options, db_path.AsUTF8Unsafe(), &db);
+ if (!status.ok()) {
+ LOG(ERROR) << "Could not open permissions db. " << db_path.AsUTF8Unsafe();
+ return false;
+ }
+
+ permissions_db_.reset(db);
+ // Load permissions from db.
+ if (!clear) {
+ std::unique_ptr<leveldb::Iterator> it(
+ permissions_db_->NewIterator(leveldb::ReadOptions()));
+ for (it->SeekToFirst(); it->Valid(); it->Next()) {
+ GURL origin(it->key().ToString());
+ bool allowed = *(const bool*)(it->value().data());
+ permissions_map_[origin] = allowed;
+ }
+ }
+
+ return (permissions_db_ != nullptr);
}
-#endif
-void NotificationControllerEfl::NotificationCancelled(uint64_t notification_id) {
- // NotificationClosed(notification_id, false);
- if (notification_cancel_callback_) {
- notification_cancel_callback_(notification_id, notification_callback_user_data_);
+
+void PermissionHandler::PutPermission(const GURL& origin, bool allowed) {
+ base::AutoLock locker(permissions_mutex_);
+ auto it = permissions_map_.find(origin);
+ if (it == permissions_map_.end() || it->second != allowed) {
+ permissions_map_[origin] = allowed;
+ if (InitializePermissionDatabase()) {
+ permissions_db_->Put(leveldb::WriteOptions(),
+ origin.possibly_invalid_spec(),
+ leveldb::Slice((const char*)&allowed, sizeof(bool)));
+ }
}
}
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
-bool NotificationControllerEfl::NotificationClicked(uint64_t notification_id) {
- NotificationData* saved_data = notifications_map_.Lookup(notification_id);
- if (!saved_data)
+
+PermissionStatus PermissionHandler::CheckPermissionForOrigin(
+ const GURL& origin) {
+ base::AutoLock locker(permissions_mutex_);
+ InitializePermissionDatabase();
+ PermissionStatus status = PermissionStatus::ASK;
+ auto it = permissions_map_.find(origin);
+ if (it != permissions_map_.end())
+ status = it->second ? PermissionStatus::GRANTED : PermissionStatus::DENIED;
+ return status;
+}
+
+void PermissionHandler::ClearPermissions() {
+ base::AutoLock locker(permissions_mutex_);
+ permissions_map_.clear();
+ permissions_db_.reset();
+ InitializePermissionDatabase(true);
+}
+
+void PermissionHandler::RemovePermissions(Eina_List* origins) {
+ Eina_List* list = nullptr;
+ void* data = nullptr;
+ base::AutoLock locker(permissions_mutex_);
+ if (eina_list_count(origins) > 0)
+ InitializePermissionDatabase();
+
+ EINA_LIST_FOREACH(origins, list, data) {
+ _Ewk_Security_Origin* origin = static_cast<_Ewk_Security_Origin*>(data);
+ if (permissions_map_.erase(origin->GetURL()) && permissions_db_) {
+ permissions_db_->Delete(leveldb::WriteOptions(),
+ origin->GetURL().possibly_invalid_spec());
+ }
+ }
+}
+
+void PermissionHandler::RequestPermission(
+ EWebView* web_view,
+ const GURL& requesting_frame,
+ base::OnceCallback<void(PermissionStatus)> result_callback) {
+ if (!web_view) {
+ LOG(ERROR) << "Dropping PermissionNotification request caused by lack "
+ "of the WebView.";
+ std::move(result_callback).Run(PermissionStatus::DENIED);
+ return;
+ }
+
+ if (!web_view->IsNotificationPermissionCallbackSet()) {
+ LOG(ERROR) << "Dropping PermissionNotification request caused by lack "
+ "of the Notification Permission Callback.";
+ std::move(result_callback).Run(PermissionStatus::DENIED);
+ return;
+ }
+
+ blink::mojom::PermissionStatus web_notification_permission =
+ CheckPermissionForOrigin(requesting_frame);
+
+ switch (web_notification_permission) {
+ case PermissionStatus::LAST:
+ {
+ std::unique_ptr<Ewk_Notification_Permission_Request> notification_permission(
+ new Ewk_Notification_Permission_Request(std::move(result_callback),
+ requesting_frame));
+ web_view->InvokeNotificationPermissionCallback(
+ notification_permission.get());
+ // If policy is suspended, the API takes over the policy object lifetime
+ // and policy will be deleted after decision is made.
+ if (notification_permission->IsSuspended())
+ ignore_result(notification_permission.release());
+ }
+ break;
+ case PermissionStatus::GRANTED:
+ std::move(result_callback).Run(PermissionStatus::GRANTED);
+ break;
+ default:
+ std::move(result_callback).Run(PermissionStatus::DENIED);
+ }
+}
+
+DefaultCallback::DefaultCallback() {}
+
+DefaultCallback::~DefaultCallback() {}
+
+#if defined(OS_TIZEN)
+uint64_t DefaultCallback::FindNotificationID(int notification_priv_id) {
+ for (auto it = key_mapper_.begin(); it != key_mapper_.end(); it++) {
+ if (it->second == notification_priv_id)
+ return it->first;
+ }
+
+ LOG(ERROR) << "Can't find notification ID " << notification_priv_id;
+ return 0;
+}
+#endif // defined(OS_TIZEN)
+
+bool DefaultCallback::ShowCallback(uint64_t tag,
+ const std::string& notification_id,
+ const GURL& origin,
+ const char* title,
+ const char* body,
+ const SkBitmap& icon,
+ const SkBitmap& badge,
+ bool is_persistent) {
+#if defined(OS_TIZEN)
+ auto found = key_mapper_.find(tag);
+ if (found != key_mapper_.end())
+ CancelCallback(tag);
+
+ notification_h noti_h =
+ notification_new(NOTIFICATION_TYPE_NOTI, NOTIFICATION_GROUP_ID_DEFAULT,
+ NOTIFICATION_PRIV_ID_NONE);
+ if (!noti_h) {
+ LOG(ERROR) << "Can't create notification handle.";
return false;
+ }
+
+ std::unique_ptr<std::remove_pointer<notification_h>::type,
+ decltype(notification_free)*>
+ auto_release{noti_h, notification_free};
+
+ // Set notification title.
+ int ret = notification_set_text(noti_h, NOTIFICATION_TEXT_TYPE_TITLE, title,
+ nullptr, NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ LOG(ERROR) << "Can't set title" << ret;
+ return false;
+ }
+
+ // Set notification content.
+ ret = notification_set_text(noti_h, NOTIFICATION_TEXT_TYPE_CONTENT, body,
+ nullptr, NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ LOG(ERROR) << "Can't set content" << ret;
+ return false;
+ }
+
+ base::FilePath noti_path;
+ if (base::PathService::Get(PathsEfl::DIR_SHARED_NOTI_ICON, ¬i_path)) {
+ bool has_images = false;
+ const std::string tag_str = std::to_string(tag);
+
+ if (SetNotificationImage(noti_h, NOTIFICATION_IMAGE_TYPE_ICON, icon,
+ noti_path.AppendASCII(tag_str + ".icon"))) {
+ has_images = true;
+ }
+ if (SetNotificationImage(noti_h, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR,
+ badge,
+ noti_path.AppendASCII(tag_str + ".badge"))) {
+ has_images = true;
+ }
+
+ // Set a tag to remove icon images after closing notification.
+ if (has_images)
+ notification_set_tag(noti_h, tag_str.c_str());
+ } else {
+ LOG(ERROR) << "Failed to retrieve the notification resource path";
+ }
+
+ // Set notification type.
+ ret = notification_set_display_applist(
+ noti_h, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+ NOTIFICATION_DISPLAY_APP_TICKER |
+ NOTIFICATION_DISPLAY_APP_INDICATOR);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ LOG(ERROR) << "notification_set_display_applist is failed with err " << ret;
+ return false;
+ }
- saved_data->notification_delegate->NotificationClick();
- notifications_map_.Remove(notification_id);
+ if (is_persistent) {
+ app_control_h app_control = nullptr;
+ ret = app_control_create(&app_control);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ LOG(ERROR) << "app_control_create is failed with err " << ret;
+ return false;
+ }
+
+ std::unique_ptr<std::remove_pointer<app_control_h>::type,
+ decltype(app_control_destroy)*>
+ auto_release{app_control, app_control_destroy};
+
+ char* app_id = nullptr;
+ int ret = app_manager_get_app_id(getpid(), &app_id);
+ if (ret != APP_MANAGER_ERROR_NONE) {
+ LOG(ERROR) << "app_manager_get_app_id is failed with err " << ret;
+ return false;
+ }
+
+ app_control_set_app_id(app_control, app_id);
+ if (app_id)
+ free(app_id);
+
+ app_control_add_extra_data(app_control, APP_CONTROL_DATA_BACKGROUND_LAUNCH,
+ "enable");
+ app_control_add_extra_data(app_control, "notification_id",
+ notification_id.c_str());
+ app_control_add_extra_data(app_control, "notification_origin",
+ origin.possibly_invalid_spec().c_str());
+
+ ret = notification_set_launch_option(
+ noti_h, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void*)app_control);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ LOG(ERROR) << "notification_set_launch_option is failed with err " << ret;
+ return false;
+ }
+ }
+ // TODO: If application has been killed, currently there is no way to launch
+ // application to run service worker when notification closed. If platform
+ // support new API, we don't need to use |notification_post_with_event_cb|.
+ ret =
+ notification_post_with_event_cb(noti_h, NotificationEventCallback, this);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ LOG(ERROR) << "notification_post_with_event_cb is failed with err " << ret;
+ return false;
+ }
+
+ int notification_priv_id = NOTIFICATION_PRIV_ID_NONE;
+ ret = notification_get_id(noti_h, nullptr, ¬ification_priv_id);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ LOG(ERROR) << "Can't get notification ID " << ret;
+ return false;
+ }
+
+ key_mapper_[tag] = notification_priv_id;
return true;
+#else
+ return false;
+#endif // defined(OS_TIZEN)
}
-bool NotificationControllerEfl::NotificationDisplayed(uint64_t notification_id) {
- NotificationData* saved_data = notifications_map_.Lookup(notification_id);
- if (!saved_data)
+bool DefaultCallback::CancelCallback(uint64_t tag) {
+#if defined(OS_TIZEN)
+ auto found = key_mapper_.find(tag);
+ if (found == key_mapper_.end()) {
+ LOG(ERROR) << "Can't find notification.";
return false;
+ }
- saved_data->notification_delegate->NotificationDisplayed();
+ notification_delete_by_priv_id(nullptr, NOTIFICATION_TYPE_NOTI,
+ found->second);
+ key_mapper_.erase(found);
return true;
+#else
+ return false;
+#endif // defined(OS_TIZEN)
}
+
+NotificationControllerEfl::NotificationControllerEfl()
+ : permission_handler_(std::make_unique<PermissionHandler>()),
+ default_callback_(std::make_unique<DefaultCallback>()),
+ notification_helper_(std::make_unique<NotificationHelper>()) {}
+
+NotificationControllerEfl::~NotificationControllerEfl() {
+#if defined(OS_TIZEN)
+ RemoveImageFiles(std::string());
#endif
+}
-blink::mojom::PermissionStatus NotificationControllerEfl::CheckPermissionOnIOThread(
+void NotificationControllerEfl::NotificationCancelled(
+ uint64_t notification_id) {
+ notification_helper_->NotificationClosed(notification_id, false);
+ if (notification_cancel_callback_) {
+ notification_cancel_callback_(notification_id,
+ notification_callback_user_data_);
+ } else {
+ default_callback_->CancelCallback(notification_id);
+ }
+}
+
+blink::mojom::PermissionStatus
+NotificationControllerEfl::CheckPermissionOnIOThread(
ResourceContext* resource_context,
const GURL& origin,
int render_process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return CheckPermissionForOrigin(origin);
+ return permission_handler_->CheckPermissionForOrigin(origin);
}
void NotificationControllerEfl::DisplayNotification(
const GURL& document_url,
const blink::PlatformNotificationData& notification_data,
const blink::NotificationResources& notification_resources) {
-#if !defined(EWK_BRINGUP) // FIXME: m76 bringup
- BrowserContextEfl* browser_context_efl =
- static_cast<BrowserContextEfl*>(browser_context);
- CHECK(browser_context_efl);
- EWebContext* ctx = browser_context_efl->WebContext();
- CHECK(ctx);
-
- bool has_callbacks = ctx->HasNotificationCallbacks()
- || (notification_show_callback_ && notification_cancel_callback_);
- if (!has_callbacks) {
- delegate->NotificationClosed();
+ if (!web_view_ || !web_view_->context() ||
+ !web_view_->context()->browser_context()) {
+ LOG(ERROR) << "Dropping DisplayNotification request caused by lack "
+ "of the WebView.";
return;
}
- uint64_t replaceUniqueId = 0;
- if (!notification_data.tag.empty() &&
- IsNotificationPresent(origin,
- base::UTF8ToUTF16(notification_data.tag), replaceUniqueId)) {
- if (!ctx->NotificationCancelCallback(replaceUniqueId))
- NotificationCancelled(replaceUniqueId);
- else
- NotificationClosed(replaceUniqueId, false);
+ EWebContext* ctx = web_view_->context()->browser_context()->WebContext();
+ CHECK(ctx);
+
+ bool has_callbacks =
+ ctx->HasNotificationCallbacks() ||
+ (notification_show_callback_ && notification_cancel_callback_);
+
+ uint64_t replace_unique_id = 0;
+ if (notification_helper_->IsNotificationPresent(origin, notification_id,
+ replace_unique_id)) {
+ if (!has_callbacks)
+ default_callback_->CancelCallback(replace_unique_id);
+ else if (!ctx->NotificationCancelCallback(replace_unique_id))
+ NotificationCancelled(replace_unique_id);
+
+ notification_helper_->NotificationClosed(replace_unique_id, false);
}
- uint64_t notificationUniqueId = reinterpret_cast<uint64_t>(delegate.get());
- NotificationAdd(notificationUniqueId, origin,
- base::UTF8ToUTF16(notification_data.tag),
- std::move(delegate));
+ uint64_t notification_unique_id = base::Hash(notification_id);
- if (cancel_callback)
- *cancel_callback =
- base::BindOnce(&NotificationControllerEfl::NotificationCancelled,
- weak_factory_.GetWeakPtr(), notificationUniqueId);
+ notification_helper_->SetNotification(origin, notification_id,
+ notification_unique_id);
- Ewk_Notification* notification =
- new Ewk_Notification(base::UTF16ToUTF8(notification_data.body),
- notification_data.tag,
- base::UTF16ToUTF8(notification_data.title),
- notification_resources.notification_icon,
- notification_data.silent,
- notificationUniqueId,
- origin);
+ Ewk_Notification notification(base::UTF16ToUTF8(notification_data.body),
+ base::UTF16ToUTF8(notification_data.title),
+ notification_resources.notification_icon,
+ notification_data.silent,
+ notification_unique_id, origin);
- if (!ctx->NotificationShowCallback(notification))
- notification_show_callback_(notification, notification_callback_user_data_);
+ if (!has_callbacks) {
+ default_callback_->ShowCallback(notification_unique_id, notification_id,
+ origin, notification.GetTitle(),
+ notification.GetBody(),
+ notification_resources.notification_icon,
+ notification_resources.badge, false);
+ notification_helper_->NotificationDisplayed(notification_unique_id);
+ } else if (!ctx->NotificationShowCallback(¬ification)) {
+ notification_show_callback_(¬ification,
+ notification_callback_user_data_);
+ }
+}
- delete notification;
-#endif
+void NotificationControllerEfl::CloseNotification(
+ const std::string& notification_id) {
+ NOTIMPLEMENTED();
+}
+
+int64_t NotificationControllerEfl::ReadNextPersistentNotificationId() {
+ NOTIMPLEMENTED();
+ return -1;
}
void NotificationControllerEfl::DisplayPersistentNotification(
const GURL& origin,
const blink::PlatformNotificationData& notification_data,
const blink::NotificationResources& notification_resources) {
- NOTIMPLEMENTED();
-}
-
-void NotificationControllerEfl::ClosePersistentNotification(
- const std::string& notification_id) {
- NOTIMPLEMENTED();
-}
+ if (!web_view_ || !web_view_->context() ||
+ !web_view_->context()->browser_context()) {
+ LOG(ERROR) << "Dropping DisplayNotification request caused by lack "
+ "of the WebView.";
+ return;
+ }
+ EWebContext* ctx = web_view_->context()->browser_context()->WebContext();
+ CHECK(ctx);
-void NotificationControllerEfl::SetPermissionForNotification(
- Ewk_Notification_Permission_Request* notification, bool isAllowed) {
+ bool has_callbacks =
+ ctx->HasNotificationCallbacks() ||
+ (notification_show_callback_ && notification_cancel_callback_);
- EWebView* wv = EWebView::FromEvasObject(notification->GetWebviewEvasObject());
- DCHECK(wv);
- RenderViewHost* render_view_host =
- wv->web_contents().GetRenderViewHost();
+ uint64_t replace_unique_id = 0;
+ if (notification_helper_->IsPersistentNotificationPresent(
+ origin, notification_id, replace_unique_id)) {
+ if (!has_callbacks)
+ default_callback_->CancelCallback(replace_unique_id);
+ else if (!ctx->NotificationCancelCallback(replace_unique_id))
+ NotificationCancelled(replace_unique_id);
- if (render_view_host) {
- GURL origin = notification->GetSecurityOrigin()->GetURL();
- // save decision in permissions map
- permissions_mutex_.Acquire();
- permissions_map_[origin] = isAllowed;
- permissions_mutex_.Release();
+ notification_helper_->NotificationClosed(replace_unique_id, false);
}
-}
-void NotificationControllerEfl::AddPermission(const GURL origin,
- bool allowed) {
- base::AutoLock locker(permissions_mutex_);
- permissions_map_[origin] = allowed;
-}
+ uint64_t notification_unique_id = base::Hash(notification_id);
-blink::mojom::PermissionStatus
-NotificationControllerEfl::CheckPermissionForOrigin(
- const GURL &origin) const {
- base::AutoLock locker(permissions_mutex_);
- std::map<GURL, bool>::const_iterator it = permissions_map_.find(origin);
- if (it == permissions_map_.end())
- return blink::mojom::PermissionStatus::ASK;
- return it->second ?
- blink::mojom::PermissionStatus::GRANTED :
- blink::mojom::PermissionStatus::DENIED;
+ notification_helper_->SetPersistentNotification(
+ web_view_->context()->browser_context(), origin, notification_id,
+ notification_unique_id);
+
+ Ewk_Notification notification(base::UTF16ToUTF8(notification_data.body),
+ base::UTF16ToUTF8(notification_data.title),
+ notification_resources.notification_icon,
+ notification_data.silent,
+ notification_unique_id, origin);
+
+ if (!has_callbacks) {
+ default_callback_->ShowCallback(notification_unique_id, notification_id,
+ origin, notification.GetTitle(),
+ notification.GetBody(),
+ notification_resources.notification_icon,
+ notification_resources.badge, true);
+ } else if (!ctx->NotificationShowCallback(¬ification)) {
+ notification_show_callback_(¬ification,
+ notification_callback_user_data_);
+ }
}
-void NotificationControllerEfl::ClearPermissions() {
- base::AutoLock locker(permissions_mutex_);
- permissions_map_.clear();
+void NotificationControllerEfl::ClosePersistentNotification(
+ const std::string& notification_id) {
+ NOTIMPLEMENTED();
}
-void NotificationControllerEfl::RemovePermissions(Eina_List* origins) {
- Eina_List* list = NULL;
- void* data = NULL;
- base::AutoLock locker(permissions_mutex_);
- EINA_LIST_FOREACH(origins, list, data) {
- _Ewk_Security_Origin* origin = static_cast<_Ewk_Security_Origin*>(data);
- permissions_map_.erase(origin->GetURL());
- }
+void NotificationControllerEfl::GetDisplayedNotifications(
+ DisplayedNotificationsCallback callback) {
+ NOTIMPLEMENTED();
}
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
-bool NotificationControllerEfl::IsNotificationPresent(
- const GURL& origin,
- const std::u16string& replaceid,
- uint64_t& notification_id) {
- IDMap<NotificationData, IDMapOwnPointer>::const_iterator it(¬ifications_map_);
- for (; !it.IsAtEnd(); it.Advance()) {
- if (replaceid == it.GetCurrentValue()->replace_id &&
- origin.spec() == it.GetCurrentValue()->origin_url) {
- notification_id = it.GetCurrentKey();
- return true;
- }
+void NotificationControllerEfl::SetPermissionForNotification(
+ Ewk_Notification_Permission_Request* notification,
+ bool allowed) {
+ GURL origin = notification->GetSecurityOrigin()->GetURL();
+
+ if (web_view_) {
+ Ewk_Notification_Permission permission;
+ permission.origin = origin.possibly_invalid_spec().c_str();
+ permission.allowed = allowed;
+ web_view_->SmartCallback<EWebViewCallbacks::NotificationPermissionReply>()
+ .call(&permission);
}
- return false;
+ // Save decision in permissions map.
+ permission_handler_->PutPermission(origin, allowed);
}
-#endif
void NotificationControllerEfl::RequestPermission(
WebContents* web_contents,
const GURL& requesting_frame,
base::OnceCallback<void(PermissionStatus)> result_callback) {
- EWebView* web_view = WebViewFromWebContents(web_contents);
- if (!web_view) {
- LOG(ERROR) << "Dropping PermissionNotification request caused by lack "
- "of the WebView";
- std::move(result_callback).Run(PermissionStatus::DENIED);
- return;
- }
- std::unique_ptr<Ewk_Notification_Permission_Request> notification_permission(
- new Ewk_Notification_Permission_Request(web_view->evas_object(),
- std::move(result_callback),
- requesting_frame));
-
- if (!web_view->IsNotificationPermissionCallbackSet()) {
- LOG(ERROR) << "Dropping PermissionNotification request caused by lack "
- "of the Notification Permission Callback";
- std::move(result_callback).Run(PermissionStatus::DENIED);
- return;
- }
-
- blink::mojom::PermissionStatus web_notification_permission =
- CheckPermissionForOrigin(requesting_frame);
- if (web_notification_permission ==
- blink::mojom::PermissionStatus::LAST) {
- web_view->InvokeNotificationPermissionCallback(
- notification_permission.get());
- // if policy is suspended, the API takes over the policy object lifetime
- // and policy will be deleted after decision is made
- if (notification_permission->IsSuspended()) {
- ignore_result(notification_permission.release());
- return;
- }
- } else {
- if (web_notification_permission == blink::mojom::PermissionStatus::GRANTED) {
- std::move(result_callback).Run(PermissionStatus::GRANTED);
- } else {
- std::move(result_callback).Run(PermissionStatus::DENIED);
- }
- }
+ web_view_ = WebViewFromWebContents(web_contents);
+ permission_handler_->RequestPermission(web_view_, requesting_frame,
+ std::move(result_callback));
}
-void NotificationControllerEfl::SetNotificationCallbacks(Ewk_Notification_Show_Callback show_callback, Ewk_Notification_Cancel_Callback cancel_callback, void* user_data) {
+void NotificationControllerEfl::SetNotificationCallbacks(
+ Ewk_Notification_Show_Callback show_callback,
+ Ewk_Notification_Cancel_Callback cancel_callback,
+ void* user_data) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
notification_show_callback_ = show_callback;
notification_cancel_callback_ = cancel_callback;
notification_callback_user_data_ = user_data;
}
-}//namespace
+void NotificationControllerEfl::ScheduleTrigger(base::Time timestamp) {
+ NOTIMPLEMENTED();
+}
+
+base::Time NotificationControllerEfl::ReadNextTriggerTimestamp() {
+ NOTIMPLEMENTED();
+ return base::Time::Max();
+}
+
+void NotificationControllerEfl::RecordNotificationUkmEvent(
+ const NotificationDatabaseData& data) {
+ NOTIMPLEMENTED();
+}
+
+} // namespace content
+
#include <Eina.h>
-#include "base/containers/id_map.h"
-#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
+#include "browser/notification/notification_helper.h"
#include "content/public/browser/platform_notification_service.h"
#include "content/public/browser/resource_context.h"
#include "public/ewk_notification_internal.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
#include "url/gurl.h"
+class EWebView;
+class SkBitmap;
+
+namespace leveldb {
+class DB;
+}
+
namespace content {
class WebContents;
+class BrowserContext;
+
+class PermissionHandler {
+ public:
+ PermissionHandler();
+ ~PermissionHandler();
+
+ // Adds permission to map
+ void PutPermission(const GURL& origin, bool allowed);
+
+ // Removes all stored permissions
+ void ClearPermissions();
+
+ // Removes stored permissions for given origins
+ void RemovePermissions(Eina_List* origins);
+
+ blink::mojom::PermissionStatus CheckPermissionForOrigin(const GURL& origin);
+
+ void RequestPermission(
+ EWebView* web_view,
+ const GURL& requesting_frame,
+ base::OnceCallback<void(blink::mojom::PermissionStatus)>
+ result_callback);
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
-// DesktopNotificationDelegate is not defined
-struct NotificationData {
- const std::string origin_url;
- const std::u16string replace_id;
- std::unique_ptr<DesktopNotificationDelegate> notification_delegate;
-
- NotificationData(const GURL& origin,
- const std::u16string& replaceid,
- std::unique_ptr<DesktopNotificationDelegate> delegate)
- : origin_url(origin.spec()),
- replace_id(replaceid),
- notification_delegate(std::move(delegate)) {}
+ private:
+ bool InitializePermissionDatabase(bool clear = false);
+
+ std::map<GURL, bool> permissions_map_;
+ mutable base::Lock permissions_mutex_;
+ std::unique_ptr<leveldb::DB> permissions_db_;
};
-#endif // !defined(EWK_BRINGUP)
-class NotificationControllerEfl: public PlatformNotificationService {
+
+class DefaultCallback {
public:
- NotificationControllerEfl();
- ~NotificationControllerEfl();
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
- // DesktopNotificationDelegate is not defined
- // Adds a new notification received from engine to a list
- void NotificationAdd(uint64_t notification_id,
- const GURL& origin,
- const std::u16string& replace_id,
- std::unique_ptr<DesktopNotificationDelegate> delegate);
-
- bool NotificationClosed(uint64_t notification_id, bool by_user);
+ DefaultCallback();
+ ~DefaultCallback();
+#if defined(OS_TIZEN)
+ uint64_t FindNotificationID(int notification_priv_id);
#endif
+ bool ShowCallback(uint64_t tag,
+ const std::string& notification_id,
+ const GURL& origin,
+ const char* title,
+ const char* body,
+ const SkBitmap& icon,
+ const SkBitmap& badge,
+ bool is_persistent);
+ bool CancelCallback(uint64_t tag);
+
+ private:
+ std::map<uint64_t, int> key_mapper_;
+};
+
+class NotificationControllerEfl : public PlatformNotificationService {
+ public:
+ NotificationControllerEfl();
+ ~NotificationControllerEfl() override;
+
void NotificationCancelled(uint64_t notification_id);
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
- // DesktopNotificationDelegate is not defined
+
+ bool NotificationClosed(uint64_t notification_id, bool by_user) {
+ return notification_helper_->NotificationClosed(notification_id, by_user);
+ }
+
// Notify engine when user clicked on the notification
- bool NotificationClicked(uint64_t notification_id);
+ bool NotificationClicked(uint64_t notification_id) {
+ return notification_helper_->NotificationClicked(notification_id);
+ }
+
+ bool PersistentNotificationClicked(BrowserContext* browser_context,
+ const char* id,
+ const char* origin) {
+ return notification_helper_->PersistentNotificationClicked(browser_context,
+ id, origin);
+ }
+
+ bool NotificationDisplayed(uint64_t notification_id) {
+ return notification_helper_->NotificationDisplayed(notification_id);
+ }
- // Notification engine that notification was displayed
- bool NotificationDisplayed(uint64_t notification_id);
-#endif
// sets the permission for a particular pending notification
void SetPermissionForNotification(
Ewk_Notification_Permission_Request* notification,
- bool isAllowed);
+ bool allowed);
// Adds permission to map
- void AddPermission(const GURL origin, bool allowed);
+ void PutPermission(const GURL& origin, bool allowed) {
+ permission_handler_->PutPermission(origin, allowed);
+ }
// Removes all stored permissions
- void ClearPermissions();
+ void ClearPermissions() { permission_handler_->ClearPermissions(); }
// Removes stored permissions for given origins
- void RemovePermissions(Eina_List* origins);
+ void RemovePermissions(Eina_List* origins) {
+ permission_handler_->RemovePermissions(origins);
+ }
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
- // DesktopNotificationDelegate is not defined
- // Checks if the notification is already present.
- // If present returns the notification id of the notification else false
- bool IsNotificationPresent(const GURL& origin,
- const std::u16string& replaceid,
- uint64_t& notification_id);
-#endif
void RequestPermission(
WebContents* web_contents,
const GURL& requesting_frame,
base::OnceCallback<void(blink::mojom::PermissionStatus)> result_callback);
void SetNotificationCallbacks(Ewk_Notification_Show_Callback show_callback,
- Ewk_Notification_Cancel_Callback close_callback, void* user_data);
+ Ewk_Notification_Cancel_Callback close_callback,
+ void* user_data);
// Checks if |origin| has permission to display Web Notifications. This method
// exists to serve the synchronous IPC required by the Notification.permission
const blink::PlatformNotificationData& notification_data,
const blink::NotificationResources& notification_resources) override;
+ void CloseNotification(const std::string& notification_id) override;
+
+ int64_t ReadNextPersistentNotificationId() override;
+
// Displays the persistent notification described in |notification_data| to
// the user. This method must be called on the UI thread.
void DisplayPersistentNotification(
// Writes the ids of all currently displaying persistent notifications for the
// given |browser_context| to |displayed_notifications|. Returns whether the
// platform is able to provide such a set.
- bool GetDisplayedPersistentNotifications(
- std::set<std::string>* displayed_notifications);
+ void GetDisplayedNotifications(
+ DisplayedNotificationsCallback callback) override;
+
+ void ScheduleTrigger(base::Time timestamp) override;
+ base::Time ReadNextTriggerTimestamp() override;
+ void RecordNotificationUkmEvent(
+ const content::NotificationDatabaseData& data) override;
+ DefaultCallback* default_callback() { return default_callback_.get(); }
+ NotificationHelper* notification_helper() {
+ return notification_helper_.get();
+ }
private:
- blink::mojom::PermissionStatus CheckPermissionForOrigin(
- const GURL &origin) const;
-
- // IDMap<NotificationData, IDMapOwnPointer> notifications_map_; // This stores
- // the notifications displayed to the user
- std::map<GURL, bool> permissions_map_;
- mutable base::Lock permissions_mutex_;
-
- Ewk_Notification_Show_Callback notification_show_callback_;
- Ewk_Notification_Cancel_Callback notification_cancel_callback_;
- void* notification_callback_user_data_;
+ Ewk_Notification_Show_Callback notification_show_callback_ = nullptr;
+ Ewk_Notification_Cancel_Callback notification_cancel_callback_ = nullptr;
+ void* notification_callback_user_data_ = nullptr;
- base::WeakPtrFactory<NotificationControllerEfl> weak_factory_;
+ EWebView* web_view_ = nullptr;
+ std::unique_ptr<PermissionHandler> permission_handler_;
+ std::unique_ptr<DefaultCallback> default_callback_;
+ std::unique_ptr<NotificationHelper> notification_helper_;
DISALLOW_COPY_AND_ASSIGN(NotificationControllerEfl);
};
-} //namespace
+} // namespace content
#endif // NOTIFICATION_CONTROLLER_EFL_H
--- /dev/null
+// Copyright 2021 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "browser/notification/notification_helper.h"
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "content/public/browser/notification_event_dispatcher.h"
+
+namespace content {
+
+void OnEventDispatchComplete(PersistentNotificationStatus status) {
+ LOG(INFO) << "Notifications.PersistentWebNotificationClickResult "
+ << (int)status;
+}
+
+NotificationHelper::NotificationHelper() {
+ notification_event_dispatcher_ =
+ content::NotificationEventDispatcher::GetInstance();
+}
+
+NotificationHelper::~NotificationHelper() {
+ notifications_map_.clear();
+ persistent_notification_map_.clear();
+}
+
+bool NotificationHelper::NotificationClosed(uint64_t notification_id,
+ bool by_user) {
+ auto itr = notifications_map_.find(notification_id);
+ if (itr != notifications_map_.end()) {
+ notification_event_dispatcher_->DispatchNonPersistentCloseEvent(
+ itr->second.non_persistent_id, base::DoNothing());
+ notifications_map_.erase(notification_id);
+ return true;
+ }
+
+ auto it = persistent_notification_map_.find(notification_id);
+ if (it != persistent_notification_map_.end()) {
+ notification_event_dispatcher_->DispatchNotificationCloseEvent(
+ it->second.browser_context, it->second.persistent_id, it->second.origin,
+ by_user, base::BindOnce(OnEventDispatchComplete));
+ persistent_notification_map_.erase(notification_id);
+ return true;
+ }
+
+ return false;
+}
+
+bool NotificationHelper::PersistentNotificationClicked(
+ BrowserContext* browser_context,
+ const char* id,
+ const char* origin) {
+ if (!browser_context)
+ return false;
+
+ notification_event_dispatcher_->DispatchNotificationClickEvent(
+ browser_context, std::string(id), GURL(base::StringPiece(origin)),
+ absl::optional<int>(), absl::optional<std::u16string>(),
+ base::BindOnce(OnEventDispatchComplete));
+ // TODO: Currently if we click notification in quick panel, it will be
+ // deleted automatically by platform. If we can keep the notification
+ // after click, we don't need to call |DispatchNotificationCloseEvent| here.
+ notification_event_dispatcher_->DispatchNotificationCloseEvent(
+ browser_context, std::string(id), GURL(base::StringPiece(origin)), false,
+ base::BindOnce(OnEventDispatchComplete));
+ return true;
+}
+
+bool NotificationHelper::NotificationClicked(uint64_t notification_id) {
+ auto itr = persistent_notification_map_.find(notification_id);
+ if (itr != persistent_notification_map_.end()) {
+ persistent_notification_map_.erase(notification_id);
+ return true;
+ }
+
+ auto it = notifications_map_.find(notification_id);
+ if (it != notifications_map_.end()) {
+ notification_event_dispatcher_->DispatchNonPersistentClickEvent(
+ it->second.non_persistent_id, base::DoNothing());
+
+ // TODO: Currently if we click notification in quick panel, it will be
+ // deleted automatically by platform. If we can keep the notification
+ // after click, we don't need to call |NotificationClosed| here.
+ notification_event_dispatcher_->DispatchNonPersistentCloseEvent(
+ it->second.non_persistent_id, base::DoNothing());
+ notifications_map_.erase(notification_id);
+ return true;
+ }
+
+ return false;
+}
+
+bool NotificationHelper::NotificationDisplayed(uint64_t notification_id) {
+ auto itr = notifications_map_.find(notification_id);
+ if (itr == notifications_map_.end())
+ return false;
+
+ notification_event_dispatcher_->DispatchNonPersistentShowEvent(
+ itr->second.non_persistent_id);
+ return true;
+}
+
+bool NotificationHelper::IsNotificationPresent(
+ const GURL& origin,
+ const std::string& notification_id,
+ uint64_t& replace_unique_id) {
+ for (auto it = notifications_map_.begin(); it != notifications_map_.end();
+ ++it) {
+ if (notification_id == it->second.non_persistent_id &&
+ origin == it->second.origin) {
+ replace_unique_id = it->first;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool NotificationHelper::IsPersistentNotificationPresent(
+ const GURL& origin,
+ const std::string& notification_id,
+ uint64_t& replace_unique_id) {
+ for (auto it = persistent_notification_map_.begin();
+ it != persistent_notification_map_.end(); ++it) {
+ if (notification_id == it->second.persistent_id &&
+ origin == it->second.origin) {
+ replace_unique_id = it->first;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void NotificationHelper::SetNotification(const GURL& origin,
+ const std::string& notification_id,
+ uint64_t notification_unique_id) {
+ NotificationData new_notification = {origin, notification_id};
+ notifications_map_[notification_unique_id] = new_notification;
+}
+
+void NotificationHelper::SetPersistentNotification(
+ BrowserContext* browser_context,
+ const GURL& origin,
+ const std::string& notification_id,
+ uint64_t notification_unique_id) {
+ PersistentNotificationData persistent_notification_data = {
+ browser_context, origin, notification_id};
+ persistent_notification_map_[notification_unique_id] =
+ persistent_notification_data;
+}
+
+} // namespace content
--- /dev/null
+// Copyright 2021 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NOTIFICATION_HELPER_H
+#define NOTIFICATION_HELPER_H
+
+#include <map>
+
+#include "url/gurl.h"
+
+namespace content {
+
+class BrowserContext;
+class NotificationEventDispatcher;
+
+struct NotificationData {
+ GURL origin;
+ std::string non_persistent_id;
+};
+
+struct PersistentNotificationData {
+ BrowserContext* browser_context;
+ GURL origin;
+ std::string persistent_id;
+};
+
+class NotificationHelper {
+ public:
+ NotificationHelper();
+ ~NotificationHelper();
+
+ bool NotificationClosed(uint64_t notification_id, bool by_user);
+
+ // Notify engine when user clicked on the notification
+ bool NotificationClicked(uint64_t notification_id);
+
+ // Notification engine that notification was displayed
+ bool NotificationDisplayed(uint64_t notification_id);
+
+ bool PersistentNotificationClicked(BrowserContext* browser_context,
+ const char* id,
+ const char* origin);
+ bool IsPersistentNotificationPresent(const GURL& origin,
+ const std::string& notification_id,
+ uint64_t& replace_unique_id);
+ bool IsNotificationPresent(const GURL& origin,
+ const std::string& notification_id,
+ uint64_t& replace_unique_id);
+ void SetNotification(const GURL& origin,
+ const std::string& notification_id,
+ uint64_t notification_unique_id);
+
+ void SetPersistentNotification(BrowserContext* browser_context,
+ const GURL& origin,
+ const std::string& notification_id,
+ uint64_t notification_unique_id);
+
+ private:
+ // This stores the notifications displayed to the user.
+ std::map<uint64_t, NotificationData> notifications_map_;
+ std::map<uint64_t, PersistentNotificationData> persistent_notification_map_;
+ NotificationEventDispatcher* notification_event_dispatcher_ = nullptr;
+};
+
+} // namespace content
+
+#endif // NOTIFICATION_HELPER_H
#include "web_contents_view_delegate_ewk.h"
#include "devtools_manager_delegate_efl.h"
#include "browser/editor_client_observer.h"
+#include "browser/notification/notification_controller_efl.h"
#include "browser/quota_permission_context_efl.h"
#include "browser/render_message_filter_efl.h"
#include "browser/web_view_browser_message_filter.h"
#include "content/browser/speech/tts_message_filter_efl.h"
#endif
-#if defined(ENABLE_NOTIFICATIONS)
-#include "browser/notification/notification_controller_efl.h"
-#endif
-
#include "private/ewk_notification_private.h"
using web_contents_utils::WebContentsFromFrameID;
ContentBrowserClientEfl::ContentBrowserClientEfl()
: browser_main_parts_efl_(nullptr),
-#if defined(ENABLE_NOTIFICATIONS)
notification_controller_(new NotificationControllerEfl),
-#endif
browser_context_efl_(nullptr),
accept_langs_(kDefaultAcceptLanguages) {
#if defined(OS_TIZEN)
#endif // !defined(EWK_BRINGUP)
}
-#if defined(ENABLE_NOTIFICATIONS)
PlatformNotificationService*
-ContentBrowserClientEfl::GetPlatformNotificationService() {
+ContentBrowserClientEfl::GetPlatformNotificationService(
+ BrowserContext* browser_context) {
return notification_controller_.get();
}
const {
return notification_controller_.get();
}
-#endif
bool ContentBrowserClientEfl::AllowGetCookie(const GURL& url,
const GURL& first_party,
namespace content {
class BrowserContextEfl;
class BrowserMainPartsEfl;
-#if defined(ENABLE_NOTIFICATIONS)
class NotificationControllerEfl;
-#endif
class SharedURLLoaderFactoryEfl;
class WebContents;
class WebContentsView;
bool strict_enforcement,
base::OnceCallback<void(CertificateRequestResultType)> callback) override;
-#if defined(ENABLE_NOTIFICATIONS)
- virtual PlatformNotificationService* GetPlatformNotificationService()
- override;
+ virtual PlatformNotificationService* GetPlatformNotificationService(
+ BrowserContext* browser_context) override;
NotificationControllerEfl* GetNotificationController() const;
-#endif
bool AllowGetCookie(const GURL& url,
const GURL& first_party,
BrowserMainPartsEfl* browser_main_parts_efl_;
-#if defined(ENABLE_NOTIFICATIONS)
std::unique_ptr<NotificationControllerEfl> notification_controller_;
-#endif
BrowserContextEfl* browser_context_efl_;
NewWindowNavigationPolicyDecision,
#endif // OS_TIZEN
URIChanged,
- DidNotAllowScript
+ DidNotAllowScript,
+ NotificationPermissionReply
};
template <CallbackType>
DECLARE_EWK_VIEW_CALLBACK(ToolbarVisible, "toolbar,visible", bool*);
DECLARE_EWK_VIEW_CALLBACK(WindowResizable, "window,resizable", bool*);
DECLARE_EWK_VIEW_CALLBACK(DidNotAllowScript, "did,not,allow,script", void);
+DECLARE_EWK_VIEW_CALLBACK(NotificationPermissionReply,
+ "notification,permission,reply",
+ Ewk_Notification_Permission*);
}
#endif
weak_ptr_factory_.GetWeakPtr(), request_id, i));
break;
}
-#if defined(ENABLE_NOTIFICATIONS)
case PermissionType::NOTIFICATIONS: {
ContentMainDelegateEfl& cmde =
- EwkGlobalData::GetInstance()->GetContentMainDelegatEfl();
+ EwkGlobalData::GetInstance()->GetContentMainDelegateEfl();
ContentBrowserClientEfl* cbce = static_cast<ContentBrowserClientEfl*>(
cmde.GetContentBrowserClient());
if (!cbce) {
weak_ptr_factory_.GetWeakPtr(), request_id, i));
break;
}
-#endif
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
case PermissionType::MIDI_SYSEX: {
NOTIMPLEMENTED() << "RequestPermission not implemented for "
const GURL& embedding_origin) {
switch (permission) {
case PermissionType::BACKGROUND_SYNC:
-#if defined(ENABLE_NOTIFICATIONS)
case PermissionType::NOTIFICATIONS: {
// requesting_origin should be the same as embedding_origin
// using push API from iframes are not allowed
return PermissionStatus::DENIED;
ContentMainDelegateEfl& cmde =
- EwkGlobalData::GetInstance()->GetContentMainDelegatEfl();
+ EwkGlobalData::GetInstance()->GetContentMainDelegateEfl();
ContentBrowserClientEfl* cbce =
static_cast<ContentBrowserClientEfl*>(cmde.GetContentBrowserClient());
if (!cbce) {
return notification_status;
}
-#endif
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
return PermissionStatus::GRANTED;
default:
using namespace blink::mojom;
Ewk_Notification::Ewk_Notification(const std::string& body,
- const std::string& replaceID,
const std::string& title,
const SkBitmap& icon,
bool silent,
const GURL& origin)
: body_(body),
icon_(icon),
- replaceID_(replaceID),
title_(title),
silent_(silent),
notificationID_(notificationID),
return body_.c_str();
}
-const char* Ewk_Notification::GetReplaceId() const {
- return replaceID_.c_str();
-}
-
const char* Ewk_Notification::GetTitle() const {
return title_.c_str();
}
}
Ewk_Notification_Permission_Request::Ewk_Notification_Permission_Request(
- Evas_Object* webview,
base::OnceCallback<void(PermissionStatus)> callback,
const GURL& source_origin)
- : webview_(webview),
- origin_(new _Ewk_Security_Origin(source_origin)),
+ : origin_(new _Ewk_Security_Origin(source_origin)),
callback_(std::move(callback)),
decided_(false),
suspended_(false) {}
-Ewk_Notification_Permission_Request::~Ewk_Notification_Permission_Request() {}
-
-Evas_Object* Ewk_Notification_Permission_Request::GetWebviewEvasObject() const {
- return webview_;
-}
-
const _Ewk_Security_Origin*
Ewk_Notification_Permission_Request::GetSecurityOrigin() const {
return origin_.get();
struct Ewk_Notification {
public:
Ewk_Notification(const std::string& body,
- const std::string& replaceID,
const std::string& title,
const SkBitmap& icon,
bool silent,
~Ewk_Notification();
const char* GetBody() const;
- const char* GetReplaceId() const;
const char* GetTitle() const;
bool IsSilent() const;
Evas_Object* GetIcon(Evas* evas) const;
private:
std::string body_;
SkBitmap icon_;
- std::string replaceID_;
std::string title_;
bool silent_;
uint64_t notificationID_;
struct Ewk_Notification_Permission_Request {
public:
Ewk_Notification_Permission_Request(
- Evas_Object* webview,
base::OnceCallback<void(blink::mojom::PermissionStatus)> callback,
const GURL& source_origin);
- ~Ewk_Notification_Permission_Request();
+ ~Ewk_Notification_Permission_Request() {}
- Evas_Object* GetWebviewEvasObject() const;
const _Ewk_Security_Origin* GetSecurityOrigin() const;
bool IsDecided() const;
bool IsSuspended() const;
bool Reply(bool allow);
private:
- Evas_Object* webview_;
std::unique_ptr<_Ewk_Security_Origin> origin_;
base::OnceCallback<void(blink::mojom::PermissionStatus)> callback_;
bool decided_;
using content::ContentBrowserClientEfl;
using content::ContentMainDelegateEfl;
+#if defined(OS_TIZEN)
+#include <app_control.h>
+
+#include "browser/notification/notification_controller_efl.h"
+#endif
+
namespace {
ContentBrowserClientEfl* GetContentBrowserClient() {
if (!EwkGlobalData::IsInitialized()) {
Eina_Bool ewk_context_app_control_set(const Ewk_Context* context, void* app_control)
{
- LOG_EWK_API_MOCKUP();
+#if defined(OS_TIZEN)
+ EINA_SAFETY_ON_NULL_RETURN_VAL(context, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(app_control, EINA_FALSE);
+
+ char* notification_id = nullptr;
+ app_control_h control = static_cast<app_control_h>(app_control);
+ int ret = app_control_get_extra_data(control, "notification_id",
+ ¬ification_id);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ LOG(ERROR) << "app_control_get_extra_data is failed with err " << ret;
+ return EINA_FALSE;
+ }
+
+ if (notification_id) {
+ ContentBrowserClientEfl* cbce = GetContentBrowserClient();
+ if (cbce) {
+ char* notification_origin = nullptr;
+ app_control_get_extra_data(control, "notification_origin",
+ ¬ification_origin);
+ cbce->GetNotificationController()->
+ PersistentNotificationClicked(context->browser_context(),
+ notification_id,
+ notification_origin);
+ }
+ }
+ return EINA_TRUE;
+#else
return EINA_FALSE;
+#endif
}
void ewk_context_max_refresh_rate_set(Ewk_Context* context, int max_refresh_rate)
#include "eweb_view.h"
#include "ewk_global_data.h"
#include "browser_context_efl.h"
-#if defined(ENABLE_NOTIFICATIONS)
#include "browser/notification/notification_controller_efl.h"
-#endif
#include "private/ewk_context_private.h"
#include "private/ewk_security_origin_private.h"
#include "private/ewk_notification_private.h"
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
-#if defined(ENABLE_NOTIFICATIONS)
cbce->GetNotificationController()->SetNotificationCallbacks(show_callback, cancel_callback, user_data);
-#endif
-
return EINA_TRUE;
}
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
-#if defined(ENABLE_NOTIFICATIONS)
cbce->GetNotificationController()->SetNotificationCallbacks(nullptr, nullptr, nullptr);
-#endif
return EINA_TRUE;
}
{
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
-#if defined(ENABLE_NOTIFICATIONS)
return cbce->GetNotificationController()->NotificationClicked(notification_id);
-#else
- return EINA_FALSE;
-#endif
}
const char* ewk_notification_icon_url_get(const Ewk_Notification* ewk_notification)
{
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
-#if defined(ENABLE_NOTIFICATIONS)
content::NotificationControllerEfl* notification_controller = cbce->GetNotificationController();
notification_controller->ClearPermissions();
Eina_List* list;
void* data;
EINA_LIST_FOREACH(ewk_notification_permissions, list, data) {
Ewk_Notification_Permission* perm = static_cast<Ewk_Notification_Permission*>(data);
- notification_controller->AddPermission(GURL(perm->origin), (perm->allowed == EINA_TRUE));
+ notification_controller->PutPermission(GURL(perm->origin), (perm->allowed == EINA_TRUE));
}
-#endif
return EINA_TRUE;
}
Eina_Bool ewk_notification_permission_reply(Ewk_Notification_Permission_Request* request, Eina_Bool allow)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(request, EINA_FALSE);
-#if defined(ENABLE_NOTIFICATIONS)
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
cbce->GetNotificationController()->SetPermissionForNotification(request, allow);
-#endif
return request->Reply(allow == EINA_TRUE);
}
Eina_Bool ewk_notification_policies_removed(Eina_List* origins)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(origins, EINA_FALSE);
-#if defined(ENABLE_NOTIFICATIONS)
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
cbce->GetNotificationController()->RemovePermissions(origins);
-#endif
return EINA_TRUE;
}
Eina_Bool ewk_notification_showed(uint64_t notification_id)
{
-#if defined(ENABLE_NOTIFICATIONS)
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
return cbce->GetNotificationController()->NotificationDisplayed(notification_id);
-#else
- return EINA_FALSE;
-#endif
}
Eina_Bool ewk_notification_closed(uint64_t notification_id, Eina_Bool by_user)
{
-#if defined(ENABLE_NOTIFICATIONS)
ContentBrowserClientEfl* cbce = GetContentBrowserClient();
EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE);
return cbce->GetNotificationController()->NotificationClosed(notification_id, by_user);
-#else
- return EINA_FALSE;
-#endif
}
const char* ewk_notification_title_get(const Ewk_Notification* ewk_notification)
#include "third_party/blink/public/common/input/web_input_event.h"
#include "url/gurl.h"
+#if defined(OS_TIZEN)
+#include <app_control.h>
+#include <app_manager.h>
+#endif
+
#if defined(TIZEN_MULTIMEDIA_SUPPORT)
#include "content/public/browser/media_capture_devices.h"
#include "media/capture/video/tizen/video_capture_device_tizen.h"
using autofill::ContentAutofillDriverFactory;
using password_manager::PasswordManagerClientEfl;
#endif
+
using std::u16string;
using namespace ui;
if (!new_object)
return NULL;
+ if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
+ ActivateContents(source);
+
EWebView* wv =
WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(new_object);
DCHECK(wv);
}
}
+void WebContentsDelegateEfl::ActivateContents(WebContents* contents) {
+#if defined(OS_TIZEN)
+ app_control_h app_control = nullptr;
+ int ret = app_control_create(&app_control);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ LOG(ERROR) << "app_control_create is failed with err " << ret;
+ return;
+ }
+
+ std::unique_ptr<std::remove_pointer<app_control_h>::type,
+ decltype(app_control_destroy)*>
+ auto_release{app_control, app_control_destroy};
+
+ char* app_id = nullptr;
+ ret = app_manager_get_app_id(getpid(), &app_id);
+ if (ret != APP_MANAGER_ERROR_NONE) {
+ LOG(ERROR) << "app_manager_get_app_id is failed with err " << ret;
+ return;
+ }
+
+ ret = app_control_set_app_id(app_control, app_id);
+ if (app_id)
+ free(app_id);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ LOG(ERROR) << "app_control_set_app_id is failed with err " << ret;
+ return;
+ }
+
+ ret = app_control_send_launch_request(app_control, nullptr, nullptr);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ LOG(ERROR) << "app_control_send_launch_request is failed with err " << ret;
+ return;
+ }
+#endif
+}
+
void WebContentsDelegateEfl::SetContentSecurityPolicy(
const std::string& policy,
Ewk_CSP_Header_Type header_type) {
JavaScriptDialogManager* GetJavaScriptDialogManager(
WebContents* source) override;
+ void ActivateContents(WebContents* contents) override;
+
void OnUpdateSettings(const Ewk_Settings* settings);
void SetContentSecurityPolicy(const std::string& policy,
Ewk_CSP_Header_Type header_type);