[Feed] Record whether viewed and opened articles are offline.
(cherry picked from commit e40a9f41ccc5f102ccf47b4267137900bc24f664)
Bug: 968593
Change-Id: I36e7e7b891e3a72492bee147444531b480107928
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1656248
Commit-Queue: Sky Malice <skym@chromium.org>
Reviewed-by: Steven Holte <holte@chromium.org>
Reviewed-by: Carlos Knippschild <carlosk@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#669405}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1661661
Reviewed-by: Sky Malice <skym@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#341}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
index de50cb6..fff0692 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
@@ -64,7 +64,8 @@
nativeOnContentViewed(mNativeFeedLoggingBridge, data.getPositionInStream(),
TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()),
- TimeUnit.SECONDS.toMillis(data.getTimeContentBecameAvailable()), data.getScore());
+ TimeUnit.SECONDS.toMillis(data.getTimeContentBecameAvailable()), data.getScore(),
+ data.isAvailableOffline());
}
@Override
@@ -103,7 +104,8 @@
recordUserAction(actionType);
nativeOnClientAction(mNativeFeedLoggingBridge,
feedActionToWindowOpenDisposition(actionType), data.getPositionInStream(),
- TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), data.getScore());
+ TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), data.getScore(),
+ data.isAvailableOffline());
}
@Override
@@ -368,12 +370,14 @@
private native long nativeInit(Profile profile);
private native void nativeDestroy(long nativeFeedLoggingBridge);
private native void nativeOnContentViewed(long nativeFeedLoggingBridge, int position,
- long publishedTimeMs, long timeContentBecameAvailableMs, float score);
+ long publishedTimeMs, long timeContentBecameAvailableMs, float score,
+ boolean isAvailableOffline);
private native void nativeOnContentDismissed(
long nativeFeedLoggingBridge, int position, String uri, boolean wasCommitted);
private native void nativeOnContentSwiped(long nativeFeedLoggingBridge);
private native void nativeOnClientAction(long nativeFeedLoggingBridge,
- int windowOpenDisposition, int position, long publishedTimeMs, float score);
+ int windowOpenDisposition, int position, long publishedTimeMs, float score,
+ boolean isAvailableOffline);
private native void nativeOnContentContextMenuOpened(
long nativeFeedLoggingBridge, int position, long publishedTimeMs, float score);
private native void nativeOnMoreButtonViewed(long nativeFeedLoggingBridge, int position);
diff --git a/chrome/browser/android/feed/feed_logging_bridge.cc b/chrome/browser/android/feed/feed_logging_bridge.cc
index 2a206f4..430fffa53 100644
--- a/chrome/browser/android/feed/feed_logging_bridge.cc
+++ b/chrome/browser/android/feed/feed_logging_bridge.cc
@@ -52,19 +52,21 @@
const jint j_position,
const jlong j_publishedTimeMs,
const jlong j_timeContentBecameAvailableMs,
- const jfloat j_score) {
+ const jfloat j_score,
+ const jboolean j_is_available_offline) {
feed_logging_metrics_->OnSuggestionShown(
j_position, base::Time::FromJavaTime(j_publishedTimeMs), j_score,
- base::Time::FromJavaTime(j_timeContentBecameAvailableMs));
+ base::Time::FromJavaTime(j_timeContentBecameAvailableMs),
+ j_is_available_offline);
}
void FeedLoggingBridge::OnContentDismissed(JNIEnv* j_env,
const JavaRef<jobject>& j_this,
const jint j_position,
const JavaRef<jstring>& j_url,
- const jboolean was_committed) {
+ const jboolean j_was_committed) {
feed_logging_metrics_->OnSuggestionDismissed(
- j_position, GURL(ConvertJavaStringToUTF8(j_env, j_url)), was_committed);
+ j_position, GURL(ConvertJavaStringToUTF8(j_env, j_url)), j_was_committed);
}
void FeedLoggingBridge::OnContentSwiped(JNIEnv* j_env,
@@ -77,9 +79,11 @@
const jint j_window_open_disposition,
const jint j_position,
const jlong j_publishedTimeMs,
- const jfloat j_score) {
+ const jfloat j_score,
+ const jboolean j_is_available_offline) {
feed_logging_metrics_->OnSuggestionOpened(
- j_position, base::Time::FromJavaTime(j_publishedTimeMs), j_score);
+ j_position, base::Time::FromJavaTime(j_publishedTimeMs), j_score,
+ j_is_available_offline);
feed_logging_metrics_->OnSuggestionWindowOpened(
static_cast<WindowOpenDisposition>(j_window_open_disposition));
}
@@ -106,18 +110,19 @@
feed_logging_metrics_->OnMoreButtonClicked(j_position);
}
-void FeedLoggingBridge::OnNotInterestedInSource(JNIEnv* j_env,
- const JavaRef<jobject>& j_this,
- const jint j_position,
- const jboolean was_committed) {
- feed_logging_metrics_->OnNotInterestedInSource(j_position, was_committed);
+void FeedLoggingBridge::OnNotInterestedInSource(
+ JNIEnv* j_env,
+ const JavaRef<jobject>& j_this,
+ const jint j_position,
+ const jboolean j_was_committed) {
+ feed_logging_metrics_->OnNotInterestedInSource(j_position, j_was_committed);
}
void FeedLoggingBridge::OnNotInterestedInTopic(JNIEnv* j_env,
const JavaRef<jobject>& j_this,
const jint j_position,
- const jboolean was_committed) {
- feed_logging_metrics_->OnNotInterestedInTopic(j_position, was_committed);
+ const jboolean j_was_committed) {
+ feed_logging_metrics_->OnNotInterestedInTopic(j_position, j_was_committed);
}
void FeedLoggingBridge::OnOpenedWithContent(JNIEnv* j_env,
@@ -232,14 +237,14 @@
void FeedLoggingBridge::OnContentTargetVisited(JNIEnv* j_env,
const JavaRef<jobject>& j_this,
const jlong visit_time_ms,
- const jboolean is_offline,
- const jboolean return_to_ntp) {
- if (is_offline) {
+ const jboolean j_is_offline,
+ const jboolean j_return_to_ntp) {
+ if (j_is_offline) {
feed_logging_metrics_->OnSuggestionOfflinePageVisited(
- base::TimeDelta::FromMilliseconds(visit_time_ms), return_to_ntp);
+ base::TimeDelta::FromMilliseconds(visit_time_ms), j_return_to_ntp);
} else {
feed_logging_metrics_->OnSuggestionArticleVisited(
- base::TimeDelta::FromMilliseconds(visit_time_ms), return_to_ntp);
+ base::TimeDelta::FromMilliseconds(visit_time_ms), j_return_to_ntp);
}
}
diff --git a/chrome/browser/android/feed/feed_logging_bridge.h b/chrome/browser/android/feed/feed_logging_bridge.h
index cbf8a1bb..5ec52f5 100644
--- a/chrome/browser/android/feed/feed_logging_bridge.h
+++ b/chrome/browser/android/feed/feed_logging_bridge.h
@@ -28,13 +28,14 @@
const jint j_position,
const jlong j_publishedTimeMs,
const jlong j_timeContentBecameAvailableMs,
- const jfloat j_score);
+ const jfloat j_score,
+ const jboolean j_is_available_offline);
void OnContentDismissed(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jint j_position,
const base::android::JavaRef<jstring>& j_url,
- const jboolean was_committed);
+ const jboolean j_was_committed);
void OnContentSwiped(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this);
@@ -44,7 +45,8 @@
const jint j_window_open_disposition,
const jint j_position,
const jlong j_publishedTimeMs,
- const jfloat j_score);
+ const jfloat j_score,
+ const jboolean j_is_available_offline);
void OnContentContextMenuOpened(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
@@ -63,12 +65,12 @@
void OnNotInterestedInSource(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jint j_position,
- const jboolean was_committed);
+ const jboolean j_was_committed);
void OnNotInterestedInTopic(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jint j_position,
- const jboolean was_committed);
+ const jboolean j_was_committed);
void OnOpenedWithContent(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
@@ -140,8 +142,8 @@
void OnContentTargetVisited(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jlong visit_time_ms,
- const jboolean is_offline,
- const jboolean return_to_ntp);
+ const jboolean j_is_offline,
+ const jboolean j_return_to_ntp);
void ReportScrolledAfterOpen(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this);
diff --git a/components/feed/core/feed_logging_metrics.cc b/components/feed/core/feed_logging_metrics.cc
index f42e042..f0392b8 100644
--- a/components/feed/core/feed_logging_metrics.cc
+++ b/components/feed/core/feed_logging_metrics.cc
@@ -433,7 +433,8 @@
void FeedLoggingMetrics::OnSuggestionShown(int position,
base::Time publish_date,
float score,
- base::Time fetch_date) {
+ base::Time fetch_date,
+ bool is_available_offline) {
UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.Shown", position,
kMaxSuggestionsTotal);
@@ -458,11 +459,15 @@
if (position == 0) {
RecordContentSuggestionsUsage(clock_->Now());
}
+
+ UMA_HISTOGRAM_BOOLEAN("ContentSuggestions.Feed.AvailableOffline.Shown",
+ is_available_offline);
}
void FeedLoggingMetrics::OnSuggestionOpened(int position,
base::Time publish_date,
- float score) {
+ float score,
+ bool is_available_offline) {
UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.Opened", position,
kMaxSuggestionsTotal);
@@ -478,6 +483,8 @@
RecordContentSuggestionsUsage(clock_->Now());
base::RecordAction(base::UserMetricsAction("Suggestions.Content.Opened"));
+ UMA_HISTOGRAM_BOOLEAN("ContentSuggestions.Feed.AvailableOffline.Opened",
+ is_available_offline);
}
void FeedLoggingMetrics::OnSuggestionWindowOpened(
diff --git a/components/feed/core/feed_logging_metrics.h b/components/feed/core/feed_logging_metrics.h
index c203e08..d5e09a388 100644
--- a/components/feed/core/feed_logging_metrics.h
+++ b/components/feed/core/feed_logging_metrics.h
@@ -51,9 +51,13 @@
void OnSuggestionShown(int position,
base::Time publish_date,
float score,
- base::Time fetch_date);
+ base::Time fetch_date,
+ bool is_available_offline);
- void OnSuggestionOpened(int position, base::Time publish_date, float score);
+ void OnSuggestionOpened(int position,
+ base::Time publish_date,
+ float score,
+ bool is_available_offline);
void OnSuggestionWindowOpened(WindowOpenDisposition disposition);
diff --git a/components/feed/core/feed_logging_metrics_unittest.cc b/components/feed/core/feed_logging_metrics_unittest.cc
index f4c3f45..5e585df 100644
--- a/components/feed/core/feed_logging_metrics_unittest.cc
+++ b/components/feed/core/feed_logging_metrics_unittest.cc
@@ -73,17 +73,21 @@
base::HistogramTester histogram_tester;
feed_logging_metrics()->OnSuggestionShown(
/*position=*/1, test_clock()->Now(),
- /*score=*/0.01f, test_clock()->Now() - base::TimeDelta::FromHours(2));
+ /*score=*/0.01f, test_clock()->Now() - base::TimeDelta::FromHours(2),
+ /*is_available_offline=*/false);
// Test corner cases for score.
feed_logging_metrics()->OnSuggestionShown(
/*position=*/2, test_clock()->Now(),
- /*score=*/0.0f, test_clock()->Now() - base::TimeDelta::FromHours(2));
+ /*score=*/0.0f, test_clock()->Now() - base::TimeDelta::FromHours(2),
+ /*is_available_offline=*/true);
feed_logging_metrics()->OnSuggestionShown(
/*position=*/3, test_clock()->Now(),
- /*score=*/1.0f, test_clock()->Now() - base::TimeDelta::FromHours(2));
+ /*score=*/1.0f, test_clock()->Now() - base::TimeDelta::FromHours(2),
+ /*is_available_offline=*/true);
feed_logging_metrics()->OnSuggestionShown(
/*position=*/4, test_clock()->Now(),
- /*score=*/8.0f, test_clock()->Now() - base::TimeDelta::FromHours(2));
+ /*score=*/8.0f, test_clock()->Now() - base::TimeDelta::FromHours(2),
+ /*is_available_offline=*/true);
EXPECT_THAT(
histogram_tester.GetAllSamples("NewTabPage.ContentSuggestions.Shown"),
@@ -98,6 +102,10 @@
base::Bucket(/*min=*/1, /*count=*/1),
base::Bucket(/*min=*/10, /*count=*/1),
base::Bucket(/*min=*/11, /*count=*/1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(
+ "ContentSuggestions.Feed.AvailableOffline.Shown"),
+ ElementsAre(base::Bucket(/*min=*/0, /*count=*/1),
+ base::Bucket(/*min=*/1, /*count=*/3)));
}
TEST_F(FeedLoggingMetricsTest, ShouldLogOnPageShown) {
@@ -112,16 +120,16 @@
base::HistogramTester histogram_tester;
feed_logging_metrics()->OnSuggestionOpened(
/*position=*/11, test_clock()->Now(),
- /*score=*/1.0f);
+ /*score=*/1.0f, /*is_available_offline=*/false);
feed_logging_metrics()->OnSuggestionOpened(
/*position=*/13, test_clock()->Now(),
- /*score=*/1.0f);
+ /*score=*/1.0f, /*is_available_offline=*/false);
feed_logging_metrics()->OnSuggestionOpened(
/*position=*/15, test_clock()->Now(),
- /*score=*/1.0f);
+ /*score=*/1.0f, /*is_available_offline=*/false);
feed_logging_metrics()->OnSuggestionOpened(
/*position=*/23, test_clock()->Now(),
- /*score=*/1.0f);
+ /*score=*/1.0f, /*is_available_offline=*/true);
EXPECT_THAT(
histogram_tester.GetAllSamples("NewTabPage.ContentSuggestions.Opened"),
@@ -129,6 +137,10 @@
base::Bucket(/*min=*/13, /*count=*/1),
base::Bucket(/*min=*/15, /*count=*/1),
base::Bucket(/*min=*/23, /*count=*/1)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(
+ "ContentSuggestions.Feed.AvailableOffline.Opened"),
+ ElementsAre(base::Bucket(/*min=*/0, /*count=*/3),
+ base::Bucket(/*min=*/1, /*count=*/1)));
}
TEST_F(FeedLoggingMetricsTest, ShouldLogOnSuggestionWindowOpened) {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9e2588a..1d49a96 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -19819,6 +19819,35 @@
</summary>
</histogram>
+<histogram name="ContentSuggestions.Feed.AvailableOffline.Opened"
+ enum="Boolean" expires_after="2020-07-01">
+ <owner>skym@chromium.org</owner>
+ <owner>carlosk@chromium.org</owner>
+ <summary>
+ When an article on the NTP is opened by the user, records whether it is
+ available offline. When an article is available offline, it will have an
+ offline badge in the UI on the NTP. Opening the article occurs when the user
+ navigates from the NTP to the article itself, which can be either in the
+ current tab or a new tab. Note that this is independent of whether the
+ article is actually opened as an offline page or not.
+ </summary>
+</histogram>
+
+<histogram name="ContentSuggestions.Feed.AvailableOffline.Shown" enum="Boolean"
+ expires_after="2020-07-01">
+ <owner>skym@chromium.org</owner>
+ <owner>carlosk@chromium.org</owner>
+ <summary>
+ Records whether an article on the NTP that is shown to the user was also
+ available offline. When an article is available offline, it will have an
+ offline badge in the UI. The initial offline status of the article is used
+ for this metric. While it is possible for the offline status to change while
+ the article is on screen, this metric will not be re-emitted. The criteria
+ for an article to be "shown" is for 2/3 of its vertical height to
+ be on screen for any amount of time.
+ </summary>
+</histogram>
+
<histogram name="ContentSuggestions.Feed.CommitMutationCount"
units="operations" expires_after="2019-10-01">
<owner>gangwu@chromium.org</owner>