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

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

Issue 2412823002: Improve the page download: (Closed)
Patch Set: merge 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 16 matching lines...) Expand all
47 return offline_pages::OfflinePageUtils::GetTabId(web_contents, tab_id); 50 return offline_pages::OfflinePageUtils::GetTabId(web_contents, tab_id);
48 } 51 }
49 }; 52 };
50 } // namespace 53 } // namespace
51 54
52 namespace offline_pages { 55 namespace offline_pages {
53 56
54 RecentTabHelper::RecentTabHelper(content::WebContents* web_contents) 57 RecentTabHelper::RecentTabHelper(content::WebContents* web_contents)
55 : content::WebContentsObserver(web_contents), 58 : content::WebContentsObserver(web_contents),
56 page_model_(nullptr), 59 page_model_(nullptr),
60 is_page_ready_for_snapshot_(false),
57 snapshots_enabled_(false), 61 snapshots_enabled_(false),
58 is_page_ready_for_snapshot_(false),
59 delegate_(new DefaultDelegate()), 62 delegate_(new DefaultDelegate()),
60 weak_ptr_factory_(this) { 63 weak_ptr_factory_(this) {
61 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 64 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
62 } 65 }
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 ReportDownloadRequestStatus(false);
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 ReportDownloadRequestStatus(download_info_->page_snapshot_completed_);
150 }
151
152 if (offline_pages::IsOffliningRecentPagesEnabled()) {
153 download_info_ = base::MakeUnique<DownloadPageInfo>(
154 GetRecentPagesClientId(), 0l);
155 } else {
156 download_info_.reset();
157 }
158
159 is_page_ready_for_snapshot_ = false;
117 160
118 // New navigation, new snapshot session. 161 // New navigation, new snapshot session.
119 snapshot_url_ = web_contents()->GetLastCommittedURL(); 162 snapshot_url_ = web_contents()->GetLastCommittedURL();
120 163
121 // Check for conditions that would cause us not to snapshot. 164 // Check for conditions that would cause us not to snapshot.
122 bool can_save = !navigation_handle->IsErrorPage() && 165 bool can_save = !navigation_handle->IsErrorPage() &&
123 OfflinePageModel::CanSaveURL(snapshot_url_); 166 OfflinePageModel::CanSaveURL(snapshot_url_);
124 167
125 UMA_HISTOGRAM_BOOLEAN("OfflinePages.CanSaveRecentPage", can_save); 168 UMA_HISTOGRAM_BOOLEAN("OfflinePages.CanSaveRecentPage", can_save);
126 169
127 // Always reset so that posted tasks get canceled. 170 // Always reset so that posted tasks get canceled.
128 snapshot_controller_->Reset(); 171 snapshot_controller_->Reset();
129 172
130 if (!can_save) 173 if (!can_save)
131 snapshot_controller_->Stop(); 174 snapshot_controller_->Stop();
132 } 175 }
133 176
134 void RecentTabHelper::DocumentAvailableInMainFrame() { 177 void RecentTabHelper::DocumentAvailableInMainFrame() {
135 EnsureInitialized(); 178 EnsureInitialized();
136 snapshot_controller_->DocumentAvailableInMainFrame(); 179 snapshot_controller_->DocumentAvailableInMainFrame();
137 } 180 }
138 181
139 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() { 182 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() {
140 EnsureInitialized(); 183 EnsureInitialized();
141 snapshot_controller_->DocumentOnLoadCompletedInMainFrame(); 184 snapshot_controller_->DocumentOnLoadCompletedInMainFrame();
142 } 185 }
143 186
187 void RecentTabHelper::WebContentsDestroyed() {
188 // WebContents (and maybe Tab) is destroyed, report status to Offliner.
189 if (!download_info_)
190 return;
191 ReportDownloadRequestStatus(download_info_->page_snapshot_completed_);
192 }
193
194
144 // This starts a sequence of async operations chained through callbacks: 195 // This starts a sequence of async operations chained through callbacks:
145 // - compute the set of old 'last_n' pages that have to be purged 196 // - compute the set of old 'last_n' pages that have to be purged
146 // - delete the pages found in the previous step 197 // - delete the pages found in the previous step
147 // - snapshot the current web contents 198 // - snapshot the current web contents
148 // Along the chain, the original URL is passed and compared, to detect 199 // Along the chain, the original URL is passed and compared, to detect
149 // possible navigation and cancel snapshot in that case. 200 // possible navigation and cancel snapshot in that case.
150 void RecentTabHelper::StartSnapshot() { 201 void RecentTabHelper::StartSnapshot() {
151 is_page_ready_for_snapshot_ = true; 202 is_page_ready_for_snapshot_ = true;
152 203
153 if (!snapshots_enabled_ || 204 if (!snapshots_enabled_ ||
154 !page_model_ || 205 !page_model_ ||
155 !offline_pages::IsOffliningRecentPagesEnabled()) { 206 !download_info_) {
156 ReportSnapshotCompleted(); 207 ReportSnapshotCompleted(false);
dewittj 2016/10/12 03:27:27 nit: either replace bool with an enum class or add
Dmitry Titov 2016/10/12 23:11:14 Done. No parameters.
157 return; 208 return;
158 } 209 }
159 210
160 // Remove previously captured pages for this tab. 211 // Remove previously captured pages for this tab.
161 page_model_->GetOfflineIdsForClientId( 212 page_model_->GetOfflineIdsForClientId(
162 client_id(), 213 GetRecentPagesClientId(),
163 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge, 214 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge,
164 weak_ptr_factory_.GetWeakPtr())); 215 weak_ptr_factory_.GetWeakPtr()));
165 } 216 }
166 217
167 void RecentTabHelper::ContinueSnapshotWithIdsToPurge( 218 void RecentTabHelper::ContinueSnapshotWithIdsToPurge(
168 const std::vector<int64_t>& page_ids) { 219 const std::vector<int64_t>& page_ids) {
220 if (!download_info_)
221 return;
222
223 // Also remove the download page if this is not a first snapshot.
224 std::vector<int64_t> ids(page_ids);
225 ids.push_back(download_info_->request_id_);
226
169 page_model_->DeletePagesByOfflineId( 227 page_model_->DeletePagesByOfflineId(
170 page_ids, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge, 228 ids, base::Bind(&RecentTabHelper::ContinueSnapshotAfterPurge,
171 weak_ptr_factory_.GetWeakPtr())); 229 weak_ptr_factory_.GetWeakPtr()));
172 } 230 }
173 231
174 void RecentTabHelper::ContinueSnapshotAfterPurge( 232 void RecentTabHelper::ContinueSnapshotAfterPurge(
175 OfflinePageModel::DeletePageResult result) { 233 OfflinePageModel::DeletePageResult result) {
176 if (result != OfflinePageModel::DeletePageResult::SUCCESS) { 234 if (!download_info_ ||
177 // If previous pages can't be deleted, don't add new ones. 235 result != OfflinePageModel::DeletePageResult::SUCCESS ||
178 ReportSnapshotCompleted(); 236 !IsSamePage()) {
237 ReportSnapshotCompleted(false);
179 return; 238 return;
180 } 239 }
181 240
182 if (!IsSamePage()) { 241 page_model_->SavePage(snapshot_url_,
183 ReportSnapshotCompleted(); 242 download_info_->client_id_,
184 return; 243 download_info_->request_id_,
185 }
186
187 page_model_->SavePage(snapshot_url_, client_id(), 0l,
188 delegate_->CreatePageArchiver(web_contents()), 244 delegate_->CreatePageArchiver(web_contents()),
189 base::Bind(&RecentTabHelper::SavePageCallback, 245 base::Bind(&RecentTabHelper::SavePageCallback,
190 weak_ptr_factory_.GetWeakPtr())); 246 weak_ptr_factory_.GetWeakPtr()));
191 } 247 }
192 248
193 void RecentTabHelper::SavePageCallback(OfflinePageModel::SavePageResult result, 249 void RecentTabHelper::SavePageCallback(OfflinePageModel::SavePageResult result,
194 int64_t offline_id) { 250 int64_t offline_id) {
195 ReportSnapshotCompleted(); 251 if (!download_info_)
252 return;
253 bool success = (result == SavePageResult::SUCCESS);
254 download_info_->page_snapshot_completed_ = success;
dewittj 2016/10/12 03:27:27 could |page_snapshot_completed_| be used instead o
Dmitry Titov 2016/10/12 23:11:14 Done. This is actually more correct, thanks!
255 ReportSnapshotCompleted(success);
196 } 256 }
197 257
198 void RecentTabHelper::ReportSnapshotCompleted() { 258 void RecentTabHelper::ReportSnapshotCompleted(bool success) {
199 snapshot_controller_->PendingSnapshotCompleted(); 259 snapshot_controller_->PendingSnapshotCompleted();
260 // Tell RequestCoordinator how the request should be processed further.
261 ReportDownloadRequestStatus(success);
262 }
263
264 void RecentTabHelper::ReportDownloadRequestStatus(bool completed) {
Pete Williamson 2016/10/12 17:33:36 The function name doesn't represent what it does w
Dmitry Titov 2016/10/12 23:11:14 Done.
265 if (!download_info_ || download_info_->request_id_ <= 0l)
266 return;
267
268 RequestCoordinator* request_coordinator =
269 RequestCoordinatorFactory::GetForBrowserContext(
270 web_contents()->GetBrowserContext());
271 if (!request_coordinator)
272 return;
273
274 // It is OK to call these methods more then once, depending on
275 // number of snapshots attempted in this tab helper. If the request_id is not
276 // in the list of RequestCoordinator, these calls have no effect.
277 if (completed)
278 request_coordinator->MarkRequestCompleted(download_info_->request_id_);
279 else
280 request_coordinator->EnableForOffliner(download_info_->request_id_);
200 } 281 }
201 282
202 bool RecentTabHelper::IsSamePage() const { 283 bool RecentTabHelper::IsSamePage() const {
203 return web_contents() && 284 return web_contents() &&
204 (web_contents()->GetLastCommittedURL() == snapshot_url_); 285 (web_contents()->GetLastCommittedURL() == snapshot_url_);
205 } 286 }
206 287
207 ClientId RecentTabHelper::client_id() const { 288 ClientId RecentTabHelper::GetRecentPagesClientId() const {
208 return ClientId(kLastNNamespace, tab_id_); 289 return ClientId(kLastNNamespace, tab_id_);
209 } 290 }
210 291
211 } // namespace offline_pages 292 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698