1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/shell/renderer/test_runner/notification_presenter.h"
6
7#include "content/shell/renderer/test_runner/WebTestDelegate.h"
8#include "third_party/WebKit/public/platform/Platform.h"
9#include "third_party/WebKit/public/platform/WebString.h"
10#include "third_party/WebKit/public/platform/WebURL.h"
11#include "third_party/WebKit/public/web/WebKit.h"
12#include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h"
13#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
14#include "url/gurl.h"
15
16using blink::Platform;
17using blink::WebNotification;
18using blink::WebNotificationPermissionCallback;
19using blink::WebNotificationPresenter;
20using blink::WebSecurityOrigin;
21using blink::WebTextDirectionRightToLeft;
22
23namespace content {
24
25namespace {
26
27void DeferredDisplayDispatch(void* context) {
28  WebNotification* notification = static_cast<WebNotification*>(context);
29  notification->dispatchDisplayEvent();
30
31  delete notification;
32}
33
34}  // namespace
35
36NotificationPresenter::NotificationPresenter() : delegate_(0) {}
37
38NotificationPresenter::~NotificationPresenter() {}
39
40void NotificationPresenter::GrantPermission(const std::string& origin,
41                                            bool permission_granted) {
42  known_origins_[origin] = permission_granted;
43}
44
45bool NotificationPresenter::SimulateClick(const std::string& title) {
46  ActiveNotificationMap::iterator iter = active_notifications_.find(title);
47  if (iter == active_notifications_.end())
48    return false;
49
50  const WebNotification& notification = iter->second;
51
52  WebNotification event_target(notification);
53  event_target.dispatchClickEvent();
54
55  return true;
56}
57
58void NotificationPresenter::Reset() {
59  while (!active_notifications_.empty()) {
60    const WebNotification& notification = active_notifications_.begin()->second;
61    cancel(notification);
62  }
63
64  known_origins_.clear();
65  replacements_.clear();
66}
67
68bool NotificationPresenter::show(const WebNotification& notification) {
69  if (!notification.replaceId().isEmpty()) {
70    std::string replaceId(notification.replaceId().utf8());
71    if (replacements_.find(replaceId) != replacements_.end()) {
72      delegate_->printMessage(std::string("REPLACING NOTIFICATION ") +
73                              replacements_.find(replaceId)->second + "\n");
74    }
75    replacements_[replaceId] = notification.title().utf8();
76  }
77
78  delegate_->printMessage("DESKTOP NOTIFICATION SHOWN: ");
79  if (!notification.title().isEmpty())
80    delegate_->printMessage(notification.title().utf8().data());
81
82  if (notification.direction() == WebTextDirectionRightToLeft)
83    delegate_->printMessage(", RTL");
84
85  // TODO(beverloo): WebNotification should expose the "lang" attribute's value.
86
87  if (!notification.body().isEmpty()) {
88    delegate_->printMessage(std::string(", body: ") +
89                            notification.body().utf8().data());
90  }
91
92  if (!notification.replaceId().isEmpty()) {
93    delegate_->printMessage(std::string(", tag: ") +
94                            notification.replaceId().utf8().data());
95  }
96
97  if (!notification.iconURL().isEmpty()) {
98    delegate_->printMessage(std::string(", icon: ") +
99                            notification.iconURL().spec().data());
100  }
101
102  delegate_->printMessage("\n");
103
104  std::string title = notification.title().utf8();
105  active_notifications_[title] = notification;
106
107  Platform::current()->callOnMainThread(DeferredDisplayDispatch,
108                                        new WebNotification(notification));
109
110  return true;
111}
112
113void NotificationPresenter::cancel(const WebNotification& notification) {
114  std::string title = notification.title().utf8();
115
116  delegate_->printMessage(std::string("DESKTOP NOTIFICATION CLOSED: ") + title +
117                          "\n");
118
119  WebNotification event_target(notification);
120  event_target.dispatchCloseEvent(false);
121
122  active_notifications_.erase(title);
123}
124
125void NotificationPresenter::objectDestroyed(
126    const WebNotification& notification) {
127  std::string title = notification.title().utf8();
128  active_notifications_.erase(title);
129}
130
131WebNotificationPresenter::Permission NotificationPresenter::checkPermission(
132    const WebSecurityOrigin& security_origin) {
133  const std::string origin = security_origin.toString().utf8();
134  const KnownOriginMap::iterator it = known_origins_.find(origin);
135  if (it == known_origins_.end())
136    return WebNotificationPresenter::PermissionNotAllowed;
137
138  // Values in |known_origins_| indicate whether permission has been granted.
139  if (it->second)
140    return WebNotificationPresenter::PermissionAllowed;
141
142  return WebNotificationPresenter::PermissionDenied;
143}
144
145void NotificationPresenter::requestPermission(
146    const WebSecurityOrigin& security_origin,
147    WebNotificationPermissionCallback* callback) {
148  std::string origin = security_origin.toString().utf8();
149  delegate_->printMessage("DESKTOP NOTIFICATION PERMISSION REQUESTED: " +
150                          origin + "\n");
151  callback->permissionRequestComplete();
152}
153
154}  // namespace content
155