[M94 Migration] Bringup notification and migrate related patches from M85 37/268837/3
authorSurya Kumar <surya.kumar7@samsung.com>
Mon, 3 Jan 2022 16:36:55 +0000 (22:06 +0530)
committerSurya Kumar <surya.kumar7@samsung.com>
Mon, 3 Jan 2022 16:38:20 +0000 (22:08 +0530)
Notification related changes have been migrated from M85

Cherry-picked from:
https://review.tizen.org/gerrit/266990
https://review.tizen.org/gerrit/267758

Change-Id: I098541a7a0782abd92d123ca5d2abac236fe62d8
Signed-off-by: Surya Kumar <surya.kumar7@samsung.com>
19 files changed:
packaging/chromium-efl.spec
tizen_src/build/BUILD.gn
tizen_src/chromium_impl/content/common/paths_efl.cc
tizen_src/chromium_impl/content/common/paths_efl.h
tizen_src/ewk/efl_integration/BUILD.gn
tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc
tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.h
tizen_src/ewk/efl_integration/browser/notification/notification_helper.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/browser/notification/notification_helper.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/content_browser_client_efl.cc
tizen_src/ewk/efl_integration/content_browser_client_efl.h
tizen_src/ewk/efl_integration/eweb_view_callbacks.h
tizen_src/ewk/efl_integration/permission_controller_delegate_efl.cc
tizen_src/ewk/efl_integration/private/ewk_notification_private.cc
tizen_src/ewk/efl_integration/private/ewk_notification_private.h
tizen_src/ewk/efl_integration/public/ewk_context.cc
tizen_src/ewk/efl_integration/public/ewk_notification.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.h

index 068b3b6..9df53bb 100644 (file)
@@ -51,6 +51,7 @@ BuildRequires: binutils-gold
 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)
@@ -93,6 +94,7 @@ BuildRequires: pkgconfig(libxml-2.0)
 BuildRequires: pkgconfig(libxslt)
 BuildRequires: pkgconfig(minizip)
 BuildRequires: pkgconfig(mm-player)
+BuildRequires: pkgconfig(notification)
 BuildRequires: pkgconfig(nspr)
 BuildRequires: pkgconfig(nss)
 BuildRequires: pkgconfig(scim)
index 2b26bb3..14ac742 100644 (file)
@@ -198,6 +198,19 @@ config("capi-appfw-application-public") {
   }
 }
 
+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" ]
@@ -505,6 +518,19 @@ config("mm-player-public") {
   }
 }
 
+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" ]
index 27efdf2..1e31cef 100644 (file)
 
 #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");
