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/notifications/desktop_notification_profile_util.h"
13 #include "chrome/browser/notifications/notification_permission_context.h"
14 #include "chrome/browser/notifications/notification_permission_context_factory.h"
15 #include "chrome/browser/notifications/notification_test_util.h"
16 #include "chrome/browser/notifications/platform_notification_service_impl.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "net/base/filename_util.h"
24 #include "net/test/spawned_test_server/spawned_test_server.h"
25 #include "testing/gmock/include/gmock/gmock.h"
27 // -----------------------------------------------------------------------------
29 // Dimensions of the icon.png resource in the notification test data directory.
30 const int kIconWidth
= 100;
31 const int kIconHeight
= 100;
33 const int kNotificationVibrationPattern
[] = { 100, 200, 300 };
35 class PlatformNotificationServiceBrowserTest
: public InProcessBrowserTest
{
37 PlatformNotificationServiceBrowserTest();
38 ~PlatformNotificationServiceBrowserTest() override
{}
40 // InProcessBrowserTest overrides.
41 void SetUp() override
;
42 void SetUpOnMainThread() override
;
43 void TearDown() override
;
46 // Returns the Platform Notification Service these unit tests are for.
47 PlatformNotificationServiceImpl
* service() const {
48 return PlatformNotificationServiceImpl::GetInstance();
51 // Grants permission to display Web Notifications for origin of the test
52 // page that's being used in this browser test.
53 void GrantNotificationPermissionForTest() const;
55 bool RequestAndAcceptPermission();
56 bool RequestAndDenyPermission();
58 // Returns the UI Manager on which notifications will be displayed.
59 StubNotificationUIManager
* ui_manager() const { return ui_manager_
.get(); }
61 const base::FilePath
& server_root() const { return server_root_
; }
63 // Navigates the browser to the test page indicated by |path|.
64 void NavigateToTestPage(const std::string
& path
) const;
66 // Executes |script| and stores the result as a string in |result|. A boolean
67 // will be returned, indicating whether the script was executed successfully.
68 bool RunScript(const std::string
& script
, std::string
* result
) const;
70 net::HostPortPair
ServerHostPort() const;
71 GURL
TestPageUrl() const;
74 std::string
RequestAndRespondToPermission(
75 PermissionBubbleManager::AutoResponseType bubble_response
);
77 content::WebContents
* GetActiveWebContents(Browser
* browser
) {
78 return browser
->tab_strip_model()->GetActiveWebContents();
81 const base::FilePath server_root_
;
82 const std::string test_page_url_
;
83 scoped_ptr
<StubNotificationUIManager
> ui_manager_
;
84 scoped_ptr
<net::SpawnedTestServer
> https_server_
;
87 // -----------------------------------------------------------------------------
90 const char kTestFileName
[] = "notifications/platform_notification_service.html";
93 PlatformNotificationServiceBrowserTest::PlatformNotificationServiceBrowserTest()
94 : server_root_(FILE_PATH_LITERAL("chrome/test/data")),
95 // The test server has a base directory that doesn't exist in the
97 test_page_url_(std::string("files/") + kTestFileName
) {
100 void PlatformNotificationServiceBrowserTest::SetUp() {
101 ui_manager_
.reset(new StubNotificationUIManager
);
102 https_server_
.reset(new net::SpawnedTestServer(
103 net::SpawnedTestServer::TYPE_HTTPS
,
104 net::BaseTestServer::SSLOptions(net::BaseTestServer::SSLOptions::CERT_OK
),
106 ASSERT_TRUE(https_server_
->Start());
108 service()->SetNotificationUIManagerForTesting(ui_manager_
.get());
110 InProcessBrowserTest::SetUp();
113 void PlatformNotificationServiceBrowserTest::SetUpOnMainThread() {
114 NavigateToTestPage(test_page_url_
);
116 InProcessBrowserTest::SetUpOnMainThread();
119 void PlatformNotificationServiceBrowserTest::TearDown() {
120 service()->SetNotificationUIManagerForTesting(nullptr);
123 void PlatformNotificationServiceBrowserTest::
124 GrantNotificationPermissionForTest() const {
125 GURL origin
= TestPageUrl().GetOrigin();
127 DesktopNotificationProfileUtil::GrantPermission(browser()->profile(), origin
);
128 ASSERT_EQ(CONTENT_SETTING_ALLOW
,
129 DesktopNotificationProfileUtil::GetContentSetting(
130 browser()->profile(), origin
));
133 void PlatformNotificationServiceBrowserTest::NavigateToTestPage(
134 const std::string
& path
) const {
135 ui_test_utils::NavigateToURL(browser(), https_server_
->GetURL(path
));
138 bool PlatformNotificationServiceBrowserTest::RunScript(
139 const std::string
& script
, std::string
* result
) const {
140 return content::ExecuteScriptAndExtractString(
141 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
146 net::HostPortPair
PlatformNotificationServiceBrowserTest::ServerHostPort()
148 return https_server_
->host_port_pair();
151 GURL
PlatformNotificationServiceBrowserTest::TestPageUrl() const {
152 return https_server_
->GetURL(test_page_url_
);
156 PlatformNotificationServiceBrowserTest::RequestAndRespondToPermission(
157 PermissionBubbleManager::AutoResponseType bubble_response
) {
159 content::WebContents
* web_contents
= GetActiveWebContents(browser());
160 PermissionBubbleManager::FromWebContents(web_contents
)
161 ->set_auto_response_for_test(bubble_response
);
162 EXPECT_TRUE(RunScript("RequestPermission();", &result
));
166 bool PlatformNotificationServiceBrowserTest::RequestAndAcceptPermission() {
168 RequestAndRespondToPermission(PermissionBubbleManager::ACCEPT_ALL
);
169 return "granted" == result
;
172 bool PlatformNotificationServiceBrowserTest::RequestAndDenyPermission() {
174 RequestAndRespondToPermission(PermissionBubbleManager::DENY_ALL
);
175 return "denied" == result
;
178 // -----------------------------------------------------------------------------
180 // TODO(peter): Move PlatformNotificationService-related tests over from
181 // notification_browsertest.cc to this file.
183 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
184 DisplayPersistentNotificationWithoutPermission
) {
185 RequestAndDenyPermission();
187 std::string script_result
;
188 ASSERT_TRUE(RunScript("DisplayPersistentNotification()", &script_result
));
190 "TypeError: No notification permission has been granted for this origin.",
193 ASSERT_EQ(0u, ui_manager()->GetNotificationCount());
196 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
197 DisplayPersistentNotificationWithPermission
) {
198 RequestAndAcceptPermission();
200 std::string script_result
;
201 ASSERT_TRUE(RunScript("DisplayPersistentNotification('action_none')",
203 EXPECT_EQ("ok", script_result
);
205 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
207 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
208 notification
.delegate()->Click();
210 ASSERT_TRUE(RunScript("GetMessageFromWorker()", &script_result
));
211 EXPECT_EQ("action_none", script_result
);
213 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
216 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
217 WebNotificationOptionsReflection
) {
218 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
220 std::string script_result
;
221 ASSERT_TRUE(RunScript("DisplayPersistentAllOptionsNotification()",
223 EXPECT_EQ("ok", script_result
);
225 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
227 // We don't use or check the notification's direction and language.
228 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
229 EXPECT_EQ("Title", base::UTF16ToUTF8(notification
.title()));
230 EXPECT_EQ("Contents", base::UTF16ToUTF8(notification
.message()));
231 EXPECT_EQ("replace-id", notification
.tag());
232 EXPECT_FALSE(notification
.icon().IsEmpty());
233 EXPECT_TRUE(notification
.silent());
235 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
236 EXPECT_EQ(kIconHeight
, notification
.icon().Height());
239 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
240 WebNotificationOptionsVibrationPattern
) {
241 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
243 std::string script_result
;
244 ASSERT_TRUE(RunScript("DisplayPersistentNotificationVibrate()",
246 EXPECT_EQ("ok", script_result
);
248 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
250 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
251 EXPECT_EQ("Title", base::UTF16ToUTF8(notification
.title()));
252 EXPECT_EQ("Contents", base::UTF16ToUTF8(notification
.message()));
254 EXPECT_THAT(notification
.vibration_pattern(),
255 testing::ElementsAreArray(kNotificationVibrationPattern
));
258 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
259 CloseDisplayedPersistentNotification
) {
260 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
262 std::string script_result
;
263 ASSERT_TRUE(RunScript("DisplayPersistentNotification('action_close')",
265 EXPECT_EQ("ok", script_result
);
267 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
269 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
270 notification
.delegate()->Click();
272 ASSERT_TRUE(RunScript("GetMessageFromWorker()", &script_result
));
273 EXPECT_EQ("action_close", script_result
);
275 ASSERT_EQ(0u, ui_manager()->GetNotificationCount());
278 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
279 TestDisplayOriginContextMessage
) {
280 RequestAndAcceptPermission();
282 // Creates a simple notification.
283 std::string script_result
;
284 ASSERT_TRUE(RunScript("DisplayPersistentNotification()", &script_result
));
286 net::HostPortPair host_port
= ServerHostPort();
288 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
290 EXPECT_TRUE(notification
.context_message().empty());
291 EXPECT_EQ("https://" + host_port
.ToString() + "/",
292 notification
.origin_url().spec());
295 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
296 CheckFilePermissionNotGranted
) {
297 // TODO(felt): This DCHECKs when bubbles are enabled, when the file_url is
298 // persisted. crbug.com/502057
299 if (PermissionBubbleManager::Enabled())
302 // TODO(dewittj): It currently isn't possible to get the notification
303 // permission for a file:// URL. If that changes, this test will fail to
304 // remind the author that the
305 // |PlatformNotificationServiceImpl::WebOriginDisplayName| function needs
306 // to be updated to properly display file:// URL origins.
307 // See crbug.com/402191.
309 // This case should succeed because a normal page URL is used.
310 std::string script_result
;
312 NotificationPermissionContext
* permission_context
=
313 NotificationPermissionContextFactory::GetForProfile(browser()->profile());
314 ASSERT_TRUE(permission_context
);
316 EXPECT_EQ(CONTENT_SETTING_ASK
,
317 permission_context
->GetPermissionStatus(TestPageUrl(),
320 RequestAndAcceptPermission();
321 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
322 permission_context
->GetPermissionStatus(TestPageUrl(),
325 // This case should fail because a file URL is used.
326 base::FilePath dir_source_root
;
327 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &dir_source_root
));
328 base::FilePath full_file_path
=
329 dir_source_root
.Append(server_root()).AppendASCII(kTestFileName
);
330 GURL
file_url(net::FilePathToFileURL(full_file_path
));
332 ui_test_utils::NavigateToURL(browser(), file_url
);
334 EXPECT_EQ(CONTENT_SETTING_ASK
,
335 permission_context
->GetPermissionStatus(file_url
, file_url
));
337 RequestAndAcceptPermission();
338 EXPECT_EQ(CONTENT_SETTING_ASK
,
339 permission_context
->GetPermissionStatus(file_url
, file_url
))
340 << "If this test fails, you may have fixed a bug preventing file origins "
341 << "from sending their origin from Blink; if so you need to update the "
342 << "display function for notification origins to show the file path.";
345 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
346 DataUrlAsNotificationImage
) {
347 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
349 std::string script_result
;
350 ASSERT_TRUE(RunScript("DisplayPersistentNotificationDataUrlImage()",
352 EXPECT_EQ("ok", script_result
);
354 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
356 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
357 EXPECT_FALSE(notification
.icon().IsEmpty());
359 EXPECT_EQ("Data URL Title", base::UTF16ToUTF8(notification
.title()));
360 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
361 EXPECT_EQ(kIconHeight
, notification
.icon().Height());
364 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest
,
365 BlobAsNotificationImage
) {
366 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest());
368 std::string script_result
;
369 ASSERT_TRUE(RunScript("DisplayPersistentNotificationBlobImage()",
371 EXPECT_EQ("ok", script_result
);
373 ASSERT_EQ(1u, ui_manager()->GetNotificationCount());
375 const Notification
& notification
= ui_manager()->GetNotificationAt(0);
376 EXPECT_FALSE(notification
.icon().IsEmpty());
378 EXPECT_EQ("Blob Title", base::UTF16ToUTF8(notification
.title()));
379 EXPECT_EQ(kIconWidth
, notification
.icon().Width());
380 EXPECT_EQ(kIconHeight
, notification
.icon().Height());