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> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/files/file_path.h" |
12 #include "base/guid.h" | 13 #include "base/guid.h" |
13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
14 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
15 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
16 #include "content/browser/background_fetch/background_fetch_data_manager.h" | 17 #include "content/browser/background_fetch/background_fetch_data_manager.h" |
17 #include "content/browser/background_fetch/background_fetch_job_info.h" | 18 #include "content/browser/background_fetch/background_fetch_job_info.h" |
18 #include "content/browser/background_fetch/background_fetch_request_info.h" | 19 #include "content/browser/background_fetch/background_fetch_request_info.h" |
19 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/test/fake_download_item.h" | 21 #include "content/public/test/fake_download_item.h" |
21 #include "content/public/test/mock_download_manager.h" | 22 #include "content/public/test/mock_download_manager.h" |
22 #include "content/public/test/test_browser_context.h" | 23 #include "content/public/test/test_browser_context.h" |
23 #include "content/public/test/test_browser_thread_bundle.h" | 24 #include "content/public/test/test_browser_thread_bundle.h" |
24 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
25 | 26 |
| 27 namespace content { |
| 28 |
26 namespace { | 29 namespace { |
27 | 30 |
28 const char kOrigin[] = "https://example.com/"; | 31 const char kOrigin[] = "https://example.com/"; |
29 const char kJobGuid[] = "TestRequestGuid"; | 32 const char kJobGuid[] = "TestRequestGuid"; |
30 constexpr int64_t kServiceWorkerRegistrationId = 9001; | 33 constexpr int64_t kServiceWorkerRegistrationId = 9001; |
31 const char kTestUrl[] = "http://www.example.com/example.html"; | 34 const char kTestUrl[] = "http://www.example.com/example.html"; |
32 const char kTag[] = "testTag"; | 35 const char kTag[] = "testTag"; |
| 36 const base::FilePath::CharType kFileName[] = FILE_PATH_LITERAL("path/file.txt"); |
33 | 37 |
34 } // namespace | 38 } // namespace |
35 | 39 |
36 namespace content { | |
37 | |
38 // Use the basic MockDownloadManager, but override it so that it implements the | 40 // Use the basic MockDownloadManager, but override it so that it implements the |
39 // functionality that the JobController requires. | 41 // functionality that the JobController requires. |
40 class MockDownloadManagerWithCallback : public MockDownloadManager { | 42 class MockDownloadManagerWithCallback : public MockDownloadManager { |
41 public: | 43 public: |
42 void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override { | 44 void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override { |
43 base::RunLoop run_loop; | 45 base::RunLoop run_loop; |
44 DownloadUrlMock(params.get()); | 46 DownloadUrlMock(params.get()); |
45 std::string guid = base::GenerateGUID(); | 47 std::string guid = base::GenerateGUID(); |
46 std::unique_ptr<FakeDownloadItem> item = | 48 std::unique_ptr<FakeDownloadItem> item = |
47 base::MakeUnique<FakeDownloadItem>(); | 49 base::MakeUnique<FakeDownloadItem>(); |
(...skipping 18 matching lines...) Expand all Loading... |
66 } | 68 } |
67 | 69 |
68 const std::vector<std::unique_ptr<FakeDownloadItem>>& download_items() const { | 70 const std::vector<std::unique_ptr<FakeDownloadItem>>& download_items() const { |
69 return download_items_; | 71 return download_items_; |
70 } | 72 } |
71 | 73 |
72 private: | 74 private: |
73 std::vector<std::unique_ptr<FakeDownloadItem>> download_items_; | 75 std::vector<std::unique_ptr<FakeDownloadItem>> download_items_; |
74 }; | 76 }; |
75 | 77 |
| 78 class FakeBackgroundFetchDataManager : public BackgroundFetchDataManager { |
| 79 public: |
| 80 FakeBackgroundFetchDataManager(BrowserContext* browser_context) |
| 81 : BackgroundFetchDataManager(browser_context) {} |
| 82 ~FakeBackgroundFetchDataManager() = default; |
| 83 |
| 84 void set_is_complete(bool is_complete) { is_complete_ = is_complete; } |
| 85 |
| 86 void set_next_request(BackgroundFetchRequestInfo* request) { |
| 87 next_request_ = request; |
| 88 } |
| 89 |
| 90 bool UpdateRequestState(const std::string& job_guid, |
| 91 const std::string& request_guid, |
| 92 DownloadItem::DownloadState state, |
| 93 DownloadInterruptReason interrupt_reason) override { |
| 94 if (state == DownloadItem::DownloadState::COMPLETE || |
| 95 state == DownloadItem::DownloadState::CANCELLED) { |
| 96 if (!next_request_) |
| 97 is_complete_ = true; |
| 98 } |
| 99 current_request_->set_state(state); |
| 100 current_request_->set_interrupt_reason(interrupt_reason); |
| 101 return next_request_; |
| 102 } |
| 103 |
| 104 void UpdateRequestDownloadGuid(const std::string& job_guid, |
| 105 const std::string& request_guid, |
| 106 const std::string& download_guid) override { |
| 107 current_request_->set_download_guid(download_guid); |
| 108 } |
| 109 |
| 110 void UpdateRequestStorageState(const std::string& job_guid, |
| 111 const std::string& request_guid, |
| 112 const base::FilePath& file_path, |
| 113 int64_t received_bytes) override { |
| 114 current_request_->set_file_path(file_path); |
| 115 current_request_->set_received_bytes(received_bytes); |
| 116 } |
| 117 |
| 118 const BackgroundFetchRequestInfo& GetNextBackgroundFetchRequestInfo( |
| 119 const std::string& job_guid) override { |
| 120 current_request_ = next_request_; |
| 121 next_request_ = nullptr; |
| 122 return *current_request_; |
| 123 } |
| 124 |
| 125 bool HasRequestsRemaining(const std::string& job_guid) const override { |
| 126 return next_request_; |
| 127 } |
| 128 bool IsComplete(const std::string& job_guid) const override { |
| 129 return is_complete_; |
| 130 } |
| 131 |
| 132 private: |
| 133 bool is_complete_ = false; |
| 134 BackgroundFetchRequestInfo* current_request_ = nullptr; |
| 135 BackgroundFetchRequestInfo* next_request_ = nullptr; |
| 136 }; |
| 137 |
76 class BackgroundFetchJobControllerTest : public ::testing::Test { | 138 class BackgroundFetchJobControllerTest : public ::testing::Test { |
77 public: | 139 public: |
78 BackgroundFetchJobControllerTest() | 140 BackgroundFetchJobControllerTest() |
79 : download_manager_(new MockDownloadManagerWithCallback()) {} | 141 : data_manager_(base::MakeUnique<FakeBackgroundFetchDataManager>( |
| 142 &browser_context_)), |
| 143 download_manager_(new MockDownloadManagerWithCallback()) {} |
80 ~BackgroundFetchJobControllerTest() override = default; | 144 ~BackgroundFetchJobControllerTest() override = default; |
81 | 145 |
82 void SetUp() override { | 146 void SetUp() override { |
83 // The download_manager_ ownership is given to the BrowserContext, and the | 147 // The download_manager_ ownership is given to the BrowserContext, and the |
84 // BrowserContext will take care of deallocating it. | 148 // BrowserContext will take care of deallocating it. |
85 BrowserContext::SetDownloadManagerForTesting(&browser_context_, | 149 BrowserContext::SetDownloadManagerForTesting(&browser_context_, |
86 download_manager_); | 150 download_manager_); |
87 } | 151 } |
88 | 152 |
89 void TearDown() override { job_controller_->Shutdown(); } | 153 void TearDown() override { job_controller_->Shutdown(); } |
90 | 154 |
91 void InitializeJobController( | 155 void InitializeJobController() { |
92 std::unique_ptr<BackgroundFetchJobData> job_data) { | |
93 job_controller_ = base::MakeUnique<BackgroundFetchJobController>( | 156 job_controller_ = base::MakeUnique<BackgroundFetchJobController>( |
94 kJobGuid, &browser_context_, | 157 kJobGuid, &browser_context_, |
95 BrowserContext::GetDefaultStoragePartition(&browser_context_), | 158 BrowserContext::GetDefaultStoragePartition(&browser_context_), |
96 std::move(job_data), | 159 data_manager_.get(), |
97 base::BindOnce(&BackgroundFetchJobControllerTest::DidCompleteJob, | 160 base::BindOnce(&BackgroundFetchJobControllerTest::DidCompleteJob, |
98 base::Unretained(this))); | 161 base::Unretained(this))); |
99 } | 162 } |
100 | 163 |
101 void DidCompleteJob() { did_complete_job_ = true; } | 164 void DidCompleteJob() { did_complete_job_ = true; } |
102 | 165 |
103 void StartProcessing() { | 166 void StartProcessing() { |
104 base::RunLoop run_loop; | 167 base::RunLoop run_loop; |
105 BrowserThread::PostTask( | 168 BrowserThread::PostTask( |
106 BrowserThread::IO, FROM_HERE, | 169 BrowserThread::IO, FROM_HERE, |
(...skipping 11 matching lines...) Expand all Loading... |
118 return job_controller_.get(); | 181 return job_controller_.get(); |
119 } | 182 } |
120 MockDownloadManagerWithCallback* download_manager() { | 183 MockDownloadManagerWithCallback* download_manager() { |
121 return download_manager_; | 184 return download_manager_; |
122 } | 185 } |
123 | 186 |
124 DownloadItem::Observer* ItemObserver() const { return job_controller_.get(); } | 187 DownloadItem::Observer* ItemObserver() const { return job_controller_.get(); } |
125 | 188 |
126 bool did_complete_job() const { return did_complete_job_; } | 189 bool did_complete_job() const { return did_complete_job_; } |
127 | 190 |
| 191 FakeBackgroundFetchDataManager* data_manager() const { |
| 192 return data_manager_.get(); |
| 193 } |
| 194 |
128 private: | 195 private: |
129 bool did_complete_job_ = false; | 196 bool did_complete_job_ = false; |
130 TestBrowserThreadBundle thread_bundle_; | 197 TestBrowserThreadBundle thread_bundle_; |
131 TestBrowserContext browser_context_; | 198 TestBrowserContext browser_context_; |
| 199 std::unique_ptr<FakeBackgroundFetchDataManager> data_manager_; |
132 std::unique_ptr<BackgroundFetchJobController> job_controller_; | 200 std::unique_ptr<BackgroundFetchJobController> job_controller_; |
133 MockDownloadManagerWithCallback* download_manager_; | 201 MockDownloadManagerWithCallback* download_manager_; |
134 }; | 202 }; |
135 | 203 |
136 TEST_F(BackgroundFetchJobControllerTest, SingleRequestJob) { | 204 TEST_F(BackgroundFetchJobControllerTest, SingleRequestJob) { |
137 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), | 205 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), |
138 kServiceWorkerRegistrationId); | 206 kServiceWorkerRegistrationId); |
139 BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); | 207 BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); |
140 std::vector<BackgroundFetchRequestInfo> request_infos{request_info}; | 208 request_info.set_state(DownloadItem::DownloadState::IN_PROGRESS); |
141 | 209 data_manager()->set_next_request(&request_info); |
142 // Get a JobData to give to the JobController. The JobController then gets | 210 InitializeJobController(); |
143 // the BackgroundFetchRequestInfos from the JobData. | |
144 std::unique_ptr<BackgroundFetchJobData> owned_job_data = | |
145 base::MakeUnique<BackgroundFetchJobData>(request_infos); | |
146 BackgroundFetchJobData* job_data = owned_job_data.get(); | |
147 InitializeJobController(std::move(owned_job_data)); | |
148 | 211 |
149 EXPECT_CALL(*(download_manager()), | 212 EXPECT_CALL(*(download_manager()), |
150 DownloadUrlMock(::testing::Pointee(::testing::Property( | 213 DownloadUrlMock(::testing::Pointee(::testing::Property( |
151 &DownloadUrlParameters::url, GURL(kTestUrl))))) | 214 &DownloadUrlParameters::url, GURL(kTestUrl))))) |
152 .Times(1); | 215 .Times(1); |
153 | 216 |
154 StartProcessing(); | 217 StartProcessing(); |
155 | 218 |
156 // Get one of the pending downloads from the download manager. | 219 // Get the pending download from the download manager. |
157 auto& download_items = download_manager()->download_items(); | 220 auto& download_items = download_manager()->download_items(); |
158 ASSERT_EQ(1U, download_items.size()); | 221 ASSERT_EQ(1U, download_items.size()); |
159 FakeDownloadItem* item = download_items[0].get(); | 222 FakeDownloadItem* item = download_items[0].get(); |
160 | 223 |
161 // Update the observer with no actual change. | 224 // Update the observer with no actual change. |
162 ItemObserver()->OnDownloadUpdated(item); | 225 ItemObserver()->OnDownloadUpdated(item); |
163 EXPECT_FALSE(job_data->IsComplete()); | 226 EXPECT_EQ(DownloadItem::DownloadState::IN_PROGRESS, request_info.state()); |
164 EXPECT_FALSE(did_complete_job()); | 227 EXPECT_FALSE(did_complete_job()); |
165 | 228 |
166 // Update the item to be completed then update the observer. The JobController | 229 // Update the item to be completed then update the observer. The JobController |
167 // should update the JobData that the request is complete. | 230 // should update the JobData that the request is complete. |
168 item->SetState(DownloadItem::DownloadState::COMPLETE); | 231 item->SetState(DownloadItem::DownloadState::COMPLETE); |
169 ItemObserver()->OnDownloadUpdated(item); | 232 ItemObserver()->OnDownloadUpdated(item); |
170 EXPECT_TRUE(job_data->IsComplete()); | |
171 | 233 |
| 234 EXPECT_EQ(DownloadItem::DownloadState::COMPLETE, request_info.state()); |
172 EXPECT_TRUE(did_complete_job()); | 235 EXPECT_TRUE(did_complete_job()); |
173 } | 236 } |
174 | 237 |
175 TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) { | 238 TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) { |
176 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), | 239 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), |
177 kServiceWorkerRegistrationId); | 240 kServiceWorkerRegistrationId); |
178 std::vector<BackgroundFetchRequestInfo> request_infos; | 241 std::vector<BackgroundFetchRequestInfo> request_infos; |
179 for (int i = 0; i < 10; i++) { | 242 for (int i = 0; i < 10; i++) { |
180 request_infos.emplace_back(GURL(kTestUrl), base::IntToString(i)); | 243 request_infos.emplace_back(GURL(kTestUrl), base::IntToString(i)); |
181 } | 244 } |
182 | 245 data_manager()->set_next_request(&request_infos[0]); |
183 // Get a JobData to give to the JobController. The JobController then gets | 246 InitializeJobController(); |
184 // the BackgroundFetchRequestInfos from the JobData. | |
185 std::unique_ptr<BackgroundFetchJobData> owned_job_data = | |
186 base::MakeUnique<BackgroundFetchJobData>(request_infos); | |
187 BackgroundFetchJobData* job_data = owned_job_data.get(); | |
188 InitializeJobController(std::move(owned_job_data)); | |
189 | 247 |
190 EXPECT_CALL(*(download_manager()), | 248 EXPECT_CALL(*(download_manager()), |
191 DownloadUrlMock(::testing::Pointee(::testing::Property( | 249 DownloadUrlMock(::testing::Pointee(::testing::Property( |
192 &DownloadUrlParameters::url, GURL(kTestUrl))))) | 250 &DownloadUrlParameters::url, GURL(kTestUrl))))) |
193 .Times(10); | 251 .Times(10); |
194 | 252 |
195 StartProcessing(); | 253 StartProcessing(); |
196 | 254 |
197 // Get one of the pending downloads from the download manager. | 255 // Get one of the pending downloads from the download manager. |
198 auto& download_items = download_manager()->download_items(); | 256 auto& download_items = download_manager()->download_items(); |
199 ASSERT_EQ(1U, download_items.size()); | 257 ASSERT_EQ(1U, download_items.size()); |
200 FakeDownloadItem* item = download_items[0].get(); | 258 FakeDownloadItem* item = download_items[0].get(); |
201 | 259 |
202 // Update the observer with no actual change. | 260 // Update the observer with no actual change. |
203 ItemObserver()->OnDownloadUpdated(item); | 261 ItemObserver()->OnDownloadUpdated(item); |
204 EXPECT_FALSE(job_data->IsComplete()); | 262 EXPECT_EQ(DownloadItem::DownloadState::IN_PROGRESS, request_infos[0].state()); |
205 ASSERT_EQ(1U, download_items.size()); | 263 ASSERT_EQ(1U, download_items.size()); |
206 | 264 |
207 for (size_t i = 0; i < 9; i++) { | 265 for (size_t i = 0; i < 9; i++) { |
| 266 // Update the FakeDataManager with the results we expect. |
| 267 if (i < 9) |
| 268 data_manager()->set_next_request(&request_infos[i + 1]); |
| 269 |
208 // Update the next item to be completed then update the observer. | 270 // Update the next item to be completed then update the observer. |
209 ASSERT_EQ(i + 1, download_items.size()); | 271 ASSERT_EQ(i + 1, download_items.size()); |
210 item = download_items[i].get(); | 272 item = download_items[i].get(); |
211 item->SetState(DownloadItem::DownloadState::COMPLETE); | 273 item->SetState(DownloadItem::DownloadState::COMPLETE); |
212 ItemObserver()->OnDownloadUpdated(item); | 274 ItemObserver()->OnDownloadUpdated(item); |
213 EXPECT_FALSE(job_data->IsComplete()); | 275 EXPECT_EQ(DownloadItem::DownloadState::COMPLETE, request_infos[i].state()); |
214 } | 276 } |
215 EXPECT_FALSE(job_data->HasRequestsRemaining()); | |
216 EXPECT_FALSE(did_complete_job()); | 277 EXPECT_FALSE(did_complete_job()); |
217 | 278 |
218 // Finally, update the last request to be complete. The JobController should | 279 // Finally, update the last request to be complete. The JobController should |
219 // see that there are no more requests and mark the job as done. | 280 // see that there are no more requests and mark the job as done. |
220 ASSERT_EQ(10U, download_items.size()); | 281 ASSERT_EQ(10U, download_items.size()); |
221 item = download_items[9].get(); | 282 item = download_items[9].get(); |
222 item->SetState(DownloadItem::DownloadState::COMPLETE); | 283 item->SetState(DownloadItem::DownloadState::COMPLETE); |
223 ItemObserver()->OnDownloadUpdated(item); | 284 ItemObserver()->OnDownloadUpdated(item); |
224 EXPECT_TRUE(job_data->IsComplete()); | |
225 | 285 |
226 EXPECT_TRUE(did_complete_job()); | 286 EXPECT_TRUE(did_complete_job()); |
227 } | 287 } |
228 | 288 |
| 289 TEST_F(BackgroundFetchJobControllerTest, UpdateStorageState) { |
| 290 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), |
| 291 kServiceWorkerRegistrationId); |
| 292 BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); |
| 293 request_info.set_state(DownloadItem::DownloadState::IN_PROGRESS); |
| 294 data_manager()->set_next_request(&request_info); |
| 295 InitializeJobController(); |
| 296 |
| 297 EXPECT_CALL(*(download_manager()), |
| 298 DownloadUrlMock(::testing::Pointee(::testing::Property( |
| 299 &DownloadUrlParameters::url, GURL(kTestUrl))))) |
| 300 .Times(1); |
| 301 |
| 302 StartProcessing(); |
| 303 |
| 304 // Get the pending download from the download manager. |
| 305 auto& download_items = download_manager()->download_items(); |
| 306 ASSERT_EQ(1U, download_items.size()); |
| 307 FakeDownloadItem* item = download_items[0].get(); |
| 308 |
| 309 item->SetTargetFilePath(base::FilePath(kFileName)); |
| 310 item->SetReceivedBytes(123); |
| 311 item->SetState(DownloadItem::DownloadState::COMPLETE); |
| 312 |
| 313 // Trigger the observer. The JobController should update the JobData that the |
| 314 // request is complete and should fill in storage state. |
| 315 ItemObserver()->OnDownloadUpdated(item); |
| 316 |
| 317 EXPECT_EQ(123, request_info.received_bytes()); |
| 318 EXPECT_TRUE(data_manager()->IsComplete(kJobGuid)); |
| 319 EXPECT_TRUE(did_complete_job()); |
| 320 } |
| 321 |
229 } // namespace content | 322 } // namespace content |
OLD | NEW |