1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h" 6 7 #include "base/time/time.h" 8 #include "components/page_load_metrics/browser/page_load_metrics_observer.h" 9 #include "components/page_load_metrics/browser/page_load_metrics_util.h" 10 #include "components/page_load_metrics/common/page_load_timing.h" 11 #include "content/public/browser/navigation_handle.h" 12 #include "services/metrics/public/cpp/ukm_builders.h" 13 #include "services/metrics/public/cpp/ukm_recorder.h" 14 #include "services/metrics/public/cpp/ukm_source.h" 15 ForegroundDurationUKMObserver()16ForegroundDurationUKMObserver::ForegroundDurationUKMObserver() 17 : last_page_input_timing_(page_load_metrics::mojom::InputTiming()) {} 18 ~ForegroundDurationUKMObserver()19ForegroundDurationUKMObserver::~ForegroundDurationUKMObserver() {} 20 21 page_load_metrics::PageLoadMetricsObserver::ObservePolicy OnStart(content::NavigationHandle * navigation_handle,const GURL & currently_committed_url,bool started_in_foreground)22ForegroundDurationUKMObserver::OnStart( 23 content::NavigationHandle* navigation_handle, 24 const GURL& currently_committed_url, 25 bool started_in_foreground) { 26 currently_in_foreground_ = started_in_foreground; 27 if (currently_in_foreground_) { 28 last_time_shown_ = navigation_handle->NavigationStart(); 29 } 30 return CONTINUE_OBSERVING; 31 } 32 33 page_load_metrics::PageLoadMetricsObserver::ObservePolicy OnCommit(content::NavigationHandle * navigation_handle,ukm::SourceId source_id)34ForegroundDurationUKMObserver::OnCommit( 35 content::NavigationHandle* navigation_handle, 36 ukm::SourceId source_id) { 37 source_id_ = source_id; 38 return CONTINUE_OBSERVING; 39 } 40 41 page_load_metrics::PageLoadMetricsObserver::ObservePolicy FlushMetricsOnAppEnterBackground(const page_load_metrics::mojom::PageLoadTiming & timing)42ForegroundDurationUKMObserver::FlushMetricsOnAppEnterBackground( 43 const page_load_metrics::mojom::PageLoadTiming& timing) { 44 RecordUkmIfInForeground(base::TimeTicks::Now()); 45 return CONTINUE_OBSERVING; 46 } 47 48 page_load_metrics::PageLoadMetricsObserver::ObservePolicy OnHidden(const page_load_metrics::mojom::PageLoadTiming & timing)49ForegroundDurationUKMObserver::OnHidden( 50 const page_load_metrics::mojom::PageLoadTiming& timing) { 51 RecordUkmIfInForeground(base::TimeTicks::Now()); 52 return CONTINUE_OBSERVING; 53 } 54 page_load_metrics::PageLoadMetricsObserver::ObservePolicy OnShown()55ForegroundDurationUKMObserver::OnShown() { 56 if (!currently_in_foreground_) { 57 last_time_shown_ = base::TimeTicks::Now(); 58 currently_in_foreground_ = true; 59 } 60 return CONTINUE_OBSERVING; 61 } 62 OnComplete(const page_load_metrics::mojom::PageLoadTiming & timing)63void ForegroundDurationUKMObserver::OnComplete( 64 const page_load_metrics::mojom::PageLoadTiming& timing) { 65 // If we have a page_end_time, use it as our end time, else fall back to the 66 // current time. Note that we expect page_end_time.has_value() to always be 67 // true in OnComplete (the PageLoadTracker destructor is supposed to guarantee 68 // it), but we use Now() as a graceful fallback just in case. 69 base::TimeTicks end_time = GetDelegate().GetPageEndTime().has_value() 70 ? GetDelegate().GetNavigationStart() + 71 GetDelegate().GetPageEndTime().value() 72 : base::TimeTicks::Now(); 73 RecordUkmIfInForeground(end_time); 74 } 75 RecordUkmIfInForeground(base::TimeTicks end_time)76void ForegroundDurationUKMObserver::RecordUkmIfInForeground( 77 base::TimeTicks end_time) { 78 if (!currently_in_foreground_) 79 return; 80 base::TimeDelta foreground_duration = end_time - last_time_shown_; 81 ukm::builders::PageForegroundSession ukm_builder(source_id_); 82 ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get(); 83 ukm_builder.SetForegroundDuration(foreground_duration.InMilliseconds()); 84 RecordInputTimingMetrics(&ukm_builder); 85 ukm_builder.Record(ukm_recorder); 86 currently_in_foreground_ = false; 87 } 88 RecordInputTimingMetrics(ukm::builders::PageForegroundSession * ukm_builder)89void ForegroundDurationUKMObserver::RecordInputTimingMetrics( 90 ukm::builders::PageForegroundSession* ukm_builder) { 91 // TODO(hbsong): crbug.com/1105665 92 if (GetDelegate().GetPageInputTiming().total_input_delay.InMilliseconds() < 0) 93 return; 94 95 ukm_builder 96 ->SetForegroundNumInputEvents( 97 GetDelegate().GetPageInputTiming().num_input_events - 98 last_page_input_timing_.num_input_events) 99 .SetForegroundTotalInputDelay( 100 (GetDelegate().GetPageInputTiming().total_input_delay - 101 last_page_input_timing_.total_input_delay) 102 .InMilliseconds()) 103 .SetForegroundTotalAdjustedInputDelay( 104 (GetDelegate().GetPageInputTiming().total_adjusted_input_delay - 105 last_page_input_timing_.total_adjusted_input_delay) 106 .InMilliseconds()); 107 last_page_input_timing_ = GetDelegate().GetPageInputTiming(); 108 } 109