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

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

Issue 2149773002: PrerenderingOffliner will abort background load if it sees chrome transitioning to foreground on lo… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Nutha try Created 4 years, 5 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 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/prerendering_offliner.h" 5 #include "chrome/browser/android/offline_pages/prerendering_offliner.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/sys_info.h"
8 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h" 9 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
9 #include "components/offline_pages/background/save_page_request.h" 10 #include "components/offline_pages/background/save_page_request.h"
10 #include "components/offline_pages/offline_page_model.h" 11 #include "components/offline_pages/offline_page_model.h"
11 #include "content/public/browser/browser_context.h" 12 #include "content/public/browser/browser_context.h"
12 #include "content/public/browser/web_contents.h" 13 #include "content/public/browser/web_contents.h"
13 14
14 namespace offline_pages { 15 namespace offline_pages {
15 16
16 PrerenderingOffliner::PrerenderingOffliner( 17 PrerenderingOffliner::PrerenderingOffliner(
17 content::BrowserContext* browser_context, 18 content::BrowserContext* browser_context,
18 const OfflinerPolicy* policy, 19 const OfflinerPolicy* policy,
19 OfflinePageModel* offline_page_model) 20 OfflinePageModel* offline_page_model)
20 : browser_context_(browser_context), 21 : browser_context_(browser_context),
21 offline_page_model_(offline_page_model), 22 offline_page_model_(offline_page_model),
22 pending_request_(nullptr), 23 pending_request_(nullptr),
24 app_listener_(nullptr),
23 weak_ptr_factory_(this) {} 25 weak_ptr_factory_(this) {}
24 26
25 PrerenderingOffliner::~PrerenderingOffliner() {} 27 PrerenderingOffliner::~PrerenderingOffliner() {}
26 28
27 void PrerenderingOffliner::OnLoadPageDone( 29 void PrerenderingOffliner::OnLoadPageDone(
28 const SavePageRequest& request, 30 const SavePageRequest& request,
29 const CompletionCallback& completion_callback,
30 Offliner::RequestStatus load_status, 31 Offliner::RequestStatus load_status,
31 content::WebContents* web_contents) { 32 content::WebContents* web_contents) {
32 // Check if request is still pending receiving a callback. 33 // Check if request is still pending receiving a callback.
33 // Note: it is possible to get a loaded page, start the save operation, 34 // Note: it is possible to get a loaded page, start the save operation,
34 // and then get another callback from the Loader (eg, if its loaded 35 // and then get another callback from the Loader (eg, if its loaded
35 // WebContents is being destroyed for some resource reclamation). 36 // WebContents is being destroyed for some resource reclamation).
36 if (!pending_request_) 37 if (!pending_request_)
37 return; 38 return;
38 39
39 // Since we are able to stop/cancel a previous load request, we should 40 // Since we are able to stop/cancel a previous load request, we should
(...skipping 14 matching lines...) Expand all
54 std::unique_ptr<OfflinePageArchiver> archiver( 55 std::unique_ptr<OfflinePageArchiver> archiver(
55 new OfflinePageMHTMLArchiver(web_contents)); 56 new OfflinePageMHTMLArchiver(web_contents));
56 // Pass in the URL from the WebContents in case it is redirected from 57 // Pass in the URL from the WebContents in case it is redirected from
57 // the requested URL. This is to work around a check in the 58 // the requested URL. This is to work around a check in the
58 // OfflinePageModel implementation that ensures URL passed in here is 59 // OfflinePageModel implementation that ensures URL passed in here is
59 // same as LastCommittedURL from the snapshot. 60 // same as LastCommittedURL from the snapshot.
60 // TODO(dougarnett): Raise issue of how to better deal with redirects. 61 // TODO(dougarnett): Raise issue of how to better deal with redirects.
61 SavePage(web_contents->GetLastCommittedURL(), request.client_id(), 62 SavePage(web_contents->GetLastCommittedURL(), request.client_id(),
62 std::move(archiver), 63 std::move(archiver),
63 base::Bind(&PrerenderingOffliner::OnSavePageDone, 64 base::Bind(&PrerenderingOffliner::OnSavePageDone,
64 weak_ptr_factory_.GetWeakPtr(), request, 65 weak_ptr_factory_.GetWeakPtr(), request));
65 completion_callback));
66 } else { 66 } else {
67 // Clear pending request and then run the completion callback. 67 // Clear pending request and then run its completion callback.
68 pending_request_.reset(nullptr); 68 pending_request_.reset(nullptr);
69 completion_callback.Run(request, load_status); 69 app_listener_.reset(nullptr);
70 completion_callback_.Run(request, load_status);
70 } 71 }
71 } 72 }
72 73
73 void PrerenderingOffliner::OnSavePageDone( 74 void PrerenderingOffliner::OnSavePageDone(
74 const SavePageRequest& request, 75 const SavePageRequest& request,
75 const CompletionCallback& completion_callback,
76 SavePageResult save_result, 76 SavePageResult save_result,
77 int64_t offline_id) { 77 int64_t offline_id) {
78 // Check if request is still pending receiving a callback. 78 // Check if request is still pending receiving a callback.
79 if (!pending_request_) 79 if (!pending_request_)
80 return; 80 return;
81 81
82 // Also check that save callback is for same request as pending request 82 // Also check that this completed request is same as the pending one
83 // (since SavePage request is not cancel-able currently and could be old). 83 // (since SavePage request is not cancel-able currently and could be old).
84 if (request.request_id() != pending_request_->request_id()) { 84 if (request.request_id() != pending_request_->request_id()) {
85 DVLOG(1) << "Ignoring save callback for old request"; 85 DVLOG(1) << "Ignoring save callback for old request";
86 return; 86 return;
87 } 87 }
88 88
89 // Clear pending request here and inform loader we are done with WebContents. 89 // Clear pending request here and inform loader we are done with WebContents.
90 pending_request_.reset(nullptr); 90 pending_request_.reset(nullptr);
91 app_listener_.reset(nullptr);
Pete Williamson 2016/07/13 23:17:55 Why do we reset for both SavePage done and LoadPag
dougarnett 2016/07/13 23:44:20 Paired with clearing pending_request_. Only reset
91 GetOrCreateLoader()->StopLoading(); 92 GetOrCreateLoader()->StopLoading();
92 93
93 // Determine status and run the completion callback. 94 // Determine status and run the completion callback.
94 Offliner::RequestStatus save_status; 95 Offliner::RequestStatus save_status;
95 if (save_result == SavePageResult::SUCCESS) { 96 if (save_result == SavePageResult::SUCCESS) {
96 save_status = RequestStatus::SAVED; 97 save_status = RequestStatus::SAVED;
97 } else { 98 } else {
98 // TODO(dougarnett): Consider reflecting some recommendation to retry the 99 // TODO(dougarnett): Consider reflecting some recommendation to retry the
99 // request based on specific save error cases. 100 // request based on specific save error cases.
100 save_status = RequestStatus::SAVE_FAILED; 101 save_status = RequestStatus::SAVE_FAILED;
101 } 102 }
102 completion_callback.Run(request, save_status); 103 completion_callback_.Run(request, save_status);
103 } 104 }
104 105
105 bool PrerenderingOffliner::LoadAndSave(const SavePageRequest& request, 106 bool PrerenderingOffliner::LoadAndSave(const SavePageRequest& request,
106 const CompletionCallback& callback) { 107 const CompletionCallback& callback) {
107 if (pending_request_) { 108 if (pending_request_) {
108 DVLOG(1) << "Already have pending request"; 109 DVLOG(1) << "Already have pending request";
109 return false; 110 return false;
110 } 111 }
111 112
112 if (!GetOrCreateLoader()->CanPrerender()) { 113 if (!GetOrCreateLoader()->CanPrerender()) {
113 DVLOG(1) << "Prerendering not allowed/configured"; 114 DVLOG(1) << "Prerendering not allowed/configured";
114 return false; 115 return false;
115 } 116 }
116 117
117 if (!OfflinePageModel::CanSaveURL(request.url())) { 118 if (!OfflinePageModel::CanSaveURL(request.url())) {
118 DVLOG(1) << "Not able to save page for requested url: " << request.url(); 119 DVLOG(1) << "Not able to save page for requested url: " << request.url();
119 return false; 120 return false;
120 } 121 }
121 122
122 // Track copy of pending request for callback handling. 123 // Track copy of pending request for callback handling.
123 pending_request_.reset(new SavePageRequest(request)); 124 pending_request_.reset(new SavePageRequest(request));
125 completion_callback_ = callback;
124 126
125 // Kick off load page attempt. 127 // Kick off load page attempt.
126 bool accepted = GetOrCreateLoader()->LoadPage( 128 bool accepted = GetOrCreateLoader()->LoadPage(
127 request.url(), 129 request.url(), base::Bind(&PrerenderingOffliner::OnLoadPageDone,
128 base::Bind(&PrerenderingOffliner::OnLoadPageDone, 130 weak_ptr_factory_.GetWeakPtr(), request));
129 weak_ptr_factory_.GetWeakPtr(), request, callback)); 131 if (!accepted) {
130 if (!accepted)
131 pending_request_.reset(nullptr); 132 pending_request_.reset(nullptr);
133 } else if (base::SysInfo::IsLowEndDevice()) {
134 app_listener_.reset(new base::android::ApplicationStatusListener(
Pete Williamson 2016/07/13 23:17:55 Would it be better to always set up a listener, ev
dougarnett 2016/07/13 23:44:20 Had that originally but didn't come up with any us
Pete Williamson 2016/07/13 23:57:12 I suppose I would be OK with waiting until we need
fgorski 2016/07/14 17:01:45 I second Pete's initial comment. It is the state c
dougarnett 2016/07/15 16:00:25 Done.
135 base::Bind(&PrerenderingOffliner::OnApplicationStateChange,
136 weak_ptr_factory_.GetWeakPtr())));
137 }
132 138
133 return accepted; 139 return accepted;
134 } 140 }
135 141
136 void PrerenderingOffliner::Cancel() { 142 void PrerenderingOffliner::Cancel() {
137 if (pending_request_) { 143 if (pending_request_) {
138 pending_request_.reset(nullptr); 144 pending_request_.reset(nullptr);
145 app_listener_.reset(nullptr);
139 GetOrCreateLoader()->StopLoading(); 146 GetOrCreateLoader()->StopLoading();
140 // TODO(dougarnett): Consider ability to cancel SavePage request. 147 // TODO(dougarnett): Consider ability to cancel SavePage request.
141 } 148 }
142 } 149 }
143 150
144 void PrerenderingOffliner::SetLoaderForTesting( 151 void PrerenderingOffliner::SetLoaderForTesting(
145 std::unique_ptr<PrerenderingLoader> loader) { 152 std::unique_ptr<PrerenderingLoader> loader) {
146 DCHECK(!loader_); 153 DCHECK(!loader_);
147 loader_ = std::move(loader); 154 loader_ = std::move(loader);
148 } 155 }
149 156
157 void PrerenderingOffliner::SetApplicationStateForTesting(
158 base::android::ApplicationState application_state) {
159 OnApplicationStateChange(application_state);
160 }
161
150 void PrerenderingOffliner::SavePage( 162 void PrerenderingOffliner::SavePage(
151 const GURL& url, 163 const GURL& url,
152 const ClientId& client_id, 164 const ClientId& client_id,
153 std::unique_ptr<OfflinePageArchiver> archiver, 165 std::unique_ptr<OfflinePageArchiver> archiver,
154 const SavePageCallback& callback) { 166 const SavePageCallback& save_callback) {
155 DCHECK(offline_page_model_); 167 DCHECK(offline_page_model_);
156 offline_page_model_->SavePage(url, client_id, std::move(archiver), callback); 168 offline_page_model_->SavePage(url, client_id, std::move(archiver),
169 save_callback);
157 } 170 }
158 171
159 PrerenderingLoader* PrerenderingOffliner::GetOrCreateLoader() { 172 PrerenderingLoader* PrerenderingOffliner::GetOrCreateLoader() {
160 if (!loader_) { 173 if (!loader_) {
161 loader_.reset(new PrerenderingLoader(browser_context_)); 174 loader_.reset(new PrerenderingLoader(browser_context_));
162 } 175 }
163 return loader_.get(); 176 return loader_.get();
164 } 177 }
165 178
179 void PrerenderingOffliner::OnApplicationStateChange(
180 base::android::ApplicationState application_state) {
181 if (pending_request_ && base::SysInfo::IsLowEndDevice() &&
182 application_state ==
183 base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
184 DVLOG(1) << "App became active, canceling current offlining request";
185 SavePageRequest* request = pending_request_.get();
186 Cancel();
187 completion_callback_.Run(*request,
188 Offliner::RequestStatus::FOREGROUND_CANCELED);
189 }
190 }
191
166 } // namespace offline_pages 192 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698