| OLD | NEW |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "chrome/browser/android/offline_pages/recent_tab_helper.h" | 5 #include "chrome/browser/android/offline_pages/recent_tab_helper.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 bool GetTabId(content::WebContents* web_contents, int* tab_id) override { | 49 bool GetTabId(content::WebContents* web_contents, int* tab_id) override { |
| 50 return offline_pages::OfflinePageUtils::GetTabId(web_contents, tab_id); | 50 return offline_pages::OfflinePageUtils::GetTabId(web_contents, tab_id); |
| 51 } | 51 } |
| 52 }; | 52 }; |
| 53 } // namespace | 53 } // namespace |
| 54 | 54 |
| 55 namespace offline_pages { | 55 namespace offline_pages { |
| 56 | 56 |
| 57 using PageQuality = SnapshotController::PageQuality; | 57 using PageQuality = SnapshotController::PageQuality; |
| 58 | 58 |
| 59 bool RecentTabHelper::SnapshotProgressInfo::IsForLastN() { | 59 // Keeps client_id/request_id that will be used for the offline snapshot. |
| 60 // A last_n snapshot always has an invalid request id. | 60 struct RecentTabHelper::SnapshotProgressInfo { |
| 61 return request_id == OfflinePageModel::kInvalidOfflineId; | 61 public: |
| 62 } | 62 // For a downloads snapshot request, where the |request_id| is defined. |
| 63 SnapshotProgressInfo(const ClientId& client_id, int64_t request_id) |
| 64 : client_id(client_id), request_id(request_id) {} |
| 65 |
| 66 // For a last_n snapshot request. |
| 67 explicit SnapshotProgressInfo(const ClientId& client_id) |
| 68 : client_id(client_id) {} |
| 69 |
| 70 bool IsForLastN() { return client_id.name_space == kLastNNamespace; } |
| 71 |
| 72 // The ClientID to go with the offline page. |
| 73 ClientId client_id; |
| 74 |
| 75 // Id of the suspended request in Background Offliner. Used to un-suspend |
| 76 // the request if the capture of the current page was not possible (e.g. |
| 77 // the user navigated to another page before current one was loaded). |
| 78 // 0 if this is a "last_n" info. |
| 79 int64_t request_id = OfflinePageModel::kInvalidOfflineId; |
| 80 |
| 81 // Expected snapshot quality should the saving succeed. This value is only |
| 82 // valid for successfully saved snapshots. |
| 83 SnapshotController::PageQuality expected_page_quality = |
| 84 SnapshotController::PageQuality::POOR; |
| 85 }; |
| 63 | 86 |
| 64 RecentTabHelper::RecentTabHelper(content::WebContents* web_contents) | 87 RecentTabHelper::RecentTabHelper(content::WebContents* web_contents) |
| 65 : content::WebContentsObserver(web_contents), | 88 : content::WebContentsObserver(web_contents), |
| 66 delegate_(new DefaultDelegate()), | 89 delegate_(new DefaultDelegate()), |
| 67 weak_ptr_factory_(this) { | 90 weak_ptr_factory_(this) { |
| 68 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 91 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 69 } | 92 } |
| 70 | 93 |
| 71 RecentTabHelper::~RecentTabHelper() { | 94 RecentTabHelper::~RecentTabHelper() { |
| 72 } | 95 } |
| 73 | 96 |
| 74 void RecentTabHelper::SetDelegate( | 97 void RecentTabHelper::SetDelegate( |
| 75 std::unique_ptr<RecentTabHelper::Delegate> delegate) { | 98 std::unique_ptr<RecentTabHelper::Delegate> delegate) { |
| 76 DCHECK(delegate); | 99 DCHECK(delegate); |
| 77 delegate_ = std::move(delegate); | 100 delegate_ = std::move(delegate); |
| 78 } | 101 } |
| 79 | 102 |
| 80 void RecentTabHelper::ObserveAndDownloadCurrentPage( | 103 void RecentTabHelper::ObserveAndDownloadCurrentPage( |
| 81 const ClientId& client_id, int64_t request_id) { | 104 const ClientId& client_id, int64_t request_id) { |
| 105 // Note: as this implementation only supports one client namespace, enforce |
| 106 // that the call is from Downloads. |
| 107 DCHECK_EQ(kDownloadNamespace, client_id.name_space); |
| 82 auto new_downloads_snapshot_info = | 108 auto new_downloads_snapshot_info = |
| 83 base::MakeUnique<SnapshotProgressInfo>(client_id, request_id); | 109 base::MakeUnique<SnapshotProgressInfo>(client_id, request_id); |
| 84 | 110 |
| 85 // If this tab helper is not enabled, immediately give the job back to | 111 // If this tab helper is not enabled, immediately give the job back to |
| 86 // RequestCoordinator. | 112 // RequestCoordinator. |
| 87 if (!EnsureInitialized()) { | 113 if (!EnsureInitialized()) { |
| 88 ReportDownloadStatusToRequestCoordinator(new_downloads_snapshot_info.get()); | 114 ReportDownloadStatusToRequestCoordinator(new_downloads_snapshot_info.get(), |
| 115 false); |
| 89 return; | 116 return; |
| 90 } | 117 } |
| 91 | 118 |
| 92 // TODO(carlosk): This is a good moment check if a snapshot is currently being | 119 // If there is an ongoing snapshot request, completely ignore this one and |
| 93 // generated. This would allow the early cancellation of this request (without | 120 // cancel the Background Offliner request. |
| 94 // incurring in scheduling a background download). | 121 // TODO(carlosk): it might be better to make the decision to schedule or not |
| 122 // the background request here. See https://crbug.com/686165. |
| 123 // TODO(carlosk): there is an edge case that happens when the ongoing request |
| 124 // was automatically and transparently scheduled by a navigation event and |
| 125 // this call happens due to the user pressing the download button. The user's |
| 126 // request to download the page will be immediately dismissed. See |
| 127 // https://crbug.com/686283. |
| 128 if (downloads_ongoing_snapshot_info_) { |
| 129 ReportDownloadStatusToRequestCoordinator(new_downloads_snapshot_info.get(), |
| 130 true); |
| 131 return; |
| 132 } |
| 95 | 133 |
| 96 // Stores the new snapshot info. | 134 // Stores the new snapshot info. |
| 97 downloads_latest_snapshot_info_ = std::move(new_downloads_snapshot_info); | 135 downloads_ongoing_snapshot_info_ = std::move(new_downloads_snapshot_info); |
| 98 | 136 |
| 99 // If the page is not yet ready for a snapshot return now as it will be | 137 // If the page is not yet ready for a snapshot return now as it will be |
| 100 // started later, once page loading advances. | 138 // started later, once page loading advances. |
| 101 if (PageQuality::POOR == snapshot_controller_->current_page_quality()) | 139 if (PageQuality::POOR == snapshot_controller_->current_page_quality()) { |
| 140 downloads_snapshot_on_hold_ = true; |
| 102 return; | 141 return; |
| 142 } |
| 103 | 143 |
| 104 // Otherwise start saving the snapshot now. | 144 // Otherwise start saving the snapshot now. |
| 105 SaveSnapshotForDownloads(); | 145 SaveSnapshotForDownloads(false); |
| 106 } | 146 } |
| 107 | 147 |
| 108 // Initialize lazily. It needs TabAndroid for initialization, which is also a | 148 // Initialize lazily. It needs TabAndroid for initialization, which is also a |
| 109 // TabHelper - so can't initialize in constructor because of uncertain order | 149 // TabHelper - so can't initialize in constructor because of uncertain order |
| 110 // of creation of TabHelpers. | 150 // of creation of TabHelpers. |
| 111 bool RecentTabHelper::EnsureInitialized() { | 151 bool RecentTabHelper::EnsureInitialized() { |
| 112 if (snapshot_controller_) // Initialized already. | 152 if (snapshot_controller_) // Initialized already. |
| 113 return snapshots_enabled_; | 153 return snapshots_enabled_; |
| 114 | 154 |
| 115 snapshot_controller_.reset( | 155 snapshot_controller_.reset( |
| (...skipping 22 matching lines...) Expand all Loading... |
| 138 void RecentTabHelper::DidFinishNavigation( | 178 void RecentTabHelper::DidFinishNavigation( |
| 139 content::NavigationHandle* navigation_handle) { | 179 content::NavigationHandle* navigation_handle) { |
| 140 if (!navigation_handle->IsInMainFrame() || | 180 if (!navigation_handle->IsInMainFrame() || |
| 141 !navigation_handle->HasCommitted()) { | 181 !navigation_handle->HasCommitted()) { |
| 142 return; | 182 return; |
| 143 } | 183 } |
| 144 | 184 |
| 145 if (!EnsureInitialized()) | 185 if (!EnsureInitialized()) |
| 146 return; | 186 return; |
| 147 | 187 |
| 148 // We navigated to a different page, lets report progress to Background | 188 // If there is an ongoing downloads request, lets allow Background Offliner to |
| 149 // Offliner. | 189 // continue downloading this page. |
| 150 if (downloads_latest_snapshot_info_) | 190 if (downloads_ongoing_snapshot_info_) { |
| 151 ReportDownloadStatusToRequestCoordinator( | 191 ReportDownloadStatusToRequestCoordinator( |
| 152 downloads_latest_snapshot_info_.get()); | 192 downloads_ongoing_snapshot_info_.get(), false); |
| 193 } |
| 153 | 194 |
| 154 // Cancel any and all in flight snapshot tasks from the previous page. | 195 // Cancel any and all in flight snapshot tasks from the previous page. |
| 155 weak_ptr_factory_.InvalidateWeakPtrs(); | 196 CancelInFlightSnapshots(); |
| 156 downloads_latest_snapshot_info_.reset(); | 197 downloads_snapshot_on_hold_ = false; |
| 157 last_n_ongoing_snapshot_info_.reset(); | |
| 158 | 198 |
| 159 // New navigation, new snapshot session. | 199 // New navigation, new snapshot session. |
| 160 snapshot_url_ = web_contents()->GetLastCommittedURL(); | 200 snapshot_url_ = web_contents()->GetLastCommittedURL(); |
| 161 | 201 |
| 162 // Always reset so that posted tasks get canceled. | 202 // Always reset so that posted tasks get canceled. |
| 163 snapshot_controller_->Reset(); | 203 snapshot_controller_->Reset(); |
| 164 | 204 |
| 165 // Check for conditions that would cause us not to snapshot. | 205 // Check for conditions that would cause us not to snapshot. |
| 166 bool can_save = !navigation_handle->IsErrorPage() && | 206 bool can_save = !navigation_handle->IsErrorPage() && |
| 167 OfflinePageModel::CanSaveURL(snapshot_url_) && | 207 OfflinePageModel::CanSaveURL(snapshot_url_) && |
| (...skipping 12 matching lines...) Expand all Loading... |
| 180 EnsureInitialized(); | 220 EnsureInitialized(); |
| 181 snapshot_controller_->DocumentAvailableInMainFrame(); | 221 snapshot_controller_->DocumentAvailableInMainFrame(); |
| 182 } | 222 } |
| 183 | 223 |
| 184 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() { | 224 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() { |
| 185 EnsureInitialized(); | 225 EnsureInitialized(); |
| 186 snapshot_controller_->DocumentOnLoadCompletedInMainFrame(); | 226 snapshot_controller_->DocumentOnLoadCompletedInMainFrame(); |
| 187 } | 227 } |
| 188 | 228 |
| 189 void RecentTabHelper::WebContentsDestroyed() { | 229 void RecentTabHelper::WebContentsDestroyed() { |
| 190 // WebContents (and maybe Tab) is destroyed, report status to Offliner. | 230 // If there is an ongoing downloads request, lets allow Background Offliner to |
| 191 if (downloads_latest_snapshot_info_) | 231 // continue downloading this page. |
| 232 if (downloads_ongoing_snapshot_info_) |
| 192 ReportDownloadStatusToRequestCoordinator( | 233 ReportDownloadStatusToRequestCoordinator( |
| 193 downloads_latest_snapshot_info_.get()); | 234 downloads_ongoing_snapshot_info_.get(), false); |
| 194 // And cancel any ongoing snapshots. | 235 // And cancel any ongoing snapshots. |
| 195 weak_ptr_factory_.InvalidateWeakPtrs(); | 236 CancelInFlightSnapshots(); |
| 196 } | 237 } |
| 197 | 238 |
| 198 // TODO(carlosk): this method is also called when the tab is being closed, when | 239 // TODO(carlosk): this method is also called when the tab is being closed, when |
| 199 // saving a snapshot is probably useless (low probability of the user undoing | 240 // saving a snapshot is probably useless (low probability of the user undoing |
| 200 // the close). We should detect that and avoid the saving. | 241 // the close). We should detect that and avoid the saving. |
| 201 void RecentTabHelper::WasHidden() { | 242 void RecentTabHelper::WasHidden() { |
| 202 if (!IsOffliningRecentPagesEnabled()) | 243 if (!IsOffliningRecentPagesEnabled()) |
| 203 return; | 244 return; |
| 204 | 245 |
| 205 // Return immediately if last_n is not listening to tab hidden events or if a | 246 // Return immediately if last_n is not listening to tab hidden events or if a |
| 206 // last_n snapshot is currently being saved. | 247 // last_n snapshot is currently being saved. |
| 207 if (!last_n_listen_to_tab_hidden_ || last_n_ongoing_snapshot_info_) | 248 if (!last_n_listen_to_tab_hidden_ || last_n_ongoing_snapshot_info_) |
| 208 return; | 249 return; |
| 209 | 250 |
| 210 // Do not save if page quality is too low or if we already have a snapshot | 251 // Do not save if page quality is too low or if we already have a snapshot |
| 211 // with the current quality level. | 252 // with the current quality level. |
| 212 // Note: we assume page quality for a page can only increase. | 253 // Note: we assume page quality for a page can only increase. |
| 213 PageQuality current_quality = snapshot_controller_->current_page_quality(); | 254 PageQuality current_quality = snapshot_controller_->current_page_quality(); |
| 214 if (current_quality == PageQuality::POOR || | 255 if (current_quality == PageQuality::POOR || |
| 215 current_quality == last_n_latest_saved_quality_) { | 256 current_quality == last_n_latest_saved_quality_) { |
| 216 return; | 257 return; |
| 217 } | 258 } |
| 218 | 259 |
| 219 last_n_ongoing_snapshot_info_ = | 260 last_n_ongoing_snapshot_info_ = |
| 220 base::MakeUnique<SnapshotProgressInfo>(GetRecentPagesClientId()); | 261 base::MakeUnique<SnapshotProgressInfo>(GetRecentPagesClientId()); |
| 262 DCHECK(last_n_ongoing_snapshot_info_->IsForLastN()); |
| 221 DCHECK(snapshots_enabled_); | 263 DCHECK(snapshots_enabled_); |
| 222 // Remove previously captured pages for this tab. | 264 // Remove previously captured pages for this tab. |
| 223 page_model_->GetOfflineIdsForClientId( | 265 page_model_->GetOfflineIdsForClientId( |
| 224 GetRecentPagesClientId(), | 266 GetRecentPagesClientId(), |
| 225 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge, | 267 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge, |
| 226 weak_ptr_factory_.GetWeakPtr(), | 268 weak_ptr_factory_.GetWeakPtr(), |
| 227 last_n_ongoing_snapshot_info_.get())); | 269 last_n_ongoing_snapshot_info_.get())); |
| 228 } | 270 } |
| 229 | 271 |
| 230 // TODO(carlosk): rename this to RequestSnapshot and make it return a bool | 272 // TODO(carlosk): rename this to RequestSnapshot and make it return a bool |
| 231 // representing the acceptance of the snapshot request. | 273 // representing the acceptance of the snapshot request. |
| 232 void RecentTabHelper::StartSnapshot() { | 274 void RecentTabHelper::StartSnapshot() { |
| 233 DCHECK_NE(PageQuality::POOR, snapshot_controller_->current_page_quality()); | 275 DCHECK_NE(PageQuality::POOR, snapshot_controller_->current_page_quality()); |
| 234 | 276 |
| 235 // This is a navigation based snapshot request so check that snapshots are | 277 // As long as snapshots are enabled for this tab, there are two situations |
| 236 // both enabled and there is a downloads request for one. | 278 // that allow for a navigation event to start a snapshot: |
| 237 // TODO(carlosk): This is a good moment to add the check for an ongoing | 279 // 1) There is a request on hold waiting for the page to be minimally loaded. |
| 238 // snapshot that could trigger the early cancellation of this request. | 280 if (snapshots_enabled_ && downloads_snapshot_on_hold_) { |
| 239 if (snapshots_enabled_ && downloads_latest_snapshot_info_) | 281 downloads_snapshot_on_hold_ = false; |
| 240 SaveSnapshotForDownloads(); | 282 SaveSnapshotForDownloads(false); |
| 241 else | 283 return; |
| 242 snapshot_controller_->PendingSnapshotCompleted(); | 284 } |
| 285 |
| 286 // 2) There's no ongoing snapshot and a previous one was saved with lower |
| 287 // expected quality than what would be possible now. |
| 288 if (snapshots_enabled_ && |
| 289 (!downloads_ongoing_snapshot_info_ && |
| 290 downloads_latest_saved_snapshot_info_ && |
| 291 downloads_latest_saved_snapshot_info_->expected_page_quality < |
| 292 snapshot_controller_->current_page_quality())) { |
| 293 SaveSnapshotForDownloads(true); |
| 294 return; |
| 295 } |
| 296 |
| 297 // Notify the controller that a snapshot was not started. |
| 298 snapshot_controller_->PendingSnapshotCompleted(); |
| 243 } | 299 } |
| 244 | 300 |
| 245 // TODO(carlosk): There is still the possibility of overlapping snapshots with | 301 void RecentTabHelper::SaveSnapshotForDownloads(bool replace_latest) { |
| 246 // some combinations of calls to ObserveAndDownloadCurrentPage and | |
| 247 // StartSnapshot. It won't cause side effects beyond wasted resources and will | |
| 248 // be dealt with later. | |
| 249 void RecentTabHelper::SaveSnapshotForDownloads() { | |
| 250 DCHECK_NE(PageQuality::POOR, snapshot_controller_->current_page_quality()); | 302 DCHECK_NE(PageQuality::POOR, snapshot_controller_->current_page_quality()); |
| 251 DCHECK(downloads_latest_snapshot_info_); | |
| 252 | 303 |
| 253 // Requests the deletion of a potentially existing previous snapshot of this | 304 if (replace_latest) { |
| 254 // page. | 305 // Start by requesting the deletion of the existing previous snapshot of |
| 255 std::vector<int64_t> ids{downloads_latest_snapshot_info_->request_id}; | 306 // this page. |
| 256 ContinueSnapshotWithIdsToPurge(downloads_latest_snapshot_info_.get(), ids); | 307 DCHECK(downloads_latest_saved_snapshot_info_); |
| 308 DCHECK(!downloads_ongoing_snapshot_info_); |
| 309 downloads_ongoing_snapshot_info_ = base::MakeUnique<SnapshotProgressInfo>( |
| 310 downloads_latest_saved_snapshot_info_->client_id, |
| 311 downloads_latest_saved_snapshot_info_->request_id); |
| 312 std::vector<int64_t> ids{downloads_latest_saved_snapshot_info_->request_id}; |
| 313 ContinueSnapshotWithIdsToPurge(downloads_ongoing_snapshot_info_.get(), ids); |
| 314 } else { |
| 315 // Otherwise go straight to saving the page. |
| 316 DCHECK(downloads_ongoing_snapshot_info_); |
| 317 ContinueSnapshotAfterPurge(downloads_ongoing_snapshot_info_.get(), |
| 318 OfflinePageModel::DeletePageResult::SUCCESS); |
| 319 } |
| 257 } | 320 } |
| 258 | 321 |
| 259 // This is the 1st step of a sequence of async operations chained through | 322 // This is the 1st step of a sequence of async operations chained through |
| 260 // callbacks, mostly shared between last_n and downloads: | 323 // callbacks, mostly shared between last_n and downloads: |
| 261 // 1) Compute the set of old 'last_n' pages that have to be purged. | 324 // 1) Compute the set of old 'last_n' pages that have to be purged. |
| 262 // 2) Delete the pages found in the previous step. | 325 // 2) Delete the pages found in the previous step. |
| 263 // 3) Snapshot the current web contents. | 326 // 3) Snapshot the current web contents. |
| 264 // 4) Notify requesters about the final result of the operation. | 327 // 4) Notify requesters about the final result of the operation. |
| 265 // | 328 // |
| 266 // For last_n requests the sequence is started in 1); for downloads it starts in | 329 // For last_n requests the sequence is always started in 1). For downloads it |
| 267 // 2). Step 4) might be called anytime during the chain for early termination in | 330 // starts in either 2) or 3). Step 4) might be called anytime during the chain |
| 268 // case of errors. | 331 // for early termination in case of errors. |
| 269 void RecentTabHelper::ContinueSnapshotWithIdsToPurge( | 332 void RecentTabHelper::ContinueSnapshotWithIdsToPurge( |
| 270 SnapshotProgressInfo* snapshot_info, | 333 SnapshotProgressInfo* snapshot_info, |
| 271 const std::vector<int64_t>& page_ids) { | 334 const std::vector<int64_t>& page_ids) { |
| 272 DCHECK(snapshot_info); | 335 DCHECK(snapshot_info); |
| 273 | 336 |
| 274 page_model_->DeletePagesByOfflineId( | 337 page_model_->DeletePagesByOfflineId( |
| 275 page_ids, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge, | 338 page_ids, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge, |
| 276 weak_ptr_factory_.GetWeakPtr(), snapshot_info)); | 339 weak_ptr_factory_.GetWeakPtr(), snapshot_info)); |
| 277 } | 340 } |
| 278 | 341 |
| 279 void RecentTabHelper::ContinueSnapshotAfterPurge( | 342 void RecentTabHelper::ContinueSnapshotAfterPurge( |
| 280 SnapshotProgressInfo* snapshot_info, | 343 SnapshotProgressInfo* snapshot_info, |
| 281 OfflinePageModel::DeletePageResult result) { | 344 OfflinePageModel::DeletePageResult result) { |
| 282 DCHECK_EQ(snapshot_url_, web_contents()->GetLastCommittedURL()); | 345 DCHECK_EQ(snapshot_url_, web_contents()->GetLastCommittedURL()); |
| 283 if (result != OfflinePageModel::DeletePageResult::SUCCESS) { | 346 if (result != OfflinePageModel::DeletePageResult::SUCCESS) { |
| 284 ReportSnapshotCompleted(snapshot_info); | 347 ReportSnapshotCompleted(snapshot_info, false); |
| 285 return; | 348 return; |
| 286 } | 349 } |
| 287 | 350 |
| 288 snapshot_info->expected_page_quality = | 351 snapshot_info->expected_page_quality = |
| 289 snapshot_controller_->current_page_quality(); | 352 snapshot_controller_->current_page_quality(); |
| 290 OfflinePageModel::SavePageParams save_page_params; | 353 OfflinePageModel::SavePageParams save_page_params; |
| 291 save_page_params.url = snapshot_url_; | 354 save_page_params.url = snapshot_url_; |
| 292 save_page_params.client_id = snapshot_info->client_id; | 355 save_page_params.client_id = snapshot_info->client_id; |
| 293 save_page_params.proposed_offline_id = snapshot_info->request_id; | 356 save_page_params.proposed_offline_id = snapshot_info->request_id; |
| 294 page_model_->SavePage( | 357 page_model_->SavePage( |
| 295 save_page_params, delegate_->CreatePageArchiver(web_contents()), | 358 save_page_params, delegate_->CreatePageArchiver(web_contents()), |
| 296 base::Bind(&RecentTabHelper::SavePageCallback, | 359 base::Bind(&RecentTabHelper::SavePageCallback, |
| 297 weak_ptr_factory_.GetWeakPtr(), snapshot_info)); | 360 weak_ptr_factory_.GetWeakPtr(), snapshot_info)); |
| 298 } | 361 } |
| 299 | 362 |
| 300 void RecentTabHelper::SavePageCallback(SnapshotProgressInfo* snapshot_info, | 363 void RecentTabHelper::SavePageCallback(SnapshotProgressInfo* snapshot_info, |
| 301 OfflinePageModel::SavePageResult result, | 364 OfflinePageModel::SavePageResult result, |
| 302 int64_t offline_id) { | 365 int64_t offline_id) { |
| 303 DCHECK(snapshot_info->IsForLastN() || | 366 DCHECK(snapshot_info->IsForLastN() || |
| 304 snapshot_info->request_id == offline_id); | 367 snapshot_info->request_id == offline_id); |
| 305 snapshot_info->page_snapshot_completed = (result == SavePageResult::SUCCESS); | 368 ReportSnapshotCompleted(snapshot_info, result == SavePageResult::SUCCESS); |
| 306 ReportSnapshotCompleted(snapshot_info); | |
| 307 } | 369 } |
| 308 | 370 |
| 309 // Note: this is the final step in the chain of callbacks and it's where the | 371 // Note: this is the final step in the chain of callbacks and it's where the |
| 310 // behavior is different depending on this being a last_n or downloads snapshot. | 372 // behavior is different depending on this being a last_n or downloads snapshot. |
| 311 void RecentTabHelper::ReportSnapshotCompleted( | 373 void RecentTabHelper::ReportSnapshotCompleted( |
| 312 SnapshotProgressInfo* snapshot_info) { | 374 SnapshotProgressInfo* snapshot_info, |
| 375 bool success) { |
| 313 if (snapshot_info->IsForLastN()) { | 376 if (snapshot_info->IsForLastN()) { |
| 314 DCHECK_EQ(snapshot_info, last_n_ongoing_snapshot_info_.get()); | 377 DCHECK_EQ(snapshot_info, last_n_ongoing_snapshot_info_.get()); |
| 315 if (snapshot_info->page_snapshot_completed) | 378 if (success) |
| 316 last_n_latest_saved_quality_ = snapshot_info->expected_page_quality; | 379 last_n_latest_saved_quality_ = snapshot_info->expected_page_quality; |
| 317 last_n_ongoing_snapshot_info_.reset(); | 380 last_n_ongoing_snapshot_info_.reset(); |
| 318 return; | 381 return; |
| 319 } | 382 } |
| 320 | 383 |
| 384 DCHECK_EQ(snapshot_info, downloads_ongoing_snapshot_info_.get()); |
| 321 snapshot_controller_->PendingSnapshotCompleted(); | 385 snapshot_controller_->PendingSnapshotCompleted(); |
| 322 // Tell RequestCoordinator how the request should be processed further. | 386 // Tell RequestCoordinator how the request should be processed further. |
| 323 ReportDownloadStatusToRequestCoordinator(snapshot_info); | 387 ReportDownloadStatusToRequestCoordinator(snapshot_info, success); |
| 388 if (success) { |
| 389 downloads_latest_saved_snapshot_info_ = |
| 390 std::move(downloads_ongoing_snapshot_info_); |
| 391 } else { |
| 392 downloads_ongoing_snapshot_info_.reset(); |
| 393 } |
| 324 } | 394 } |
| 325 | 395 |
| 326 // Note: we cannot assume that snapshot_info == downloads_latest_snapshot_info_ | 396 // Note: we cannot assume that snapshot_info == downloads_latest_snapshot_info_ |
| 327 // because further calls made to ObserveAndDownloadCurrentPage will replace | 397 // because further calls made to ObserveAndDownloadCurrentPage will replace |
| 328 // downloads_latest_snapshot_info_ with a new instance. | 398 // downloads_latest_snapshot_info_ with a new instance. |
| 329 void RecentTabHelper::ReportDownloadStatusToRequestCoordinator( | 399 void RecentTabHelper::ReportDownloadStatusToRequestCoordinator( |
| 330 SnapshotProgressInfo* snapshot_info) { | 400 SnapshotProgressInfo* snapshot_info, |
| 401 bool cancel_background_request) { |
| 331 DCHECK(snapshot_info); | 402 DCHECK(snapshot_info); |
| 332 DCHECK(!snapshot_info->IsForLastN()); | 403 DCHECK(!snapshot_info->IsForLastN()); |
| 333 | 404 |
| 334 RequestCoordinator* request_coordinator = | 405 RequestCoordinator* request_coordinator = |
| 335 RequestCoordinatorFactory::GetForBrowserContext( | 406 RequestCoordinatorFactory::GetForBrowserContext( |
| 336 web_contents()->GetBrowserContext()); | 407 web_contents()->GetBrowserContext()); |
| 337 if (!request_coordinator) | 408 if (!request_coordinator) |
| 338 return; | 409 return; |
| 339 | 410 |
| 340 // It is OK to call these methods more then once, depending on | 411 // It is OK to call these methods more then once, depending on |
| 341 // number of snapshots attempted in this tab helper. If the request_id is not | 412 // number of snapshots attempted in this tab helper. If the request_id is not |
| 342 // in the list of RequestCoordinator, these calls have no effect. | 413 // in the list of RequestCoordinator, these calls have no effect. |
| 343 if (snapshot_info->page_snapshot_completed) | 414 if (cancel_background_request) |
| 344 request_coordinator->MarkRequestCompleted(snapshot_info->request_id); | 415 request_coordinator->MarkRequestCompleted(snapshot_info->request_id); |
| 345 else | 416 else |
| 346 request_coordinator->EnableForOffliner(snapshot_info->request_id, | 417 request_coordinator->EnableForOffliner(snapshot_info->request_id, |
| 347 snapshot_info->client_id); | 418 snapshot_info->client_id); |
| 348 } | 419 } |
| 349 | 420 |
| 350 ClientId RecentTabHelper::GetRecentPagesClientId() const { | 421 ClientId RecentTabHelper::GetRecentPagesClientId() const { |
| 351 return ClientId(kLastNNamespace, tab_id_); | 422 return ClientId(kLastNNamespace, tab_id_); |
| 352 } | 423 } |
| 353 | 424 |
| 425 void RecentTabHelper::CancelInFlightSnapshots() { |
| 426 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 427 downloads_ongoing_snapshot_info_.reset(); |
| 428 downloads_latest_saved_snapshot_info_.reset(); |
| 429 last_n_ongoing_snapshot_info_.reset(); |
| 430 } |
| 431 |
| 354 } // namespace offline_pages | 432 } // namespace offline_pages |
| OLD | NEW |