OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "base/test/simple_test_clock.h" | |
12 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
13 #include "content/browser/notifications/platform_notification_context_impl.h" | 14 #include "content/browser/notifications/platform_notification_context_impl.h" |
14 #include "content/browser/service_worker/embedded_worker_test_helper.h" | 15 #include "content/browser/service_worker/embedded_worker_test_helper.h" |
15 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 16 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
16 #include "content/common/service_worker/service_worker_types.h" | 17 #include "content/common/service_worker/service_worker_types.h" |
17 #include "content/public/browser/notification_database_data.h" | 18 #include "content/public/browser/notification_database_data.h" |
18 #include "content/public/common/notification_resources.h" | 19 #include "content/public/common/notification_resources.h" |
19 #include "content/public/test/test_browser_context.h" | 20 #include "content/public/test/test_browser_context.h" |
20 #include "content/public/test/test_browser_thread_bundle.h" | 21 #include "content/public/test/test_browser_thread_bundle.h" |
21 #include "content/test/mock_platform_notification_service.h" | 22 #include "content/test/mock_platform_notification_service.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 // Callback to provide when unregistering a Service Worker. Will write the | 79 // Callback to provide when unregistering a Service Worker. Will write the |
79 // resulting status code to |store_status|. | 80 // resulting status code to |store_status|. |
80 void DidUnregisterServiceWorker(ServiceWorkerStatusCode* store_status, | 81 void DidUnregisterServiceWorker(ServiceWorkerStatusCode* store_status, |
81 ServiceWorkerStatusCode status) { | 82 ServiceWorkerStatusCode status) { |
82 DCHECK(store_status); | 83 DCHECK(store_status); |
83 *store_status = status; | 84 *store_status = status; |
84 } | 85 } |
85 | 86 |
86 // Callback to provide when reading multiple notifications from the database. | 87 // Callback to provide when reading multiple notifications from the database. |
87 // Will store the success value in the class member, and write the read | 88 // Will store the success value in the class member, and write the read |
88 // notification datas to |store_notification_datas|. | 89 // notification datas to |*out_notification_datas|. |
89 void DidReadAllNotificationDatas( | 90 void DidReadAllNotificationDatas( |
90 std::vector<NotificationDatabaseData>* store_notification_datas, | 91 std::vector<NotificationDatabaseData>* out_notification_datas, |
91 bool success, | 92 bool success, |
92 const std::vector<NotificationDatabaseData>& notification_datas) { | 93 const std::vector<NotificationDatabaseData>& notification_datas) { |
93 DCHECK(store_notification_datas); | 94 DCHECK(out_notification_datas); |
94 | 95 |
95 success_ = success; | 96 success_ = success; |
96 *store_notification_datas = notification_datas; | 97 *out_notification_datas = notification_datas; |
98 } | |
99 | |
100 // Callback to provide when calling GetDisplayedNotifications on the | |
101 // PlatformNotificationService. | |
102 void DidGetDisplayedNotifications( | |
103 std::unique_ptr<std::set<std::string>>* out_notifications, | |
104 bool* out_supports_synchronization, | |
105 std::unique_ptr<std::set<std::string>> notifications, | |
106 bool supports_synchronization) { | |
107 DCHECK(out_notifications); | |
108 DCHECK(out_supports_synchronization); | |
109 | |
110 *out_notifications = std::move(notifications); | |
111 *out_supports_synchronization = supports_synchronization; | |
97 } | 112 } |
98 | 113 |
99 protected: | 114 protected: |
100 // Creates a new PlatformNotificationContextImpl instance. When using this | 115 // Creates a new PlatformNotificationContextImpl instance. When using this |
101 // method, the underlying database will always be created in memory. | 116 // method, the underlying database will always be created in memory. |
102 PlatformNotificationContextImpl* CreatePlatformNotificationContext() { | 117 PlatformNotificationContextImpl* CreatePlatformNotificationContext() { |
103 PlatformNotificationContextImpl* context = | 118 PlatformNotificationContextImpl* context = |
104 new PlatformNotificationContextImpl(base::FilePath(), &browser_context_, | 119 new PlatformNotificationContextImpl(base::FilePath(), &browser_context_, |
105 nullptr); | 120 nullptr); |
106 context->Initialize(); | 121 context->Initialize(); |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
544 // Delete the notification from the display service without removing it from | 559 // Delete the notification from the display service without removing it from |
545 // the database. It should automatically synchronize on the next read. | 560 // the database. It should automatically synchronize on the next read. |
546 service->ClosePersistentNotification(browser_context(), notification_id()); | 561 service->ClosePersistentNotification(browser_context(), notification_id()); |
547 context->ReadAllNotificationDataForServiceWorkerRegistration( | 562 context->ReadAllNotificationDataForServiceWorkerRegistration( |
548 origin, kFakeServiceWorkerRegistrationId, | 563 origin, kFakeServiceWorkerRegistrationId, |
549 base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas, | 564 base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas, |
550 base::Unretained(this), ¬ification_database_datas)); | 565 base::Unretained(this), ¬ification_database_datas)); |
551 base::RunLoop().RunUntilIdle(); | 566 base::RunLoop().RunUntilIdle(); |
552 | 567 |
553 ASSERT_TRUE(success()); | 568 ASSERT_TRUE(success()); |
554 ASSERT_EQ(0u, notification_database_datas.size()); | 569 ASSERT_EQ(0u, notification_database_datas.size()); |
awdf
2017/05/10 17:01:57
This line is now failing - see https://00e9e64baca
Peter Beverloo
2017/05/10 17:09:22
Done.
| |
555 | 570 |
556 context->ReadNotificationData( | 571 context->ReadNotificationData( |
557 notification_id(), origin, | 572 notification_id(), origin, |
558 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, | 573 base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, |
559 base::Unretained(this))); | 574 base::Unretained(this))); |
560 | 575 |
561 base::RunLoop().RunUntilIdle(); | 576 base::RunLoop().RunUntilIdle(); |
562 | 577 |
563 // The notification was removed, so we shouldn't be able to read it from | 578 // The notification was removed, so we shouldn't be able to read it from |
564 // the database anymore. | 579 // the database anymore. |
565 EXPECT_FALSE(success()); | 580 EXPECT_FALSE(success()); |
566 } | 581 } |
567 | 582 |
583 TEST_F(PlatformNotificationContextTest, SynchronizeNotificationsDisplayRace) { | |
584 // This test verifies that a possible race condition where a developer shows | |
585 // a notification, and then gets all shown notifications before waiting for | |
586 // acknowledgement (which, in itself, is too optimistic), is made less severe | |
587 // by remembering the most recently shown notification for a brief period of | |
588 // time. | |
589 | |
590 NotificationBrowserClient notification_browser_client; | |
591 SetBrowserClientForTesting(¬ification_browser_client); | |
592 | |
593 scoped_refptr<PlatformNotificationContextImpl> context = | |
594 CreatePlatformNotificationContext(); | |
595 | |
596 base::SimpleTestClock* clock = new base::SimpleTestClock(); | |
597 context->clock_ = base::WrapUnique(clock); | |
598 | |
599 GURL origin("https://example.com"); | |
600 NotificationDatabaseData notification_database_data; | |
601 notification_database_data.service_worker_registration_id = | |
602 kFakeServiceWorkerRegistrationId; | |
603 PlatformNotificationData notification_data; | |
604 content::NotificationResources notification_resources; | |
605 | |
606 context->WriteNotificationData( | |
607 origin, notification_database_data, | |
608 base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData, | |
609 base::Unretained(this))); | |
610 | |
611 base::RunLoop().RunUntilIdle(); | |
612 ASSERT_TRUE(success()); | |
613 EXPECT_FALSE(notification_id().empty()); | |
614 | |
615 // The |notification_data| deliberately has not been dispatched to the | |
616 // PlatformNotificationService yet. This will cause the mock to return that | |
617 // no notifications have been displayed, simulating the race condition. | |
618 | |
619 std::unique_ptr<std::set<std::string>> notifications; | |
620 bool supports_synchronization = false; | |
621 | |
622 PlatformNotificationService* service = | |
623 notification_browser_client.GetPlatformNotificationService(); | |
624 service->GetDisplayedNotifications( | |
625 browser_context(), | |
626 base::Bind(&PlatformNotificationContextTest::DidGetDisplayedNotifications, | |
627 base::Unretained(this), ¬ifications, | |
628 &supports_synchronization)); | |
629 | |
630 base::RunLoop().RunUntilIdle(); | |
631 ASSERT_TRUE(supports_synchronization); | |
632 ASSERT_EQ(notifications->size(), 0u); | |
633 | |
634 // Reading all notifications should still return the one notification that was | |
635 // displayed, since it was the most recent one. | |
636 | |
637 std::vector<NotificationDatabaseData> notification_database_datas; | |
638 context->ReadAllNotificationDataForServiceWorkerRegistration( | |
639 origin, kFakeServiceWorkerRegistrationId, | |
640 base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas, | |
641 base::Unretained(this), ¬ification_database_datas)); | |
642 | |
643 base::RunLoop().RunUntilIdle(); | |
644 | |
645 ASSERT_TRUE(success()); | |
646 ASSERT_EQ(1u, notification_database_datas.size()); | |
647 | |
648 // Now forward the time by a minute, which means that the grace period should | |
649 // have exceeded. Getting the notifications again should ignore it now. | |
650 clock->Advance(base::TimeDelta::FromMinutes(1)); | |
651 | |
652 context->ReadAllNotificationDataForServiceWorkerRegistration( | |
653 origin, kFakeServiceWorkerRegistrationId, | |
654 base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas, | |
655 base::Unretained(this), ¬ification_database_datas)); | |
656 | |
657 base::RunLoop().RunUntilIdle(); | |
658 | |
659 ASSERT_TRUE(success()); | |
660 ASSERT_EQ(0u, notification_database_datas.size()); | |
661 } | |
662 | |
568 } // namespace content | 663 } // namespace content |
OLD | NEW |