blob: 4ffc890718f619cea3df70ecfb9f88353f116cef [file] [log] [blame]
// Copyright 2014 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/child/notifications/notification_manager.h"
#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
#include "content/child/notifications/notification_dispatcher.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/worker_task_runner.h"
#include "content/common/platform_notification_messages.h"
#include "content/public/common/show_desktop_notification_params.h"
#include "third_party/WebKit/public/platform/WebNotificationData.h"
#include "third_party/WebKit/public/platform/WebNotificationDelegate.h"
#include "third_party/WebKit/public/platform/WebSerializedOrigin.h"
#include "third_party/skia/include/core/SkBitmap.h"
using blink::WebNotificationPermission;
namespace content {
namespace {
int CurrentWorkerId() {
return WorkerTaskRunner::Instance()->CurrentWorkerId();
}
} // namespace
static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER;
NotificationManager::NotificationManager(
ThreadSafeSender* thread_safe_sender,
NotificationDispatcher* notification_dispatcher)
: thread_safe_sender_(thread_safe_sender),
notification_dispatcher_(notification_dispatcher) {
g_notification_manager_tls.Pointer()->Set(this);
}
NotificationManager::~NotificationManager() {
g_notification_manager_tls.Pointer()->Set(nullptr);
}
NotificationManager* NotificationManager::ThreadSpecificInstance(
ThreadSafeSender* thread_safe_sender,
NotificationDispatcher* notification_dispatcher) {
if (g_notification_manager_tls.Pointer()->Get())
return g_notification_manager_tls.Pointer()->Get();
NotificationManager* manager = new NotificationManager(
thread_safe_sender, notification_dispatcher);
if (WorkerTaskRunner::Instance()->CurrentWorkerId())
WorkerTaskRunner::Instance()->AddStopObserver(manager);
return manager;
}
void NotificationManager::OnWorkerRunLoopStopped() {
delete this;
}
void NotificationManager::show(
const blink::WebSerializedOrigin& origin,
const blink::WebNotificationData& notification_data,
blink::WebNotificationDelegate* delegate) {
int notification_id =
notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
active_notifications_[notification_id] = delegate;
ShowDesktopNotificationHostMsgParams params;
params.origin = GURL(origin.string());
// TODO(peter): Move the notification_icon_loader to //content/child/ and use
// it to download Notification icons here.
params.icon = SkBitmap();
params.title = notification_data.title;
params.body = notification_data.body;
// TODO(peter): Remove the usage of the Blink WebTextDirection enumeration for
// the text direction of notifications throughout Chrome.
params.direction = blink::WebTextDirectionLeftToRight;
params.replace_id = notification_data.tag;
thread_safe_sender_->Send(new PlatformNotificationHostMsg_Show(
notification_id, params));
}
void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
auto iter = active_notifications_.begin();
for (; iter != active_notifications_.end(); ++iter) {
if (iter->second != delegate)
continue;
thread_safe_sender_->Send(
new PlatformNotificationHostMsg_Close(iter->first));
active_notifications_.erase(iter);
delegate->dispatchCloseEvent();
return;
}
// It should not be possible for Blink to call close() on a Notification which
// does not exist anymore in the manager.
NOTREACHED();
}
void NotificationManager::notifyDelegateDestroyed(
blink::WebNotificationDelegate* delegate) {
auto iter = active_notifications_.begin();
for (; iter != active_notifications_.end(); ++iter) {
if (iter->second != delegate)
continue;
active_notifications_.erase(iter);
return;
}
}
WebNotificationPermission NotificationManager::checkPermission(
const blink::WebSerializedOrigin& origin) {
WebNotificationPermission permission =
blink::WebNotificationPermissionAllowed;
thread_safe_sender_->Send(new PlatformNotificationHostMsg_CheckPermission(
GURL(origin.string()), &permission));
return permission;
}
bool NotificationManager::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NotificationManager, message)
IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidShow, OnShow);
IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClose, OnClose);
IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClick, OnClick);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void NotificationManager::OnShow(int id) {
const auto& iter = active_notifications_.find(id);
if (iter == active_notifications_.end())
return;
iter->second->dispatchShowEvent();
}
void NotificationManager::OnClose(int id) {
const auto& iter = active_notifications_.find(id);
if (iter == active_notifications_.end())
return;
iter->second->dispatchCloseEvent();
active_notifications_.erase(iter);
}
void NotificationManager::OnClick(int id) {
const auto& iter = active_notifications_.find(id);
if (iter == active_notifications_.end())
return;
iter->second->dispatchClickEvent();
}
} // namespace content