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.
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/path_service.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
14 #include "chrome/browser/notifications/notification_permission_context.h"
15 #include "chrome/browser/notifications/notification_permission_context_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/browser/ui/website_settings/permission_bubble_manager.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "chrome/test/base/ui_test_utils.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"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "ui/base/l10n/l10n_util.h"
31 // -----------------------------------------------------------------------------
33 // Dimensions of the icon.png resource in the notification test data directory.
34 const int kIconWidth
= 100;
35 const int kIconHeight
= 100;
37 const int kNotificationVibrationPattern
[] = { 100, 200, 300 };
39 class PlatformNotificationServiceBrowserTest
: public InProcessBrowserTest
{
41 PlatformNotificationServiceBrowserTest();
42 ~PlatformNotificationServiceBrowserTest() override
{}
44 // InProcessBrowserTest overrides.
45 void SetUp() override
;
46 void SetUpCommandLine(base::CommandLine
* command_line
) override
;
47 void SetUpOnMainThread() override
;
48 void TearDown() override
;
51 // Returns the Platform Notification Service these unit tests are for.
52 PlatformNotificationServiceImpl
* service() const {
53 return PlatformNotificationServiceImpl::GetInstance();
56 // Grants permission to display Web Notifications for origin of the test
57 // page that's being used in this browser test.
58 void GrantNotificationPermissionForTest() const;
60 bool RequestAndAcceptPermission();
61 bool RequestAndDenyPermission();
63 // Returns the UI Manager on which notifications will be displayed.
64 StubNotificationUIManager
* ui_manager() const { return ui_manager_
.get(); }
66 const base::FilePath
& server_root() const { return server_root_
; }
68 // Navigates the browser to the test page indicated by |path|.
69 void NavigateToTestPage(const std::string
& path
) const;
71 // Executes |script| and stores the result as a string in |result|. A boolean
72 // will be returned, indicating whether the script was executed successfully.
73 bool RunScript(const std::string
& script
, std::string
* result
) const;
75 net::HostPortPair
ServerHostPort() const;
76 GURL
TestPageUrl() const;
79 std::string
RequestAndRespondToPermission(
80 PermissionBubbleManager::AutoResponseType bubble_response
);
82 content::WebContents
* GetActiveWebContents(Browser
* browser
) {
83 return browser
->tab_strip_model()->GetActiveWebContents();
86 const base::FilePath server_root_
;
87 const std::string test_page_url_
;
88 scoped_ptr
<StubNotificationUIManager
> ui_manager_
;
89 scoped_ptr
<net::SpawnedTestServer
> https_server_
;
92 // -----------------------------------------------------------------------------
95 const char kTestFileName
[] = "notifications/platform_notification_service.html";
98 PlatformNotificationServiceBrowserTest::PlatformNotificationServiceBrowserTest()
99 : server_root_(FILE_PATH_LITERAL("chrome/test/data")),
100 // The test server has a base directory that doesn't exist in the
102 test_page_url_(std::string("files/") + kTestFileName
) {
105 void PlatformNotificationServiceBrowserTest::SetUpCommandLine(
106 base::CommandLine
* command_line
) {
107 const testing::TestInfo
* const test_info
=
108 testing::UnitTest::GetInstance()->current_test_info();
109 if (strcmp(test_info
->name(), "WebNotificationSiteSettingsButton") == 0)
110 command_line
->AppendSwitch(switches::kNotificationSettingsButton
);
113 void PlatformNotificationServiceBrowserTest::SetUp() {
114 ui_manager_
.reset(new StubNotificationUIManager
);
115 https_server_
.reset(new net::SpawnedTestServer(
116 net::SpawnedTestServer::TYPE_HTTPS
,
117 net::BaseTestServer::SSLOptions(net::BaseTestServer::SSLOptions::CERT_OK
),
119 ASSERT_TRUE(https_server_
->Start());
121 service()->SetNotificationUIManagerForTesting(ui_manager_
.get());
123 InProcessBrowserTest::SetUp();
126 void PlatformNotificationServiceBrowserTest::SetUpOnMainThread() {
127 NavigateToTestPage(test_page_url_
);
129 InProcessBrowserTest::SetUpOnMainThread();
132 void PlatformNotificationServiceBrowserTest::TearDown() {
133 service()->SetNotificationUIManagerForTesting(nullptr);
136 void PlatformNotificationServiceBrowserTest::
137 GrantNotificationPermissionForTest() const {
138 GURL origin
= TestPageUrl().GetOrigin();
140 DesktopNotificationProfileUtil::GrantPermission(browser()->profile(), origin
);
141 ASSERT_EQ(CONTENT_SETTING_ALLOW
,
142 DesktopNotificationProfileUtil::GetContentSetting(
143 browser()->profile(), origin
));
146 void PlatformNotificationServiceBrowserTest::NavigateToTestPage(
147 const std::string
& path
) const {
148 ui_test_utils::NavigateToURL(browser(), https_server_
->GetURL(path
));
151 bool PlatformNotificationServiceBrowserTest::RunScript(
152 const std::string
& script
, std::string
* result
) const {
153 return content::ExecuteScriptAndExtractString(
154 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
159 net::HostPortPair
PlatformNotificationServiceBrowserTest::ServerHostPort()
161 return https_server_
->host_port_pair();
164 GURL
PlatformNotificationServiceBrowserTest::TestPageUrl() const {
165 return https_server_
->GetURL(test_page_url_
);
169 PlatformNotificationServiceBrowserTest::RequestAndRespondToPermission(
170 PermissionBubbleManager::AutoResponseType bubble_response
) {
172 content::WebContents
* web_contents
= GetActiveWebContents(browser());
173 PermissionBubbleManager::FromWebContents(web_contents
)
174 ->set_auto_response_for_test(bubble_response
);
175 EXPECT_TRUE(RunScript("RequestPermission();", &result
));
179 bool PlatformNotificationServiceBrowserTest::RequestAndAcceptPermission() {
181 RequestAndRespondToPermission(PermissionBubbleManager::ACCEPT_ALL
);
182 return "granted" == result
;
185 bool PlatformNotificationServiceBrowserTest::RequestAndDenyPermission() {
187 RequestAndRespondToPermission(PermissionBubbleManager::DENY_ALL
);
188 return "denied" == result
;
191 // -----------------------------------------------------------------------------
193 // TODO(peter): Move PlatformNotificationService-related tests over from
194 // notification_browsertest.cc to this file.
196 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
197 DisplayPersistentNotificationWithoutPermission
) {
198 RequestAndDenyPermission();
200 std::string script_result
;
201 ASSERT_TRUE(RunScript("DisplayPersistentNotification()", &script_result
));
203 "TypeError: No notification permission has been granted for this origin.",
206 ASSERT_EQ(0u, ui_manager()->GetNotificationCount());
209 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
210 DisplayPersistentNotificationWithPermission
) {
211 RequestAndAcceptPermission();
213 std::string script_result
;
214 ASSERT_TRUE(RunScript("DisplayPersistentNotification('action_none')",
216 EXPECT_EQ("ok", script_result
);
218 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
220 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
221 notification
.delegate()->Click();
223 ASSERT_TRUE(RunScript("GetMessageFromWorker()", &script_result
));
224 EXPECT_EQ("action_none", script_result
);
226 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
229 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
230 WebNotificationOptionsReflection
) {
231 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
233 // First, test the default values.
235 std::string script_result
;
236 ASSERT_TRUE(RunScript("DisplayPersistentNotification('Some title', {})",
238 EXPECT_EQ("ok", script_result
);
240 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
242 // We don't use or check the notification's direction and language.
243 const Notification
& default_notification
= ui_manager()->GetNotificationAt(0);
244 EXPECT_EQ("Some title", base::UTF16ToUTF8(default_notification
.title()));
245 EXPECT_EQ("", base::UTF16ToUTF8(default_notification
.message()));
246 EXPECT_EQ("", default_notification
.tag());
247 EXPECT_TRUE(default_notification
.icon().IsEmpty());
248 EXPECT_FALSE(default_notification
.silent());
249 EXPECT_FALSE(default_notification
.never_timeout());
251 // Now, test the non-default values.
253 ASSERT_TRUE(RunScript("DisplayPersistentAllOptionsNotification()",
255 EXPECT_EQ("ok", script_result
);
257 ASSERT_EQ(2u, ui_manager()->GetNotificationCount());
259 // We don't use or check the notification's direction and language.
260 const Notification
& all_options_notification
=
261 ui_manager()->GetNotificationAt(1);
262 EXPECT_EQ("Title", base::UTF16ToUTF8(all_options_notification
.title()));
263 EXPECT_EQ("Contents", base::UTF16ToUTF8(all_options_notification
.message()));
264 EXPECT_EQ("replace-id", all_options_notification
.tag());
265 EXPECT_FALSE(all_options_notification
.icon().IsEmpty());
266 EXPECT_TRUE(all_options_notification
.silent());
267 EXPECT_TRUE(all_options_notification
.never_timeout());
269 EXPECT_EQ(kIconWidth
, all_options_notification
.icon().Width());
270 EXPECT_EQ(kIconHeight
, all_options_notification
.icon().Height());
273 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
274 WebNotificationSiteSettingsButton
) {
275 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
277 std::string script_result
;
279 RunScript("DisplayPersistentAllOptionsNotification()", &script_result
));
280 EXPECT_EQ("ok", script_result
);
282 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
284 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
285 const std::vector
<message_center::ButtonInfo
>& buttons
=
286 notification
.buttons();
287 EXPECT_EQ(1u, buttons
.size());
288 EXPECT_EQ(l10n_util::GetStringUTF16(IDS_NOTIFICATION_SETTINGS
),
291 notification
.delegate()->ButtonClick(0);
292 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
295 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
296 WebNotificationOptionsVibrationPattern
) {
297 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
299 std::string script_result
;
300 ASSERT_TRUE(RunScript("DisplayPersistentNotificationVibrate()",
302 EXPECT_EQ("ok", script_result
);
304 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
306 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
307 EXPECT_EQ("Title", base::UTF16ToUTF8(notification
.title()));
308 EXPECT_EQ("Contents", base::UTF16ToUTF8(notification
.message()));
310 EXPECT_THAT(notification
.vibration_pattern(),
311 testing::ElementsAreArray(kNotificationVibrationPattern
));
314 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
315 CloseDisplayedPersistentNotification
) {
316 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
318 std::string script_result
;
319 ASSERT_TRUE(RunScript("DisplayPersistentNotification('action_close')",
321 EXPECT_EQ("ok", script_result
);
323 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
325 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
326 notification
.delegate()->Click();
328 ASSERT_TRUE(RunScript("GetMessageFromWorker()", &script_result
));
329 EXPECT_EQ("action_close", script_result
);
331 ASSERT_EQ(0u, ui_manager()->GetNotificationCount());
334 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
335 TestDisplayOriginContextMessage
) {
336 RequestAndAcceptPermission();
338 // Creates a simple notification.
339 std::string script_result
;
340 ASSERT_TRUE(RunScript("DisplayPersistentNotification()", &script_result
));
342 net::HostPortPair host_port
= ServerHostPort();
344 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
346 EXPECT_TRUE(notification
.context_message().empty());
347 EXPECT_EQ("https://" + host_port
.ToString() + "/",
348 notification
.origin_url().spec());
351 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
352 CheckFilePermissionNotGranted
) {
353 // TODO(felt): This DCHECKs when bubbles are enabled, when the file_url is
354 // persisted. crbug.com/502057
355 if (PermissionBubbleManager::Enabled())
358 // TODO(dewittj): It currently isn't possible to get the notification
359 // permission for a file:// URL. If that changes, this test will fail to
360 // remind the author that the
361 // |PlatformNotificationServiceImpl::WebOriginDisplayName| function needs
362 // to be updated to properly display file:// URL origins.
363 // See crbug.com/402191.
365 // This case should succeed because a normal page URL is used.
366 std::string script_result
;
368 NotificationPermissionContext
* permission_context
=
369 NotificationPermissionContextFactory::GetForProfile(browser()->profile());
370 ASSERT_TRUE(permission_context
);
372 EXPECT_EQ(CONTENT_SETTING_ASK
,
373 permission_context
->GetPermissionStatus(TestPageUrl(),
376 RequestAndAcceptPermission();
377 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
378 permission_context
->GetPermissionStatus(TestPageUrl(),
381 // This case should fail because a file URL is used.
382 base::FilePath dir_source_root
;
383 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &dir_source_root
));
384 base::FilePath full_file_path
=
385 dir_source_root
.Append(server_root()).AppendASCII(kTestFileName
);
386 GURL
file_url(net::FilePathToFileURL(full_file_path
));
388 ui_test_utils::NavigateToURL(browser(), file_url
);
390 EXPECT_EQ(CONTENT_SETTING_ASK
,
391 permission_context
->GetPermissionStatus(file_url
, file_url
));
393 RequestAndAcceptPermission();
394 EXPECT_EQ(CONTENT_SETTING_ASK
,
395 permission_context
->GetPermissionStatus(file_url
, file_url
))
396 << "If this test fails, you may have fixed a bug preventing file origins "
397 << "from sending their origin from Blink; if so you need to update the "
398 << "display function for notification origins to show the file path.";
401 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
402 DataUrlAsNotificationImage
) {
403 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
405 std::string script_result
;
406 ASSERT_TRUE(RunScript("DisplayPersistentNotificationDataUrlImage()",
408 EXPECT_EQ("ok", script_result
);
410 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
412 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
413 EXPECT_FALSE(notification
.icon().IsEmpty());
415 EXPECT_EQ("Data URL Title", base::UTF16ToUTF8(notification
.title()));
416 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
417 EXPECT_EQ(kIconHeight
, notification
.icon().Height());
420 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
421 BlobAsNotificationImage
) {
422 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
424 std::string script_result
;
425 ASSERT_TRUE(RunScript("DisplayPersistentNotificationBlobImage()",
427 EXPECT_EQ("ok", script_result
);
429 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
431 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
432 EXPECT_FALSE(notification
.icon().IsEmpty());
434 EXPECT_EQ("Blob Title", base::UTF16ToUTF8(notification
.title()));
435 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
436 EXPECT_EQ(kIconHeight
, notification
.icon().Height());