Index: chrome/browser/android/offline_pages/background_loader_offliner.cc |
diff --git a/chrome/browser/android/offline_pages/background_loader_offliner.cc b/chrome/browser/android/offline_pages/background_loader_offliner.cc |
index 2bf511a66d992509ba0bf92c682e0e22dc883d88..f0cd44576de9ae90c8d1921925c917396cda4038 100644 |
--- a/chrome/browser/android/offline_pages/background_loader_offliner.cc |
+++ b/chrome/browser/android/offline_pages/background_loader_offliner.cc |
@@ -18,6 +18,10 @@ |
namespace offline_pages { |
+namespace { |
+long kOfflinePageDelayMs = 2000; |
+} // namespace |
+ |
BackgroundLoaderOffliner::BackgroundLoaderOffliner( |
content::BrowserContext* browser_context, |
const OfflinerPolicy* policy, |
@@ -27,6 +31,7 @@ BackgroundLoaderOffliner::BackgroundLoaderOffliner( |
is_low_end_device_(base::SysInfo::IsLowEndDevice()), |
save_state_(NONE), |
page_load_state_(SUCCESS), |
+ page_delay_ms_(kOfflinePageDelayMs), |
weak_ptr_factory_(this) { |
DCHECK(offline_page_model_); |
DCHECK(browser_context_); |
@@ -94,6 +99,9 @@ bool BackgroundLoaderOffliner::LoadAndSave(const SavePageRequest& request, |
if (!loader_) |
ResetState(); |
+ // Invalidate ptrs for all delayed/saving tasks. |
+ weak_ptr_factory_.InvalidateWeakPtrs(); |
+ |
// Track copy of pending request. |
pending_request_.reset(new SavePageRequest(request)); |
completion_callback_ = callback; |
@@ -129,40 +137,15 @@ void BackgroundLoaderOffliner::DidStopLoading() { |
return; |
} |
- SavePageRequest request(*pending_request_.get()); |
- // If there was an error navigating to page, return loading failed. |
- if (page_load_state_ != SUCCESS) { |
- Offliner::RequestStatus status = |
- (page_load_state_ == RETRIABLE) |
- ? Offliner::RequestStatus::LOADING_FAILED |
- : Offliner::RequestStatus::LOADING_FAILED_NO_RETRY; |
- completion_callback_.Run(request, status); |
- ResetState(); |
- return; |
- } |
- |
- save_state_ = SAVING; |
- content::WebContents* web_contents( |
- content::WebContentsObserver::web_contents()); |
- |
- std::unique_ptr<OfflinePageArchiver> archiver( |
- new OfflinePageMHTMLArchiver(web_contents)); |
+ // Invalidate ptrs for any ongoing save operation. |
+ weak_ptr_factory_.InvalidateWeakPtrs(); |
- OfflinePageModel::SavePageParams params; |
- params.url = web_contents->GetLastCommittedURL(); |
- params.client_id = request.client_id(); |
- params.proposed_offline_id = request.request_id(); |
- params.is_background = true; |
- |
- // Pass in the original URL if it's different from last committed |
- // when redirects occur. |
- if (params.url != request.url()) |
- params.original_url = request.url(); |
- |
- offline_page_model_->SavePage( |
- params, std::move(archiver), |
- base::Bind(&BackgroundLoaderOffliner::OnPageSaved, |
- weak_ptr_factory_.GetWeakPtr())); |
+ // Post SavePage task with 2 second delay. |
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&BackgroundLoaderOffliner::SavePage, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::TimeDelta::FromMilliseconds(page_delay_ms_)); |
} |
void BackgroundLoaderOffliner::RenderProcessGone( |
@@ -230,6 +213,62 @@ void BackgroundLoaderOffliner::DidFinishNavigation( |
page_load_state_ = RETRIABLE; |
} |
} |
+ |
+ // If the page is not the same, invalidate any pending save tasks. |
+ // |
+ // Downloads or 204/205 response codes do not commit (no new navigation) |
+ // Same-Page (committed) navigations are: |
+ // - reference fragment navigations |
+ // - pushState/replaceState |
+ // - same page history navigation |
+ if (navigation_handle->HasCommitted() && !navigation_handle->IsSamePage()) |
+ weak_ptr_factory_.InvalidateWeakPtrs(); |
+} |
+ |
+void BackgroundLoaderOffliner::SetPageDelayForTest(long delay_ms) { |
+ page_delay_ms_ = delay_ms; |
+} |
+ |
+void BackgroundLoaderOffliner::SavePage() { |
+ if (!pending_request_.get()) { |
+ DVLOG(1) << "Pending request was cleared during delay."; |
+ return; |
+ } |
+ |
+ SavePageRequest request(*pending_request_.get()); |
+ // If there was an error navigating to page, return loading failed. |
+ if (page_load_state_ != SUCCESS) { |
+ Offliner::RequestStatus status = |
+ (page_load_state_ == RETRIABLE) |
+ ? Offliner::RequestStatus::LOADING_FAILED |
+ : Offliner::RequestStatus::LOADING_FAILED_NO_RETRY; |
+ completion_callback_.Run(request, status); |
+ ResetState(); |
+ return; |
+ } |
+ |
+ save_state_ = SAVING; |
+ content::WebContents* web_contents( |
+ content::WebContentsObserver::web_contents()); |
+ |
+ std::unique_ptr<OfflinePageArchiver> archiver( |
+ new OfflinePageMHTMLArchiver(web_contents)); |
+ |
+ OfflinePageModel::SavePageParams params; |
+ params.url = web_contents->GetLastCommittedURL(); |
+ params.client_id = request.client_id(); |
+ params.proposed_offline_id = request.request_id(); |
+ params.is_background = true; |
+ |
+ // Pass in the original URL if it's different from last committed |
+ // when redirects occur. |
+ if (params.url != request.url()) |
+ params.original_url = request.url(); |
+ |
+ offline_page_model_->SavePage( |
+ params, std::move(archiver), |
+ base::Bind(&BackgroundLoaderOffliner::OnPageSaved, |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
void BackgroundLoaderOffliner::OnPageSaved(SavePageResult save_result, |