[go: nahoru, domu]

[iOS] Add Save to Photos metrics

This CL adds three histograms related to Save to Photos:

- `IOS.SaveToPhotos` records failure or success of the Save to Photos
  flow with cause of failure if any, and some additional info about
  actions performed by the user with the Photo once uploaded.
- `IOS.SaveToPhotos.AccountPicker` records how the account picker was
  used i.e. whether the user cancelled, or selected an account, or if
  the account picker was skipped.
- `IOS.SaveToPhotos.Settings` records the state of the Save to Photos
  default account preference. This will be recorded in a separate CL by
  the Photos service.

Low-Coverage-Reason: TRIVIAL_CHANGE logging statements
Bug: 1484607
Change-Id: Ib6a964e61870cc7cf652c4c1afad72b1a2b967ff
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4874920
Reviewed-by: Mark Cogan <marq@chromium.org>
Commit-Queue: Quentin Pubert <qpubert@google.com>
Reviewed-by: Olivier Robin <olivierrobin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1199542}
diff --git a/ios/chrome/browser/ui/save_to_photos/BUILD.gn b/ios/chrome/browser/ui/save_to_photos/BUILD.gn
index db1df7f..3b30e34 100644
--- a/ios/chrome/browser/ui/save_to_photos/BUILD.gn
+++ b/ios/chrome/browser/ui/save_to_photos/BUILD.gn
@@ -16,6 +16,7 @@
     "//components/strings:components_strings_grit",
     "//ios/chrome/app/strings:ios_strings_grit",
     "//ios/chrome/browser/photos",
+    "//ios/chrome/browser/photos:metrics",
     "//ios/chrome/browser/photos:photos_service_factory",
     "//ios/chrome/browser/shared/coordinator/alert",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
@@ -53,6 +54,7 @@
     "//components/strings:components_strings_grit",
     "//components/variations:test_support",
     "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/photos:metrics",
     "//ios/chrome/browser/photos:photos_service_factory",
     "//ios/chrome/browser/shared/coordinator/alert",
     "//ios/chrome/browser/shared/model/application_context",
diff --git a/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator.mm b/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator.mm
index dca93551..8ea4bd45 100644
--- a/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator.mm
+++ b/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator.mm
@@ -7,10 +7,13 @@
 #import <UIKit/UIKit.h>
 
 #import "base/ios/block_types.h"
+#import "base/metrics/histogram_functions.h"
+#import "base/metrics/histogram_macros.h"
 #import "base/strings/sys_string_conversions.h"
 #import "components/prefs/pref_service.h"
 #import "components/signin/public/base/signin_metrics.h"
 #import "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/photos/photos_metrics.h"
 #import "ios/chrome/browser/photos/photos_service.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
@@ -96,6 +99,9 @@
   // If the web state does not exist anymore (which can happen when the user
   // tries again), hide Save to Photos.
   if (!webState) {
+    base::UmaHistogramEnumeration(
+        kSaveToPhotosActionsHistogram,
+        SaveToPhotosActions::kFailureWebStateDestroyed);
     [self.delegate hideSaveToPhotos];
     return;
   }
@@ -125,6 +131,9 @@
 - (void)accountPickerDidSelectIdentity:(id<SystemIdentity>)identity
                           askEveryTime:(BOOL)askEveryTime {
   CHECK(identity);
+  base::UmaHistogramEnumeration(
+      kSaveToPhotosAccountPickerActionsHistogram,
+      SaveToPhotosAccountPickerActions::kSelectedIdentity);
   [self.delegate hideAccountPicker];
 
   // Memorize the account that was picked if the user does not want to be asked
@@ -138,11 +147,16 @@
 }
 
 - (void)accountPickerDidCancel {
+  base::UmaHistogramEnumeration(kSaveToPhotosAccountPickerActionsHistogram,
+                                SaveToPhotosAccountPickerActions::kCancelled);
   [self.delegate hideAccountPicker];
 }
 
 - (void)accountPickerWasHidden {
   if (!_identity) {
+    base::UmaHistogramEnumeration(
+        kSaveToPhotosActionsHistogram,
+        SaveToPhotosActions::kFailureUserCancelledWithAccountPicker);
     [self.delegate hideSaveToPhotos];
     return;
   }
@@ -150,6 +164,13 @@
 }
 
 - (void)storeKitWantsToHide {
+  BOOL photosAppInstalled =
+      [UIApplication.sharedApplication canOpenURL:GetGooglePhotosAppURL()];
+  base::UmaHistogramEnumeration(
+      kSaveToPhotosActionsHistogram,
+      photosAppInstalled
+          ? SaveToPhotosActions::kSuccessAndOpenStoreKitAndAppInstalled
+          : SaveToPhotosActions::kSuccessAndOpenStoreKitAndAppNotInstalled);
   [self.delegate hideSaveToPhotos];
 }
 
@@ -173,6 +194,8 @@
   // Although it is unlikely, the user could sign-out while the image data is
   // being fetched. Exit now if that happened.
   if (!_identityManager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
+    base::UmaHistogramEnumeration(kSaveToPhotosActionsHistogram,
+                                  SaveToPhotosActions::kFailureUserSignedOut);
     [self.delegate hideSaveToPhotos];
     return;
   }
@@ -186,6 +209,8 @@
   // Photos, use that default.
   if (defaultIdentity) {
     _identity = defaultIdentity;
+    base::UmaHistogramEnumeration(kSaveToPhotosAccountPickerActionsHistogram,
+                                  SaveToPhotosAccountPickerActions::kSkipped);
     [self tryUploadImage];
     return;
   }
