1 // Copyright 2018 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 "components/offline_pages/core/background/offliner_client.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "components/offline_pages/core/background/save_page_request.h"
11 
12 namespace offline_pages {
13 
OfflinerClient(std::unique_ptr<Offliner> offliner,const Offliner::ProgressCallback & progress_callback)14 OfflinerClient::OfflinerClient(
15     std::unique_ptr<Offliner> offliner,
16     const Offliner::ProgressCallback& progress_callback)
17     : offliner_(std::move(offliner)), progress_callback_(progress_callback) {}
18 
19 OfflinerClient::~OfflinerClient() = default;
20 
LoadAndSave(const SavePageRequest & request,base::TimeDelta timeout,CompleteCallback complete_callback)21 bool OfflinerClient::LoadAndSave(const SavePageRequest& request,
22                                  base::TimeDelta timeout,
23                                  CompleteCallback complete_callback) {
24   if (Active())
25     return false;
26   if (!offliner_->LoadAndSave(request,
27                               base::BindOnce(&OfflinerClient::OfflinerComplete,
28                                              base::Unretained(this)),
29                               progress_callback_)) {
30     return false;
31   }
32   stopping_ = false;
33   active_request_ = std::make_unique<SavePageRequest>(request);
34   complete_callback_ = std::move(complete_callback);
35   watchdog_timer_.Start(FROM_HERE, timeout, this,
36                         &OfflinerClient::HandleWatchdogTimeout);
37   return true;
38 }
39 
Stop(Offliner::RequestStatus status)40 void OfflinerClient::Stop(Offliner::RequestStatus status) {
41   if (!active_request_ || stopping_)
42     return;
43   if (offliner_->Cancel(base::BindOnce(&OfflinerClient::CancelComplete,
44                                        base::Unretained(this), status))) {
45     stopping_ = true;
46   } else {
47     Finish(status);
48   }
49 }
50 
HandleWatchdogTimeout()51 void OfflinerClient::HandleWatchdogTimeout() {
52   if (!active_request_ || stopping_)
53     return;
54   // Check if the offliner can finish up now.
55   if (offliner_->HandleTimeout(active_request_->request_id()))
56     return;
57   if (offliner_->Cancel(base::BindOnce(
58           &OfflinerClient::CancelComplete, base::Unretained(this),
59           Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT))) {
60     stopping_ = true;
61   } else {
62     Finish(Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT);
63   }
64 }
65 
CancelComplete(Offliner::RequestStatus cancel_reason,const SavePageRequest & request)66 void OfflinerClient::CancelComplete(Offliner::RequestStatus cancel_reason,
67                                     const SavePageRequest& request) {
68   watchdog_timer_.Stop();
69   if (active_request_)
70     Finish(cancel_reason);
71 }
72 
OfflinerComplete(const SavePageRequest & request,Offliner::RequestStatus status)73 void OfflinerClient::OfflinerComplete(const SavePageRequest& request,
74                                       Offliner::RequestStatus status) {
75   if (active_request_)
76     Finish(status);
77   watchdog_timer_.Stop();
78 }
79 
Finish(Offliner::RequestStatus status)80 void OfflinerClient::Finish(Offliner::RequestStatus status) {
81   stopping_ = false;
82   std::unique_ptr<SavePageRequest> request = std::move(active_request_);
83   std::move(complete_callback_).Run(*request, status);
84 }
85 
86 }  // namespace offline_pages
87