Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(950)

Unified Diff: content/browser/notifications/blink_notification_service_impl.cc

Issue 1904163002: Move Web Notifications to use Mojo Base URL: https://chromium.googlesource.com/chromium/src.git@skbitmap-blink
Patch Set: it works \o/ Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/notifications/blink_notification_service_impl.cc
diff --git a/content/browser/notifications/blink_notification_service_impl.cc b/content/browser/notifications/blink_notification_service_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5e2c1020edac232889f6b056b98edad3850e14fc
--- /dev/null
+++ b/content/browser/notifications/blink_notification_service_impl.cc
@@ -0,0 +1,319 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/notifications/blink_notification_service_impl.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/notifications/notification_id_generator.h"
+#include "content/browser/notifications/page_notification_delegate.h"
+#include "content/browser/notifications/platform_notification_context_impl.h"
+#include "content/browser/notifications/type_converters.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/notification_database_data.h"
+#include "content/public/browser/platform_notification_service.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/notification_resources.h"
+#include "content/public/common/platform_notification_data.h"
+#include "skia/public/type_converters.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+// Returns the implementation of the PlatformNotificationService. May be NULL.
+PlatformNotificationService* service() {
+ return GetContentClient()->browser()->GetPlatformNotificationService();
+}
+
+// Displays a non-persistent notification with the given information on the UI
+// thread. The close closure will be written to |*close_closure|.
+void DisplayNonPersistentNotificationOnUI(
+ BrowserContext* browser_context,
+ const GURL& origin,
+ blink::mojom::NotificationPtr notification,
+ blink::mojom::NotificationResourcesPtr notification_resources,
+ blink::mojom::NotificationClientPtrInfo notification_client_info,
+ base::Closure* close_closure) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ blink::mojom::NotificationClientPtr notification_client =
+ mojo::MakeProxy(std::move(notification_client_info));
+
+ std::unique_ptr<PageNotificationDelegate> delegate(
+ new PageNotificationDelegate(std::move(notification_client)));
+
+ // TODO(peter): Use the |notification_id| when showing a notification.
+ service()->DisplayNotification(
+ browser_context, origin, notification.To<PlatformNotificationData>(),
+ notification_resources.To<NotificationResources>(), std::move(delegate),
+ close_closure);
+
+ DCHECK(!close_closure->is_null());
+}
+
+} // namespace
+
+BlinkNotificationServiceImpl::BlinkNotificationServiceImpl(
+ PlatformNotificationContextImpl* notification_context,
+ BrowserContext* browser_context,
+ ResourceContext* resource_context,
+ int render_process_id,
+ mojo::InterfaceRequest<blink::mojom::NotificationService> request)
+ : notification_context_(notification_context),
+ browser_context_(browser_context),
+ resource_context_(resource_context),
+ render_process_id_(render_process_id),
+ binding_(this, std::move(request)),
+ weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(notification_context_);
+ DCHECK(browser_context_);
+
+ notification_id_generator_.reset(
+ new NotificationIdGenerator(browser_context_, render_process_id_));
+
+ binding_.set_connection_error_handler(
+ base::Bind(&BlinkNotificationServiceImpl::OnConnectionError,
+ base::Unretained(this) /* the channel is owned by this */));
+}
+
+BlinkNotificationServiceImpl::~BlinkNotificationServiceImpl() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void BlinkNotificationServiceImpl::GetPermissionStatus(
+ const mojo::String& origin,
+ const GetPermissionStatusCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!service()) {
+ callback.Run(blink::mojom::PermissionStatus::DENIED);
+ return;
+ }
+
+ blink::mojom::PermissionStatus permission_status =
+ service()->CheckPermissionOnIOThread(
+ resource_context_, GURL(origin.get()), render_process_id_);
+
+ callback.Run(permission_status);
+}
+
+void BlinkNotificationServiceImpl::Display(
+ const mojo::String& origin,
+ blink::mojom::NotificationPtr notification,
+ blink::mojom::NotificationResourcesPtr notification_resources,
+ blink::mojom::NotificationClientPtr notification_client,
+ const DisplayCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(service()); // TODO: This should be BadMessage?
+
+ // TODO(peter): Verify the notification's data and that permission has been
+ // granted for the given |origin|.
+
+ GURL origin_url(origin.get());
+
+ std::string notification_id =
+ notification_id_generator_->GenerateForNonPersistentNotification(
+ origin_url, notification->tag, ++non_persistent_notification_id_);
+
+ LOG(ERROR) << "Notification Id: " << notification_id;
+
+ std::unique_ptr<base::Closure> close_closure(new base::Closure());
+
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DisplayNonPersistentNotificationOnUI, browser_context_,
+ origin_url, base::Passed(&notification),
+ base::Passed(&notification_resources),
+ base::Passed(notification_client.PassInterface()),
+ base::Unretained(close_closure.get())),
+ base::Bind(&BlinkNotificationServiceImpl::DidDisplay,
+ weak_ptr_factory_.GetWeakPtr(), notification_id,
+ base::Passed(std::move(close_closure)), callback));
+}
+
+void BlinkNotificationServiceImpl::DidDisplay(
+ const std::string& notification_id,
+ std::unique_ptr<base::Closure> close_closure,
+ const DisplayCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ close_closures_[notification_id] = *close_closure;
+
+ callback.Run(blink::mojom::NotificationDisplayResult::SUCCESS,
+ notification_id);
+}
+
+void BlinkNotificationServiceImpl::DisplayPersistent(
+ const mojo::String& origin,
+ int64_t service_worker_registration_id,
+ blink::mojom::NotificationPtr notification,
+ blink::mojom::NotificationResourcesPtr notification_resources,
+ const DisplayPersistentCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(service()); // TODO: This should be BadMessage?
+
+ // TODO(peter): Verify the notification's data and that permission has been
+ // granted for the given |origin|.
+
+ GURL origin_url(origin.get());
+
+ NotificationDatabaseData database_data;
+ database_data.origin = origin_url;
+ database_data.service_worker_registration_id = service_worker_registration_id;
+ database_data.notification_data = notification.To<PlatformNotificationData>();
+
+ notification_context_->WriteNotificationData(
+ origin_url, database_data,
+ base::Bind(&BlinkNotificationServiceImpl::DidStorePersistent,
+ weak_ptr_factory_.GetWeakPtr(), origin_url,
+ base::Passed(&notification),
+ base::Passed(&notification_resources), callback));
+}
+
+void BlinkNotificationServiceImpl::DidStorePersistent(
+ const GURL& origin,
+ blink::mojom::NotificationPtr notification,
+ blink::mojom::NotificationResourcesPtr notification_resources,
+ const DisplayPersistentCallback& callback,
+ bool success,
+ int64_t persistent_notification_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!success) {
+ callback.Run(blink::mojom::NotificationDisplayResult::FAILED_STORAGE_ERROR);
+ return;
+ }
+
+ // TODO(peter): Send an Id generated by the NotificationIdGenerator to the
+ // service rather than the integral database id.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&PlatformNotificationService::DisplayPersistentNotification,
+ base::Unretained(service()), browser_context_,
+ persistent_notification_id, origin,
+ notification.To<PlatformNotificationData>(),
+ notification_resources.To<NotificationResources>()));
+
+ callback.Run(blink::mojom::NotificationDisplayResult::SUCCESS);
+}
+
+void BlinkNotificationServiceImpl::GetNotifications(
+ const mojo::String& origin,
+ int64_t service_worker_registration_id,
+ const mojo::String& tag,
+ const GetNotificationsCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // TODO(peter): If no permission has been granted, invoke |callback| quickly
+ // with an empty Mojo array and avoid hitting the database.
+
+ GURL origin_url(origin.get());
+
+ notification_context_->ReadAllNotificationDataForServiceWorkerRegistration(
+ origin_url, service_worker_registration_id,
+ base::Bind(&BlinkNotificationServiceImpl::DidGetNotifications,
+ weak_ptr_factory_.GetWeakPtr(), tag.get(), callback));
+}
+
+void BlinkNotificationServiceImpl::DidGetNotifications(
+ const std::string& tag,
+ const GetNotificationsCallback& callback,
+ bool success,
+ const std::vector<NotificationDatabaseData>& notifications) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!success) {
+ callback.Run(mojo::Array<blink::mojom::NotificationPtr>());
+ return;
+ }
+
+ mojo::Array<blink::mojom::NotificationPtr> mojo_notifications;
+
+ for (const auto& notification : notifications) {
+ if (!tag.empty() && notification.notification_data.tag != tag)
+ continue;
+
+ blink::mojom::NotificationPtr mojo_notification =
+ blink::mojom::Notification::From(notification.notification_data);
+
+ // TODO(peter): Use the NotificationIdGenerator when the database has been
+ // taught to work with these identifiers rather than the current numbers.
+ mojo_notification->id = base::Int64ToString(notification.notification_id);
+
+ mojo_notifications.push_back(std::move(mojo_notification));
+ }
+
+ callback.Run(std::move(mojo_notifications));
+}
+
+void BlinkNotificationServiceImpl::Close(const mojo::String& origin,
+ const mojo::String& notification_id,
+ const CloseCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(service()); // TODO: This should be BadMessage?
+
+ // TODO(peter): Do the necessary permission checks.
+
+ const std::string id = notification_id.get();
+
+ int64_t persistent_notification_id = 0;
+
+ // TODO(peter): Use NotificationIdGenerator::IsPersistentNotification when
+ // the notification system is in charge of generating its own ids.
+ if (base::StringToInt64(notification_id.get(), &persistent_notification_id)) {
+ // There's no point in waiting until the database has been updated before
+ // closing the notification presented to the user.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&PlatformNotificationService::ClosePersistentNotification,
+ base::Unretained(service()), // The service is a singleton.
+ browser_context_, persistent_notification_id));
+
+ notification_context_->DeleteNotificationData(
+ persistent_notification_id, GURL(origin.get()),
+ base::Bind(&BlinkNotificationServiceImpl::DidClosePersistent,
+ weak_ptr_factory_.GetWeakPtr(), callback));
+
+ return;
+ } else if (NotificationIdGenerator::IsNonPersistentNotification(id)) {
+ const auto& notification_iter = close_closures_.find(id);
+ if (notification_iter != close_closures_.end()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE, notification_iter->second);
+
+ close_closures_.erase(notification_iter);
+
+ callback.Run(blink::mojom::NotificationCloseResult::CLOSED);
+ return;
+ }
+ } else {
+ // TODO: This should be BadMessage?
+ NOTREACHED() << "Unrecognized notification id";
+ }
+
+ callback.Run(blink::mojom::NotificationCloseResult::NOT_FOUND);
+}
+
+void BlinkNotificationServiceImpl::DidClosePersistent(
+ const CloseCallback& callback,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto result = success ? blink::mojom::NotificationCloseResult::CLOSED
+ : blink::mojom::NotificationCloseResult::NOT_FOUND;
+
+ callback.Run(result);
+}
+
+void BlinkNotificationServiceImpl::OnConnectionError() {
+ notification_context_->RemoveService(this);
+ // |this| has now been deleted.
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698