[go: up one dir, main page]

[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 &quot;shown&quot; 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>