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, |
| 114 weak_ptr_factory_.GetWeakPtr(), entry.URL()), |
| 115 entry.TimeUntilNextTry()); |
| 116 } |
| 117 |
| 118 void ReadingListDownloadService::ScheduleDownloadEntryFromURL(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 |
| 125 void ReadingListDownloadService::DownloadEntryFromURL(const GURL& url) { |
| 126 auto download_callback = base::Bind( |
| 127 &ReadingListDownloadService::DownloadEntry, base::Unretained(this)); |
| 128 reading_list_model_->CallbackEntryURL(url, download_callback); |
| 129 } |
| 130 |
89 void ReadingListDownloadService::DownloadEntry(const ReadingListEntry& entry) { | 131 void ReadingListDownloadService::DownloadEntry(const ReadingListEntry& entry) { |
90 DCHECK(reading_list_model_->loaded()); | 132 DCHECK(reading_list_model_->loaded()); |
91 if (entry.DistilledState() != ReadingListEntry::ERROR) { | 133 if (entry.DistilledState() == ReadingListEntry::ERROR || |
| 134 entry.DistilledState() == ReadingListEntry::PROCESSED) |
| 135 return; |
| 136 |
| 137 if (net::NetworkChangeNotifier::IsOffline()) { |
| 138 // There is no connection, save it for download only if we did not exceed |
| 139 // the maximaxum number of tries. |
| 140 if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly) |
| 141 url_to_download_cellular_.push_back(entry.URL()); |
| 142 if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeStop) |
| 143 url_to_download_wifi_.push_back(entry.URL()); |
| 144 return; |
| 145 } |
| 146 |
| 147 // There is a connection. |
| 148 if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly) { |
| 149 // Try to download the page, whatever the connection. |
92 reading_list_model_->SetEntryDistilledState(entry.URL(), | 150 reading_list_model_->SetEntryDistilledState(entry.URL(), |
93 ReadingListEntry::PROCESSING); | 151 ReadingListEntry::PROCESSING); |
94 url_downloader_->DownloadOfflineURL(entry.URL()); | 152 url_downloader_->DownloadOfflineURL(entry.URL()); |
| 153 |
| 154 } else if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeStop) { |
| 155 // Try to download the page only if the connection is wifi. |
| 156 if (net::NetworkChangeNotifier::GetConnectionType() == |
| 157 net::NetworkChangeNotifier::CONNECTION_WIFI) { |
| 158 // The connection is wifi, download the page. |
| 159 reading_list_model_->SetEntryDistilledState(entry.URL(), |
| 160 ReadingListEntry::PROCESSING); |
| 161 url_downloader_->DownloadOfflineURL(entry.URL()); |
| 162 |
| 163 } else { |
| 164 // The connection is not wifi, save it for download when the connection |
| 165 // changes to wifi. |
| 166 url_to_download_wifi_.push_back(entry.URL()); |
| 167 } |
95 } | 168 } |
96 } | 169 } |
97 | 170 |
98 void ReadingListDownloadService::RemoveDownloadedEntry( | 171 void ReadingListDownloadService::RemoveDownloadedEntry( |
99 const ReadingListEntry& entry) { | 172 const ReadingListEntry& entry) { |
100 DCHECK(reading_list_model_->loaded()); | 173 DCHECK(reading_list_model_->loaded()); |
101 url_downloader_->RemoveOfflineURL(entry.URL()); | 174 url_downloader_->RemoveOfflineURL(entry.URL()); |
102 } | 175 } |
103 | 176 |
104 void ReadingListDownloadService::OnDownloadEnd( | 177 void ReadingListDownloadService::OnDownloadEnd( |
105 const GURL& url, | 178 const GURL& url, |
106 URLDownloader::SuccessState success, | 179 URLDownloader::SuccessState success, |
107 const GURL& distilled_url, | 180 const GURL& distilled_url, |
108 const std::string& title) { | 181 const std::string& title) { |
109 DCHECK(reading_list_model_->loaded()); | 182 DCHECK(reading_list_model_->loaded()); |
110 if ((success == URLDownloader::DOWNLOAD_SUCCESS || | 183 if ((success == URLDownloader::DOWNLOAD_SUCCESS || |
111 success == URLDownloader::DOWNLOAD_EXISTS) && | 184 success == URLDownloader::DOWNLOAD_EXISTS) && |
112 distilled_url.is_valid()) { | 185 distilled_url.is_valid()) { |
113 reading_list_model_->SetEntryDistilledURL(url, distilled_url); | 186 reading_list_model_->SetEntryDistilledURL(url, distilled_url); |
| 187 |
114 } else if (success == URLDownloader::ERROR_RETRY) { | 188 } else if (success == URLDownloader::ERROR_RETRY) { |
115 reading_list_model_->SetEntryDistilledState(url, | 189 reading_list_model_->SetEntryDistilledState(url, |
116 ReadingListEntry::WILL_RETRY); | 190 ReadingListEntry::WILL_RETRY); |
| 191 ScheduleDownloadEntryFromURL(url); |
| 192 |
117 } else if (success == URLDownloader::ERROR_PERMANENT) { | 193 } else if (success == URLDownloader::ERROR_PERMANENT) { |
118 reading_list_model_->SetEntryDistilledState(url, ReadingListEntry::ERROR); | 194 reading_list_model_->SetEntryDistilledState(url, ReadingListEntry::ERROR); |
119 } | 195 } |
120 } | 196 } |
121 | 197 |
122 void ReadingListDownloadService::OnDeleteEnd(const GURL& url, bool success) { | 198 void ReadingListDownloadService::OnDeleteEnd(const GURL& url, bool success) { |
123 // Nothing to update as this is only called when deleting reading list entries | 199 // Nothing to update as this is only called when deleting reading list entries |
124 } | 200 } |
| 201 |
| 202 void ReadingListDownloadService::OnConnectionTypeChanged( |
| 203 net::NetworkChangeNotifier::ConnectionType type) { |
| 204 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) { |
| 205 had_connection_ = false; |
| 206 return; |
| 207 } |
| 208 |
| 209 if (!had_connection_) { |
| 210 had_connection_ = true; |
| 211 for (auto& url : url_to_download_cellular_) { |
| 212 ScheduleDownloadEntryFromURL(url); |
| 213 } |
| 214 } |
| 215 if (type == net::NetworkChangeNotifier::CONNECTION_WIFI) { |
| 216 for (auto& url : url_to_download_wifi_) { |
| 217 ScheduleDownloadEntryFromURL(url); |
| 218 } |
| 219 } |
| 220 } |
OLD | NEW |