OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "content/browser/background_fetch/background_fetch_job_controller.h" | 5 #include "content/browser/background_fetch/background_fetch_job_controller.h" |
6 | 6 |
| 7 #include <string> |
| 8 #include <vector> |
| 9 |
7 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
8 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/guid.h" |
9 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
10 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
| 15 #include "base/strings/string_number_conversions.h" |
11 #include "content/browser/background_fetch/background_fetch_data_manager.h" | 16 #include "content/browser/background_fetch/background_fetch_data_manager.h" |
12 #include "content/browser/background_fetch/background_fetch_job_info.h" | 17 #include "content/browser/background_fetch/background_fetch_job_info.h" |
13 #include "content/browser/background_fetch/background_fetch_request_info.h" | 18 #include "content/browser/background_fetch/background_fetch_request_info.h" |
14 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
15 #include "content/public/test/mock_download_item.h" | 20 #include "content/public/test/fake_download_item.h" |
16 #include "content/public/test/mock_download_manager.h" | 21 #include "content/public/test/mock_download_manager.h" |
17 #include "content/public/test/test_browser_context.h" | 22 #include "content/public/test/test_browser_context.h" |
18 #include "content/public/test/test_browser_thread_bundle.h" | 23 #include "content/public/test/test_browser_thread_bundle.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
20 | 25 |
21 namespace { | 26 namespace { |
22 | 27 |
23 const char kOrigin[] = "https://example.com/"; | 28 const char kOrigin[] = "https://example.com/"; |
24 const char kJobGuid[] = "TestRequestGuid"; | 29 const char kJobGuid[] = "TestRequestGuid"; |
25 constexpr int64_t kServiceWorkerRegistrationId = 9001; | 30 constexpr int64_t kServiceWorkerRegistrationId = 9001; |
26 const char kTestUrl[] = "http://www.example.com/example.html"; | 31 const char kTestUrl[] = "http://www.example.com/example.html"; |
27 const char kTag[] = "testTag"; | 32 const char kTag[] = "testTag"; |
28 | 33 |
29 } // namespace | 34 } // namespace |
30 | 35 |
31 namespace content { | 36 namespace content { |
32 | 37 |
33 // Use the basic MockDownloadItem, but override it to provide a valid GUID. | |
34 class MockDownloadItemWithValues : public MockDownloadItem { | |
35 public: | |
36 const std::string& GetGuid() const override { return guid_; } | |
37 void SetGuid(const std::string& guid) { guid_ = guid; } | |
38 | |
39 private: | |
40 std::string guid_; | |
41 }; | |
42 | |
43 // Use the basic MockDownloadManager, but override it so that it implements the | 38 // Use the basic MockDownloadManager, but override it so that it implements the |
44 // functionality that the JobController requires. | 39 // functionality that the JobController requires. |
45 class MockDownloadManagerWithCallback : public MockDownloadManager { | 40 class MockDownloadManagerWithCallback : public MockDownloadManager { |
46 public: | 41 public: |
47 void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override { | 42 void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override { |
| 43 base::RunLoop run_loop; |
48 DownloadUrlMock(params.get()); | 44 DownloadUrlMock(params.get()); |
| 45 std::string guid = base::GenerateGUID(); |
| 46 std::unique_ptr<FakeDownloadItem> item = |
| 47 base::MakeUnique<FakeDownloadItem>(); |
| 48 item->SetState(DownloadItem::DownloadState::IN_PROGRESS); |
| 49 item->SetGuid(guid); |
49 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 50 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
50 base::Bind(params->callback(), &download_item_, | 51 base::Bind(params->callback(), item.get(), |
51 DOWNLOAD_INTERRUPT_REASON_NONE)); | 52 DOWNLOAD_INTERRUPT_REASON_NONE)); |
| 53 download_items_.push_back(std::move(item)); |
| 54 run_loop.RunUntilIdle(); |
52 } | 55 } |
53 | 56 |
| 57 // This is called during shutdown for each DownloadItem so can be an |
| 58 // O(n^2) where n is controlled by the users of the API. If n is expected to |
| 59 // be larger or the method is called in more places, consider alternatives. |
54 DownloadItem* GetDownloadByGuid(const std::string& guid) override { | 60 DownloadItem* GetDownloadByGuid(const std::string& guid) override { |
55 DCHECK_EQ(download_item_.GetGuid(), guid); | 61 for (const auto& item : download_items_) { |
56 return &download_item_; | 62 if (item->GetGuid() == guid) |
| 63 return item.get(); |
| 64 } |
| 65 return nullptr; |
57 } | 66 } |
58 | 67 |
59 MockDownloadItemWithValues* download_item() { return &download_item_; } | 68 const std::vector<std::unique_ptr<FakeDownloadItem>>& download_items() const { |
| 69 return download_items_; |
| 70 } |
60 | 71 |
61 private: | 72 private: |
62 MockDownloadItemWithValues download_item_; | 73 std::vector<std::unique_ptr<FakeDownloadItem>> download_items_; |
63 }; | 74 }; |
64 | 75 |
65 class BackgroundFetchJobControllerTest : public ::testing::Test { | 76 class BackgroundFetchJobControllerTest : public ::testing::Test { |
66 public: | 77 public: |
67 BackgroundFetchJobControllerTest() | 78 BackgroundFetchJobControllerTest() |
68 : download_manager_(new MockDownloadManagerWithCallback()) {} | 79 : download_manager_(new MockDownloadManagerWithCallback()) {} |
69 ~BackgroundFetchJobControllerTest() override = default; | 80 ~BackgroundFetchJobControllerTest() override = default; |
70 | 81 |
71 void SetUp() override { | 82 void SetUp() override { |
72 // The download_manager_ ownership is given to the BrowserContext, and the | 83 // The download_manager_ ownership is given to the BrowserContext, and the |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 | 119 |
109 DownloadItem::Observer* ItemObserver() const { return job_controller_.get(); } | 120 DownloadItem::Observer* ItemObserver() const { return job_controller_.get(); } |
110 | 121 |
111 private: | 122 private: |
112 TestBrowserThreadBundle thread_bundle_; | 123 TestBrowserThreadBundle thread_bundle_; |
113 TestBrowserContext browser_context_; | 124 TestBrowserContext browser_context_; |
114 std::unique_ptr<BackgroundFetchJobController> job_controller_; | 125 std::unique_ptr<BackgroundFetchJobController> job_controller_; |
115 MockDownloadManagerWithCallback* download_manager_; | 126 MockDownloadManagerWithCallback* download_manager_; |
116 }; | 127 }; |
117 | 128 |
118 TEST_F(BackgroundFetchJobControllerTest, StartDownload) { | 129 TEST_F(BackgroundFetchJobControllerTest, SingleRequestJob) { |
119 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), | 130 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), |
120 kServiceWorkerRegistrationId); | 131 kServiceWorkerRegistrationId); |
121 BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); | 132 BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); |
122 std::vector<BackgroundFetchRequestInfo> request_infos{request_info}; | 133 std::vector<BackgroundFetchRequestInfo> request_infos{request_info}; |
123 | 134 |
124 // Create a MockDownloadItem that the test can manipulate. | |
125 MockDownloadItemWithValues* item = download_manager()->download_item(); | |
126 item->SetGuid("foo"); | |
127 | |
128 // Get a JobData to give to the JobController. The JobController then gets | 135 // Get a JobData to give to the JobController. The JobController then gets |
129 // the BackgroundFetchRequestInfos from the JobData. | 136 // the BackgroundFetchRequestInfos from the JobData. |
130 std::unique_ptr<BackgroundFetchJobData> job_data = | 137 std::unique_ptr<BackgroundFetchJobData> owned_job_data = |
131 base::MakeUnique<BackgroundFetchJobData>(request_infos); | 138 base::MakeUnique<BackgroundFetchJobData>(request_infos); |
132 InitializeJobController(std::move(job_data)); | 139 BackgroundFetchJobData* job_data = owned_job_data.get(); |
| 140 InitializeJobController(std::move(owned_job_data)); |
133 | 141 |
134 EXPECT_CALL(*(download_manager()), | 142 EXPECT_CALL(*(download_manager()), |
135 DownloadUrlMock(::testing::Pointee(::testing::Property( | 143 DownloadUrlMock(::testing::Pointee(::testing::Property( |
136 &DownloadUrlParameters::url, GURL(kTestUrl))))) | 144 &DownloadUrlParameters::url, GURL(kTestUrl))))) |
137 .Times(1); | 145 .Times(1); |
138 | 146 |
139 StartProcessing(); | 147 StartProcessing(); |
| 148 |
| 149 // Get one of the pending downloads from the download manager. |
| 150 auto& download_items = download_manager()->download_items(); |
| 151 ASSERT_EQ(1U, download_items.size()); |
| 152 FakeDownloadItem* item = download_items[0].get(); |
| 153 |
| 154 // Update the observer with no actual change. |
| 155 ItemObserver()->OnDownloadUpdated(item); |
| 156 EXPECT_FALSE(job_data->IsComplete()); |
| 157 |
| 158 // Update the item to be completed then update the observer. The JobController |
| 159 // should update the JobData that the request is complete. |
| 160 item->SetState(DownloadItem::DownloadState::COMPLETE); |
| 161 ItemObserver()->OnDownloadUpdated(item); |
| 162 EXPECT_TRUE(job_data->IsComplete()); |
| 163 } |
| 164 |
| 165 TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) { |
| 166 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), |
| 167 kServiceWorkerRegistrationId); |
| 168 std::vector<BackgroundFetchRequestInfo> request_infos; |
| 169 for (int i = 0; i < 10; i++) { |
| 170 request_infos.emplace_back(GURL(kTestUrl), base::IntToString(i)); |
| 171 } |
| 172 |
| 173 // Get a JobData to give to the JobController. The JobController then gets |
| 174 // the BackgroundFetchRequestInfos from the JobData. |
| 175 std::unique_ptr<BackgroundFetchJobData> owned_job_data = |
| 176 base::MakeUnique<BackgroundFetchJobData>(request_infos); |
| 177 BackgroundFetchJobData* job_data = owned_job_data.get(); |
| 178 InitializeJobController(std::move(owned_job_data)); |
| 179 |
| 180 EXPECT_CALL(*(download_manager()), |
| 181 DownloadUrlMock(::testing::Pointee(::testing::Property( |
| 182 &DownloadUrlParameters::url, GURL(kTestUrl))))) |
| 183 .Times(10); |
| 184 |
| 185 StartProcessing(); |
| 186 |
| 187 // Get one of the pending downloads from the download manager. |
| 188 auto& download_items = download_manager()->download_items(); |
| 189 ASSERT_EQ(1U, download_items.size()); |
| 190 FakeDownloadItem* item = download_items[0].get(); |
| 191 |
| 192 // Update the observer with no actual change. |
| 193 ItemObserver()->OnDownloadUpdated(item); |
| 194 EXPECT_FALSE(job_data->IsComplete()); |
| 195 ASSERT_EQ(1U, download_items.size()); |
| 196 |
| 197 for (size_t i = 0; i < 9; i++) { |
| 198 // Update the next item to be completed then update the observer. |
| 199 ASSERT_EQ(i + 1, download_items.size()); |
| 200 item = download_items[i].get(); |
| 201 item->SetState(DownloadItem::DownloadState::COMPLETE); |
| 202 ItemObserver()->OnDownloadUpdated(item); |
| 203 EXPECT_FALSE(job_data->IsComplete()); |
| 204 } |
| 205 EXPECT_FALSE(job_data->HasRequestsRemaining()); |
| 206 |
| 207 // Finally, update the last request to be complete. The JobController should |
| 208 // see that there are no more requests and mark the job as done. |
| 209 ASSERT_EQ(10U, download_items.size()); |
| 210 item = download_items[9].get(); |
| 211 item->SetState(DownloadItem::DownloadState::COMPLETE); |
| 212 ItemObserver()->OnDownloadUpdated(item); |
| 213 EXPECT_TRUE(job_data->IsComplete()); |
140 } | 214 } |
141 | 215 |
142 } // namespace content | 216 } // namespace content |
OLD | NEW |