Index: chrome/browser/android/logo_bridge.cc |
diff --git a/chrome/browser/android/logo_bridge.cc b/chrome/browser/android/logo_bridge.cc |
index 8b24611abf5673c2f5d5822656c2494971bc0b04..6e4bcddc552dc0881c1b01a0e841caa9e69cb13d 100644 |
--- a/chrome/browser/android/logo_bridge.cc |
+++ b/chrome/browser/android/logo_bridge.cc |
@@ -77,12 +77,43 @@ ScopedJavaLocalRef<jobject> ConvertLogoToJavaObject( |
GURL(logo->metadata.animated_url)); |
} |
+class LoadTimeMetricRecorderImpl : public LogoBridge::LoadTimeMetricRecorder { |
+ public: |
+ LoadTimeMetricRecorderImpl() |
+ : logo_load_start_(base::TimeTicks::Now()), is_recording_(true) {} |
+ |
+ void Cancel() override { is_recording_ = false; } |
+ |
+ void Finish() override { |
+ if (!is_recording_) { |
+ return; |
+ } |
+ is_recording_ = false; |
+ UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.LogoShownTime", |
+ base::TimeTicks::Now() - logo_load_start_); |
+ } |
+ |
+ private: |
+ base::TimeTicks logo_load_start_; |
+ bool is_recording_; |
+ bool waiting_for_result_; |
+}; |
+ |
+class LoadTimeMetricRecorderNullImpl |
+ : public LogoBridge::LoadTimeMetricRecorder { |
+ public: |
+ LoadTimeMetricRecorderNullImpl() {} |
+ void Cancel() override {} |
+ void Finish() override {} |
+}; |
+ |
class LogoObserverAndroid : public search_provider_logos::LogoObserver { |
public: |
LogoObserverAndroid(base::WeakPtr<LogoBridge> logo_bridge, |
JNIEnv* env, |
jobject j_logo_observer) |
- : logo_bridge_(logo_bridge) { |
+ : logo_bridge_(logo_bridge), |
+ load_time_recorder_(new LoadTimeMetricRecorderImpl()) { |
j_logo_observer_.Reset(env, j_logo_observer); |
} |
@@ -96,6 +127,7 @@ class LogoObserverAndroid : public search_provider_logos::LogoObserver { |
JNIEnv* env = base::android::AttachCurrentThread(); |
ScopedJavaLocalRef<jobject> j_logo = ConvertLogoToJavaObject(env, logo); |
+ load_time_recorder_->Finish(); |
Java_LogoObserver_onLogoAvailable(env, j_logo_observer_, j_logo, |
from_cache); |
} |
@@ -107,6 +139,7 @@ class LogoObserverAndroid : public search_provider_logos::LogoObserver { |
// been destroyed. |
base::WeakPtr<LogoBridge> logo_bridge_; |
+ std::unique_ptr<LogoBridge::LoadTimeMetricRecorder> load_time_recorder_; |
base::android::ScopedJavaGlobalRef<jobject> j_logo_observer_; |
DISALLOW_COPY_AND_ASSIGN(LogoObserverAndroid); |
@@ -220,16 +253,28 @@ void LogoBridge::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
delete this; |
} |
+LogoBridge::LoadTimeMetricRecorder* LogoBridge::load_time_recorder() { |
+ if (!load_time_recorder_) { |
+ load_time_recorder_ = base::MakeUnique<LoadTimeMetricRecorderNullImpl>(); |
+ } |
+ return load_time_recorder_.get(); |
+} |
+ |
void LogoBridge::GetCurrentLogo(JNIEnv* env, |
const JavaParamRef<jobject>& obj, |
const JavaParamRef<jobject>& j_logo_observer) { |
if (doodle_service_) { |
j_logo_observer_.Reset(j_logo_observer); |
+ load_time_recorder_ = base::MakeUnique<LoadTimeMetricRecorderImpl>(); |
// Immediately hand out any current cached config. |
- DoodleConfigReceived(doodle_service_->config(), /*from_cache=*/true); |
+ bool cache_hit = |
+ DoodleConfigReceived(doodle_service_->config(), /*from_cache=*/true); |
// Also request a refresh, in case something changed. |
- doodle_service_->Refresh(); |
+ bool refresh_triggered = |
+ doodle_service_->Refresh() if (!cache_hit && !refresh_triggered) { |
+ load_time_recorder()->Cancel(); |
+ } |
} else { |
// |observer| is deleted in LogoObserverAndroid::OnObserverRemoved(). |
LogoObserverAndroid* observer = new LogoObserverAndroid( |
@@ -254,7 +299,7 @@ void LogoBridge::OnDoodleConfigUpdated( |
DoodleConfigReceived(maybe_doodle_config, /*from_cache=*/false); |
} |
-void LogoBridge::DoodleConfigReceived( |
+bool LogoBridge::DoodleConfigReceived( |
const base::Optional<doodle::DoodleConfig>& maybe_doodle_config, |
bool from_cache) { |
DCHECK(!j_logo_observer_.is_null()); |
@@ -263,8 +308,9 @@ void LogoBridge::DoodleConfigReceived( |
JNIEnv* env = base::android::AttachCurrentThread(); |
Java_LogoObserver_onLogoAvailable( |
env, j_logo_observer_, ScopedJavaLocalRef<jobject>(), from_cache); |
- return; |
+ return false; |
} |
+ load_time_recorder()->WaitForResult(); |
const doodle::DoodleConfig& doodle_config = maybe_doodle_config.value(); |
// If there is a CTA image, that means the main image is animated. Show the |
// non-animated CTA image first, and load the animated one only when the |
@@ -282,6 +328,7 @@ void LogoBridge::DoodleConfigReceived( |
image_url.spec(), image_url, |
base::Bind(&LogoBridge::DoodleImageFetched, base::Unretained(this), |
from_cache, on_click_url, alt_text, animated_image_url)); |
+ return true; |
} |
void LogoBridge::DoodleImageFetched( |
@@ -296,6 +343,7 @@ void LogoBridge::DoodleImageFetched( |
if (image.IsEmpty()) { |
DLOG(WARNING) << "Failed to download doodle image"; |
+ load_time_recorder()->Cancel(); |
Java_LogoObserver_onLogoAvailable(env, j_logo_observer_, |
ScopedJavaLocalRef<jobject>(), |
config_from_cache); |
@@ -305,6 +353,7 @@ void LogoBridge::DoodleImageFetched( |
UMA_HISTOGRAM_BOOLEAN("NewTabPage.LogoImageDownloaded", |
metadata.from_http_cache); |
+ load_time_recorder()->Finish(); |
ScopedJavaLocalRef<jobject> j_logo = MakeJavaLogo( |
env, image.ToSkBitmap(), on_click_url, alt_text, animated_image_url); |
Java_LogoObserver_onLogoAvailable(env, j_logo_observer_, j_logo, |