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.
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
14 #include "chrome/browser/notifications/desktop_notification_service.h"
15 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
16 #include "chrome/browser/notifications/notification_test_util.h"
17 #include "chrome/browser/notifications/platform_notification_service_impl.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "components/infobars/core/confirm_infobar_delegate.h"
23 #include "components/infobars/core/infobar.h"
24 #include "components/infobars/core/infobar_manager.h"
25 #include "content/public/test/browser_test_utils.h"
26 #include "net/base/filename_util.h"
27 #include "net/test/spawned_test_server/spawned_test_server.h"
29 // -----------------------------------------------------------------------------
31 // Accept or rejects the first shown confirm infobar. The infobar will be
32 // responsed to asynchronously, to imitate the behavior of a user.
33 // TODO(peter): Generalize this class, as it's commonly useful.
34 class InfoBarResponder
: public infobars::InfoBarManager::Observer
{
36 InfoBarResponder(Browser
* browser
, bool accept
);
37 ~InfoBarResponder() override
;
39 // infobars::InfoBarManager::Observer overrides.
40 void OnInfoBarAdded(infobars::InfoBar
* infobar
) override
;
43 void Respond(ConfirmInfoBarDelegate
* delegate
);
45 InfoBarService
* infobar_service_
;
50 InfoBarResponder::InfoBarResponder(Browser
* browser
, bool accept
)
51 : infobar_service_(InfoBarService::FromWebContents(
52 browser
->tab_strip_model()->GetActiveWebContents())),
54 has_observed_(false) {
55 infobar_service_
->AddObserver(this);
58 InfoBarResponder::~InfoBarResponder() {
59 infobar_service_
->RemoveObserver(this);
62 void InfoBarResponder::OnInfoBarAdded(infobars::InfoBar
* infobar
) {
67 ConfirmInfoBarDelegate
* delegate
=
68 infobar
->delegate()->AsConfirmInfoBarDelegate();
71 // Respond to the infobar asynchronously, like a person.
72 base::MessageLoop::current()->PostTask(
75 &InfoBarResponder::Respond
, base::Unretained(this), delegate
));
78 void InfoBarResponder::Respond(ConfirmInfoBarDelegate
* delegate
) {
85 // -----------------------------------------------------------------------------
87 // Dimensions of the icon.png resource in the notification test data directory.
88 const int kIconWidth
= 100;
89 const int kIconHeight
= 100;
91 class PlatformNotificationServiceBrowserTest
: public InProcessBrowserTest
{
93 PlatformNotificationServiceBrowserTest();
94 ~PlatformNotificationServiceBrowserTest() override
{}
96 // InProcessBrowserTest overrides.
97 void SetUp() override
;
98 void SetUpOnMainThread() override
;
99 void TearDown() override
;
102 // Returns the Platform Notification Service these unit tests are for.
103 PlatformNotificationServiceImpl
* service() const {
104 return PlatformNotificationServiceImpl::GetInstance();
107 // Grants permission to display Web Notifications for origin of the test
108 // page that's being used in this browser test.
109 void GrantNotificationPermissionForTest() const;
111 // Returns the UI Manager on which notifications will be displayed.
112 StubNotificationUIManager
* ui_manager() const { return ui_manager_
.get(); }
114 const base::FilePath
& server_root() const { return server_root_
; }
116 // Navigates the browser to the test page indicated by |path|.
117 void NavigateToTestPage(const std::string
& path
) const;
119 // Executes |script| and stores the result as a string in |result|. A boolean
120 // will be returned, indicating whether the script was executed successfully.
121 bool RunScript(const std::string
& script
, std::string
* result
) const;
123 net::HostPortPair
ServerHostPort() const;
124 GURL
TestPageUrl() const;
127 const base::FilePath server_root_
;
128 const std::string test_page_url_
;
129 scoped_ptr
<StubNotificationUIManager
> ui_manager_
;
130 scoped_ptr
<net::SpawnedTestServer
> https_server_
;
133 // -----------------------------------------------------------------------------
136 const char kTestFileName
[] = "notifications/platform_notification_service.html";
139 PlatformNotificationServiceBrowserTest::PlatformNotificationServiceBrowserTest()
140 : server_root_(FILE_PATH_LITERAL("chrome/test/data")),
141 // The test server has a base directory that doesn't exist in the
143 test_page_url_(std::string("files/") + kTestFileName
) {
146 void PlatformNotificationServiceBrowserTest::SetUp() {
147 ui_manager_
.reset(new StubNotificationUIManager
);
148 https_server_
.reset(new net::SpawnedTestServer(
149 net::SpawnedTestServer::TYPE_HTTPS
,
150 net::BaseTestServer::SSLOptions(net::BaseTestServer::SSLOptions::CERT_OK
),
152 ASSERT_TRUE(https_server_
->Start());
154 service()->SetNotificationUIManagerForTesting(ui_manager_
.get());
156 InProcessBrowserTest::SetUp();
159 void PlatformNotificationServiceBrowserTest::SetUpOnMainThread() {
160 NavigateToTestPage(test_page_url_
);
162 InProcessBrowserTest::SetUpOnMainThread();
165 void PlatformNotificationServiceBrowserTest::TearDown() {
166 service()->SetNotificationUIManagerForTesting(nullptr);
169 void PlatformNotificationServiceBrowserTest::
170 GrantNotificationPermissionForTest() const {
171 GURL origin
= TestPageUrl().GetOrigin();
173 DesktopNotificationProfileUtil::GrantPermission(browser()->profile(), origin
);
174 ASSERT_EQ(CONTENT_SETTING_ALLOW
,
175 DesktopNotificationProfileUtil::GetContentSetting(
176 browser()->profile(), origin
));
179 void PlatformNotificationServiceBrowserTest::NavigateToTestPage(
180 const std::string
& path
) const {
181 ui_test_utils::NavigateToURL(browser(), https_server_
->GetURL(path
));
184 bool PlatformNotificationServiceBrowserTest::RunScript(
185 const std::string
& script
, std::string
* result
) const {
186 return content::ExecuteScriptAndExtractString(
187 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
192 net::HostPortPair
PlatformNotificationServiceBrowserTest::ServerHostPort()
194 return https_server_
->host_port_pair();
197 GURL
PlatformNotificationServiceBrowserTest::TestPageUrl() const {
198 return https_server_
->GetURL(test_page_url_
);
201 // -----------------------------------------------------------------------------
203 // TODO(peter): Move PlatformNotificationService-related tests over from
204 // notification_browsertest.cc to this file.
206 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
207 DisplayPersistentNotificationWithoutPermission
) {
208 std::string script_result
;
210 InfoBarResponder
accepting_responder(browser(), false);
211 ASSERT_TRUE(RunScript("RequestPermission()", &script_result
));
212 EXPECT_EQ("denied", script_result
);
214 ASSERT_TRUE(RunScript("DisplayPersistentNotification()", &script_result
));
216 "TypeError: No notification permission has been granted for this origin.",
219 ASSERT_EQ(0u, ui_manager()->GetNotificationCount());
222 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
223 DisplayPersistentNotificationWithPermission
) {
224 std::string script_result
;
226 InfoBarResponder
accepting_responder(browser(), true);
227 ASSERT_TRUE(RunScript("RequestPermission()", &script_result
));
228 EXPECT_EQ("granted", script_result
);
230 ASSERT_TRUE(RunScript("DisplayPersistentNotification('action_none')",
232 EXPECT_EQ("ok", script_result
);
234 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
236 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
237 notification
.delegate()->Click();
239 ASSERT_TRUE(RunScript("GetMessageFromWorker()", &script_result
));
240 EXPECT_EQ("action_none", script_result
);
242 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
245 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
246 WebNotificationOptionsReflection
) {
247 std::string script_result
;
249 // TODO(peter): It doesn't add much value if we use the InfoBarResponder for
250 // each test. Rather, we should just toggle the content setting.
251 InfoBarResponder
accepting_responder(browser(), true);
252 ASSERT_TRUE(RunScript("RequestPermission()", &script_result
));
253 EXPECT_EQ("granted", script_result
);
255 ASSERT_TRUE(RunScript("DisplayPersistentAllOptionsNotification()",
257 EXPECT_EQ("ok", script_result
);
259 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
261 // We don't use or check the notification's direction and language.
262 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
263 EXPECT_EQ("Title", base::UTF16ToUTF8(notification
.title()));
264 EXPECT_EQ("Contents", base::UTF16ToUTF8(notification
.message()));
265 EXPECT_EQ("replace-id", notification
.tag());
266 EXPECT_FALSE(notification
.icon().IsEmpty());
267 EXPECT_TRUE(notification
.silent());
269 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
270 EXPECT_EQ(kIconHeight
, notification
.icon().Height());
273 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
274 CloseDisplayedPersistentNotification
) {
275 std::string script_result
;
277 InfoBarResponder
accepting_responder(browser(), true);
278 ASSERT_TRUE(RunScript("RequestPermission()", &script_result
));
279 EXPECT_EQ("granted", script_result
);
281 ASSERT_TRUE(RunScript("DisplayPersistentNotification('action_close')",
283 EXPECT_EQ("ok", script_result
);
285 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
287 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
288 notification
.delegate()->Click();
290 ASSERT_TRUE(RunScript("GetMessageFromWorker()", &script_result
));
291 EXPECT_EQ("action_close", script_result
);
293 ASSERT_EQ(0u, ui_manager()->GetNotificationCount());
296 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
297 TestDisplayOriginContextMessage
) {
298 std::string script_result
;
300 // Creates a simple notification.
301 InfoBarResponder
accepting_responder(browser(), true);
302 ASSERT_TRUE(RunScript("RequestPermission()", &script_result
));
303 ASSERT_EQ("granted", script_result
);
304 ASSERT_TRUE(RunScript("DisplayPersistentNotification()", &script_result
));
306 net::HostPortPair host_port
= ServerHostPort();
308 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
310 EXPECT_EQ(base::UTF8ToUTF16(host_port
.ToString()),
311 notification
.context_message());
314 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
315 CheckFilePermissionNotGranted
) {
316 // TODO(dewittj): This test verifies that a bug exists in Chrome; the test
317 // will fail if the bug is fixed. The
318 // |PlatformNotificationServiceImpl::WebOriginDisplayName| function needs
319 // to be updated to properly display file:// URL origins.
320 // See crbug.com/402191.
321 std::string script_result
;
323 InfoBarResponder
accepting_responder_web(browser(), true);
325 DesktopNotificationService
* notification_service
=
326 DesktopNotificationServiceFactory::GetForProfile(browser()->profile());
327 ASSERT_TRUE(notification_service
);
328 message_center::NotifierId
web_notifier(TestPageUrl());
329 EXPECT_FALSE(notification_service
->IsNotifierEnabled(web_notifier
));
330 ASSERT_TRUE(RunScript("RequestPermission()", &script_result
));
331 EXPECT_EQ("granted", script_result
);
333 EXPECT_TRUE(notification_service
->IsNotifierEnabled(web_notifier
));
335 base::FilePath dir_source_root
;
336 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &dir_source_root
));
337 base::FilePath full_file_path
=
338 dir_source_root
.Append(server_root()).AppendASCII(kTestFileName
);
339 GURL
file_url(net::FilePathToFileURL(full_file_path
));
340 ui_test_utils::NavigateToURL(browser(), file_url
);
342 message_center::NotifierId
file_notifier(file_url
);
343 EXPECT_FALSE(notification_service
->IsNotifierEnabled(file_notifier
));
345 InfoBarResponder
accepting_responder_file(browser(), true);
346 ASSERT_TRUE(RunScript("RequestPermission()", &script_result
));
347 EXPECT_EQ("granted", script_result
);
349 EXPECT_FALSE(notification_service
->IsNotifierEnabled(file_notifier
))
350 << "If this test fails, you may have fixed a bug preventing file origins "
351 << "from sending their origin from Blink; if so you need to update the "
352 << "display function for notification origins to show the file path.";
355 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
356 DataUrlAsNotificationImage
) {
357 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
359 std::string script_result
;
360 ASSERT_TRUE(RunScript("DisplayPersistentNotificationDataUrlImage()",
362 EXPECT_EQ("ok", script_result
);
364 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
366 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
367 EXPECT_FALSE(notification
.icon().IsEmpty());
369 EXPECT_EQ("Data URL Title", base::UTF16ToUTF8(notification
.title()));
370 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
371 EXPECT_EQ(kIconHeight
, notification
.icon().Height());
374 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
375 BlobAsNotificationImage
) {
376 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
378 std::string script_result
;
379 ASSERT_TRUE(RunScript("DisplayPersistentNotificationBlobImage()",
381 EXPECT_EQ("ok", script_result
);
383 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
385 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
386 EXPECT_FALSE(notification
.icon().IsEmpty());
388 EXPECT_EQ("Blob Title", base::UTF16ToUTF8(notification
.title()));
389 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
390 EXPECT_EQ(kIconHeight
, notification
.icon().Height());