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

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

Issue 2819393002: Collect loading signal data from the background loader offliner (Closed)
Patch Set: Merge in the "extra headers" change Created 3 years, 8 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/background_loader_offliner.h" 5 #include "chrome/browser/android/offline_pages/background_loader_offliner.h"
6 6
7 #include "base/json/json_writer.h"
7 #include "base/metrics/histogram_macros.h" 8 #include "base/metrics/histogram_macros.h"
8 #include "base/sys_info.h" 9 #include "base/sys_info.h"
10 #include "base/time/time.h"
9 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h" 11 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
10 #include "chrome/browser/android/offline_pages/offliner_helper.h" 12 #include "chrome/browser/android/offline_pages/offliner_helper.h"
11 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
12 #include "components/offline_pages/core/background/offliner_policy.h" 14 #include "components/offline_pages/core/background/offliner_policy.h"
13 #include "components/offline_pages/core/background/save_page_request.h" 15 #include "components/offline_pages/core/background/save_page_request.h"
14 #include "components/offline_pages/core/client_namespace_constants.h" 16 #include "components/offline_pages/core/client_namespace_constants.h"
17 #include "components/offline_pages/core/offline_page_feature.h"
15 #include "components/offline_pages/core/offline_page_model.h" 18 #include "components/offline_pages/core/offline_page_model.h"
16 #include "content/public/browser/browser_context.h" 19 #include "content/public/browser/browser_context.h"
20 #include "content/public/browser/mhtml_extra_parts.h"
17 #include "content/public/browser/navigation_handle.h" 21 #include "content/public/browser/navigation_handle.h"
18 #include "content/public/browser/render_frame_host.h" 22 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/web_contents.h" 23 #include "content/public/browser/web_contents.h"
20 #include "content/public/browser/web_contents_user_data.h" 24 #include "content/public/browser/web_contents_user_data.h"
21 25
22 namespace offline_pages { 26 namespace offline_pages {
23 27
24 namespace { 28 namespace {
25 const long kOfflinePageDelayMs = 2000; 29 const long kOfflinePageDelayMs = 2000;
26 const long kOfflineDomContentLoadedMs = 25000; 30 const long kOfflineDomContentLoadedMs = 25000;
31 const char kContentType[] = "text/plain";
32 const char kContentTransferEncodingBinary[] =
33 "Content-Transfer-Encoding: binary";
34 const char kXHeaderForSignals[] = "X-Chrome-Loading-Metrics-Data: 1";
27 35
28 class OfflinerData : public content::WebContentsUserData<OfflinerData> { 36 class OfflinerData : public content::WebContentsUserData<OfflinerData> {
29 public: 37 public:
30 static void AddToWebContents(content::WebContents* webcontents, 38 static void AddToWebContents(content::WebContents* webcontents,
31 BackgroundLoaderOffliner* offliner) { 39 BackgroundLoaderOffliner* offliner) {
32 DCHECK(offliner); 40 DCHECK(offliner);
33 webcontents->SetUserData(UserDataKey(), std::unique_ptr<OfflinerData>( 41 webcontents->SetUserData(UserDataKey(), std::unique_ptr<OfflinerData>(
34 new OfflinerData(offliner))); 42 new OfflinerData(offliner)));
35 } 43 }
36 44
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 } 160 }
153 161
154 if (!OfflinePageModel::CanSaveURL(request.url())) { 162 if (!OfflinePageModel::CanSaveURL(request.url())) {
155 DVLOG(1) << "Not able to save page for requested url: " << request.url(); 163 DVLOG(1) << "Not able to save page for requested url: " << request.url();
156 return false; 164 return false;
157 } 165 }
158 166
159 if (!loader_) 167 if (!loader_)
160 ResetState(); 168 ResetState();
161 169
170 MarkLoadStartTime();
171
162 // Track copy of pending request. 172 // Track copy of pending request.
163 pending_request_.reset(new SavePageRequest(request)); 173 pending_request_.reset(new SavePageRequest(request));
164 completion_callback_ = completion_callback; 174 completion_callback_ = completion_callback;
165 progress_callback_ = progress_callback; 175 progress_callback_ = progress_callback;
166 176
167 // Listen for app foreground/background change. 177 // Listen for app foreground/background change.
168 app_listener_.reset(new base::android::ApplicationStatusListener( 178 app_listener_.reset(new base::android::ApplicationStatusListener(
169 base::Bind(&BackgroundLoaderOffliner::OnApplicationStateChange, 179 base::Bind(&BackgroundLoaderOffliner::OnApplicationStateChange,
170 weak_ptr_factory_.GetWeakPtr()))); 180 weak_ptr_factory_.GetWeakPtr())));
171 181
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 if (save_state_ == NONE) { 221 if (save_state_ == NONE) {
212 did_snapshot_on_last_retry_ = true; 222 did_snapshot_on_last_retry_ = true;
213 StartSnapshot(); 223 StartSnapshot();
214 } 224 }
215 return true; 225 return true;
216 } 226 }
217 } 227 }
218 return false; 228 return false;
219 } 229 }
220 230
231 void BackgroundLoaderOffliner::MarkLoadStartTime() {
232 load_start_time_ = base::TimeTicks::Now();
233 }
234
221 void BackgroundLoaderOffliner::DocumentAvailableInMainFrame() { 235 void BackgroundLoaderOffliner::DocumentAvailableInMainFrame() {
222 snapshot_controller_->DocumentAvailableInMainFrame(); 236 snapshot_controller_->DocumentAvailableInMainFrame();
223 is_low_bar_met_ = true; 237 is_low_bar_met_ = true;
238
239 // Add this signal to signal_data_.
240 AddLoadingSignal("DocumentAvailableInMainFrame");
224 } 241 }
225 242
226 void BackgroundLoaderOffliner::DocumentOnLoadCompletedInMainFrame() { 243 void BackgroundLoaderOffliner::DocumentOnLoadCompletedInMainFrame() {
227 if (!pending_request_.get()) { 244 if (!pending_request_.get()) {
228 DVLOG(1) << "DidStopLoading called even though no pending request."; 245 DVLOG(1) << "DidStopLoading called even though no pending request.";
229 return; 246 return;
230 } 247 }
231 248
249 // Add this signal to signal_data_.
250 AddLoadingSignal("DocumentOnLoadCompletedInMainFrame");
251
232 snapshot_controller_->DocumentOnLoadCompletedInMainFrame(); 252 snapshot_controller_->DocumentOnLoadCompletedInMainFrame();
233 } 253 }
234 254
235 void BackgroundLoaderOffliner::RenderProcessGone( 255 void BackgroundLoaderOffliner::RenderProcessGone(
236 base::TerminationStatus status) { 256 base::TerminationStatus status) {
237 if (pending_request_) { 257 if (pending_request_) {
238 SavePageRequest request(*pending_request_.get()); 258 SavePageRequest request(*pending_request_.get());
239 switch (status) { 259 switch (status) {
240 case base::TERMINATION_STATUS_OOM: 260 case base::TERMINATION_STATUS_OOM:
241 case base::TERMINATION_STATUS_PROCESS_CRASHED: 261 case base::TERMINATION_STATUS_PROCESS_CRASHED:
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 progress_callback_.Run(*pending_request_, network_bytes_); 309 progress_callback_.Run(*pending_request_, network_bytes_);
290 } 310 }
291 } 311 }
292 312
293 void BackgroundLoaderOffliner::StartSnapshot() { 313 void BackgroundLoaderOffliner::StartSnapshot() {
294 if (!pending_request_.get()) { 314 if (!pending_request_.get()) {
295 DVLOG(1) << "Pending request was cleared during delay."; 315 DVLOG(1) << "Pending request was cleared during delay.";
296 return; 316 return;
297 } 317 }
298 318
319 // Add this signal to signal_data_.
320 AddLoadingSignal("Snapshotting");
321
299 SavePageRequest request(*pending_request_.get()); 322 SavePageRequest request(*pending_request_.get());
300 // If there was an error navigating to page, return loading failed. 323 // If there was an error navigating to page, return loading failed.
301 if (page_load_state_ != SUCCESS) { 324 if (page_load_state_ != SUCCESS) {
302 Offliner::RequestStatus status; 325 Offliner::RequestStatus status;
303 switch (page_load_state_) { 326 switch (page_load_state_) {
304 case RETRIABLE: 327 case RETRIABLE:
305 status = Offliner::RequestStatus::LOADING_FAILED; 328 status = Offliner::RequestStatus::LOADING_FAILED;
306 break; 329 break;
307 case NONRETRIABLE: 330 case NONRETRIABLE:
308 status = Offliner::RequestStatus::LOADING_FAILED_NO_RETRY; 331 status = Offliner::RequestStatus::LOADING_FAILED_NO_RETRY;
309 break; 332 break;
310 case DELAY_RETRY: 333 case DELAY_RETRY:
311 status = Offliner::RequestStatus::LOADING_FAILED_NO_NEXT; 334 status = Offliner::RequestStatus::LOADING_FAILED_NO_NEXT;
312 break; 335 break;
313 default: 336 default:
314 // We should've already checked for Success before entering here. 337 // We should've already checked for Success before entering here.
315 NOTREACHED(); 338 NOTREACHED();
316 status = Offliner::RequestStatus::LOADING_FAILED; 339 status = Offliner::RequestStatus::LOADING_FAILED;
317 } 340 }
341
318 completion_callback_.Run(request, status); 342 completion_callback_.Run(request, status);
319 ResetState(); 343 ResetState();
320 return; 344 return;
321 } 345 }
322 346
323 save_state_ = SAVING; 347 save_state_ = SAVING;
324 content::WebContents* web_contents( 348 content::WebContents* web_contents(
325 content::WebContentsObserver::web_contents()); 349 content::WebContentsObserver::web_contents());
326 350
351 // Add loading signal into the MHTML that will be generated if the command
352 // line flag is set for it.
353 if (IsOfflinePagesLoadSignalCollectingEnabled()) {
354 // Stash loading signals for writing when we write out the MHTML.
355 std::string headers = base::StringPrintf(
356 "%s\r\n%s\r\n\r\n", kContentTransferEncodingBinary, kXHeaderForSignals);
357 std::string body;
358 base::JSONWriter::Write(signal_data_, &body);
359 std::string content_type = kContentType;
360 std::string content_location = base::StringPrintf(
361 "cid:signal-data-%" PRId64 "@mhtml.blink", request.request_id());
362
363 content::MHTMLExtraParts* extra_parts =
364 content::MHTMLExtraParts::FromWebContents(web_contents);
365 DCHECK(extra_parts);
366 if (extra_parts != nullptr) {
367 extra_parts->AddExtraMHTMLPart(content_type, content_location, headers,
368 body);
369 }
370 }
371
327 std::unique_ptr<OfflinePageArchiver> archiver( 372 std::unique_ptr<OfflinePageArchiver> archiver(
328 new OfflinePageMHTMLArchiver(web_contents)); 373 new OfflinePageMHTMLArchiver(web_contents));
329 374
330 OfflinePageModel::SavePageParams params; 375 OfflinePageModel::SavePageParams params;
331 params.url = web_contents->GetLastCommittedURL(); 376 params.url = web_contents->GetLastCommittedURL();
332 params.client_id = request.client_id(); 377 params.client_id = request.client_id();
333 params.proposed_offline_id = request.request_id(); 378 params.proposed_offline_id = request.request_id();
334 params.is_background = true; 379 params.is_background = true;
335 380
336 // Pass in the original URL if it's different from last committed 381 // Pass in the original URL if it's different from last committed
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 457
413 void BackgroundLoaderOffliner::HandleApplicationStateChangeCancel( 458 void BackgroundLoaderOffliner::HandleApplicationStateChangeCancel(
414 const SavePageRequest& request, 459 const SavePageRequest& request,
415 int64_t offline_id) { 460 int64_t offline_id) {
416 // If for some reason the request was reset during while waiting for callback 461 // If for some reason the request was reset during while waiting for callback
417 // ignore the completion callback. 462 // ignore the completion callback.
418 if (pending_request_ && pending_request_->request_id() != offline_id) 463 if (pending_request_ && pending_request_->request_id() != offline_id)
419 return; 464 return;
420 completion_callback_.Run(request, RequestStatus::FOREGROUND_CANCELED); 465 completion_callback_.Run(request, RequestStatus::FOREGROUND_CANCELED);
421 } 466 }
467
468 void BackgroundLoaderOffliner::AddLoadingSignal(const char* signal_name) {
469 base::TimeTicks current_time = base::TimeTicks::Now();
470 base::TimeDelta delay_so_far = current_time - load_start_time_;
471 double delay = delay_so_far.InMilliseconds();
fgorski 2017/04/20 16:59:02 Please add comment explaining what happens here: W
Pete Williamson 2017/04/20 17:06:36 Done.
472 signal_data_.SetDouble(signal_name, delay);
473 }
474
422 } // namespace offline_pages 475 } // namespace offline_pages
423 476
424 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinerData); 477 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinerData);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698