Chromium Code Reviews| 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 |