| 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(¬ification),
|
| + base::Passed(¬ification_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(¬ification),
|
| + base::Passed(¬ification_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
|
|
|