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(&notification_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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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(&registration);
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