Index: ios/chrome/browser/reading_list/reading_list_download_service.cc |
diff --git a/ios/chrome/browser/reading_list/reading_list_download_service.cc b/ios/chrome/browser/reading_list/reading_list_download_service.cc |
index aacdee7fc76be033206e1f5eed0528629004a73a..c6a2a0bb8ecd6188e6f3bc84c3991ae6cc354ad4 100644 |
--- a/ios/chrome/browser/reading_list/reading_list_download_service.cc |
+++ b/ios/chrome/browser/reading_list/reading_list_download_service.cc |
@@ -11,13 +11,25 @@ |
#include "base/memory/ptr_util.h" |
#include "ios/chrome/browser/reading_list/reading_list_entry.h" |
#include "ios/chrome/browser/reading_list/reading_list_model.h" |
+#include "ios/web/public/web_thread.h" |
+ |
+namespace { |
+// Number of time the download must fail before the download occurs only in |
+// wifi. |
+const int kNumberOfFailsBeforeWifiOnly = 5; |
+// Number of time the download must fail before we give up trying to download |
+// it. |
+const int kNumberOfFailsBeforeStop = 7; |
+} // namespace |
ReadingListDownloadService::ReadingListDownloadService( |
ReadingListModel* reading_list_model, |
dom_distiller::DomDistillerService* distiller_service, |
PrefService* prefs, |
base::FilePath chrome_profile_path) |
- : reading_list_model_(reading_list_model) { |
+ : reading_list_model_(reading_list_model), |
+ had_connection_(!net::NetworkChangeNotifier::IsOffline()), |
+ weak_ptr_factory_(this) { |
DCHECK(reading_list_model); |
url_downloader_ = base::MakeUnique<URLDownloader>( |
distiller_service, prefs, chrome_profile_path, |
@@ -25,9 +37,12 @@ ReadingListDownloadService::ReadingListDownloadService( |
base::Unretained(this)), |
base::Bind(&ReadingListDownloadService::OnDeleteEnd, |
base::Unretained(this))); |
+ net::NetworkChangeNotifier::AddConnectionTypeObserver(this); |
} |
-ReadingListDownloadService::~ReadingListDownloadService() {} |
+ReadingListDownloadService::~ReadingListDownloadService() { |
+ net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
+} |
void ReadingListDownloadService::Initialize() { |
reading_list_model_->AddObserver(this); |
@@ -61,14 +76,14 @@ void ReadingListDownloadService::ReadingListWillAddUnreadEntry( |
const ReadingListModel* model, |
const ReadingListEntry& entry) { |
DCHECK_EQ(reading_list_model_, model); |
- DownloadEntry(entry); |
+ ScheduleDownloadEntry(entry); |
} |
void ReadingListDownloadService::ReadingListWillAddReadEntry( |
const ReadingListModel* model, |
const ReadingListEntry& entry) { |
DCHECK_EQ(reading_list_model_, model); |
- DownloadEntry(entry); |
+ ScheduleDownloadEntry(entry); |
} |
void ReadingListDownloadService::DownloadAllEntries() { |
@@ -77,21 +92,79 @@ void ReadingListDownloadService::DownloadAllEntries() { |
for (size_t i = 0; i < size; i++) { |
const ReadingListEntry& entry = |
reading_list_model_->GetUnreadEntryAtIndex(i); |
- this->DownloadEntry(entry); |
+ this->ScheduleDownloadEntry(entry); |
} |
size = reading_list_model_->read_size(); |
for (size_t i = 0; i < size; i++) { |
const ReadingListEntry& entry = reading_list_model_->GetReadEntryAtIndex(i); |
- this->DownloadEntry(entry); |
+ this->ScheduleDownloadEntry(entry); |
} |
} |
+void ReadingListDownloadService::ScheduleDownloadEntry( |
+ const ReadingListEntry& entry) { |
+ DCHECK(reading_list_model_->loaded()); |
+ if (entry.DistilledState() == ReadingListEntry::ERROR || |
+ entry.DistilledState() == ReadingListEntry::PROCESSED) |
+ return; |
+ |
+ web::WebThread::PostDelayedTask( |
+ web::WebThread::UI, FROM_HERE, |
+ base::Bind(&ReadingListDownloadService::DownloadEntryFromURL, |
+ weak_ptr_factory_.GetWeakPtr(), entry.URL()), |
+ entry.TimeUntilNextTry()); |
+} |
+ |
+void ReadingListDownloadService::ScheduleDownloadEntryFromURL(const GURL& url) { |
+ auto download_callback = |
+ base::Bind(&ReadingListDownloadService::ScheduleDownloadEntry, |
+ base::Unretained(this)); |
+ reading_list_model_->CallbackEntryURL(url, download_callback); |
+} |
+ |
+void ReadingListDownloadService::DownloadEntryFromURL(const GURL& url) { |
+ auto download_callback = base::Bind( |
+ &ReadingListDownloadService::DownloadEntry, base::Unretained(this)); |
+ reading_list_model_->CallbackEntryURL(url, download_callback); |
+} |
+ |
void ReadingListDownloadService::DownloadEntry(const ReadingListEntry& entry) { |
DCHECK(reading_list_model_->loaded()); |
- if (entry.DistilledState() != ReadingListEntry::ERROR) { |
+ if (entry.DistilledState() == ReadingListEntry::ERROR || |
+ entry.DistilledState() == ReadingListEntry::PROCESSED) |
+ return; |
+ |
+ if (net::NetworkChangeNotifier::IsOffline()) { |
+ // There is no connection, save it for download only if we did not exceed |
+ // the maximaxum number of tries. |
+ if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly) |
+ url_to_download_cellular_.push_back(entry.URL()); |
+ if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeStop) |
+ url_to_download_wifi_.push_back(entry.URL()); |
+ return; |
+ } |
+ |
+ // There is a connection. |
+ if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeWifiOnly) { |
+ // Try to download the page, whatever the connection. |
reading_list_model_->SetEntryDistilledState(entry.URL(), |
ReadingListEntry::PROCESSING); |
url_downloader_->DownloadOfflineURL(entry.URL()); |
+ |
+ } else if (entry.FailedDownloadCounter() < kNumberOfFailsBeforeStop) { |
+ // Try to download the page only if the connection is wifi. |
+ if (net::NetworkChangeNotifier::GetConnectionType() == |
+ net::NetworkChangeNotifier::CONNECTION_WIFI) { |
+ // The connection is wifi, download the page. |
+ reading_list_model_->SetEntryDistilledState(entry.URL(), |
+ ReadingListEntry::PROCESSING); |
+ url_downloader_->DownloadOfflineURL(entry.URL()); |
+ |
+ } else { |
+ // The connection is not wifi, save it for download when the connection |
+ // changes to wifi. |
+ url_to_download_wifi_.push_back(entry.URL()); |
+ } |
} |
} |
@@ -111,9 +184,12 @@ void ReadingListDownloadService::OnDownloadEnd( |
success == URLDownloader::DOWNLOAD_EXISTS) && |
distilled_url.is_valid()) { |
reading_list_model_->SetEntryDistilledURL(url, distilled_url); |
+ |
} else if (success == URLDownloader::ERROR_RETRY) { |
reading_list_model_->SetEntryDistilledState(url, |
ReadingListEntry::WILL_RETRY); |
+ ScheduleDownloadEntryFromURL(url); |
+ |
} else if (success == URLDownloader::ERROR_PERMANENT) { |
reading_list_model_->SetEntryDistilledState(url, ReadingListEntry::ERROR); |
} |
@@ -122,3 +198,23 @@ void ReadingListDownloadService::OnDownloadEnd( |
void ReadingListDownloadService::OnDeleteEnd(const GURL& url, bool success) { |
// Nothing to update as this is only called when deleting reading list entries |
} |
+ |
+void ReadingListDownloadService::OnConnectionTypeChanged( |
+ net::NetworkChangeNotifier::ConnectionType type) { |
+ if (type == net::NetworkChangeNotifier::CONNECTION_NONE) { |
+ had_connection_ = false; |
+ return; |
+ } |
+ |
+ if (!had_connection_) { |
+ had_connection_ = true; |
+ for (auto& url : url_to_download_cellular_) { |
+ ScheduleDownloadEntryFromURL(url); |
+ } |
+ } |
+ if (type == net::NetworkChangeNotifier::CONNECTION_WIFI) { |
+ for (auto& url : url_to_download_wifi_) { |
+ ScheduleDownloadEntryFromURL(url); |
+ } |
+ } |
+} |