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/offline_pages/background_loader_offliner.h"
6
7 #include <utility>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/run_loop.h"
13 #include "base/test/metrics/histogram_tester.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "chrome/browser/net/prediction_options.h"
18 #include "chrome/browser/offline_pages/offliner_helper.h"
19 #include "chrome/browser/previews/previews_ui_tab_helper.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "components/content_settings/core/browser/cookie_settings.h"
23 #include "components/content_settings/core/common/pref_names.h"
24 #include "components/offline_pages/content/background_loader/background_loader_contents_stub.h"
25 #include "components/offline_pages/core/background/load_termination_listener.h"
26 #include "components/offline_pages/core/background/offliner.h"
27 #include "components/offline_pages/core/background/offliner_policy.h"
28 #include "components/offline_pages/core/background/save_page_request.h"
29 #include "components/offline_pages/core/offline_page_feature.h"
30 #include "components/offline_pages/core/stub_offline_page_model.h"
31 #include "components/prefs/pref_service.h"
32 #include "components/previews/content/previews_user_data.h"
33 #include "components/security_state/core/security_state.h"
34 #include "content/public/browser/mhtml_extra_parts.h"
35 #include "content/public/browser/web_contents.h"
36 #include "content/public/test/browser_task_environment.h"
37 #include "content/public/test/mock_navigation_handle.h"
38 #include "content/public/test/test_renderer_host.h"
39 #include "content/public/test/web_contents_tester.h"
40 #include "net/base/net_errors.h"
41 #include "net/http/http_response_headers.h"
42 #include "net/test/cert_test_util.h"
43 #include "net/test/test_data_directory.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45
46 namespace {
47 char kShortSnapshotDelayForTest[] =
48 "short-offline-page-snapshot-delay-for-test";
49 } // namespace
50
51 namespace offline_pages {
52
53 namespace {
54
55 using security_state::VisibleSecurityState;
56
57 const int64_t kRequestId = 7;
58 const ClientId kClientId("async_loading", "88");
59 const bool kUserRequested = true;
60 const char kRequestOrigin[] = "abc.xyz";
61
62 // TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
63 // function.
HttpUrl()64 GURL HttpUrl() {
65 return GURL("http://www.tunafish.com");
66 }
HttpsUrl()67 GURL HttpsUrl() {
68 return GURL("https://www.yellowtail.com");
69 }
FileUrl()70 GURL FileUrl() {
71 return GURL("file://salmon.png");
72 }
73
74 class TestLoadTerminationListener : public LoadTerminationListener {
75 public:
76 TestLoadTerminationListener() = default;
77 ~TestLoadTerminationListener() override = default;
78
TerminateLoad()79 void TerminateLoad() { offliner()->TerminateLoadIfInProgress(); }
80
offliner()81 Offliner* offliner() { return offliner_; }
82
83 private:
84 DISALLOW_COPY_AND_ASSIGN(TestLoadTerminationListener);
85 };
86
87 // Mock OfflinePageModel for testing the SavePage calls
88 class MockOfflinePageModel : public StubOfflinePageModel {
89 public:
MockOfflinePageModel()90 MockOfflinePageModel() : mock_saving_(false), mock_deleting_(false) {}
~MockOfflinePageModel()91 ~MockOfflinePageModel() override {}
92
SavePage(const SavePageParams & save_page_params,std::unique_ptr<OfflinePageArchiver> archiver,content::WebContents * web_contents,SavePageCallback callback)93 void SavePage(const SavePageParams& save_page_params,
94 std::unique_ptr<OfflinePageArchiver> archiver,
95 content::WebContents* web_contents,
96 SavePageCallback callback) override {
97 mock_saving_ = true;
98 save_page_callback_ = std::move(callback);
99 save_page_params_ = save_page_params;
100 }
101
CompleteSavingAsArchiveCreationFailed()102 void CompleteSavingAsArchiveCreationFailed() {
103 DCHECK(mock_saving_);
104 mock_saving_ = false;
105 base::ThreadTaskRunnerHandle::Get()->PostTask(
106 FROM_HERE, base::BindOnce(std::move(save_page_callback_),
107 SavePageResult::ARCHIVE_CREATION_FAILED, 0));
108 }
109
CompleteSavingAsSuccess()110 void CompleteSavingAsSuccess() {
111 DCHECK(mock_saving_);
112 mock_saving_ = false;
113 base::ThreadTaskRunnerHandle::Get()->PostTask(
114 FROM_HERE, base::BindOnce(std::move(save_page_callback_),
115 SavePageResult::SUCCESS, 123456));
116 }
117
CompleteSavingAsAlreadyExists()118 void CompleteSavingAsAlreadyExists() {
119 DCHECK(mock_saving_);
120 mock_saving_ = false;
121 base::ThreadTaskRunnerHandle::Get()->PostTask(
122 FROM_HERE, base::BindOnce(std::move(save_page_callback_),
123 SavePageResult::ALREADY_EXISTS, 123456));
124 }
125
DeletePagesWithCriteria(const PageCriteria & criteria,DeletePageCallback callback)126 void DeletePagesWithCriteria(const PageCriteria& criteria,
127 DeletePageCallback callback) override {
128 mock_deleting_ = true;
129 std::move(callback).Run(DeletePageResult::SUCCESS);
130 }
131
mock_saving() const132 bool mock_saving() const { return mock_saving_; }
mock_deleting() const133 bool mock_deleting() const { return mock_deleting_; }
save_page_params()134 SavePageParams& save_page_params() { return save_page_params_; }
135
136 private:
137 bool mock_saving_;
138 bool mock_deleting_;
139 SavePageCallback save_page_callback_;
140 SavePageParams save_page_params_;
141
142 DISALLOW_COPY_AND_ASSIGN(MockOfflinePageModel);
143 };
144
145 } // namespace
146
147 // A BackgroundLoader that we can run tests on.
148 // Overrides the ResetState so we don't actually try to create any web contents.
149 // This is a temporary solution to test core BackgroundLoaderOffliner
150 // functionality until we straighten out assumptions made by RequestCoordinator
151 // so that the ResetState method is no longer needed.
152 class TestBackgroundLoaderOffliner : public BackgroundLoaderOffliner {
153 public:
154 explicit TestBackgroundLoaderOffliner(
155 content::BrowserContext* browser_context,
156 const OfflinerPolicy* policy,
157 OfflinePageModel* offline_page_model,
158 std::unique_ptr<LoadTerminationListener> load_termination_listener);
159 ~TestBackgroundLoaderOffliner() override;
web_contents_tester()160 content::WebContentsTester* web_contents_tester() {
161 return content::WebContentsTester::For(stub_->web_contents());
162 }
163
web_contents()164 content::WebContents* web_contents() { return stub_->web_contents(); }
stub()165 background_loader::BackgroundLoaderContents* stub() { return stub_; }
166
is_loading()167 bool is_loading() { return loader_ && stub_->is_loading(); }
168
set_custom_visible_security_state(std::unique_ptr<VisibleSecurityState> visible_security_state)169 void set_custom_visible_security_state(
170 std::unique_ptr<VisibleSecurityState> visible_security_state) {
171 custom_visible_security_state_ = std::move(visible_security_state);
172 }
set_page_type(content::PageType page_type)173 void set_page_type(content::PageType page_type) { page_type_ = page_type; }
174
175 private:
176 // BackgroundLoaderOffliner overrides.
177 void ResetLoader() override;
178 std::unique_ptr<VisibleSecurityState> GetVisibleSecurityState(
179 content::WebContents* web_contents) override;
180 content::PageType GetPageType(content::WebContents* web_contents) override;
181
182 background_loader::BackgroundLoaderContentsStub* stub_;
183 std::unique_ptr<VisibleSecurityState> custom_visible_security_state_;
184 content::PageType page_type_ = content::PageType::PAGE_TYPE_NORMAL;
185 };
186
TestBackgroundLoaderOffliner(content::BrowserContext * browser_context,const OfflinerPolicy * policy,OfflinePageModel * offline_page_model,std::unique_ptr<LoadTerminationListener> load_termination_listener)187 TestBackgroundLoaderOffliner::TestBackgroundLoaderOffliner(
188 content::BrowserContext* browser_context,
189 const OfflinerPolicy* policy,
190 OfflinePageModel* offline_page_model,
191 std::unique_ptr<LoadTerminationListener> load_termination_listener)
192 : BackgroundLoaderOffliner(browser_context,
193 policy,
194 offline_page_model,
195 std::move(load_termination_listener)) {}
196
~TestBackgroundLoaderOffliner()197 TestBackgroundLoaderOffliner::~TestBackgroundLoaderOffliner() {}
198
ResetLoader()199 void TestBackgroundLoaderOffliner::ResetLoader() {
200 stub_ = new background_loader::BackgroundLoaderContentsStub(browser_context_);
201 loader_.reset(stub_);
202 loader_->SetDelegate(this);
203 }
204
205 std::unique_ptr<VisibleSecurityState>
GetVisibleSecurityState(content::WebContents * web_contents)206 TestBackgroundLoaderOffliner::GetVisibleSecurityState(
207 content::WebContents* web_contents) {
208 if (custom_visible_security_state_)
209 return std::move(custom_visible_security_state_);
210 return BackgroundLoaderOffliner::GetVisibleSecurityState(web_contents);
211 }
212
GetPageType(content::WebContents * web_contents)213 content::PageType TestBackgroundLoaderOffliner::GetPageType(
214 content::WebContents* web_contents) {
215 return page_type_;
216 }
217
218 class BackgroundLoaderOfflinerTest : public testing::Test {
219 public:
220 BackgroundLoaderOfflinerTest();
221 ~BackgroundLoaderOfflinerTest() override;
222
223 void SetUp() override;
224
offliner() const225 TestBackgroundLoaderOffliner* offliner() const { return offliner_.get(); }
completion_callback()226 Offliner::CompletionCallback completion_callback() {
227 return base::BindOnce(&BackgroundLoaderOfflinerTest::OnCompletion,
228 base::Unretained(this));
229 }
progress_callback()230 Offliner::ProgressCallback const progress_callback() {
231 return base::BindRepeating(&BackgroundLoaderOfflinerTest::OnProgress,
232 base::Unretained(this));
233 }
cancel_callback()234 Offliner::CancelCallback cancel_callback() {
235 return base::BindOnce(&BackgroundLoaderOfflinerTest::OnCancel,
236 base::Unretained(this));
237 }
can_download_callback()238 base::OnceCallback<void(bool)> can_download_callback() {
239 return base::BindOnce(&BackgroundLoaderOfflinerTest::OnCanDownload,
240 base::Unretained(this));
241 }
profile()242 Profile* profile() { return &profile_; }
completion_callback_called()243 bool completion_callback_called() { return completion_callback_called_; }
request_status()244 Offliner::RequestStatus request_status() { return request_status_; }
cancel_callback_called()245 bool cancel_callback_called() { return cancel_callback_called_; }
can_download_callback_called()246 bool can_download_callback_called() { return can_download_callback_called_; }
can_download()247 bool can_download() { return can_download_; }
SaveInProgress() const248 bool SaveInProgress() const { return model_->mock_saving(); }
DeleteCalled() const249 bool DeleteCalled() const { return model_->mock_deleting(); }
model() const250 MockOfflinePageModel* model() const { return model_; }
histograms() const251 const base::HistogramTester& histograms() const { return histogram_tester_; }
progress()252 int64_t progress() { return progress_; }
policy() const253 OfflinerPolicy* policy() const { return policy_.get(); }
load_termination_listener()254 TestLoadTerminationListener* load_termination_listener() {
255 return load_termination_listener_;
256 }
257
PumpLoop()258 void PumpLoop() { base::RunLoop().RunUntilIdle(); }
259
CompleteLoading()260 void CompleteLoading() {
261 // Reset snapshot controller.
262 std::unique_ptr<BackgroundSnapshotController> snapshot_controller(
263 new BackgroundSnapshotController(base::ThreadTaskRunnerHandle::Get(),
264 offliner_.get(),
265 false /* RenovationsEnabled */));
266 offliner_->SetBackgroundSnapshotControllerForTest(
267 std::move(snapshot_controller));
268 // Call complete loading.
269 offliner()->DocumentAvailableInMainFrame();
270 offliner()->DocumentOnLoadCompletedInMainFrame();
271 PumpLoop();
272 }
273
GetRequestStats()274 offline_pages::RequestStats* GetRequestStats() {
275 return offliner_->GetRequestStatsForTest();
276 }
277
BaseVisibleSecurityState()278 std::unique_ptr<VisibleSecurityState> BaseVisibleSecurityState() {
279 auto visible_security_state = std::make_unique<VisibleSecurityState>();
280 visible_security_state->connection_info_initialized = true;
281 visible_security_state->url = HttpsUrl();
282 visible_security_state->certificate =
283 net::ImportCertFromFile(net::GetTestCertsDirectory(), "sha1_2016.pem");
284 visible_security_state->cert_status =
285 net::CERT_STATUS_SHA1_SIGNATURE_PRESENT;
286 return visible_security_state;
287 }
288
289 private:
290 void OnCompletion(const SavePageRequest& request,
291 Offliner::RequestStatus status);
292 void OnProgress(const SavePageRequest& request, int64_t bytes);
293 void OnCancel(const SavePageRequest& request);
294 void OnCanDownload(bool allowed);
295 content::BrowserTaskEnvironment task_environment_;
296 content::RenderViewHostTestEnabler rvhte_;
297 TestingProfile profile_;
298 std::unique_ptr<OfflinerPolicy> policy_;
299 TestLoadTerminationListener* load_termination_listener_;
300 std::unique_ptr<TestBackgroundLoaderOffliner> offliner_;
301 MockOfflinePageModel* model_;
302 bool completion_callback_called_;
303 bool cancel_callback_called_;
304 bool can_download_callback_called_;
305 bool can_download_;
306 int64_t progress_;
307 Offliner::RequestStatus request_status_;
308 base::HistogramTester histogram_tester_;
309
310 DISALLOW_COPY_AND_ASSIGN(BackgroundLoaderOfflinerTest);
311 };
312
BackgroundLoaderOfflinerTest()313 BackgroundLoaderOfflinerTest::BackgroundLoaderOfflinerTest()
314 : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
315 load_termination_listener_(nullptr),
316 model_(nullptr),
317 completion_callback_called_(false),
318 cancel_callback_called_(false),
319 can_download_callback_called_(false),
320 can_download_(false),
321 progress_(0LL),
322 request_status_(Offliner::RequestStatus::UNKNOWN) {}
323
~BackgroundLoaderOfflinerTest()324 BackgroundLoaderOfflinerTest::~BackgroundLoaderOfflinerTest() {}
325
SetUp()326 void BackgroundLoaderOfflinerTest::SetUp() {
327 // Set the snapshot controller delay command line switch to short delays.
328 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
329 cl->AppendSwitch(kShortSnapshotDelayForTest);
330
331 std::unique_ptr<TestLoadTerminationListener> listener =
332 std::make_unique<TestLoadTerminationListener>();
333 load_termination_listener_ = listener.get();
334 model_ = new MockOfflinePageModel();
335 policy_.reset(new OfflinerPolicy());
336 offliner_.reset(new TestBackgroundLoaderOffliner(
337 profile(), policy_.get(), model_, std::move(listener)));
338 }
339
OnCompletion(const SavePageRequest & request,Offliner::RequestStatus status)340 void BackgroundLoaderOfflinerTest::OnCompletion(
341 const SavePageRequest& request,
342 Offliner::RequestStatus status) {
343 DCHECK(!completion_callback_called_); // Expect 1 callback per request.
344 completion_callback_called_ = true;
345 request_status_ = status;
346 }
347
OnProgress(const SavePageRequest & request,int64_t bytes)348 void BackgroundLoaderOfflinerTest::OnProgress(const SavePageRequest& request,
349 int64_t bytes) {
350 progress_ = bytes;
351 }
352
OnCancel(const SavePageRequest & request)353 void BackgroundLoaderOfflinerTest::OnCancel(const SavePageRequest& request) {
354 DCHECK(!cancel_callback_called_);
355 cancel_callback_called_ = true;
356 }
357
OnCanDownload(bool allowed)358 void BackgroundLoaderOfflinerTest::OnCanDownload(bool allowed) {
359 can_download_callback_called_ = true;
360 can_download_ = allowed;
361 }
362
TEST_F(BackgroundLoaderOfflinerTest,LoadTerminationListenerSetup)363 TEST_F(BackgroundLoaderOfflinerTest, LoadTerminationListenerSetup) {
364 // Verify that back pointer to offliner is set up in the listener.
365 Offliner* base_offliner = offliner();
366 EXPECT_NE(base_offliner, nullptr);
367 EXPECT_EQ(base_offliner, load_termination_listener()->offliner());
368 }
369
TEST_F(BackgroundLoaderOfflinerTest,LoadAndSaveBlockThirdPartyCookiesForCustomTabs)370 TEST_F(BackgroundLoaderOfflinerTest,
371 LoadAndSaveBlockThirdPartyCookiesForCustomTabs) {
372 base::Time creation_time = base::Time::Now();
373 ClientId custom_tabs_client_id("custom_tabs", "88");
374 SavePageRequest request(kRequestId, HttpUrl(), custom_tabs_client_id,
375 creation_time, kUserRequested);
376
377 profile()->GetPrefs()->SetInteger(
378 prefs::kCookieControlsMode,
379 static_cast<int>(content_settings::CookieControlsMode::kBlockThirdParty));
380 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(),
381 progress_callback()));
382 }
383
TEST_F(BackgroundLoaderOfflinerTest,LoadAndSaveNetworkPredictionDisabledForCustomTabs)384 TEST_F(BackgroundLoaderOfflinerTest,
385 LoadAndSaveNetworkPredictionDisabledForCustomTabs) {
386 base::Time creation_time = base::Time::Now();
387 ClientId custom_tabs_client_id("custom_tabs", "88");
388 SavePageRequest request(kRequestId, HttpUrl(), custom_tabs_client_id,
389 creation_time, kUserRequested);
390
391 profile()->GetPrefs()->SetInteger(
392 prefs::kNetworkPredictionOptions,
393 chrome_browser_net::NETWORK_PREDICTION_NEVER);
394 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(),
395 progress_callback()));
396 }
397
TEST_F(BackgroundLoaderOfflinerTest,LoadAndSaveStartsLoading)398 TEST_F(BackgroundLoaderOfflinerTest, LoadAndSaveStartsLoading) {
399 base::Time creation_time = base::Time::Now();
400 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
401 kUserRequested);
402 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
403 progress_callback()));
404 EXPECT_TRUE(offliner()->is_loading());
405 EXPECT_FALSE(SaveInProgress());
406 EXPECT_FALSE(completion_callback_called());
407 EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status());
408 }
409
TEST_F(BackgroundLoaderOfflinerTest,BytesReportedWillUpdateProgress)410 TEST_F(BackgroundLoaderOfflinerTest, BytesReportedWillUpdateProgress) {
411 base::Time creation_time = base::Time::Now();
412 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
413 kUserRequested);
414 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
415 progress_callback()));
416 offliner()->OnNetworkBytesChanged(5LL);
417 EXPECT_EQ(progress(), 5LL);
418 offliner()->OnNetworkBytesChanged(10LL);
419 EXPECT_EQ(progress(), 15LL);
420 }
421
TEST_F(BackgroundLoaderOfflinerTest,CompleteLoadingInitiatesSave)422 TEST_F(BackgroundLoaderOfflinerTest, CompleteLoadingInitiatesSave) {
423 base::Time creation_time = base::Time::Now();
424 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
425 kUserRequested);
426 request.set_request_origin(kRequestOrigin);
427 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
428 progress_callback()));
429 CompleteLoading();
430 PumpLoop();
431 // Verify that request origin is propagated.
432 EXPECT_EQ(kRequestOrigin, model()->save_page_params().request_origin);
433 EXPECT_FALSE(completion_callback_called());
434 EXPECT_TRUE(SaveInProgress());
435 EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status());
436 }
437
TEST_F(BackgroundLoaderOfflinerTest,CancelWhenLoading)438 TEST_F(BackgroundLoaderOfflinerTest, CancelWhenLoading) {
439 base::Time creation_time = base::Time::Now();
440 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
441 kUserRequested);
442 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
443 progress_callback()));
444 offliner()->Cancel(cancel_callback());
445 PumpLoop();
446 offliner()->OnNetworkBytesChanged(15LL);
447 EXPECT_TRUE(cancel_callback_called());
448 EXPECT_FALSE(completion_callback_called());
449 EXPECT_FALSE(offliner()->is_loading()); // Offliner reset.
450 EXPECT_EQ(progress(), 0LL); // network bytes not recorded when not busy.
451 }
452
TEST_F(BackgroundLoaderOfflinerTest,CancelWhenLoadTerminated)453 TEST_F(BackgroundLoaderOfflinerTest, CancelWhenLoadTerminated) {
454 base::Time creation_time = base::Time::Now();
455 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
456 kUserRequested);
457 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
458 progress_callback()));
459 load_termination_listener()->TerminateLoad();
460 PumpLoop();
461 EXPECT_TRUE(completion_callback_called());
462 EXPECT_FALSE(offliner()->is_loading()); // Offliner reset.
463 EXPECT_EQ(Offliner::RequestStatus::FOREGROUND_CANCELED, request_status());
464 }
465
TEST_F(BackgroundLoaderOfflinerTest,CancelWhenLoaded)466 TEST_F(BackgroundLoaderOfflinerTest, CancelWhenLoaded) {
467 base::Time creation_time = base::Time::Now();
468 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
469 kUserRequested);
470 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
471 progress_callback()));
472 CompleteLoading();
473 PumpLoop();
474 offliner()->Cancel(cancel_callback());
475 PumpLoop();
476
477 // Subsequent save callback cause no crash.
478 model()->CompleteSavingAsArchiveCreationFailed();
479 PumpLoop();
480 EXPECT_TRUE(cancel_callback_called());
481 EXPECT_TRUE(DeleteCalled());
482 EXPECT_FALSE(completion_callback_called());
483 EXPECT_FALSE(SaveInProgress());
484 EXPECT_FALSE(offliner()->is_loading()); // Offliner reset.
485 }
486
TEST_F(BackgroundLoaderOfflinerTest,LoadedButSaveFails)487 TEST_F(BackgroundLoaderOfflinerTest, LoadedButSaveFails) {
488 base::Time creation_time = base::Time::Now();
489 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
490 kUserRequested);
491 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
492 progress_callback()));
493
494 CompleteLoading();
495 PumpLoop();
496 model()->CompleteSavingAsArchiveCreationFailed();
497 PumpLoop();
498
499 EXPECT_TRUE(completion_callback_called());
500 EXPECT_EQ(Offliner::RequestStatus::SAVE_FAILED, request_status());
501 EXPECT_FALSE(offliner()->is_loading());
502 EXPECT_FALSE(SaveInProgress());
503 }
504
TEST_F(BackgroundLoaderOfflinerTest,ProgressDoesNotUpdateDuringSave)505 TEST_F(BackgroundLoaderOfflinerTest, ProgressDoesNotUpdateDuringSave) {
506 base::Time creation_time = base::Time::Now();
507 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
508 kUserRequested);
509 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
510 progress_callback()));
511 offliner()->OnNetworkBytesChanged(10LL);
512 CompleteLoading();
513 PumpLoop();
514 offliner()->OnNetworkBytesChanged(15LL);
515 EXPECT_EQ(progress(), 10LL);
516 }
517
TEST_F(BackgroundLoaderOfflinerTest,LoadAndSaveSuccess)518 TEST_F(BackgroundLoaderOfflinerTest, LoadAndSaveSuccess) {
519 base::Time creation_time = base::Time::Now();
520 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
521 kUserRequested);
522 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
523 progress_callback()));
524
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(can_download_callback_called());
534 EXPECT_FALSE(SaveInProgress());
535 }
536
TEST_F(BackgroundLoaderOfflinerTest,LoadAndSaveAlreadyExists)537 TEST_F(BackgroundLoaderOfflinerTest, LoadAndSaveAlreadyExists) {
538 base::Time creation_time = base::Time::Now();
539 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
540 kUserRequested);
541 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
542 progress_callback()));
543
544 CompleteLoading();
545 PumpLoop();
546 model()->CompleteSavingAsAlreadyExists();
547 PumpLoop();
548
549 EXPECT_TRUE(completion_callback_called());
550 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status());
551 EXPECT_FALSE(offliner()->is_loading());
552 EXPECT_FALSE(SaveInProgress());
553 }
554
TEST_F(BackgroundLoaderOfflinerTest,ResetsWhenDownloadStarts)555 TEST_F(BackgroundLoaderOfflinerTest, ResetsWhenDownloadStarts) {
556 base::Time creation_time = base::Time::Now();
557 ClientId browser_actions("browser_actions", "123");
558 SavePageRequest request(kRequestId, HttpUrl(), browser_actions, creation_time,
559 kUserRequested);
560 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
561 progress_callback()));
562 offliner()->stub()->CanDownload(HttpUrl(), "foo", can_download_callback());
563 PumpLoop();
564 EXPECT_TRUE(can_download_callback_called());
565 EXPECT_TRUE(can_download());
566 EXPECT_TRUE(completion_callback_called());
567 EXPECT_EQ(Offliner::RequestStatus::DOWNLOAD_THROTTLED, request_status());
568 }
569
TEST_F(BackgroundLoaderOfflinerTest,ResetsWhenDownloadEncountered)570 TEST_F(BackgroundLoaderOfflinerTest, ResetsWhenDownloadEncountered) {
571 base::Time creation_time = base::Time::Now();
572 ClientId prefetching("suggested_articles", "123");
573 SavePageRequest request(kRequestId, HttpUrl(), prefetching, creation_time,
574 kUserRequested);
575 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
576 progress_callback()));
577 offliner()->stub()->CanDownload(HttpUrl(), "foo", can_download_callback());
578 PumpLoop();
579 EXPECT_TRUE(can_download_callback_called());
580 EXPECT_FALSE(can_download());
581 EXPECT_TRUE(completion_callback_called());
582 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED_DOWNLOAD, request_status());
583 }
584
TEST_F(BackgroundLoaderOfflinerTest,CanDownloadReturnsIfNoPendingRequest)585 TEST_F(BackgroundLoaderOfflinerTest, CanDownloadReturnsIfNoPendingRequest) {
586 offliner()->CanDownload(can_download_callback());
587 PumpLoop();
588 EXPECT_TRUE(can_download_callback_called());
589 EXPECT_FALSE(can_download());
590 }
591
TEST_F(BackgroundLoaderOfflinerTest,FailsOnInvalidURL)592 TEST_F(BackgroundLoaderOfflinerTest, FailsOnInvalidURL) {
593 base::Time creation_time = base::Time::Now();
594 SavePageRequest request(kRequestId, FileUrl(), kClientId, creation_time,
595 kUserRequested);
596 EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(),
597 progress_callback()));
598 }
599
TEST_F(BackgroundLoaderOfflinerTest,ReturnsOnRenderCrash)600 TEST_F(BackgroundLoaderOfflinerTest, ReturnsOnRenderCrash) {
601 base::Time creation_time = base::Time::Now();
602 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
603 kUserRequested);
604 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
605 progress_callback()));
606 offliner()->RenderProcessGone(
607 base::TerminationStatus::TERMINATION_STATUS_PROCESS_CRASHED);
608
609 EXPECT_TRUE(completion_callback_called());
610 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED_NO_NEXT, request_status());
611 }
612
TEST_F(BackgroundLoaderOfflinerTest,ReturnsOnRenderKilled)613 TEST_F(BackgroundLoaderOfflinerTest, ReturnsOnRenderKilled) {
614 base::Time creation_time = base::Time::Now();
615 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
616 kUserRequested);
617 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
618 progress_callback()));
619 offliner()->RenderProcessGone(
620 base::TerminationStatus::TERMINATION_STATUS_PROCESS_WAS_KILLED);
621
622 EXPECT_TRUE(completion_callback_called());
623 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status());
624 }
625
TEST_F(BackgroundLoaderOfflinerTest,ReturnsOnWebContentsDestroyed)626 TEST_F(BackgroundLoaderOfflinerTest, ReturnsOnWebContentsDestroyed) {
627 base::Time creation_time = base::Time::Now();
628 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
629 kUserRequested);
630 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
631 progress_callback()));
632 offliner()->WebContentsDestroyed();
633
634 EXPECT_TRUE(completion_callback_called());
635 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status());
636 }
637
TEST_F(BackgroundLoaderOfflinerTest,FailsOnErrorPage)638 TEST_F(BackgroundLoaderOfflinerTest, FailsOnErrorPage) {
639 base::Time creation_time = base::Time::Now();
640 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
641 kUserRequested);
642 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
643 progress_callback()));
644 // Create handle with net error code.
645 // Called after calling LoadAndSave so we have web_contents to work with.
646 content::MockNavigationHandle handle(
647 HttpUrl(), offliner()->web_contents()->GetMainFrame());
648 handle.set_has_committed(true);
649 handle.set_is_error_page(true);
650 handle.set_net_error_code(net::Error::ERR_NAME_NOT_RESOLVED);
651 offliner()->DidFinishNavigation(&handle);
652
653 histograms().ExpectBucketCount(
654 "OfflinePages.Background.LoadingErrorStatusCode.async_loading",
655 -105, // ERR_NAME_NOT_RESOLVED
656 1);
657 CompleteLoading();
658 PumpLoop();
659
660 EXPECT_TRUE(completion_callback_called());
661 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED_NET_ERROR,
662 request_status());
663 }
664
TEST_F(BackgroundLoaderOfflinerTest,FailsOnCertificateError)665 TEST_F(BackgroundLoaderOfflinerTest, FailsOnCertificateError) {
666 base::Time creation_time = base::Time::Now();
667 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
668 kUserRequested);
669 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
670 progress_callback()));
671
672 // Sets the certificate status as having been revoked.
673 std::unique_ptr<VisibleSecurityState> visible_security_state =
674 BaseVisibleSecurityState();
675 visible_security_state->cert_status |= net::CERT_STATUS_REVOKED;
676 offliner()->set_custom_visible_security_state(
677 std::move(visible_security_state));
678
679 // Called after calling LoadAndSave so we have web_contents to work with.
680 content::MockNavigationHandle handle(
681 HttpUrl(), offliner()->web_contents()->GetMainFrame());
682 handle.set_has_committed(true);
683 offliner()->DidFinishNavigation(&handle);
684
685 CompleteLoading();
686 PumpLoop();
687
688 EXPECT_FALSE(SaveInProgress());
689 EXPECT_TRUE(completion_callback_called());
690 EXPECT_EQ(Offliner::RequestStatus::LOADED_PAGE_HAS_CERTIFICATE_ERROR,
691 request_status());
692 }
693
TEST_F(BackgroundLoaderOfflinerTest,FailsOnRevocationCheckingFailure)694 TEST_F(BackgroundLoaderOfflinerTest, FailsOnRevocationCheckingFailure) {
695 base::Time creation_time = base::Time::Now();
696 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
697 kUserRequested);
698 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
699 progress_callback()));
700
701 // Sets a revocation checking failure certificate error that should not be
702 // allowed.
703 std::unique_ptr<VisibleSecurityState> visible_security_state =
704 BaseVisibleSecurityState();
705 visible_security_state->cert_status |=
706 net::CERT_STATUS_NO_REVOCATION_MECHANISM;
707 offliner()->set_custom_visible_security_state(
708 std::move(visible_security_state));
709
710 // Called after calling LoadAndSave so we have web_contents to work with.
711 content::MockNavigationHandle handle(
712 HttpUrl(), offliner()->web_contents()->GetMainFrame());
713 handle.set_has_committed(true);
714 offliner()->DidFinishNavigation(&handle);
715
716 CompleteLoading();
717 PumpLoop();
718
719 EXPECT_FALSE(SaveInProgress());
720 EXPECT_TRUE(completion_callback_called());
721 EXPECT_EQ(Offliner::RequestStatus::LOADED_PAGE_HAS_CERTIFICATE_ERROR,
722 request_status());
723 }
724
TEST_F(BackgroundLoaderOfflinerTest,SucceedsOnHttp)725 TEST_F(BackgroundLoaderOfflinerTest, SucceedsOnHttp) {
726 base::Time creation_time = base::Time::Now();
727 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
728 kUserRequested);
729 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
730 progress_callback()));
731
732 // Sets the URL to HTTP while still setting a major certificate error (should
733 // be ignored).
734 std::unique_ptr<VisibleSecurityState> visible_security_state =
735 BaseVisibleSecurityState();
736 visible_security_state->url = HttpUrl();
737 visible_security_state->cert_status |= net::CERT_STATUS_REVOKED;
738 offliner()->set_custom_visible_security_state(
739 std::move(visible_security_state));
740
741 // Called after calling LoadAndSave so we have web_contents to work with.
742 content::MockNavigationHandle handle(
743 HttpUrl(), offliner()->web_contents()->GetMainFrame());
744 handle.set_has_committed(true);
745 offliner()->DidFinishNavigation(&handle);
746
747 CompleteLoading();
748 PumpLoop();
749
750 EXPECT_TRUE(SaveInProgress());
751 EXPECT_FALSE(completion_callback_called());
752 }
753
TEST_F(BackgroundLoaderOfflinerTest,FailsOnUnwantedContent)754 TEST_F(BackgroundLoaderOfflinerTest, FailsOnUnwantedContent) {
755 base::Time creation_time = base::Time::Now();
756 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
757 kUserRequested);
758 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
759 progress_callback()));
760
761 // Sets the page as containing SafeBrowsing unwanted content.
762 std::unique_ptr<VisibleSecurityState> visible_security_state =
763 BaseVisibleSecurityState();
764 visible_security_state->malicious_content_status = security_state::
765 MaliciousContentStatus::MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING;
766 offliner()->set_custom_visible_security_state(
767 std::move(visible_security_state));
768 // Called after calling LoadAndSave so we have web_contents to work with.
769 content::MockNavigationHandle handle(
770 HttpUrl(), offliner()->web_contents()->GetMainFrame());
771 handle.set_has_committed(true);
772 offliner()->DidFinishNavigation(&handle);
773
774 CompleteLoading();
775 PumpLoop();
776
777 EXPECT_FALSE(SaveInProgress());
778 EXPECT_TRUE(completion_callback_called());
779 EXPECT_EQ(Offliner::RequestStatus::LOADED_PAGE_IS_BLOCKED, request_status());
780 }
781
TEST_F(BackgroundLoaderOfflinerTest,FailsOnInterstitialPage)782 TEST_F(BackgroundLoaderOfflinerTest, FailsOnInterstitialPage) {
783 base::Time creation_time = base::Time::Now();
784 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
785 kUserRequested);
786 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
787 progress_callback()));
788
789 // Sets the page as being an interstitial.
790 offliner()->set_page_type(content::PageType::PAGE_TYPE_INTERSTITIAL);
791 // Called after calling LoadAndSave so we have web_contents to work with.
792 content::MockNavigationHandle handle(
793 HttpUrl(), offliner()->web_contents()->GetMainFrame());
794 handle.set_has_committed(true);
795 offliner()->DidFinishNavigation(&handle);
796
797 CompleteLoading();
798 PumpLoop();
799
800 EXPECT_FALSE(SaveInProgress());
801 EXPECT_TRUE(completion_callback_called());
802 EXPECT_EQ(Offliner::RequestStatus::LOADED_PAGE_IS_CHROME_INTERNAL,
803 request_status());
804 }
805
TEST_F(BackgroundLoaderOfflinerTest,FailsOnInternetDisconnected)806 TEST_F(BackgroundLoaderOfflinerTest, FailsOnInternetDisconnected) {
807 base::Time creation_time = base::Time::Now();
808 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
809 kUserRequested);
810 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
811 progress_callback()));
812
813 // Create handle with net error code.
814 // Called after calling LoadAndSave so we have web_contents to work with.
815 content::MockNavigationHandle handle(
816 HttpUrl(), offliner()->web_contents()->GetMainFrame());
817 handle.set_has_committed(true);
818 handle.set_is_error_page(true);
819 handle.set_net_error_code(net::Error::ERR_INTERNET_DISCONNECTED);
820 offliner()->DidFinishNavigation(&handle);
821
822 CompleteLoading();
823 PumpLoop();
824
825 EXPECT_TRUE(completion_callback_called());
826 EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED_NET_ERROR,
827 request_status());
828 }
829
TEST_F(BackgroundLoaderOfflinerTest,DoesNotCrashWithNullResponseHeaders)830 TEST_F(BackgroundLoaderOfflinerTest, DoesNotCrashWithNullResponseHeaders) {
831 base::Time creation_time = base::Time::Now();
832 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
833 kUserRequested);
834 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
835 progress_callback()));
836
837 // Called after calling LoadAndSave so we have web_contents to work with.
838 content::MockNavigationHandle handle(
839 HttpUrl(), offliner()->web_contents()->GetMainFrame());
840 handle.set_has_committed(true);
841 offliner()->DidFinishNavigation(&handle);
842 }
843
TEST_F(BackgroundLoaderOfflinerTest,OffliningPreviewsStatusOffHistogram)844 TEST_F(BackgroundLoaderOfflinerTest, OffliningPreviewsStatusOffHistogram) {
845 base::Time creation_time = base::Time::Now();
846 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
847 kUserRequested);
848 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
849 progress_callback()));
850
851 // Called after calling LoadAndSave so we have web_contents to work with.
852 content::MockNavigationHandle handle(
853 HttpUrl(), offliner()->web_contents()->GetMainFrame());
854 handle.set_has_committed(true);
855 // Set up PreviewsUserData on the handle.
856 PreviewsUITabHelper::CreateForWebContents(offliner()->web_contents());
857 PreviewsUITabHelper::FromWebContents(offliner()->web_contents())
858 ->CreatePreviewsUserDataForNavigationHandle(&handle, 1u)
859 ->set_committed_previews_state(
860 blink::PreviewsTypes::PREVIEWS_NO_TRANSFORM);
861 scoped_refptr<net::HttpResponseHeaders> header(
862 new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
863 handle.set_response_headers(header.get());
864 // Call DidFinishNavigation with handle.
865 offliner()->DidFinishNavigation(&handle);
866
867 histograms().ExpectBucketCount(
868 "OfflinePages.Background.OffliningPreviewStatus.async_loading",
869 0, // Previews Disabled
870 1);
871 }
872
TEST_F(BackgroundLoaderOfflinerTest,OffliningPreviewsStatusOnHistogram)873 TEST_F(BackgroundLoaderOfflinerTest, OffliningPreviewsStatusOnHistogram) {
874 base::Time creation_time = base::Time::Now();
875 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
876 kUserRequested);
877 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
878 progress_callback()));
879
880 // Called after calling LoadAndSave so we have web_contents to work with.
881 content::MockNavigationHandle handle(
882 HttpUrl(), offliner()->web_contents()->GetMainFrame());
883 handle.set_has_committed(true);
884 // Set up PreviewsUserData on the handle.
885 PreviewsUITabHelper::CreateForWebContents(offliner()->web_contents());
886 PreviewsUITabHelper::FromWebContents(offliner()->web_contents())
887 ->CreatePreviewsUserDataForNavigationHandle(&handle, 1u)
888 ->set_committed_previews_state(blink::PreviewsTypes::NOSCRIPT_ON);
889 scoped_refptr<net::HttpResponseHeaders> header(
890 new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
891 handle.set_response_headers(header.get());
892
893 // Call DidFinishNavigation with handle.
894 offliner()->DidFinishNavigation(&handle);
895
896 histograms().ExpectBucketCount(
897 "OfflinePages.Background.OffliningPreviewStatus.async_loading",
898 1, // Previews Enabled
899 1);
900 }
901
TEST_F(BackgroundLoaderOfflinerTest,OnlySavesOnceOnMultipleLoads)902 TEST_F(BackgroundLoaderOfflinerTest, OnlySavesOnceOnMultipleLoads) {
903 base::Time creation_time = base::Time::Now();
904 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
905 kUserRequested);
906 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
907 progress_callback()));
908 // First load
909 CompleteLoading();
910 // Second load
911 CompleteLoading();
912 PumpLoop();
913 model()->CompleteSavingAsSuccess();
914 PumpLoop();
915
916 EXPECT_TRUE(completion_callback_called());
917 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status());
918 EXPECT_FALSE(offliner()->is_loading());
919 EXPECT_FALSE(SaveInProgress());
920 }
921
TEST_F(BackgroundLoaderOfflinerTest,HandleTimeoutWithLowBarStartedTriesMet)922 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithLowBarStartedTriesMet) {
923 base::Time creation_time = base::Time::Now();
924 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
925 kUserRequested);
926 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1);
927 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
928 progress_callback()));
929 // Guarantees low bar for saving is met.
930 offliner()->DocumentAvailableInMainFrame();
931 // Timeout
932 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId));
933 EXPECT_TRUE(SaveInProgress());
934 model()->CompleteSavingAsSuccess();
935 PumpLoop();
936 EXPECT_EQ(Offliner::RequestStatus::SAVED_ON_LAST_RETRY, request_status());
937 }
938
TEST_F(BackgroundLoaderOfflinerTest,HandleTimeoutWithLowBarCompletedTriesMet)939 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithLowBarCompletedTriesMet) {
940 base::Time creation_time = base::Time::Now();
941 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
942 kUserRequested);
943 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1);
944 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
945 progress_callback()));
946 // Guarantees low bar for saving is met.
947 offliner()->DocumentAvailableInMainFrame();
948 // Timeout
949 EXPECT_TRUE(offliner()->HandleTimeout(kRequestId));
950 EXPECT_TRUE(SaveInProgress());
951 model()->CompleteSavingAsSuccess();
952 PumpLoop();
953 EXPECT_EQ(Offliner::RequestStatus::SAVED_ON_LAST_RETRY, request_status());
954 }
955
TEST_F(BackgroundLoaderOfflinerTest,HandleTimeoutWithNoLowBarStartedTriesMet)956 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithNoLowBarStartedTriesMet) {
957 base::Time creation_time = base::Time::Now();
958 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
959 kUserRequested);
960 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
961 progress_callback()));
962 request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1);
963 // Timeout
964 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId));
965 EXPECT_FALSE(SaveInProgress());
966 }
967
TEST_F(BackgroundLoaderOfflinerTest,HandleTimeoutWithNoLowBarCompletedTriesMet)968 TEST_F(BackgroundLoaderOfflinerTest,
969 HandleTimeoutWithNoLowBarCompletedTriesMet) {
970 base::Time creation_time = base::Time::Now();
971 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
972 kUserRequested);
973 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
974 progress_callback()));
975 request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1);
976 // Timeout
977 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId));
978 EXPECT_FALSE(SaveInProgress());
979 }
980
TEST_F(BackgroundLoaderOfflinerTest,HandleTimeoutWithLowBarNoRetryLimit)981 TEST_F(BackgroundLoaderOfflinerTest, HandleTimeoutWithLowBarNoRetryLimit) {
982 base::Time creation_time = base::Time::Now();
983 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
984 kUserRequested);
985 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
986 progress_callback()));
987 // Sets lowbar.
988 offliner()->DocumentAvailableInMainFrame();
989 // Timeout
990 EXPECT_FALSE(offliner()->HandleTimeout(kRequestId));
991 EXPECT_FALSE(SaveInProgress());
992 }
993
TEST_F(BackgroundLoaderOfflinerTest,SignalCollectionDisabled)994 TEST_F(BackgroundLoaderOfflinerTest, SignalCollectionDisabled) {
995 // Ensure feature flag for Signal collection is off,
996 EXPECT_FALSE(offline_pages::IsOfflinePagesLoadSignalCollectingEnabled());
997
998 base::Time creation_time = base::Time::Now();
999 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
1000 kUserRequested);
1001 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
1002 progress_callback()));
1003
1004 CompleteLoading();
1005 PumpLoop();
1006
1007 // No extra parts should be added if the flag is off.
1008 content::MHTMLExtraParts* extra_parts =
1009 content::MHTMLExtraParts::FromWebContents(offliner()->web_contents());
1010 EXPECT_EQ(extra_parts->size(), 0);
1011 }
1012
TEST_F(BackgroundLoaderOfflinerTest,SignalCollectionEnabled)1013 TEST_F(BackgroundLoaderOfflinerTest, SignalCollectionEnabled) {
1014 // Ensure feature flag for signal collection is on.
1015 base::test::ScopedFeatureList scoped_feature_list;
1016 scoped_feature_list.InitAndEnableFeature(
1017 kOfflinePagesLoadSignalCollectingFeature);
1018 EXPECT_TRUE(IsOfflinePagesLoadSignalCollectingEnabled());
1019
1020 base::Time creation_time = base::Time::Now();
1021 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
1022 kUserRequested);
1023 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
1024 progress_callback()));
1025
1026 CompleteLoading();
1027 PumpLoop();
1028
1029 // One extra part should be added if the flag is on.
1030 content::MHTMLExtraParts* extra_parts =
1031 content::MHTMLExtraParts::FromWebContents(offliner()->web_contents());
1032 EXPECT_EQ(extra_parts->size(), 1);
1033 }
1034
TEST_F(BackgroundLoaderOfflinerTest,ResourceSignalCollection)1035 TEST_F(BackgroundLoaderOfflinerTest, ResourceSignalCollection) {
1036 // Ensure feature flag for signal collection is on.
1037 base::test::ScopedFeatureList scoped_feature_list;
1038 scoped_feature_list.InitAndEnableFeature(
1039 kOfflinePagesLoadSignalCollectingFeature);
1040 EXPECT_TRUE(IsOfflinePagesLoadSignalCollectingEnabled());
1041
1042 base::Time creation_time = base::Time::Now();
1043 SavePageRequest request(kRequestId, HttpUrl(), kClientId, creation_time,
1044 kUserRequested);
1045 EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
1046 progress_callback()));
1047
1048 // Simulate resource requests starting and completing
1049 offliner()->ObserveResourceLoading(
1050 ResourceLoadingObserver::ResourceDataType::IMAGE, true);
1051 offliner()->ObserveResourceLoading(
1052 ResourceLoadingObserver::ResourceDataType::IMAGE, false);
1053 offliner()->ObserveResourceLoading(
1054 ResourceLoadingObserver::ResourceDataType::TEXT_CSS, true);
1055 offliner()->ObserveResourceLoading(
1056 ResourceLoadingObserver::ResourceDataType::TEXT_CSS, true);
1057 offliner()->ObserveResourceLoading(
1058 ResourceLoadingObserver::ResourceDataType::XHR, true);
1059
1060 CompleteLoading();
1061 PumpLoop();
1062
1063 // One extra part should be added if the flag is on.
1064 content::MHTMLExtraParts* extra_parts =
1065 content::MHTMLExtraParts::FromWebContents(offliner()->web_contents());
1066 EXPECT_EQ(extra_parts->size(), 1);
1067
1068 offline_pages::RequestStats* stats = GetRequestStats();
1069 EXPECT_EQ(1,
1070 stats[ResourceLoadingObserver::ResourceDataType::IMAGE].requested);
1071 EXPECT_EQ(1,
1072 stats[ResourceLoadingObserver::ResourceDataType::IMAGE].completed);
1073 EXPECT_EQ(
1074 2, stats[ResourceLoadingObserver::ResourceDataType::TEXT_CSS].requested);
1075 EXPECT_EQ(1, stats[ResourceLoadingObserver::ResourceDataType::XHR].requested);
1076 }
1077
1078 } // namespace offline_pages
1079