Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: chrome/browser/android/offline_pages/recent_tab_helper.cc

Issue 2420543004: Improve the page download: (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/threading/thread_task_runner_handle.h" 16 #include "base/threading/thread_task_runner_handle.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "chrome/browser/android/offline_pages/downloads/offline_page_notificati on_bridge.h"
18 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h" 19 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
19 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" 20 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h"
20 #include "chrome/browser/android/offline_pages/offline_page_utils.h" 21 #include "chrome/browser/android/offline_pages/offline_page_utils.h"
22 #include "chrome/browser/android/offline_pages/request_coordinator_factory.h"
23 #include "components/offline_pages/background/request_coordinator.h"
21 #include "components/offline_pages/client_namespace_constants.h" 24 #include "components/offline_pages/client_namespace_constants.h"
22 #include "components/offline_pages/offline_page_feature.h" 25 #include "components/offline_pages/offline_page_feature.h"
23 #include "components/offline_pages/offline_page_item.h" 26 #include "components/offline_pages/offline_page_item.h"
24 #include "components/offline_pages/offline_page_model.h" 27 #include "components/offline_pages/offline_page_model.h"
25 #include "content/public/browser/browser_context.h" 28 #include "content/public/browser/browser_context.h"
26 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/navigation_entry.h" 30 #include "content/public/browser/navigation_entry.h"
28 #include "content/public/browser/navigation_handle.h" 31 #include "content/public/browser/navigation_handle.h"
29 32
30 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::RecentTabHelper); 33 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::RecentTabHelper);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 66
64 RecentTabHelper::~RecentTabHelper() { 67 RecentTabHelper::~RecentTabHelper() {
65 } 68 }
66 69
67 void RecentTabHelper::SetDelegate( 70 void RecentTabHelper::SetDelegate(
68 std::unique_ptr<RecentTabHelper::Delegate> delegate) { 71 std::unique_ptr<RecentTabHelper::Delegate> delegate) {
69 DCHECK(delegate); 72 DCHECK(delegate);
70 delegate_ = std::move(delegate); 73 delegate_ = std::move(delegate);
71 } 74 }
72 75
76 void RecentTabHelper::ObserveAndDownloadCurrentPage(
77 const ClientId& client_id, int64_t request_id) {
78 EnsureInitialized();
79 download_info_ = base::MakeUnique<DownloadPageInfo>(client_id, request_id);
80
81 // If this tab helper is not enabled, immediately give the job back to
82 // RequestCoordinator.
83 if (!snapshots_enabled_ || !page_model_) {
84 ReportDownloadStatusToRequestCoordinator();
85 download_info_.reset();
86 return;
87 }
88
89 // No snapshots yet happened on the current page - return and wait for some.
90 if (!is_page_ready_for_snapshot_)
91 return;
92
93 // If snapshot already happened and we missed it, go ahead and snapshot now.
94 page_model_->SavePage(
95 web_contents()->GetLastCommittedURL(),
96 client_id,
97 request_id,
98 delegate_->CreatePageArchiver(web_contents()),
99 base::Bind(&RecentTabHelper::SavePageCallback,
100 weak_ptr_factory_.GetWeakPtr()));
101 }
102
73 // Initialize lazily. It needs TabAndroid for initialization, which is also a 103 // Initialize lazily. It needs TabAndroid for initialization, which is also a
74 // TabHelper - so can't initialize in constructor because of uncertain order 104 // TabHelper - so can't initialize in constructor because of uncertain order
75 // of creation of TabHelpers. 105 // of creation of TabHelpers.
76 void RecentTabHelper::EnsureInitialized() { 106 void RecentTabHelper::EnsureInitialized() {
77 if (snapshot_controller_) // Initialized already. 107 if (snapshot_controller_) // Initialized already.
78 return; 108 return;
79 109
80 snapshot_controller_.reset( 110 snapshot_controller_.reset(
81 new SnapshotController(delegate_->GetTaskRunner(), this)); 111 new SnapshotController(delegate_->GetTaskRunner(), this));
82 snapshot_controller_->Stop(); // It is reset when navigation commits. 112 snapshot_controller_->Stop(); // It is reset when navigation commits.
(...skipping 18 matching lines...) Expand all
101 131
102 void RecentTabHelper::DidFinishNavigation( 132 void RecentTabHelper::DidFinishNavigation(
103 content::NavigationHandle* navigation_handle) { 133 content::NavigationHandle* navigation_handle) {
104 if (!navigation_handle->IsInMainFrame() || 134 if (!navigation_handle->IsInMainFrame() ||
105 !navigation_handle->HasCommitted()) { 135 !navigation_handle->HasCommitted()) {
106 return; 136 return;
107 } 137 }
108 138
109 // Cancel tasks in flight that relate to the previous page. 139 // Cancel tasks in flight that relate to the previous page.
110 weak_ptr_factory_.InvalidateWeakPtrs(); 140 weak_ptr_factory_.InvalidateWeakPtrs();
111 is_page_ready_for_snapshot_ = false;
112 141
113 EnsureInitialized(); 142 EnsureInitialized();
114 if (!snapshots_enabled_) 143 if (!snapshots_enabled_)
115 return; 144 return;
116 145
146 // We navigated to a different page, lets report progress to Background
147 // Offliner.
148 if (download_info_ && !navigation_handle->IsSamePage()) {
149 ReportDownloadStatusToRequestCoordinator();
150 }
151
152 if (offline_pages::IsOffliningRecentPagesEnabled()) {
153 int64_t proposed_id = OfflinePageModel::kInvalidOfflineId;
154 download_info_ = base::MakeUnique<DownloadPageInfo>(
155 GetRecentPagesClientId(), proposed_id);
156 } else {
157 download_info_.reset();
158 }
159
160 is_page_ready_for_snapshot_ = false;
117 161
118 // New navigation, new snapshot session. 162 // New navigation, new snapshot session.
119 snapshot_url_ = web_contents()->GetLastCommittedURL(); 163 snapshot_url_ = web_contents()->GetLastCommittedURL();
120 164
121 // Check for conditions that would cause us not to snapshot. 165 // Check for conditions that would cause us not to snapshot.
122 bool can_save = !navigation_handle->IsErrorPage() && 166 bool can_save = !navigation_handle->IsErrorPage() &&
123 OfflinePageModel::CanSaveURL(snapshot_url_); 167 OfflinePageModel::CanSaveURL(snapshot_url_);
124 168
125 UMA_HISTOGRAM_BOOLEAN("OfflinePages.CanSaveRecentPage", can_save); 169 UMA_HISTOGRAM_BOOLEAN("OfflinePages.CanSaveRecentPage", can_save);
126 170
127 // Always reset so that posted tasks get canceled. 171 // Always reset so that posted tasks get canceled.
128 snapshot_controller_->Reset(); 172 snapshot_controller_->Reset();
129 173
130 if (!can_save) 174 if (!can_save)
131 snapshot_controller_->Stop(); 175 snapshot_controller_->Stop();
132 } 176 }
133 177
134 void RecentTabHelper::DocumentAvailableInMainFrame() { 178 void RecentTabHelper::DocumentAvailableInMainFrame() {
135 EnsureInitialized(); 179 EnsureInitialized();
136 snapshot_controller_->DocumentAvailableInMainFrame(); 180 snapshot_controller_->DocumentAvailableInMainFrame();
137 } 181 }
138 182
139 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() { 183 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() {
140 EnsureInitialized(); 184 EnsureInitialized();
141 snapshot_controller_->DocumentOnLoadCompletedInMainFrame(); 185 snapshot_controller_->DocumentOnLoadCompletedInMainFrame();
142 } 186 }
143 187
188 void RecentTabHelper::WebContentsDestroyed() {
189 // WebContents (and maybe Tab) is destroyed, report status to Offliner.
190 if (!download_info_)
191 return;
192 ReportDownloadStatusToRequestCoordinator();
193 }
194
195
144 // This starts a sequence of async operations chained through callbacks: 196 // This starts a sequence of async operations chained through callbacks:
145 // - compute the set of old 'last_n' pages that have to be purged 197 // - compute the set of old 'last_n' pages that have to be purged
146 // - delete the pages found in the previous step 198 // - delete the pages found in the previous step
147 // - snapshot the current web contents 199 // - snapshot the current web contents
148 // Along the chain, the original URL is passed and compared, to detect 200 // Along the chain, the original URL is passed and compared, to detect
149 // possible navigation and cancel snapshot in that case. 201 // possible navigation and cancel snapshot in that case.
150 void RecentTabHelper::StartSnapshot() { 202 void RecentTabHelper::StartSnapshot() {
151 is_page_ready_for_snapshot_ = true; 203 is_page_ready_for_snapshot_ = true;
152 204
153 if (!snapshots_enabled_ || 205 if (!snapshots_enabled_ ||
154 !page_model_ || 206 !page_model_ ||
155 !offline_pages::IsOffliningRecentPagesEnabled()) { 207 !download_info_) {
156 ReportSnapshotCompleted(); 208 ReportSnapshotCompleted();
157 return; 209 return;
158 } 210 }
159 211
160 // Remove previously captured pages for this tab. 212 // Remove previously captured pages for this tab.
161 page_model_->GetOfflineIdsForClientId( 213 page_model_->GetOfflineIdsForClientId(
162 client_id(), 214 GetRecentPagesClientId(),
163 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge, 215 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge,
164 weak_ptr_factory_.GetWeakPtr())); 216 weak_ptr_factory_.GetWeakPtr()));
165 } 217 }
166 218
167 void RecentTabHelper::ContinueSnapshotWithIdsToPurge( 219 void RecentTabHelper::ContinueSnapshotWithIdsToPurge(
168 const std::vector<int64_t>& page_ids) { 220 const std::vector<int64_t>& page_ids) {
221 if (!download_info_)
222 return;
223
224 // Also remove the download page if this is not a first snapshot.
225 std::vector<int64_t> ids(page_ids);
226 ids.push_back(download_info_->request_id_);
227
169 page_model_->DeletePagesByOfflineId( 228 page_model_->DeletePagesByOfflineId(
170 page_ids, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge, 229 ids, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge,
171 weak_ptr_factory_.GetWeakPtr())); 230 weak_ptr_factory_.GetWeakPtr()));
172 } 231 }
173 232
174 void RecentTabHelper::ContinueSnapshotAfterPurge( 233 void RecentTabHelper::ContinueSnapshotAfterPurge(
175 OfflinePageModel::DeletePageResult result) { 234 OfflinePageModel::DeletePageResult result) {
176 if (result != OfflinePageModel::DeletePageResult::SUCCESS) { 235 if (!download_info_ ||
177 // If previous pages can't be deleted, don't add new ones. 236 result != OfflinePageModel::DeletePageResult::SUCCESS ||
237 !IsSamePage()) {
178 ReportSnapshotCompleted(); 238 ReportSnapshotCompleted();
179 return; 239 return;
180 } 240 }
181 241
182 if (!IsSamePage()) { 242 page_model_->SavePage(snapshot_url_,
183 ReportSnapshotCompleted(); 243 download_info_->client_id_,
184 return; 244 download_info_->request_id_,
185 }
186
187 page_model_->SavePage(snapshot_url_, client_id(), 0l,
188 delegate_->CreatePageArchiver(web_contents()), 245 delegate_->CreatePageArchiver(web_contents()),
189 base::Bind(&RecentTabHelper::SavePageCallback, 246 base::Bind(&RecentTabHelper::SavePageCallback,
190 weak_ptr_factory_.GetWeakPtr())); 247 weak_ptr_factory_.GetWeakPtr()));
191 } 248 }
192 249
193 void RecentTabHelper::SavePageCallback(OfflinePageModel::SavePageResult result, 250 void RecentTabHelper::SavePageCallback(OfflinePageModel::SavePageResult result,
194 int64_t offline_id) { 251 int64_t offline_id) {
252 if (!download_info_)
253 return;
254 download_info_->page_snapshot_completed_ =
255 (result == SavePageResult::SUCCESS);
195 ReportSnapshotCompleted(); 256 ReportSnapshotCompleted();
196 } 257 }
197 258
198 void RecentTabHelper::ReportSnapshotCompleted() { 259 void RecentTabHelper::ReportSnapshotCompleted() {
199 snapshot_controller_->PendingSnapshotCompleted(); 260 snapshot_controller_->PendingSnapshotCompleted();
261 // Tell RequestCoordinator how the request should be processed further.
262 ReportDownloadStatusToRequestCoordinator();
263 }
264
265 void RecentTabHelper::ReportDownloadStatusToRequestCoordinator() {
266 if (!download_info_)
267 return;
268
269 if (download_info_->request_id_ == OfflinePageModel::kInvalidOfflineId)
270 return;
271
272 RequestCoordinator* request_coordinator =
273 RequestCoordinatorFactory::GetForBrowserContext(
274 web_contents()->GetBrowserContext());
275 if (!request_coordinator)
276 return;
277
278 // It is OK to call these methods more then once, depending on
279 // number of snapshots attempted in this tab helper. If the request_id is not
280 // in the list of RequestCoordinator, these calls have no effect.
281 if (download_info_->page_snapshot_completed_)
282 request_coordinator->MarkRequestCompleted(download_info_->request_id_);
283 else
284 request_coordinator->EnableForOffliner(download_info_->request_id_);
200 } 285 }
201 286
202 bool RecentTabHelper::IsSamePage() const { 287 bool RecentTabHelper::IsSamePage() const {
203 return web_contents() && 288 return web_contents() &&
204 (web_contents()->GetLastCommittedURL() == snapshot_url_); 289 (web_contents()->GetLastCommittedURL() == snapshot_url_);
205 } 290 }
206 291
207 ClientId RecentTabHelper::client_id() const { 292 ClientId RecentTabHelper::GetRecentPagesClientId() const {
208 return ClientId(kLastNNamespace, tab_id_); 293 return ClientId(kLastNNamespace, tab_id_);
209 } 294 }
210 295
211 } // namespace offline_pages 296 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698