@@ -240,6 +265,9 @@
 // Cancels the ongoing upload and exit hide Save to Photos.
 - (void)cancelUpload {
   _photosService->CancelUpload();
+  base::UmaHistogramEnumeration(
+      kSaveToPhotosActionsHistogram,
+      SaveToPhotosActions::kFailureUserCancelledWithSnackbar);
   [self.delegate hideSaveToPhotos];
 }
 
@@ -270,14 +298,19 @@
   NSString* tryAgainTitle = l10n_util::GetNSString(
       IDS_IOS_SAVE_TO_PHOTOS_THIS_FILE_COULD_NOT_BE_UPLOADED_TRY_AGAIN);
   __weak __typeof(self.delegate) weakDelegate = self.delegate;
-  [self.delegate showTryAgainOrCancelAlertWithTitle:title
-                                            message:message
-                                      tryAgainTitle:tryAgainTitle
-                                     tryAgainAction:tryAgain
-                                        cancelTitle:cancelTitle
-                                       cancelAction:^{
-                                         [weakDelegate hideSaveToPhotos];
-                                       }];
+  [self.delegate
+      showTryAgainOrCancelAlertWithTitle:title
+                                 message:message
+                           tryAgainTitle:tryAgainTitle
+                          tryAgainAction:tryAgain
+                             cancelTitle:cancelTitle
+                            cancelAction:^{
+                              base::UmaHistogramEnumeration(
+                                  kSaveToPhotosActionsHistogram,
+                                  SaveToPhotosActions::
+                                      kFailureUserCancelledWithAlert);
+                              [weakDelegate hideSaveToPhotos];
+                            }];
 }
 
 // Shows a snackbar to let the user know the Photos service started to upload
@@ -327,6 +360,8 @@
     [self openPhotosAppOrShowInStoreKit];
     return;
   }
+  base::UmaHistogramEnumeration(kSaveToPhotosActionsHistogram,
+                                SaveToPhotosActions::kSuccess);
   [self.delegate hideSaveToPhotos];
 }
 
@@ -348,6 +383,8 @@
                 openURL:photosURL
                 options:@{UIApplicationOpenURLOptionUniversalLinksOnly : @YES}
       completionHandler:nil];
+  base::UmaHistogramEnumeration(kSaveToPhotosActionsHistogram,
+                                SaveToPhotosActions::kSuccessAndOpenPhotosApp);
   [self.delegate hideSaveToPhotos];
 }
 
diff --git a/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator_unittest.mm b/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator_unittest.mm
index c7a6736..8a04aa31 100644
--- a/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/save_to_photos/save_to_photos_mediator_unittest.mm
@@ -8,11 +8,13 @@
 
 #import "base/functional/callback_forward.h"
 #import "base/strings/sys_string_conversions.h"
+#import "base/test/metrics/histogram_tester.h"
 #import "base/test/task_environment.h"
 #import "components/prefs/pref_service.h"
 #import "components/signin/public/base/consent_level.h"
 #import "components/signin/public/identity_manager/identity_test_utils.h"
 #import "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/photos/photos_metrics.h"
 #import "ios/chrome/browser/photos/photos_service_factory.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h"
@@ -196,6 +198,7 @@
   std::unique_ptr<web::FakeWebState> web_state_;
   id mock_application_;
   id<SystemIdentity> fake_identity_;
+  base::HistogramTester histogram_tester_;
 };
 
 // Tests that the mediator attempts to fetch the image data when started.
@@ -297,6 +300,10 @@
                      webState:web_state_.get()];
   task_environment_.RunUntilQuit();
 
+  histogram_tester_.ExpectUniqueSample(
+      kSaveToPhotosAccountPickerActionsHistogram,
+      SaveToPhotosAccountPickerActions::kSkipped, 1);
+
   // Test that the Photos service has already been called with the identity from
   // the prefs.
   EXPECT_FALSE(GetTestPhotosService()->IsAvailable());
@@ -341,6 +348,9 @@
   // Give the selected identity to the mediator and verify that the mediator
   // asked to hide the account picker.
   [mediator accountPickerDidSelectIdentity:fake_identity_ askEveryTime:YES];
+  histogram_tester_.ExpectUniqueSample(
+      kSaveToPhotosAccountPickerActionsHistogram,
+      SaveToPhotosAccountPickerActions::kSelectedIdentity, 1);
   EXPECT_OCMOCK_VERIFY(mock_save_to_photos_mediator_delegate);
 
   // Expect the the mediator will start uploading and show a snackbar when the
@@ -466,6 +476,10 @@
   // Simulate the snackbar was dismissed because of user interaction.
   savedCompletionAction(/* user_triggered= */ YES);
 
+  histogram_tester_.ExpectUniqueSample(
+      kSaveToPhotosActionsHistogram,
+      SaveToPhotosActions::kSuccessAndOpenPhotosApp, 1);
+
   [mediator disconnect];
 
   // Verify that the mediator detected that the app is installed and tried to
@@ -551,6 +565,9 @@
   OCMExpect([mock_save_to_photos_mediator_delegate hideSaveToPhotos]);
   [mediator storeKitWantsToHide];
   EXPECT_OCMOCK_VERIFY(mock_save_to_photos_mediator_delegate);
+  histogram_tester_.ExpectUniqueSample(
+      kSaveToPhotosActionsHistogram,
+      SaveToPhotosActions::kSuccessAndOpenStoreKitAndAppNotInstalled, 1);
 
   [mediator disconnect];
 }