OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "chrome/browser/android/offline_pages/background_loader_offliner.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/run_loop.h" | |
9 #include "base/test/histogram_tester.h" | |
10 #include "base/test/scoped_feature_list.h" | |
11 #include "base/test/scoped_mock_time_message_loop_task_runner.h" | |
12 #include "base/threading/thread_task_runner_handle.h" | |
13 #include "chrome/browser/android/offline_pages/offliner_helper.h" | |
14 #include "chrome/browser/net/prediction_options.h" | |
15 #include "chrome/common/pref_names.h" | |
16 #include "chrome/test/base/testing_profile.h" | |
17 #include "components/content_settings/core/common/pref_names.h" | |
18 #include "components/offline_pages/content/background_loader/background_loader_c
ontents_stub.h" | |
19 #include "components/offline_pages/core/background/offliner.h" | |
20 #include "components/offline_pages/core/background/offliner_policy.h" | |
21 #include "components/offline_pages/core/background/save_page_request.h" | |
22 #include "components/offline_pages/core/offline_page_feature.h" | |
23 #include "components/offline_pages/core/stub_offline_page_model.h" | |
24 #include "components/prefs/pref_service.h" | |
25 #include "content/public/browser/mhtml_extra_parts.h" | |
26 #include "content/public/browser/navigation_handle.h" | |
27 #include "content/public/browser/web_contents.h" | |
28 #include "content/public/test/test_browser_thread_bundle.h" | |
29 #include "content/public/test/web_contents_tester.h" | |
30 #include "net/base/net_errors.h" | |
31 #include "testing/gtest/include/gtest/gtest.h" | |
32 | |
33 namespace offline_pages { | |
34 | |
35 namespace { | |
36 | |
37 const int64_t kRequestId = 7; | |
38 const GURL kHttpUrl("http://www.tunafish.com"); | |
39 const GURL kFileUrl("file://salmon.png"); | |
40 const ClientId kClientId("async_loading", "88"); | |
41 const bool kUserRequested = true; | |
42 | |
43 // Mock OfflinePageModel for testing the SavePage calls | |
44 class MockOfflinePageModel : public StubOfflinePageModel { | |
45 public: | |
46 MockOfflinePageModel() : mock_saving_(false), mock_deleting_(false) {} | |
47 ~MockOfflinePageModel() override {} | |
48 | |
49 void SavePage(const SavePageParams& save_page_params, | |
50 std::unique_ptr<OfflinePageArchiver> archiver, | |
51 const SavePageCallback& callback) override { | |
52 mock_saving_ = true; | |
53 save_page_callback_ = callback; | |
54 } | |
55 | |
56 void CompleteSavingAsArchiveCreationFailed() { | |
57 DCHECK(mock_saving_); | |
58 mock_saving_ = false; | |
59 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
60 FROM_HERE, base::Bind(save_page_callback_, | |
61 SavePageResult::ARCHIVE_CREATION_FAILED, 0)); | |
62 } | |
63 | |
64 void CompleteSavingAsSuccess() { | |
65 DCHECK(mock_saving_); | |
66 mock_saving_ = false; | |
67 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
68 FROM_HERE, | |
69 base::Bind(save_page_callback_, SavePageResult::SUCCESS, 123456)); | |
70 } | |
71 | |
72 void CompleteSavingAsAlreadyExists() { | |
73 DCHECK(mock_saving_); | |
74 mock_saving_ = false; | |
75 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
76 FROM_HERE, base::Bind(save_page_callback_, | |
77 SavePageResult::ALREADY_EXISTS, 123456)); | |
78 } | |
79 | |
80 void DeletePagesByOfflineId(const std::vector<int64_t>& offline_ids, | |
81 const DeletePageCallback& callback) override { | |
82 mock_deleting_ = true; | |
83 callback.Run(DeletePageResult::SUCCESS); | |
84 } | |
85 | |
86 bool mock_saving() const { return mock_saving_; } | |
87 bool mock_deleting() const { return mock_deleting_; } | |
88 | |
89 private: | |
90 bool mock_saving_; | |
91 bool mock_deleting_; | |
92 SavePageCallback save_page_callback_; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(MockOfflinePageModel); | |
95 }; | |
96 | |
97 } // namespace | |
98 | |
99 // A BackgroundLoader that we can run tests on. | |
100 // Overrides the ResetState so we don't actually try to create any web contents. | |
101 // This is a temporary solution to test core BackgroundLoaderOffliner | |
102 // functionality until we straighten out assumptions made by RequestCoordinator | |
103 // so that the ResetState method is no longer needed. | |
104 class TestBackgroundLoaderOffliner : public BackgroundLoaderOffliner { | |
105 public: | |
106 explicit TestBackgroundLoaderOffliner( | |
107 content::BrowserContext* browser_context, | |
108 const OfflinerPolicy* policy, | |
109 OfflinePageModel* offline_page_model); | |
110 ~TestBackgroundLoaderOffliner() override; | |
111 content::WebContentsTester* web_contents_tester() { | |
112 return content::WebContentsTester::For(stub_->web_contents()); | |
113 } | |
114 | |
115 content::WebContents* web_contents() { return stub_->web_contents(); } | |
116 | |
117 bool is_loading() { return loader_ && stub_->is_loading(); } | |
118 | |
119 protected: | |
120 void ResetLoader() override; | |
121 | |
122 private: | |
123 background_loader::BackgroundLoaderContentsStub* stub_; | |
124 }; | |
125 | |
126 TestBackgroundLoaderOffliner::TestBackgroundLoaderOffliner( | |
127 content::BrowserContext* browser_context, | |
128 const OfflinerPolicy* policy, | |
129 OfflinePageModel* offline_page_model) | |
130 : BackgroundLoaderOffliner(browser_context, policy, offline_page_model) {} | |
131 | |
132 TestBackgroundLoaderOffliner::~TestBackgroundLoaderOffliner() {} | |
133 | |
134 void TestBackgroundLoaderOffliner::ResetLoader() { | |
135 stub_ = new background_loader::BackgroundLoaderContentsStub(browser_context_); | |
136 loader_.reset(stub_); | |
137 } | |
138 | |
139 class BackgroundLoaderOfflinerTest : public testing::Test { | |
140 public: | |
141 BackgroundLoaderOfflinerTest(); | |
142 ~BackgroundLoaderOfflinerTest() override; | |
143 | |
144 void SetUp() override; | |
145 | |
146 TestBackgroundLoaderOffliner* offliner() const { return offliner_.get(); } | |
147 Offliner::CompletionCallback const completion_callback() { | |
148 return base::Bind(&BackgroundLoaderOfflinerTest::OnCompletion, | |
149 base::Unretained(this)); | |
150 } | |
151 Offliner::ProgressCallback const progress_callback() { | |
152 return base::Bind(&BackgroundLoaderOfflinerTest::OnProgress, | |
153 base::Unretained(this)); | |
154 } | |
155 Offliner::CancelCallback const cancel_callback() { | |
156 return base::Bind(&BackgroundLoaderOfflinerTest::OnCancel, | |
157 base::Unretained(this)); | |
158 } | |
159 Profile* profile() { return &profile_; } | |
160 bool completion_callback_called() { return completion_callback_called_; } | |
161 Offliner::RequestStatus request_status() { return request_status_; } | |
162 bool cancel_callback_called() { return cancel_callback_called_; } | |
163 bool SaveInProgress() const { return model_->mock_saving(); } | |
164 bool DeleteCalled() const { return model_->mock_deleting(); } | |
165 MockOfflinePageModel* model() const { return model_; } | |
166 const base::HistogramTester& histograms() const { return histogram_tester_; } | |
167 int64_t progress() { return progress_; } | |
168 OfflinerPolicy* policy() const { return policy_.get(); } | |
169 | |
170 void PumpLoop() { base::RunLoop().RunUntilIdle(); } | |
171 | |
172 void CompleteLoading() { | |
173 // Reset snapshot controller. | |
174 std::unique_ptr<SnapshotController> snapshot_controller( | |
175 new SnapshotController(base::ThreadTaskRunnerHandle::Get(), | |
176 offliner_.get(), | |
177 0L /* DelayAfterDocumentAvailable */, | |
178 0L /* DelayAfterDocumentOnLoad */, | |
179 false /* DocumentAvailableTriggersSnapshot */)); | |
180 offliner_->SetSnapshotControllerForTest(std::move(snapshot_controller)); | |
181 // Call complete loading. | |
182 offliner()->DocumentOnLoadCompletedInMainFrame(); | |
183 PumpLoop(); | |
184 } | |
185 | |
186 private: | |
187 void OnCompletion(const SavePageRequest& request, | |
188 Offliner::RequestStatus status); | |
189 void OnProgress(const SavePageRequest& request, int64_t bytes); | |
190 void OnCancel(const SavePageRequest& request); | |
191 content::TestBrowserThreadBundle thread_bundle_; | |
192 TestingProfile profile_; | |
193 std::unique_ptr<OfflinerPolicy> policy_; | |
194 std::unique_ptr<TestBackgroundLoaderOffliner> offliner_; | |
195 MockOfflinePageModel* model_; | |
196 bool completion_callback_called_; | |
197 bool cancel_callback_called_; | |
198 int64_t progress_; | |
199 Offliner::RequestStatus request_status_; | |
200 base::HistogramTester histogram_tester_; | |
201 | |
202 DISALLOW_COPY_AND_ASSIGN(BackgroundLoaderOfflinerTest); | |
203 }; | |
204 | |
205 BackgroundLoaderOfflinerTest::BackgroundLoaderOfflinerTest() | |
206 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | |
207 completion_callback_called_(false), | |
208 cancel_callback_called_(false), | |
209 progress_(0LL), | |
210 request_status_(Offliner::RequestStatus::UNKNOWN) {} | |
211 | |
212 BackgroundLoaderOfflinerTest::~BackgroundLoaderOfflinerTest() {} | |
213 | |
214 void BackgroundLoaderOfflinerTest::SetUp() { | |
215 model_ = new MockOfflinePageModel(); | |
216 policy_.reset(new OfflinerPolicy()); | |
217 offliner_.reset( | |
218 new TestBackgroundLoaderOffliner(profile(), policy_.get(), model_)); | |
219 } | |
220 | |
221 void BackgroundLoaderOfflinerTest::OnCompletion( | |
222 const SavePageRequest& request, | |
223 Offliner::RequestStatus status) { | |
224 DCHECK(!completion_callback_called_); // Expect 1 callback per request. | |
225 completion_callback_called_ = true; | |
226 request_status_ = status; | |
227 } | |
228 | |
229 void BackgroundLoaderOfflinerTest::OnProgress(const SavePageRequest& request, | |
230 int64_t bytes) { | |
231 progress_ = bytes; | |
232 } | |
233 | |
234 void BackgroundLoaderOfflinerTest::OnCancel(const SavePageRequest& request) { | |
235 DCHECK(!cancel_callback_called_); | |
236 cancel_callback_called_ = true; | |
237 } | |
238 | |
239 TEST_F(BackgroundLoaderOfflinerTest, | |
240 LoadAndSaveBlockThirdPartyCookiesForCustomTabs) { | |
241 base::Time creation_time = base::Time::Now(); | |
242 ClientId custom_tabs_client_id("custom_tabs", "88"); | |
243 SavePageRequest request(kRequestId, kHttpUrl, custom_tabs_client_id, | |
244 creation_time, kUserRequested); | |
245 | |
246 profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); | |
247 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), | |
248 progress_callback())); | |
249 histograms().ExpectBucketCount( | |
250 "OfflinePages.Background.CctApiDisableStatus", | |
251 static_cast<int>(OfflinePagesCctApiPrerenderAllowedStatus:: | |
252 THIRD_PARTY_COOKIES_DISABLED), | |
253 1); | |
254 histograms().ExpectBucketCount("OfflinePages.Background.CctApiDisableStatus", | |
255 0 /* PRERENDER_ALLOWED */, 0); | |
256 } | |
257 | |
258 TEST_F(BackgroundLoaderOfflinerTest, | |
259 LoadAndSaveNetworkPredictionDisabledForCustomTabs) { | |
260 base::Time creation_time = base::Time::Now(); | |
261 ClientId custom_tabs_client_id("custom_tabs", "88"); | |
262 SavePageRequest request(kRequestId, kHttpUrl, custom_tabs_client_id, | |
263 creation_time, kUserRequested); | |
264 | |
265 profile()->GetPrefs()->SetInteger( | |
266 prefs::kNetworkPredictionOptions, | |
267 chrome_browser_net::NETWORK_PREDICTION_NEVER); | |
268 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), | |
269 progress_callback())); | |
270 histograms().ExpectBucketCount( | |
271 "OfflinePages.Background.CctApiDisableStatus", | |
272 static_cast<int>(OfflinePagesCctApiPrerenderAllowedStatus:: | |
273 NETWORK_PREDICTION_DISABLED), | |
274 1); | |
275 histograms().ExpectBucketCount( | |
276 "OfflinePages.Background.CctApiDisableStatus", | |
277 static_cast<int>( | |
278 OfflinePagesCctApiPrerenderAllowedStatus::PRERENDER_ALLOWED), | |
279 0); | |
280 } | |
281 | |
282 TEST_F(BackgroundLoaderOfflinerTest, LoadAndSaveStartsLoading) { | |
283 base::Time creation_time = base::Time::Now(); | |
284 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
285 kUserRequested); | |
286 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
287 progress_callback())); | |
288 EXPECT_TRUE(offliner()->is_loading()); | |
289 EXPECT_FALSE(SaveInProgress()); | |
290 EXPECT_FALSE(completion_callback_called()); | |
291 EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); | |
292 } | |
293 | |
294 TEST_F(BackgroundLoaderOfflinerTest, BytesReportedWillUpdateProgress) { | |
295 base::Time creation_time = base::Time::Now(); | |
296 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
297 kUserRequested); | |
298 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
299 progress_callback())); | |
300 offliner()->OnNetworkBytesChanged(5LL); | |
301 EXPECT_EQ(progress(), 5LL); | |
302 offliner()->OnNetworkBytesChanged(10LL); | |
303 EXPECT_EQ(progress(), 15LL); | |
304 } | |
305 | |
306 TEST_F(BackgroundLoaderOfflinerTest, CompleteLoadingInitiatesSave) { | |
307 base::Time creation_time = base::Time::Now(); | |
308 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
309 kUserRequested); | |
310 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
311 progress_callback())); | |
312 CompleteLoading(); | |
313 PumpLoop(); | |
314 EXPECT_FALSE(completion_callback_called()); | |
315 EXPECT_TRUE(SaveInProgress()); | |
316 EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); | |
317 } | |
318 | |
319 TEST_F(BackgroundLoaderOfflinerTest, CancelWhenLoading) { | |
320 base::Time creation_time = base::Time::Now(); | |
321 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
322 kUserRequested); | |
323 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
324 progress_callback())); | |
325 offliner()->Cancel(cancel_callback()); | |
326 PumpLoop(); | |
327 offliner()->OnNetworkBytesChanged(15LL); | |
328 EXPECT_TRUE(cancel_callback_called()); | |
329 EXPECT_FALSE(offliner()->is_loading()); // Offliner reset. | |
330 EXPECT_EQ(progress(), 0LL); // network bytes not recorded when not busy. | |
331 } | |
332 | |
333 TEST_F(BackgroundLoaderOfflinerTest, CancelWhenLoaded) { | |
334 base::Time creation_time = base::Time::Now(); | |
335 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
336 kUserRequested); | |
337 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
338 progress_callback())); | |
339 CompleteLoading(); | |
340 PumpLoop(); | |
341 offliner()->Cancel(cancel_callback()); | |
342 PumpLoop(); | |
343 | |
344 // Subsequent save callback cause no crash. | |
345 model()->CompleteSavingAsArchiveCreationFailed(); | |
346 PumpLoop(); | |
347 EXPECT_TRUE(cancel_callback_called()); | |
348 EXPECT_TRUE(DeleteCalled()); | |
349 EXPECT_FALSE(completion_callback_called()); | |
350 EXPECT_FALSE(SaveInProgress()); | |
351 EXPECT_FALSE(offliner()->is_loading()); // Offliner reset. | |
352 } | |
353 | |
354 TEST_F(BackgroundLoaderOfflinerTest, LoadedButSaveFails) { | |
355 base::Time creation_time = base::Time::Now(); | |
356 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
357 kUserRequested); | |
358 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
359 progress_callback())); | |
360 | |
361 CompleteLoading(); | |
362 PumpLoop(); | |
363 model()->CompleteSavingAsArchiveCreationFailed(); | |
364 PumpLoop(); | |
365 | |
366 EXPECT_TRUE(completion_callback_called()); | |
367 EXPECT_EQ(Offliner::RequestStatus::SAVE_FAILED, request_status()); | |
368 EXPECT_FALSE(offliner()->is_loading()); | |
369 EXPECT_FALSE(SaveInProgress()); | |
370 } | |
371 | |
372 TEST_F(BackgroundLoaderOfflinerTest, ProgressDoesNotUpdateDuringSave) { | |
373 base::Time creation_time = base::Time::Now(); | |
374 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
375 kUserRequested); | |
376 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
377 progress_callback())); | |
378 offliner()->OnNetworkBytesChanged(10LL); | |
379 CompleteLoading(); | |
380 PumpLoop(); | |
381 offliner()->OnNetworkBytesChanged(15LL); | |
382 EXPECT_EQ(progress(), 10LL); | |
383 } | |
384 | |
385 TEST_F(BackgroundLoaderOfflinerTest, LoadAndSaveSuccess) { | |
386 base::Time creation_time = base::Time::Now(); | |
387 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
388 kUserRequested); | |
389 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
390 progress_callback())); | |
391 | |
392 CompleteLoading(); | |
393 PumpLoop(); | |
394 model()->CompleteSavingAsSuccess(); | |
395 PumpLoop(); | |
396 | |
397 EXPECT_TRUE(completion_callback_called()); | |
398 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status()); | |
399 EXPECT_FALSE(offliner()->is_loading()); | |
400 EXPECT_FALSE(SaveInProgress()); | |
401 } | |
402 | |
403 TEST_F(BackgroundLoaderOfflinerTest, LoadAndSaveAlreadyExists) { | |
404 base::Time creation_time = base::Time::Now(); | |
405 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
406 kUserRequested); | |
407 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
408 progress_callback())); | |
409 | |
410 CompleteLoading(); | |
411 PumpLoop(); | |
412 model()->CompleteSavingAsAlreadyExists(); | |
413 PumpLoop(); | |
414 | |
415 EXPECT_TRUE(completion_callback_called()); | |
416 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status()); | |
417 EXPECT_FALSE(offliner()->is_loading()); | |
418 EXPECT_FALSE(SaveInProgress()); | |
419 } | |
420 | |
421 TEST_F(BackgroundLoaderOfflinerTest, FailsOnInvalidURL) { | |
422 base::Time creation_time = base::Time::Now(); | |
423 SavePageRequest request(kRequestId, kFileUrl, kClientId, creation_time, | |
424 kUserRequested); | |
425 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), | |
426 progress_callback())); | |
427 } | |
428 | |
429 TEST_F(BackgroundLoaderOfflinerTest, ReturnsOnRenderCrash) { | |
430 base::Time creation_time = base::Time::Now(); | |
431 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
432 kUserRequested); | |
433 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
434 progress_callback())); | |
435 offliner()->RenderProcessGone( | |
436 base::TerminationStatus::TERMINATION_STATUS_PROCESS_CRASHED); | |
437 | |
438 EXPECT_TRUE(completion_callback_called()); | |
439 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED_NO_NEXT, request_status()); | |
440 } | |
441 | |
442 TEST_F(BackgroundLoaderOfflinerTest, ReturnsOnRenderKilled) { | |
443 base::Time creation_time = base::Time::Now(); | |
444 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
445 kUserRequested); | |
446 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
447 progress_callback())); | |
448 offliner()->RenderProcessGone( | |
449 base::TerminationStatus::TERMINATION_STATUS_PROCESS_WAS_KILLED); | |
450 | |
451 EXPECT_TRUE(completion_callback_called()); | |
452 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status()); | |
453 } | |
454 | |
455 TEST_F(BackgroundLoaderOfflinerTest, ReturnsOnWebContentsDestroyed) { | |
456 base::Time creation_time = base::Time::Now(); | |
457 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
458 kUserRequested); | |
459 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
460 progress_callback())); | |
461 offliner()->WebContentsDestroyed(); | |
462 | |
463 EXPECT_TRUE(completion_callback_called()); | |
464 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status()); | |
465 } | |
466 | |
467 TEST_F(BackgroundLoaderOfflinerTest, FailsOnErrorPage) { | |
468 base::Time creation_time = base::Time::Now(); | |
469 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
470 kUserRequested); | |
471 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
472 progress_callback())); | |
473 // Create handle with net error code. | |
474 // Called after calling LoadAndSave so we have web_contents to work with. | |
475 std::unique_ptr<content::NavigationHandle> handle( | |
476 content::NavigationHandle::CreateNavigationHandleForTesting( | |
477 kHttpUrl, offliner()->web_contents()->GetMainFrame(), true, | |
478 net::Error::ERR_NAME_NOT_RESOLVED)); | |
479 // NavigationHandle destruction will trigger DidFinishNavigation code. | |
480 handle.reset(); | |
481 histograms().ExpectBucketCount( | |
482 "OfflinePages.Background.BackgroundLoadingFailedCode.async_loading", | |
483 105, // ERR_NAME_NOT_RESOLVED | |
484 1); | |
485 CompleteLoading(); | |
486 PumpLoop(); | |
487 | |
488 EXPECT_TRUE(completion_callback_called()); | |
489 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status()); | |
490 } | |
491 | |
492 TEST_F(BackgroundLoaderOfflinerTest, NoNextOnInternetDisconnected) { | |
493 base::Time creation_time = base::Time::Now(); | |
494 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
495 kUserRequested); | |
496 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
497 progress_callback())); | |
498 | |
499 // Create handle with net error code. | |
500 // Called after calling LoadAndSave so we have web_contents to work with. | |
501 std::unique_ptr<content::NavigationHandle> handle( | |
502 content::NavigationHandle::CreateNavigationHandleForTesting( | |
503 kHttpUrl, offliner()->web_contents()->GetMainFrame(), true, | |
504 net::Error::ERR_INTERNET_DISCONNECTED)); | |
505 // Call DidFinishNavigation with handle that contains error. | |
506 offliner()->DidFinishNavigation(handle.get()); | |
507 // NavigationHandle is always destroyed after finishing navigation. | |
508 handle.reset(); | |
509 CompleteLoading(); | |
510 PumpLoop(); | |
511 | |
512 EXPECT_TRUE(completion_callback_called()); | |
513 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED_NO_NEXT, request_status()); | |
514 } | |
515 | |
516 TEST_F(BackgroundLoaderOfflinerTest, OnlySavesOnceOnMultipleLoads) { | |
517 base::Time creation_time = base::Time::Now(); | |
518 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
519 kUserRequested); | |
520 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
521 progress_callback())); | |
522 // First load | |
523 CompleteLoading(); | |
524 // Second load | |
525 CompleteLoading(); | |
526 PumpLoop(); | |
527 model()->CompleteSavingAsSuccess(); | |
528 PumpLoop(); | |
529 | |
530 EXPECT_TRUE(completion_callback_called()); | |
531 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status()); | |
532 EXPECT_FALSE(offliner()->is_loading()); | |
533 EXPECT_FALSE(SaveInProgress()); | |
534 } | |
535 | |
536 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithLowBarStartedTriesMet) { | |
537 base::Time creation_time = base::Time::Now(); | |
538 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
539 kUserRequested); | |
540 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1); | |
541 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
542 progress_callback())); | |
543 // Guarantees low bar for saving is met. | |
544 offliner()->DocumentAvailableInMainFrame(); | |
545 // Timeout | |
546 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId)); | |
547 EXPECT_TRUE(SaveInProgress()); | |
548 model()->CompleteSavingAsSuccess(); | |
549 PumpLoop(); | |
550 EXPECT_EQ(Offliner::RequestStatus::SAVED_ON_LAST_RETRY, request_status()); | |
551 } | |
552 | |
553 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithLowBarCompletedTriesMet) { | |
554 base::Time creation_time = base::Time::Now(); | |
555 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
556 kUserRequested); | |
557 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); | |
558 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
559 progress_callback())); | |
560 // Guarantees low bar for saving is met. | |
561 offliner()->DocumentAvailableInMainFrame(); | |
562 // Timeout | |
563 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId)); | |
564 EXPECT_TRUE(SaveInProgress()); | |
565 model()->CompleteSavingAsSuccess(); | |
566 PumpLoop(); | |
567 EXPECT_EQ(Offliner::RequestStatus::SAVED_ON_LAST_RETRY, request_status()); | |
568 } | |
569 | |
570 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithNoLowBarStartedTriesMet) { | |
571 base::Time creation_time = base::Time::Now(); | |
572 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
573 kUserRequested); | |
574 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
575 progress_callback())); | |
576 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1); | |
577 // Timeout | |
578 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); | |
579 EXPECT_FALSE(SaveInProgress()); | |
580 } | |
581 | |
582 TEST_F(BackgroundLoaderOfflinerTest, | |
583 HandleTimeoutWithNoLowBarCompletedTriesMet) { | |
584 base::Time creation_time = base::Time::Now(); | |
585 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
586 kUserRequested); | |
587 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
588 progress_callback())); | |
589 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); | |
590 // Timeout | |
591 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); | |
592 EXPECT_FALSE(SaveInProgress()); | |
593 } | |
594 | |
595 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithLowBarNoRetryLimit) { | |
596 base::Time creation_time = base::Time::Now(); | |
597 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
598 kUserRequested); | |
599 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
600 progress_callback())); | |
601 // Sets lowbar. | |
602 offliner()->DocumentAvailableInMainFrame(); | |
603 // Timeout | |
604 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId)); | |
605 EXPECT_FALSE(SaveInProgress()); | |
606 } | |
607 | |
608 TEST_F(BackgroundLoaderOfflinerTest, SignalCollectionDisabled) { | |
609 // Ensure feature flag for Signal collection is off, | |
610 EXPECT_FALSE(offline_pages::IsOfflinePagesLoadSignalCollectingEnabled()); | |
611 | |
612 base::Time creation_time = base::Time::Now(); | |
613 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
614 kUserRequested); | |
615 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
616 progress_callback())); | |
617 | |
618 CompleteLoading(); | |
619 PumpLoop(); | |
620 | |
621 // No extra parts should be added if the flag is off. | |
622 content::MHTMLExtraParts* extra_parts = | |
623 content::MHTMLExtraParts::FromWebContents(offliner()->web_contents()); | |
624 EXPECT_EQ(extra_parts->size(), 0); | |
625 } | |
626 | |
627 TEST_F(BackgroundLoaderOfflinerTest, SignalCollectionEnabled) { | |
628 // Ensure feature flag for signal collection is on. | |
629 base::test::ScopedFeatureList scoped_feature_list; | |
630 scoped_feature_list.InitAndEnableFeature( | |
631 kOfflinePagesLoadSignalCollectingFeature); | |
632 EXPECT_TRUE(IsOfflinePagesLoadSignalCollectingEnabled()); | |
633 | |
634 base::Time creation_time = base::Time::Now(); | |
635 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
636 kUserRequested); | |
637 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), | |
638 progress_callback())); | |
639 | |
640 CompleteLoading(); | |
641 PumpLoop(); | |
642 | |
643 // One extra part should be added if the flag is on. | |
644 content::MHTMLExtraParts* extra_parts = | |
645 content::MHTMLExtraParts::FromWebContents(offliner()->web_contents()); | |
646 EXPECT_EQ(extra_parts->size(), 1); | |
647 } | |
648 | |
649 } // namespace offline_pages | |
OLD | NEW |