@@ -46,6 +55,20 @@ bool GetDirAppDataTizen(base::FilePath& result) {
   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) {
@@ -177,6 +200,17 @@ bool PathProvider(int key, base::FilePath* result) {
         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;
   }
index 1aaaabf..5a4c3b2 100644 (file)
@@ -18,6 +18,8 @@ enum {
   DIR_DOWNLOADS,
   DIR_DOWNLOAD_IMAGE,
   DIR_LOCALE,
+  DIR_SHARED,
+  DIR_SHARED_NOTI_ICON,
   PATH_END
 };
 
index e956ddf..9494d43 100644 (file)
@@ -58,6 +58,8 @@ shared_library("chromium-ewk") {
   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",
@@ -120,6 +122,8 @@ shared_library("chromium-ewk") {
       "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" ]
@@ -148,11 +152,6 @@ shared_library("chromium-ewk") {
     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" ]
   }
@@ -179,7 +178,7 @@ shared_library("chromium-ewk") {
     libs = [ "atomic" ]
   }
 
-  sources += [
+  sources = [
     "authentication_challenge_popup.cc",
     "authentication_challenge_popup.h",
     "autofill_popup_view_efl.cc",
@@ -301,6 +300,10 @@ shared_library("chromium-ewk") {
     "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",
index de7810d..4ff2e6b 100644 (file)
 
 #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, &notification_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, &noti_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, &notification_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(
@@ -90,54 +480,63 @@ 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(&notification)) {
+    notification_show_callback_(&notification,
+                                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(
@@ -146,132 +545,114 @@ 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(&notification)) {
+    notification_show_callback_(&notification,
+                                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(&notifications_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
+
index 5292855..19df7a9 100644 (file)
 
 #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
@@ -109,6 +153,10 @@ class NotificationControllerEfl: public PlatformNotificationService {
       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(
@@ -127,27 +175,31 @@ class NotificationControllerEfl: public PlatformNotificationService {
   // 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
diff --git a/tizen_src/ewk/efl_integration/browser/notification/notification_helper.cc b/tizen_src/ewk/efl_integration/browser/notification/notification_helper.cc
new file mode 100644 (file)
index 0000000..92492b9
--- /dev/null
@@ -0,0 +1,156 @@
+// 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
diff --git a/tizen_src/ewk/efl_integration/browser/notification/notification_helper.h b/tizen_src/ewk/efl_integration/browser/notification/notification_helper.h
new file mode 100644 (file)
index 0000000..8e50c9b
--- /dev/null
@@ -0,0 +1,68 @@
+// 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
index 508f87a..1a35d5b 100644 (file)
@@ -14,6 +14,7 @@
 #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;
@@ -79,9 +76,7 @@ void PlatformLanguageChanged(keynode_t* keynode, void* data) {
 
 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)
@@ -254,9 +249,9 @@ void ContentBrowserClientEfl::AllowCertificateError(
 #endif  // !defined(EWK_BRINGUP)
 }
 
-#if defined(ENABLE_NOTIFICATIONS)
 PlatformNotificationService*
-ContentBrowserClientEfl::GetPlatformNotificationService() {
+ContentBrowserClientEfl::GetPlatformNotificationService(
+   BrowserContext* browser_context) {
   return notification_controller_.get();
 }
 
@@ -264,7 +259,6 @@ NotificationControllerEfl* ContentBrowserClientEfl::GetNotificationController()
     const {
   return notification_controller_.get();
 }
-#endif
 
 bool ContentBrowserClientEfl::AllowGetCookie(const GURL& url,
                                              const GURL& first_party,
index 6df35ec..19ed7c3 100644 (file)
@@ -19,9 +19,7 @@ class Ewk_Notification;
 namespace content {
 class BrowserContextEfl;
 class BrowserMainPartsEfl;
-#if defined(ENABLE_NOTIFICATIONS)
 class NotificationControllerEfl;
-#endif
 class SharedURLLoaderFactoryEfl;
 class WebContents;
 class WebContentsView;
@@ -70,12 +68,10 @@ class ContentBrowserClientEfl : public ContentBrowserClient {
       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,
@@ -144,9 +140,7 @@ class ContentBrowserClientEfl : public ContentBrowserClient {
 
   BrowserMainPartsEfl* browser_main_parts_efl_;
 
-#if defined(ENABLE_NOTIFICATIONS)
   std::unique_ptr<NotificationControllerEfl> notification_controller_;
-#endif
 
   BrowserContextEfl* browser_context_efl_;
 
index c4eaca4..28593b6 100644 (file)
@@ -140,7 +140,8 @@ enum CallbackType {
   NewWindowNavigationPolicyDecision,
 #endif // OS_TIZEN
   URIChanged,
-  DidNotAllowScript
+  DidNotAllowScript,
+  NotificationPermissionReply
 };
 
 template <CallbackType>
@@ -292,6 +293,9 @@ DECLARE_EWK_VIEW_CALLBACK(StatusBarVisible, "statusbar,visible", bool*);
 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
index 4d9ac86..3993839 100644 (file)
@@ -123,10 +123,9 @@ void PermissionControllerDelegateEfl::RequestPermissions(
                 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) {
@@ -142,7 +141,6 @@ void PermissionControllerDelegateEfl::RequestPermissions(
                 weak_ptr_factory_.GetWeakPtr(), request_id, i));
         break;
       }
-#endif
       case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
       case PermissionType::MIDI_SYSEX: {
         NOTIMPLEMENTED() << "RequestPermission not implemented for "
@@ -190,7 +188,6 @@ PermissionStatus PermissionControllerDelegateEfl::GetPermissionStatus(
                                                  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
@@ -198,7 +195,7 @@ PermissionStatus PermissionControllerDelegateEfl::GetPermissionStatus(
         return PermissionStatus::DENIED;
 
       ContentMainDelegateEfl& cmde =
-          EwkGlobalData::GetInstance()->GetContentMainDelegatEfl();
+          EwkGlobalData::GetInstance()->GetContentMainDelegateEfl();
       ContentBrowserClientEfl* cbce =
           static_cast<ContentBrowserClientEfl*>(cmde.GetContentBrowserClient());
       if (!cbce) {
@@ -215,7 +212,6 @@ PermissionStatus PermissionControllerDelegateEfl::GetPermissionStatus(
 
       return notification_status;
     }
-#endif
     case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
       return PermissionStatus::GRANTED;
     default:
index 60704c0..1378ac6 100644 (file)
@@ -11,7 +11,6 @@ using content::BrowserThread;
 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,
@@ -19,7 +18,6 @@ Ewk_Notification::Ewk_Notification(const std::string& body,
                                    const GURL& origin)
     : body_(body),
       icon_(icon),
-      replaceID_(replaceID),
       title_(title),
       silent_(silent),
       notificationID_(notificationID),
@@ -31,10 +29,6 @@ const char* Ewk_Notification::GetBody() const {
   return body_.c_str();
 }
 
-const char* Ewk_Notification::GetReplaceId() const {
-  return replaceID_.c_str();
-}
-
 const char* Ewk_Notification::GetTitle() const {
   return title_.c_str();
 }
@@ -82,21 +76,13 @@ bool Ewk_Notification::SaveAsPng(const char* path) const {
 }
 
 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();
index 2414a35..a6b9de7 100644 (file)
@@ -19,7 +19,6 @@ class GURL;
 struct Ewk_Notification {
  public:
   Ewk_Notification(const std::string& body,
-                   const std::string& replaceID,
                    const std::string& title,
                    const SkBitmap& icon,
                    bool silent,
@@ -28,7 +27,6 @@ struct Ewk_Notification {
   ~Ewk_Notification();
 
   const char* GetBody() const;
-  const char* GetReplaceId() const;
   const char* GetTitle() const;
   bool IsSilent() const;
   Evas_Object* GetIcon(Evas* evas) const;
@@ -39,7 +37,6 @@ struct Ewk_Notification {
  private:
   std::string body_;
   SkBitmap icon_;
-  std::string replaceID_;
   std::string title_;
   bool silent_;
   uint64_t notificationID_;
@@ -52,12 +49,10 @@ struct Ewk_Notification {
 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;
@@ -65,7 +60,6 @@ struct Ewk_Notification_Permission_Request {
   bool Reply(bool allow);
 
  private:
-  Evas_Object* webview_;
   std::unique_ptr<_Ewk_Security_Origin> origin_;
   base::OnceCallback<void(blink::mojom::PermissionStatus)> callback_;
   bool decided_;
index e9676da..1b017b7 100644 (file)
 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()) {
@@ -906,8 +912,35 @@ Eina_Bool ewk_context_sound_overlap_set(Ewk_Context* context, Eina_Bool enable)
 
 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",
+                                       &notification_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",
+                                 &notification_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)
index 5327cf8..e237480 100644 (file)
@@ -32,9 +32,7 @@
 #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"
@@ -65,10 +63,7 @@ Eina_Bool ewk_notification_callbacks_set(Ewk_Notification_Show_Callback show_cal
   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;
 }
 
@@ -77,9 +72,7 @@ Eina_Bool ewk_notification_callbacks_reset()
   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;
 }
 
@@ -109,11 +102,7 @@ Eina_Bool ewk_notification_clicked(uint64_t notification_id)
 {
   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)
@@ -131,16 +120,14 @@ Eina_Bool ewk_notification_cached_permissions_set(Eina_List* ewk_notification_pe
 {
   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;
 }
@@ -155,11 +142,9 @@ const Ewk_Security_Origin* ewk_notification_permission_request_origin_get(
 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);
 }
 
@@ -177,11 +162,9 @@ Eina_Bool ewk_notification_permission_request_suspend(Ewk_Notification_Permissio
 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;
 }
 
@@ -193,24 +176,16 @@ const Ewk_Security_Origin* ewk_notification_security_origin_get(const Ewk_Notifi
 
 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)
index a8e50a8..024ed6b 100644 (file)
 #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"
@@ -55,6 +60,7 @@ using autofill::AutofillClientEfl;
 using autofill::ContentAutofillDriverFactory;
 using password_manager::PasswordManagerClientEfl;
 #endif
+
 using std::u16string;
 using namespace ui;
 
@@ -140,6 +146,9 @@ WebContents* WebContentsDelegateEfl::OpenURLFromTab(
     if (!new_object)
       return NULL;
 
+    if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
+      ActivateContents(source);
+
     EWebView* wv =
         WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(new_object);
     DCHECK(wv);
@@ -460,6 +469,42 @@ void WebContentsDelegateEfl::RequestCertificateConfirm(
   }
 }
 
+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) {
index dbb08ea..2b68c33 100644 (file)
@@ -106,6 +106,8 @@ class WebContentsDelegateEfl : public WebContentsDelegate,
   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);