1 // Copyright 2018 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 <stdint.h>
6 #include <memory>
7 #include <set>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/callback_forward.h"
13 #include "base/callback_helpers.h"
14 #include "base/macros.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "base/optional.h"
17 #include "base/run_loop.h"
18 #include "base/test/scoped_feature_list.h"
19 #include "base/test/test_simple_task_runner.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "base/time/time.h"
22 #include "content/browser/notifications/blink_notification_service_impl.h"
23 #include "content/browser/notifications/platform_notification_context_impl.h"
24 #include "content/browser/service_worker/embedded_worker_test_helper.h"
25 #include "content/browser/service_worker/service_worker_context_wrapper.h"
26 #include "content/public/browser/permission_type.h"
27 #include "content/public/common/content_client.h"
28 #include "content/public/common/content_features.h"
29 #include "content/public/test/browser_task_environment.h"
30 #include "content/public/test/mock_permission_manager.h"
31 #include "content/public/test/test_browser_context.h"
32 #include "content/public/test/test_utils.h"
33 #include "content/test/mock_platform_notification_service.h"
34 #include "content/test/test_content_browser_client.h"
35 #include "mojo/core/embedder/embedder.h"
36 #include "mojo/public/cpp/bindings/pending_remote.h"
37 #include "mojo/public/cpp/bindings/remote.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40 #include "third_party/blink/public/common/notifications/notification_constants.h"
41 #include "third_party/blink/public/common/notifications/notification_resources.h"
42 #include "third_party/blink/public/mojom/notifications/notification_service.mojom.h"
43 #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
44 #include "third_party/skia/include/core/SkBitmap.h"
45
46 using ::testing::Return;
47 using ::testing::_;
48
49 namespace content {
50
51 namespace {
52
53 const char kTestOrigin[] = "https://example.com";
54 const char kTestServiceWorkerUrl[] = "https://example.com/sw.js";
55 const char kBadMessageImproperNotificationImage[] =
56 "Received an unexpected message with image while notification images are "
57 "disabled.";
58 const char kBadMessageInvalidNotificationTriggerTimestamp[] =
59 "Received an invalid notification trigger timestamp.";
60
CreateBitmap(int width,int height,SkColor color)61 SkBitmap CreateBitmap(int width, int height, SkColor color) {
62 SkBitmap bitmap;
63 bitmap.allocN32Pixels(width, height);
64 bitmap.eraseColor(color);
65 return bitmap;
66 }
67
68 class MockNonPersistentNotificationListener
69 : public blink::mojom::NonPersistentNotificationListener {
70 public:
71 MockNonPersistentNotificationListener() = default;
72 ~MockNonPersistentNotificationListener() override = default;
73
74 mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener>
GetRemote()75 GetRemote() {
76 mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> remote;
77 receiver_.Bind(remote.InitWithNewPipeAndPassReceiver());
78 return remote;
79 }
80
81 // NonPersistentNotificationListener interface.
OnShow()82 void OnShow() override {}
OnClick(OnClickCallback completed_closure)83 void OnClick(OnClickCallback completed_closure) override {
84 std::move(completed_closure).Run();
85 }
OnClose(OnCloseCallback completed_closure)86 void OnClose(OnCloseCallback completed_closure) override {
87 std::move(completed_closure).Run();
88 }
89
90 private:
91 mojo::Receiver<blink::mojom::NonPersistentNotificationListener> receiver_{
92 this};
93 };
94
95 // This is for overriding the Platform Notification Service with a mock one.
96 class NotificationBrowserClient : public TestContentBrowserClient {
97 public:
NotificationBrowserClient(MockPlatformNotificationService * mock_platform_service)98 NotificationBrowserClient(
99 MockPlatformNotificationService* mock_platform_service)
100 : platform_notification_service_(mock_platform_service) {}
101
GetPlatformNotificationService(BrowserContext * browser_context)102 PlatformNotificationService* GetPlatformNotificationService(
103 BrowserContext* browser_context) override {
104 return platform_notification_service_;
105 }
106
107 private:
108 MockPlatformNotificationService* platform_notification_service_;
109 };
110
111 } // anonymous namespace
112
113 class BlinkNotificationServiceImplTest : public ::testing::Test {
114 public:
115 // Using REAL_IO_THREAD would give better coverage for thread safety, but
116 // at time of writing EmbeddedWorkerTestHelper didn't seem to support that.
BlinkNotificationServiceImplTest()117 BlinkNotificationServiceImplTest()
118 : task_environment_(BrowserTaskEnvironment::IO_MAINLOOP),
119 embedded_worker_helper_(
120 std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath())),
121 mock_platform_service_(&browser_context_),
122 notification_browser_client_(&mock_platform_service_) {
123 SetBrowserClientForTesting(¬ification_browser_client_);
124 }
125
126 ~BlinkNotificationServiceImplTest() override = default;
127
128 // ::testing::Test overrides.
SetUp()129 void SetUp() override {
130 notification_context_ = new PlatformNotificationContextImpl(
131 base::FilePath(), &browser_context_,
132 embedded_worker_helper_->context_wrapper());
133 notification_context_->Initialize();
134
135 // Wait for notification context to be initialized to avoid TSAN detecting
136 // a memory race in tests - in production the PlatformNotificationContext
137 // will be initialized long before it is read from so this is fine.
138 RunAllTasksUntilIdle();
139
140 notification_service_ = std::make_unique<BlinkNotificationServiceImpl>(
141 notification_context_.get(), &browser_context_,
142 embedded_worker_helper_->context_wrapper(),
143 url::Origin::Create(GURL(kTestOrigin)),
144 notification_service_remote_.BindNewPipeAndPassReceiver());
145
146 // Provide a mock permission manager to the |browser_context_|.
147 browser_context_.SetPermissionControllerDelegate(
148 std::make_unique<testing::NiceMock<MockPermissionManager>>());
149
150 mojo::core::SetDefaultProcessErrorCallback(base::AdaptCallbackForRepeating(
151 base::BindOnce(&BlinkNotificationServiceImplTest::OnMojoError,
152 base::Unretained(this))));
153 }
154
TearDown()155 void TearDown() override {
156 mojo::core::SetDefaultProcessErrorCallback(
157 mojo::core::ProcessErrorCallback());
158
159 embedded_worker_helper_.reset();
160
161 // Give pending shutdown operations a chance to finish.
162 base::RunLoop().RunUntilIdle();
163 }
164
RegisterServiceWorker(scoped_refptr<ServiceWorkerRegistration> * service_worker_registration)165 void RegisterServiceWorker(
166 scoped_refptr<ServiceWorkerRegistration>* service_worker_registration) {
167 int64_t service_worker_registration_id =
168 blink::mojom::kInvalidServiceWorkerRegistrationId;
169
170 blink::mojom::ServiceWorkerRegistrationOptions options;
171 options.scope = GURL(kTestOrigin);
172
173 {
174 base::RunLoop run_loop;
175 embedded_worker_helper_->context()->RegisterServiceWorker(
176 GURL(kTestServiceWorkerUrl), options,
177 blink::mojom::FetchClientSettingsObject::New(),
178 base::BindOnce(
179 &BlinkNotificationServiceImplTest::DidRegisterServiceWorker,
180 base::Unretained(this), &service_worker_registration_id,
181 run_loop.QuitClosure()));
182 run_loop.Run();
183 }
184
185 if (service_worker_registration_id ==
186 blink::mojom::kInvalidServiceWorkerRegistrationId) {
187 ADD_FAILURE() << "Could not obtain a valid Service Worker registration";
188 }
189
190 {
191 base::RunLoop run_loop;
192 embedded_worker_helper_->context()->registry()->FindRegistrationForId(
193 service_worker_registration_id, GURL(kTestOrigin),
194 base::BindOnce(&BlinkNotificationServiceImplTest::
195 DidFindServiceWorkerRegistration,
196 base::Unretained(this), service_worker_registration,
197 run_loop.QuitClosure()));
198
199 run_loop.Run();
200 }
201
202 // Wait for the worker to be activated.
203 base::RunLoop().RunUntilIdle();
204
205 if (!*service_worker_registration) {
206 ADD_FAILURE() << "Could not find the new Service Worker registration.";
207 }
208 }
209
DidRegisterServiceWorker(int64_t * out_service_worker_registration_id,base::OnceClosure quit_closure,blink::ServiceWorkerStatusCode status,const std::string & status_message,int64_t service_worker_registration_id)210 void DidRegisterServiceWorker(int64_t* out_service_worker_registration_id,
211 base::OnceClosure quit_closure,
212 blink::ServiceWorkerStatusCode status,
213 const std::string& status_message,
214 int64_t service_worker_registration_id) {
215 DCHECK(out_service_worker_registration_id);
216 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
217 << blink::ServiceWorkerStatusToString(status);
218
219 *out_service_worker_registration_id = service_worker_registration_id;
220
221 std::move(quit_closure).Run();
222 }
223
DidFindServiceWorkerRegistration(scoped_refptr<ServiceWorkerRegistration> * out_service_worker_registration,base::OnceClosure quit_closure,blink::ServiceWorkerStatusCode status,scoped_refptr<ServiceWorkerRegistration> service_worker_registration)224 void DidFindServiceWorkerRegistration(
225 scoped_refptr<ServiceWorkerRegistration>* out_service_worker_registration,
226 base::OnceClosure quit_closure,
227 blink::ServiceWorkerStatusCode status,
228 scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
229 DCHECK(out_service_worker_registration);
230 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
231 << blink::ServiceWorkerStatusToString(status);
232
233 *out_service_worker_registration = service_worker_registration;
234
235 std::move(quit_closure).Run();
236 }
237
DidGetPermissionStatus(base::OnceClosure quit_closure,blink::mojom::PermissionStatus permission_status)238 void DidGetPermissionStatus(
239 base::OnceClosure quit_closure,
240 blink::mojom::PermissionStatus permission_status) {
241 permission_callback_result_ = permission_status;
242 std::move(quit_closure).Run();
243 }
244
GetPermissionCallbackResult()245 blink::mojom::PermissionStatus GetPermissionCallbackResult() {
246 return permission_callback_result_;
247 }
248
DidDisplayPersistentNotification(base::OnceClosure quit_closure,blink::mojom::PersistentNotificationError error)249 void DidDisplayPersistentNotification(
250 base::OnceClosure quit_closure,
251 blink::mojom::PersistentNotificationError error) {
252 display_persistent_callback_result_ = error;
253 std::move(quit_closure).Run();
254 }
255
DidGetNotifications(base::OnceClosure quit_closure,const std::vector<std::string> & notification_ids,const std::vector<blink::PlatformNotificationData> & notification_datas)256 void DidGetNotifications(
257 base::OnceClosure quit_closure,
258 const std::vector<std::string>& notification_ids,
259 const std::vector<blink::PlatformNotificationData>& notification_datas) {
260 get_notifications_callback_result_ = notification_ids;
261 std::move(quit_closure).Run();
262 }
263
DidGetNotificationDataFromContext(base::OnceClosure quit_closure,bool success,const std::vector<NotificationDatabaseData> & notification_datas)264 void DidGetNotificationDataFromContext(
265 base::OnceClosure quit_closure,
266 bool success,
267 const std::vector<NotificationDatabaseData>& notification_datas) {
268 get_notifications_data_ = notification_datas;
269 std::move(quit_closure).Run();
270 }
271
DidGetNotificationResourcesFromContext(base::OnceClosure quit_closure,bool success,const blink::NotificationResources & notification_resources)272 void DidGetNotificationResourcesFromContext(
273 base::OnceClosure quit_closure,
274 bool success,
275 const blink::NotificationResources& notification_resources) {
276 if (success) {
277 get_notification_resources_ = notification_resources;
278 } else {
279 get_notification_resources_ = base::nullopt;
280 }
281 std::move(quit_closure).Run();
282 }
283
DidGetDisplayedNotifications(base::OnceClosure quit_closure,std::set<std::string> notification_ids,bool supports_synchronization)284 void DidGetDisplayedNotifications(base::OnceClosure quit_closure,
285 std::set<std::string> notification_ids,
286 bool supports_synchronization) {
287 get_displayed_callback_result_ = std::move(notification_ids);
288 std::move(quit_closure).Run();
289 }
290
DidReadNotificationData(base::OnceClosure quit_closure,bool success,const NotificationDatabaseData & data)291 void DidReadNotificationData(base::OnceClosure quit_closure,
292 bool success,
293 const NotificationDatabaseData& data) {
294 read_notification_data_callback_result_ = success;
295 std::move(quit_closure).Run();
296 }
297
DisplayNonPersistentNotification(const std::string & token,const blink::PlatformNotificationData & platform_notification_data,const blink::NotificationResources & notification_resources,mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> event_listener_remote)298 void DisplayNonPersistentNotification(
299 const std::string& token,
300 const blink::PlatformNotificationData& platform_notification_data,
301 const blink::NotificationResources& notification_resources,
302 mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener>
303 event_listener_remote) {
304 notification_service_remote_->DisplayNonPersistentNotification(
305 token, platform_notification_data, notification_resources,
306 std::move(event_listener_remote));
307 // TODO(https://crbug.com/787459): Pass a callback to
308 // DisplayNonPersistentNotification instead of waiting for all tasks to run
309 // here; a callback parameter will be needed anyway to enable
310 // non-persistent notification event acknowledgements - see bug.
311 RunAllTasksUntilIdle();
312 }
313
DisplayPersistentNotificationSync(int64_t service_worker_registration_id,const blink::PlatformNotificationData & platform_notification_data,const blink::NotificationResources & notification_resources)314 void DisplayPersistentNotificationSync(
315 int64_t service_worker_registration_id,
316 const blink::PlatformNotificationData& platform_notification_data,
317 const blink::NotificationResources& notification_resources) {
318 base::RunLoop run_loop;
319 notification_service_remote_.set_disconnect_handler(run_loop.QuitClosure());
320 notification_service_remote_->DisplayPersistentNotification(
321 service_worker_registration_id, platform_notification_data,
322 notification_resources,
323 base::BindOnce(
324 &BlinkNotificationServiceImplTest::DidDisplayPersistentNotification,
325 base::Unretained(this), run_loop.QuitClosure()));
326 run_loop.Run();
327 }
328
GetNotificationsSync(int64_t service_worker_registration_id,const std::string & filter_tag,bool include_triggered)329 std::vector<std::string> GetNotificationsSync(
330 int64_t service_worker_registration_id,
331 const std::string& filter_tag,
332 bool include_triggered) {
333 base::RunLoop run_loop;
334 notification_service_->GetNotifications(
335 service_worker_registration_id, filter_tag, include_triggered,
336 base::BindOnce(&BlinkNotificationServiceImplTest::DidGetNotifications,
337 base::Unretained(this), run_loop.QuitClosure()));
338 run_loop.Run();
339 return get_notifications_callback_result_;
340 }
341
CountDisplayedNotificationsSync(int64_t service_worker_registration_id,const std::string & filter_tag)342 size_t CountDisplayedNotificationsSync(int64_t service_worker_registration_id,
343 const std::string& filter_tag) {
344 return GetNotificationsSync(service_worker_registration_id, filter_tag,
345 /* include_triggered= */ false)
346 .size();
347 }
348
CountScheduledNotificationsSync(int64_t service_worker_registration_id,const std::string & filter_tag)349 size_t CountScheduledNotificationsSync(int64_t service_worker_registration_id,
350 const std::string& filter_tag) {
351 return GetNotificationsSync(service_worker_registration_id, filter_tag,
352 /* include_triggered= */ true)
353 .size();
354 }
355
GetNotificationDataFromContextSync(int64_t service_worker_registration_id,const std::string & filter_tag,bool include_triggered)356 std::vector<NotificationDatabaseData> GetNotificationDataFromContextSync(
357 int64_t service_worker_registration_id,
358 const std::string& filter_tag,
359 bool include_triggered) {
360 base::RunLoop run_loop;
361 notification_context_->ReadAllNotificationDataForServiceWorkerRegistration(
362 GURL(kTestOrigin), service_worker_registration_id,
363 base::AdaptCallbackForRepeating(
364 base::BindOnce(&BlinkNotificationServiceImplTest::
365 DidGetNotificationDataFromContext,
366 base::Unretained(this), run_loop.QuitClosure())));
367 run_loop.Run();
368 return get_notifications_data_;
369 }
370
371 base::Optional<blink::NotificationResources>
GetNotificationResourcesFromContextSync(const std::string & notification_id)372 GetNotificationResourcesFromContextSync(const std::string& notification_id) {
373 base::RunLoop run_loop;
374 notification_context_->ReadNotificationResources(
375 notification_id, GURL(kTestOrigin),
376 base::AdaptCallbackForRepeating(
377 base::BindOnce(&BlinkNotificationServiceImplTest::
378 DidGetNotificationResourcesFromContext,
379 base::Unretained(this), run_loop.QuitClosure())));
380 run_loop.Run();
381 return get_notification_resources_;
382 }
383
384 // Synchronous wrapper of
385 // PlatformNotificationService::GetDisplayedNotifications
GetDisplayedNotifications()386 std::set<std::string> GetDisplayedNotifications() {
387 base::RunLoop run_loop;
388 mock_platform_service_.GetDisplayedNotifications(
389 base::BindOnce(
390 &BlinkNotificationServiceImplTest::DidGetDisplayedNotifications,
391 base::Unretained(this), run_loop.QuitClosure()));
392 run_loop.Run();
393 return get_displayed_callback_result_;
394 }
395
396 // Synchronous wrapper of
397 // PlatformNotificationContext::ReadNotificationData
ReadNotificationData(const std::string & notification_id)398 bool ReadNotificationData(const std::string& notification_id) {
399 base::RunLoop run_loop;
400 notification_context_->ReadNotificationDataAndRecordInteraction(
401 notification_id, GURL(kTestOrigin),
402 PlatformNotificationContext::Interaction::NONE,
403 base::AdaptCallbackForRepeating(base::BindOnce(
404 &BlinkNotificationServiceImplTest::DidReadNotificationData,
405 base::Unretained(this), run_loop.QuitClosure())));
406 run_loop.Run();
407 return read_notification_data_callback_result_;
408 }
409
410 // Updates the permission status for the |kTestOrigin| to the given
411 // |permission_status| through the PermissionManager.
SetPermissionStatus(blink::mojom::PermissionStatus permission_status)412 void SetPermissionStatus(blink::mojom::PermissionStatus permission_status) {
413 MockPermissionManager* mock_permission_manager =
414 static_cast<MockPermissionManager*>(
415 browser_context_.GetPermissionControllerDelegate());
416
417 ON_CALL(*mock_permission_manager,
418 GetPermissionStatus(PermissionType::NOTIFICATIONS, _, _))
419 .WillByDefault(Return(permission_status));
420 }
421
422 protected:
OnMojoError(const std::string & error)423 void OnMojoError(const std::string& error) { bad_messages_.push_back(error); }
424
425 BrowserTaskEnvironment task_environment_; // Must be first member.
426
427 std::unique_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_;
428
429 std::unique_ptr<BlinkNotificationServiceImpl> notification_service_;
430
431 mojo::Remote<blink::mojom::NotificationService> notification_service_remote_;
432
433 TestBrowserContext browser_context_;
434
435 scoped_refptr<PlatformNotificationContextImpl> notification_context_;
436
437 MockPlatformNotificationService mock_platform_service_;
438
439 MockNonPersistentNotificationListener non_persistent_notification_listener_;
440
441 blink::mojom::PersistentNotificationError display_persistent_callback_result_;
442
443 std::vector<std::string> bad_messages_;
444
445 private:
446 NotificationBrowserClient notification_browser_client_;
447
448 blink::mojom::PermissionStatus permission_callback_result_ =
449 blink::mojom::PermissionStatus::ASK;
450
451 std::set<std::string> get_displayed_callback_result_;
452
453 std::vector<std::string> get_notifications_callback_result_;
454
455 std::vector<NotificationDatabaseData> get_notifications_data_;
456
457 base::Optional<blink::NotificationResources> get_notification_resources_;
458
459 bool read_notification_data_callback_result_ = false;
460
461 DISALLOW_COPY_AND_ASSIGN(BlinkNotificationServiceImplTest);
462 };
463
TEST_F(BlinkNotificationServiceImplTest,GetPermissionStatus)464 TEST_F(BlinkNotificationServiceImplTest, GetPermissionStatus) {
465 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
466
467 {
468 base::RunLoop run_loop;
469 notification_service_->GetPermissionStatus(base::BindOnce(
470 &BlinkNotificationServiceImplTest::DidGetPermissionStatus,
471 base::Unretained(this), run_loop.QuitClosure()));
472 run_loop.Run();
473 }
474
475 EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED,
476 GetPermissionCallbackResult());
477
478 SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
479
480 {
481 base::RunLoop run_loop;
482 notification_service_->GetPermissionStatus(base::BindOnce(
483 &BlinkNotificationServiceImplTest::DidGetPermissionStatus,
484 base::Unretained(this), run_loop.QuitClosure()));
485 run_loop.Run();
486 }
487
488 EXPECT_EQ(blink::mojom::PermissionStatus::DENIED,
489 GetPermissionCallbackResult());
490
491 SetPermissionStatus(blink::mojom::PermissionStatus::ASK);
492
493 {
494 base::RunLoop run_loop;
495 notification_service_->GetPermissionStatus(base::BindOnce(
496 &BlinkNotificationServiceImplTest::DidGetPermissionStatus,
497 base::Unretained(this), run_loop.QuitClosure()));
498 run_loop.Run();
499 }
500
501 EXPECT_EQ(blink::mojom::PermissionStatus::ASK, GetPermissionCallbackResult());
502 }
503
TEST_F(BlinkNotificationServiceImplTest,DisplayNonPersistentNotificationWithPermission)504 TEST_F(BlinkNotificationServiceImplTest,
505 DisplayNonPersistentNotificationWithPermission) {
506 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
507
508 DisplayNonPersistentNotification(
509 "token", blink::PlatformNotificationData(),
510 blink::NotificationResources(),
511 non_persistent_notification_listener_.GetRemote());
512
513 EXPECT_EQ(1u, GetDisplayedNotifications().size());
514 }
515
TEST_F(BlinkNotificationServiceImplTest,DisplayNonPersistentNotificationWithoutPermission)516 TEST_F(BlinkNotificationServiceImplTest,
517 DisplayNonPersistentNotificationWithoutPermission) {
518 SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
519
520 DisplayNonPersistentNotification(
521 "token", blink::PlatformNotificationData(),
522 blink::NotificationResources(),
523 non_persistent_notification_listener_.GetRemote());
524
525 EXPECT_EQ(0u, GetDisplayedNotifications().size());
526 }
527
TEST_F(BlinkNotificationServiceImplTest,DisplayNonPersistentNotificationWithContentImageSwitchOn)528 TEST_F(BlinkNotificationServiceImplTest,
529 DisplayNonPersistentNotificationWithContentImageSwitchOn) {
530 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
531
532 blink::NotificationResources resources;
533 resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
534 DisplayNonPersistentNotification(
535 "token", blink::PlatformNotificationData(), resources,
536 non_persistent_notification_listener_.GetRemote());
537
538 EXPECT_EQ(1u, GetDisplayedNotifications().size());
539 }
540
TEST_F(BlinkNotificationServiceImplTest,DisplayNonPersistentNotificationWithContentImageSwitchOff)541 TEST_F(BlinkNotificationServiceImplTest,
542 DisplayNonPersistentNotificationWithContentImageSwitchOff) {
543 base::test::ScopedFeatureList scoped_feature_list;
544 scoped_feature_list.InitAndDisableFeature(
545 features::kNotificationContentImage);
546 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
547
548 ASSERT_TRUE(bad_messages_.empty());
549 blink::NotificationResources resources;
550 resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
551 DisplayNonPersistentNotification(
552 "token", blink::PlatformNotificationData(), resources,
553 non_persistent_notification_listener_.GetRemote());
554 EXPECT_EQ(1u, bad_messages_.size());
555 EXPECT_EQ(kBadMessageImproperNotificationImage, bad_messages_[0]);
556 }
557
TEST_F(BlinkNotificationServiceImplTest,DisplayPersistentNotificationWithContentImageSwitchOn)558 TEST_F(BlinkNotificationServiceImplTest,
559 DisplayPersistentNotificationWithContentImageSwitchOn) {
560 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
561
562 scoped_refptr<ServiceWorkerRegistration> registration;
563 RegisterServiceWorker(®istration);
564
565 blink::NotificationResources resources;
566 resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
567 DisplayPersistentNotificationSync(
568 registration->id(), blink::PlatformNotificationData(), resources);
569
570 EXPECT_EQ(blink::mojom::PersistentNotificationError::NONE,
571 display_persistent_callback_result_);
572
573 // Wait for service to receive the Display call.
574 RunAllTasksUntilIdle();
575
576 EXPECT_EQ(1u, GetDisplayedNotifications().size());
577 }
578
TEST_F(BlinkNotificationServiceImplTest,DisplayPersistentNotificationWithContentImageSwitchOff)579 TEST_F(BlinkNotificationServiceImplTest,
580 DisplayPersistentNotificationWithContentImageSwitchOff) {
581 base::test::ScopedFeatureList scoped_feature_list;
582 scoped_feature_list.InitAndDisableFeature(
583 features::kNotificationContentImage);
584 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
585
586 scoped_refptr<ServiceWorkerRegistration> registration;
587 RegisterServiceWorker(®istration);
588
589 ASSERT_TRUE(bad_messages_.empty());
590 blink::NotificationResources resources;
591 resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
592 DisplayPersistentNotificationSync(
593 registration->id(), blink::PlatformNotificationData(), resources);
594 EXPECT_EQ(1u, bad_messages_.size());
595 EXPECT_EQ(kBadMessageImproperNotificationImage, bad_messages_[0]);
596 }
597
TEST_F(BlinkNotificationServiceImplTest,DisplayPersistentNotificationWithPermission)598 TEST_F(BlinkNotificationServiceImplTest,
599 DisplayPersistentNotificationWithPermission) {
600 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
601
602 scoped_refptr<ServiceWorkerRegistration> registration;
603 RegisterServiceWorker(®istration);
604
605 DisplayPersistentNotificationSync(registration->id(),
606 blink::PlatformNotificationData(),
607 blink::NotificationResources());
608
609 EXPECT_EQ(blink::mojom::PersistentNotificationError::NONE,
610 display_persistent_callback_result_);
611
612 // Wait for service to receive the Display call.
613 RunAllTasksUntilIdle();
614
615 EXPECT_EQ(1u, GetDisplayedNotifications().size());
616 }
617
TEST_F(BlinkNotificationServiceImplTest,CloseDisplayedPersistentNotification)618 TEST_F(BlinkNotificationServiceImplTest, CloseDisplayedPersistentNotification) {
619 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
620
621 scoped_refptr<ServiceWorkerRegistration> registration;
622 RegisterServiceWorker(®istration);
623
624 DisplayPersistentNotificationSync(registration->id(),
625 blink::PlatformNotificationData(),
626 blink::NotificationResources());
627
628 ASSERT_EQ(blink::mojom::PersistentNotificationError::NONE,
629 display_persistent_callback_result_);
630
631 // Wait for service to receive the Display call.
632 RunAllTasksUntilIdle();
633
634 std::set<std::string> notification_ids = GetDisplayedNotifications();
635 ASSERT_EQ(1u, notification_ids.size());
636
637 notification_service_->ClosePersistentNotification(*notification_ids.begin());
638
639 // Wait for service to receive the Close call.
640 RunAllTasksUntilIdle();
641
642 EXPECT_EQ(0u, GetDisplayedNotifications().size());
643 }
644
TEST_F(BlinkNotificationServiceImplTest,ClosePersistentNotificationDeletesFromDatabase)645 TEST_F(BlinkNotificationServiceImplTest,
646 ClosePersistentNotificationDeletesFromDatabase) {
647 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
648
649 scoped_refptr<ServiceWorkerRegistration> registration;
650 RegisterServiceWorker(®istration);
651
652 DisplayPersistentNotificationSync(registration->id(),
653 blink::PlatformNotificationData(),
654 blink::NotificationResources());
655
656 ASSERT_EQ(blink::mojom::PersistentNotificationError::NONE,
657 display_persistent_callback_result_);
658
659 // Wait for service to receive the Display call.
660 RunAllTasksUntilIdle();
661
662 std::set<std::string> notification_ids = GetDisplayedNotifications();
663 ASSERT_EQ(1u, notification_ids.size());
664
665 std::string notification_id = *notification_ids.begin();
666
667 // Check data was indeed written.
668 ASSERT_EQ(true /* success */, ReadNotificationData(notification_id));
669
670 notification_service_->ClosePersistentNotification(notification_id);
671
672 // Wait for service to receive the Close call.
673 RunAllTasksUntilIdle();
674
675 // Data should now be deleted.
676 EXPECT_EQ(false /* success */, ReadNotificationData(notification_id));
677 }
678
TEST_F(BlinkNotificationServiceImplTest,DisplayPersistentNotificationWithoutPermission)679 TEST_F(BlinkNotificationServiceImplTest,
680 DisplayPersistentNotificationWithoutPermission) {
681 SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
682
683 scoped_refptr<ServiceWorkerRegistration> registration;
684 RegisterServiceWorker(®istration);
685
686 DisplayPersistentNotificationSync(registration->id(),
687 blink::PlatformNotificationData(),
688 blink::NotificationResources());
689
690 EXPECT_EQ(blink::mojom::PersistentNotificationError::PERMISSION_DENIED,
691 display_persistent_callback_result_);
692
693 // Give Service a chance to receive any unexpected Display calls.
694 RunAllTasksUntilIdle();
695
696 EXPECT_EQ(0u, GetDisplayedNotifications().size());
697 }
698
TEST_F(BlinkNotificationServiceImplTest,DisplayMultiplePersistentNotifications)699 TEST_F(BlinkNotificationServiceImplTest,
700 DisplayMultiplePersistentNotifications) {
701 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
702
703 scoped_refptr<ServiceWorkerRegistration> registration;
704 RegisterServiceWorker(®istration);
705
706 DisplayPersistentNotificationSync(registration->id(),
707 blink::PlatformNotificationData(),
708 blink::NotificationResources());
709
710 DisplayPersistentNotificationSync(registration->id(),
711 blink::PlatformNotificationData(),
712 blink::NotificationResources());
713
714 // Wait for service to receive all the Display calls.
715 RunAllTasksUntilIdle();
716
717 EXPECT_EQ(2u, GetDisplayedNotifications().size());
718 }
719
TEST_F(BlinkNotificationServiceImplTest,GetNotifications)720 TEST_F(BlinkNotificationServiceImplTest, GetNotifications) {
721 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
722
723 scoped_refptr<ServiceWorkerRegistration> registration;
724 RegisterServiceWorker(®istration);
725
726 EXPECT_EQ(0u, CountDisplayedNotificationsSync(registration->id(),
727 /* filter_tag= */ ""));
728
729 DisplayPersistentNotificationSync(registration->id(),
730 blink::PlatformNotificationData(),
731 blink::NotificationResources());
732
733 // Wait for service to receive all the Display calls.
734 RunAllTasksUntilIdle();
735
736 EXPECT_EQ(1u, CountDisplayedNotificationsSync(registration->id(),
737 /* filter_tag= */ ""));
738 }
739
TEST_F(BlinkNotificationServiceImplTest,GetNotificationsWithoutPermission)740 TEST_F(BlinkNotificationServiceImplTest, GetNotificationsWithoutPermission) {
741 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
742
743 scoped_refptr<ServiceWorkerRegistration> registration;
744 RegisterServiceWorker(®istration);
745
746 DisplayPersistentNotificationSync(registration->id(),
747 blink::PlatformNotificationData(),
748 blink::NotificationResources());
749
750 // Wait for service to receive all the Display calls.
751 RunAllTasksUntilIdle();
752
753 SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
754
755 EXPECT_EQ(0u, CountDisplayedNotificationsSync(registration->id(),
756 /* filter_tag= */ ""));
757 }
758
TEST_F(BlinkNotificationServiceImplTest,GetNotificationsWithFilter)759 TEST_F(BlinkNotificationServiceImplTest, GetNotificationsWithFilter) {
760 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
761
762 scoped_refptr<ServiceWorkerRegistration> registration;
763 RegisterServiceWorker(®istration);
764
765 blink::PlatformNotificationData platform_notification_data;
766 platform_notification_data.tag = "tagA";
767
768 blink::PlatformNotificationData other_platform_notification_data;
769 other_platform_notification_data.tag = "tagB";
770
771 DisplayPersistentNotificationSync(registration->id(),
772 platform_notification_data,
773 blink::NotificationResources());
774
775 DisplayPersistentNotificationSync(registration->id(),
776 other_platform_notification_data,
777 blink::NotificationResources());
778
779 // Wait for service to receive all the Display calls.
780 RunAllTasksUntilIdle();
781
782 EXPECT_EQ(2u, CountDisplayedNotificationsSync(registration->id(), ""));
783 EXPECT_EQ(1u, CountDisplayedNotificationsSync(registration->id(), "tagA"));
784 EXPECT_EQ(1u, CountDisplayedNotificationsSync(registration->id(), "tagB"));
785 EXPECT_EQ(0u, CountDisplayedNotificationsSync(registration->id(), "tagC"));
786 EXPECT_EQ(0u, CountDisplayedNotificationsSync(registration->id(), "tag"));
787 }
788
TEST_F(BlinkNotificationServiceImplTest,GetTriggeredNotificationsWithFilter)789 TEST_F(BlinkNotificationServiceImplTest, GetTriggeredNotificationsWithFilter) {
790 base::test::ScopedFeatureList scoped_feature_list;
791 scoped_feature_list.InitAndEnableFeature(features::kNotificationTriggers);
792
793 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
794
795 scoped_refptr<ServiceWorkerRegistration> registration;
796 RegisterServiceWorker(®istration);
797
798 base::Time timestamp = base::Time::Now() + base::TimeDelta::FromSeconds(10);
799 blink::PlatformNotificationData platform_notification_data;
800 platform_notification_data.tag = "tagA";
801 platform_notification_data.show_trigger_timestamp = timestamp;
802
803 blink::PlatformNotificationData other_platform_notification_data;
804 other_platform_notification_data.tag = "tagB";
805 other_platform_notification_data.show_trigger_timestamp = timestamp;
806
807 blink::PlatformNotificationData displayed_notification_data;
808 displayed_notification_data.tag = "tagC";
809
810 DisplayPersistentNotificationSync(registration->id(),
811 platform_notification_data,
812 blink::NotificationResources());
813
814 DisplayPersistentNotificationSync(registration->id(),
815 other_platform_notification_data,
816 blink::NotificationResources());
817
818 // Wait for service to receive all the Display calls.
819 RunAllTasksUntilIdle();
820
821 EXPECT_EQ(0u, CountDisplayedNotificationsSync(registration->id(), ""));
822 EXPECT_EQ(2u, CountScheduledNotificationsSync(registration->id(), ""));
823 EXPECT_EQ(1u, CountScheduledNotificationsSync(registration->id(), "tagA"));
824 EXPECT_EQ(1u, CountScheduledNotificationsSync(registration->id(), "tagB"));
825 EXPECT_EQ(0u, CountScheduledNotificationsSync(registration->id(), "tagC"));
826 EXPECT_EQ(0u, CountScheduledNotificationsSync(registration->id(), "tag"));
827 }
828
TEST_F(BlinkNotificationServiceImplTest,ResourcesStoredForTriggered)829 TEST_F(BlinkNotificationServiceImplTest, ResourcesStoredForTriggered) {
830 base::test::ScopedFeatureList scoped_feature_list;
831 scoped_feature_list.InitAndEnableFeature(features::kNotificationTriggers);
832
833 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
834
835 scoped_refptr<ServiceWorkerRegistration> registration;
836 RegisterServiceWorker(®istration);
837
838 base::Time timestamp = base::Time::Now() + base::TimeDelta::FromSeconds(10);
839 blink::PlatformNotificationData scheduled_notification_data;
840 scheduled_notification_data.tag = "tagA";
841 scheduled_notification_data.show_trigger_timestamp = timestamp;
842
843 blink::NotificationResources resources;
844 resources.notification_icon = CreateBitmap(10, 10, SK_ColorMAGENTA);
845
846 blink::PlatformNotificationData displayed_notification_data;
847 displayed_notification_data.tag = "tagB";
848
849 DisplayPersistentNotificationSync(registration->id(),
850 scheduled_notification_data, resources);
851
852 DisplayPersistentNotificationSync(registration->id(),
853 displayed_notification_data, resources);
854
855 // Wait for service to receive all the Display calls.
856 RunAllTasksUntilIdle();
857
858 auto notification_data =
859 GetNotificationDataFromContextSync(registration->id(), "", true);
860
861 EXPECT_EQ(2u, notification_data.size());
862
863 auto notification_a = notification_data[0].notification_data.tag == "tagA"
864 ? notification_data[0]
865 : notification_data[1];
866 auto notification_b = notification_data[0].notification_data.tag == "tagB"
867 ? notification_data[0]
868 : notification_data[1];
869 auto stored_resources_a =
870 GetNotificationResourcesFromContextSync(notification_a.notification_id);
871 auto stored_resources_b =
872 GetNotificationResourcesFromContextSync(notification_b.notification_id);
873
874 EXPECT_TRUE(stored_resources_a.has_value());
875 EXPECT_EQ(10, stored_resources_a.value().notification_icon.width());
876
877 EXPECT_FALSE(stored_resources_b.has_value());
878 }
879
TEST_F(BlinkNotificationServiceImplTest,NotCallingDisplayForTriggered)880 TEST_F(BlinkNotificationServiceImplTest, NotCallingDisplayForTriggered) {
881 base::test::ScopedFeatureList scoped_feature_list;
882 scoped_feature_list.InitAndEnableFeature(features::kNotificationTriggers);
883
884 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
885
886 scoped_refptr<ServiceWorkerRegistration> registration;
887 RegisterServiceWorker(®istration);
888
889 base::Time timestamp = base::Time::Now() + base::TimeDelta::FromSeconds(10);
890 blink::PlatformNotificationData scheduled_notification_data;
891 scheduled_notification_data.show_trigger_timestamp = timestamp;
892 blink::NotificationResources resources;
893
894 DisplayPersistentNotificationSync(registration->id(),
895 scheduled_notification_data, resources);
896
897 // Wait for service to receive all the Display calls.
898 RunAllTasksUntilIdle();
899
900 EXPECT_EQ(0u, GetDisplayedNotifications().size());
901 }
902
TEST_F(BlinkNotificationServiceImplTest,RejectsTriggerTimestampOverAYear)903 TEST_F(BlinkNotificationServiceImplTest, RejectsTriggerTimestampOverAYear) {
904 base::test::ScopedFeatureList scoped_feature_list;
905 scoped_feature_list.InitAndEnableFeature(features::kNotificationTriggers);
906
907 ASSERT_TRUE(bad_messages_.empty());
908
909 SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
910
911 scoped_refptr<ServiceWorkerRegistration> registration;
912 RegisterServiceWorker(®istration);
913
914 base::Time timestamp = base::Time::Now() +
915 blink::kMaxNotificationShowTriggerDelay +
916 base::TimeDelta::FromDays(1);
917
918 blink::PlatformNotificationData scheduled_notification_data;
919 scheduled_notification_data.show_trigger_timestamp = timestamp;
920 blink::NotificationResources resources;
921
922 DisplayPersistentNotificationSync(registration->id(),
923 scheduled_notification_data, resources);
924
925 EXPECT_EQ(1u, bad_messages_.size());
926 EXPECT_EQ(kBadMessageInvalidNotificationTriggerTimestamp, bad_messages_[0]);
927 }
928
929 } // namespace content
930