OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 "ios/chrome/browser/reading_list/reading_list_download_service.h" | 5 #include "ios/chrome/browser/reading_list/reading_list_download_service.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "ios/chrome/browser/reading_list/reading_list_entry.h" | 12 #include "ios/chrome/browser/reading_list/reading_list_entry.h" |
13 #include "ios/chrome/browser/reading_list/reading_list_model.h" | 13 #include "ios/chrome/browser/reading_list/reading_list_model.h" |
14 #include "ios/web/public/web_thread.h" | |
15 | |
16 namespace { | |
17 // Number of time the download must fail before the download occurs only in | |
18 // wifi. | |
19 const int kNumberOfFailsBeforeWifiOnly = 5; | |
20 // Number of time the download must fail before we give up trying to download | |
21 // it. | |
22 const int kNumberOfFailsBeforeStop = 7; | |
23 } // namespace | |
14 | 24 |
15 ReadingListDownloadService::ReadingListDownloadService( | 25 ReadingListDownloadService::ReadingListDownloadService( |
16 ReadingListModel* reading_list_model, | 26 ReadingListModel* reading_list_model, |
17 dom_distiller::DomDistillerService* distiller_service, | 27 dom_distiller::DomDistillerService* distiller_service, |
18 PrefService* prefs, | 28 PrefService* prefs, |
19 base::FilePath chrome_profile_path) | 29 base::FilePath chrome_profile_path) |
20 : reading_list_model_(reading_list_model) { | 30 : reading_list_model_(reading_list_model), |
31 had_connection_(!net::NetworkChangeNotifier::IsOffline()), | |
32 weak_ptr_factory_(this) { | |
21 DCHECK(reading_list_model); | 33 DCHECK(reading_list_model); |
22 url_downloader_ = base::MakeUnique<URLDownloader>( | 34 url_downloader_ = base::MakeUnique<URLDownloader>( |
23 distiller_service, prefs, chrome_profile_path, | 35 distiller_service, prefs, chrome_profile_path, |
24 base::Bind(&ReadingListDownloadService::OnDownloadEnd, | 36 base::Bind(&ReadingListDownloadService::OnDownloadEnd, |
25 base::Unretained(this)), | 37 base::Unretained(this)), |
26 base::Bind(&ReadingListDownloadService::OnDeleteEnd, | 38 base::Bind(&ReadingListDownloadService::OnDeleteEnd, |
27 base::Unretained(this))); | 39 base::Unretained(this))); |
40 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | |
28 } | 41 } |
29 | 42 |
30 ReadingListDownloadService::~ReadingListDownloadService() {} | 43 ReadingListDownloadService::~ReadingListDownloadService() { |
44 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | |
45 } | |
31 | 46 |
32 void ReadingListDownloadService::Initialize() { | 47 void ReadingListDownloadService::Initialize() { |
33 reading_list_model_->AddObserver(this); | 48 reading_list_model_->AddObserver(this); |
34 } | 49 } |
35 | 50 |
36 void ReadingListDownloadService::Shutdown() { | 51 void ReadingListDownloadService::Shutdown() { |
37 reading_list_model_->RemoveObserver(this); | 52 reading_list_model_->RemoveObserver(this); |
38 } | 53 } |
39 | 54 |
40 void ReadingListDownloadService::ReadingListModelLoaded( | 55 void ReadingListDownloadService::ReadingListModelLoaded( |
(...skipping 13 matching lines...) Expand all Loading... | |
54 const ReadingListModel* model, | 69 const ReadingListModel* model, |
55 size_t index) { | 70 size_t index) { |
56 DCHECK_EQ(reading_list_model_, model); | 71 DCHECK_EQ(reading_list_model_, model); |
57 RemoveDownloadedEntry(model->GetUnreadEntryAtIndex(index)); | 72 RemoveDownloadedEntry(model->GetUnreadEntryAtIndex(index)); |
58 } | 73 } |
59 | 74 |
60 void ReadingListDownloadService::ReadingListWillAddUnreadEntry( | 75 void ReadingListDownloadService::ReadingListWillAddUnreadEntry( |
61 const ReadingListModel* model, | 76 const ReadingListModel* model, |
62 const ReadingListEntry& entry) { | 77 const ReadingListEntry& entry) { |
63 DCHECK_EQ(reading_list_model_, model); | 78 DCHECK_EQ(reading_list_model_, model); |
64 DownloadEntry(entry); | 79 ScheduleDownloadEntry(entry); |
65 } | 80 } |
66 | 81 |
67 void ReadingListDownloadService::ReadingListWillAddReadEntry( | 82 void ReadingListDownloadService::ReadingListWillAddReadEntry( |
68 const ReadingListModel* model, | 83 const ReadingListModel* model, |
69 const ReadingListEntry& entry) { | 84 const ReadingListEntry& entry) { |
70 DCHECK_EQ(reading_list_model_, model); | 85 DCHECK_EQ(reading_list_model_, model); |
71 DownloadEntry(entry); | 86 ScheduleDownloadEntry(entry); |
72 } | 87 } |
73 | 88 |
74 void ReadingListDownloadService::DownloadAllEntries() { | 89 void ReadingListDownloadService::DownloadAllEntries() { |
75 DCHECK(reading_list_model_->loaded()); | 90 DCHECK(reading_list_model_->loaded()); |
76 size_t size = reading_list_model_->unread_size(); | 91 size_t size = reading_list_model_->unread_size(); |
77 for (size_t i = 0; i < size; i++) { | 92 for (size_t i = 0; i < size; i++) { |
78 const ReadingListEntry& entry = | 93 const ReadingListEntry& entry = |
79 reading_list_model_->GetUnreadEntryAtIndex(i); | 94 reading_list_model_->GetUnreadEntryAtIndex(i); |
80 this->DownloadEntry(entry); | 95 this->ScheduleDownloadEntry(entry); |
81 } | 96 } |
82 size = reading_list_model_->read_size(); | 97 size = reading_list_model_->read_size(); |
83 for (size_t i = 0; i < size; i++) { | 98 for (size_t i = 0; i < size; i++) { |
84 const ReadingListEntry& entry = reading_list_model_->GetReadEntryAtIndex(i); | 99 const ReadingListEntry& entry = reading_list_model_->GetReadEntryAtIndex(i); |
85 this->DownloadEntry(entry); | 100 this->ScheduleDownloadEntry(entry); |
86 } | 101 } |
87 } | 102 } |
88 | 103 |
104 void ReadingListDownloadService::ScheduleDownloadEntry( | |
105 const ReadingListEntry& entry) { | |
106 DCHECK(reading_list_model_->loaded()); | |
107 if (entry.DistilledState() == ReadingListEntry::ERROR || | |
108 entry.DistilledState() == ReadingListEntry::PROCESSED) | |
109 return; | |
110 | |
111 web::WebThread::PostDelayedTask( | |
112 web::WebThread::UI, FROM_HERE, | |
113 base::Bind(&ReadingListDownloadService::DownloadEntryFromURL, | |
gambard
2016/09/22 16:46:55
This is a loop
| |
114 weak_ptr_factory_.GetWeakPtr(), entry.URL()), | |
115 entry.TimeUntilNextTry()); | |
116 } | |
117 | |
118 void ReadingListDownloadService::DownloadEntryFromURL(const GURL& url) { | |
119 auto download_callback = | |
120 base::Bind(&ReadingListDownloadService::ScheduleDownloadEntry, | |
121 base::Unretained(this)); | |
122 reading_list_model_->CallbackEntryURL(url, download_callback); | |
123 } | |
124 | |
89 void ReadingListDownloadService::DownloadEntry(const ReadingListEntry& entry) { | 125 void ReadingListDownloadService::DownloadEntry(const ReadingListEntry& entry) { |
90 DCHECK(reading_list_model_->loaded()); | 126 DCHECK(reading_list_model_->loaded()); |
91 if (entry.DistilledState() != ReadingListEntry::ERROR) { | 127 if (entry.DistilledState() == ReadingListEntry::ERROR || |
128 entry.DistilledState() == ReadingListEntry::PROCESSED) | |
129 return; | |
130 | |
131 if (net::NetworkChangeNotifier::IsOffline()) { | |
132 // There is no connection, save it for download only if we did not exceed | |
133 // the maximaxum number of tries. | |
134 if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly) | |
135 url_to_download_cellular_.push_back(entry.URL()); | |
136 if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeStop) | |
137 url_to_download_wifi_.push_back(entry.URL()); | |
138 return; | |
139 } | |
140 | |
141 // There is a connection. | |
142 if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly) { | |
143 // Try to download the page, whatever the connection. | |
92 reading_list_model_->SetEntryDistilledState(entry.URL(), | 144 reading_list_model_->SetEntryDistilledState(entry.URL(), |
93 ReadingListEntry::PROCESSING); | 145 ReadingListEntry::PROCESSING); |
94 url_downloader_->DownloadOfflineURL(entry.URL()); | 146 url_downloader_->DownloadOfflineURL(entry.URL()); |
147 | |
148 } else if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeStop) { | |
149 // Try to download the page only if the connection is wifi. | |
150 if (net::NetworkChangeNotifier::GetConnectionType() == | |
151 net::NetworkChangeNotifier::CONNECTION_WIFI) { | |
152 // The connection is wifi, download the page. | |
153 reading_list_model_->SetEntryDistilledState(entry.URL(), | |
154 ReadingListEntry::PROCESSING); | |
155 url_downloader_->DownloadOfflineURL(entry.URL()); | |
156 | |
157 } else { | |
158 // The connection is not wifi, save it for download when the connection | |
159 // changes to wifi. | |
160 url_to_download_wifi_.push_back(entry.URL()); | |
161 } | |
95 } | 162 } |
96 } | 163 } |
97 | 164 |
98 void ReadingListDownloadService::RemoveDownloadedEntry( | 165 void ReadingListDownloadService::RemoveDownloadedEntry( |
99 const ReadingListEntry& entry) { | 166 const ReadingListEntry& entry) { |
100 DCHECK(reading_list_model_->loaded()); | 167 DCHECK(reading_list_model_->loaded()); |
101 url_downloader_->RemoveOfflineURL(entry.URL()); | 168 url_downloader_->RemoveOfflineURL(entry.URL()); |
102 } | 169 } |
103 | 170 |
104 void ReadingListDownloadService::OnDownloadEnd( | 171 void ReadingListDownloadService::OnDownloadEnd( |
105 const GURL& url, | 172 const GURL& url, |
106 URLDownloader::SuccessState success, | 173 URLDownloader::SuccessState success, |
107 const GURL& distilled_url, | 174 const GURL& distilled_url, |
108 const std::string& title) { | 175 const std::string& title) { |
109 DCHECK(reading_list_model_->loaded()); | 176 DCHECK(reading_list_model_->loaded()); |
110 if ((success == URLDownloader::DOWNLOAD_SUCCESS || | 177 if ((success == URLDownloader::DOWNLOAD_SUCCESS || |
111 success == URLDownloader::DOWNLOAD_EXISTS) && | 178 success == URLDownloader::DOWNLOAD_EXISTS) && |
112 distilled_url.is_valid()) { | 179 distilled_url.is_valid()) { |
113 reading_list_model_->SetEntryDistilledURL(url, distilled_url); | 180 reading_list_model_->SetEntryDistilledURL(url, distilled_url); |
181 | |
114 } else if (success == URLDownloader::ERROR_RETRY) { | 182 } else if (success == URLDownloader::ERROR_RETRY) { |
115 reading_list_model_->SetEntryDistilledState(url, | 183 reading_list_model_->SetEntryDistilledState(url, |
116 ReadingListEntry::WILL_RETRY); | 184 ReadingListEntry::WILL_RETRY); |
185 DownloadEntryFromURL(url); | |
186 | |
117 } else if (success == URLDownloader::ERROR_PERMANENT) { | 187 } else if (success == URLDownloader::ERROR_PERMANENT) { |
118 reading_list_model_->SetEntryDistilledState(url, ReadingListEntry::ERROR); | 188 reading_list_model_->SetEntryDistilledState(url, ReadingListEntry::ERROR); |
119 } | 189 } |
120 } | 190 } |
121 | 191 |
122 void ReadingListDownloadService::OnDeleteEnd(const GURL& url, bool success) { | 192 void ReadingListDownloadService::OnDeleteEnd(const GURL& url, bool success) { |
123 // Nothing to update as this is only called when deleting reading list entries | 193 // Nothing to update as this is only called when deleting reading list entries |
124 } | 194 } |
195 | |
196 void ReadingListDownloadService::OnConnectionTypeChanged( | |
197 net::NetworkChangeNotifier::ConnectionType type) { | |
198 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) { | |
199 had_connection_ = false; | |
200 return; | |
201 } | |
202 | |
203 if (!had_connection_) { | |
204 had_connection_ = true; | |
205 for (auto& url : url_to_download_cellular_) { | |
206 DownloadEntryFromURL(url); | |
207 } | |
208 } | |
209 if (type == net::NetworkChangeNotifier::CONNECTION_WIFI) { | |
210 for (auto& url : url_to_download_wifi_) { | |
211 DownloadEntryFromURL(url); | |
212 } | |
213 } | |
214 } | |
OLD | NEW |