[iOS][BWG] Add Gemini session duration histograms by session type.

Add IOS.Gemini.SessionLength.{SessionType} and
IOS.Gemini.SessionLength.FRE.{SessionType} UMA histograms to record
session duration segmented by session type, for both general and First
Run Experience sessions.

(cherry picked from commit 099849eb20d0458e72cf7e5ee90cab0a0a5893ff)

Bug: 435649967, 436844461, 436839273
Change-Id: If594b026cf22f2699f47b90bbf9669f0fcb0e0a2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6849516
Reviewed-by: Sebastien S-G <sebsg@chromium.org>
Commit-Queue: Ibrahim Kanouche <kanouche@google.com>
Auto-Submit: Ibrahim Kanouche <kanouche@google.com>
Reviewed-by: Nicolas MacBeth <nicolasmacbeth@google.com>
Cr-Original-Commit-Position: refs/heads/main@{#1501996}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6858552
Commit-Queue: Sebastien S-G <sebsg@chromium.org>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/7339@{#829}
Cr-Branched-From: 27be8b77710f4405fdfeb4ee946fcabb0f6c92b2-refs/heads/main@{#1496484}
diff --git a/ios/chrome/browser/intelligence/bwg/coordinator/bwg_mediator.mm b/ios/chrome/browser/intelligence/bwg/coordinator/bwg_mediator.mm
index dcc715e..9ceae14 100644
--- a/ios/chrome/browser/intelligence/bwg/coordinator/bwg_mediator.mm
+++ b/ios/chrome/browser/intelligence/bwg/coordinator/bwg_mediator.mm
@@ -88,11 +88,17 @@
   }
 
   _didPresentBWGFRE = [self.delegate maybePresentBWGFRE];
-  // Not presenting the FRE implies that the promo was shown and user consent
-  // was given which means we can navigate to the BWG overlay immediately.
-  if (!_didPresentBWGFRE) {
-    [self prepareBWGOverlay];
+  if (_didPresentBWGFRE) {
+    BwgTabHelper* BWGTabHelper = [self activeWebStateBWGTabHelper];
+    if (!BWGTabHelper) {
+      return;
+    }
+    BWGTabHelper->SetIsFirstRun(true);
+
+    return;
   }
+
+  [self prepareBWGOverlay];
 }
 
 #pragma mark - BWGConsentMutator
diff --git a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h
index 3d859696..fc2c362 100644
--- a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h
+++ b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h
@@ -64,6 +64,18 @@
 // UMA histogram key for IOS.Gemini.Session.Time.
 extern const char kBWGSessionTimeHistogram[];
 
+// UMA histogram key for IOS.Gemini.SessionLength.WithPrompt.
+extern const char kBWGSessionLengthWithPromptHistogram[];
+
+// UMA histogram key for IOS.Gemini.SessionLength.Abandoned.
+extern const char kBWGSessionLengthAbandonedHistogram[];
+
+// UMA histogram key for IOS.Gemini.SessionLength.FRE.WithPrompt.
+extern const char kBWGSessionLengthFREWithPromptHistogram[];
+
+// UMA histogram key for IOS.Gemini.SessionLength.FRE.Abandoned.
+extern const char kBWGSessionLengthFREWithAbandonedHistogram[];
+
 // Enum for the IOS.Gemini.FirstPrompt.SubmissionMethod histogram.
 // LINT.IfChange(IOSGeminiFirstPromptSubmissionMethod)
 enum class IOSGeminiFirstPromptSubmissionMethod {
@@ -89,9 +101,22 @@
 // UMA histogram key for IOS.Gemini.Response.Latency.WithoutContext.
 extern const char kResponseLatencyWithoutContextHistogram[];
 
+// Represents the completed Gemini session types.
+enum class IOSGeminiSessionType {
+  kUnknown = 0,
+  kWithPrompt = 1,
+  kAbandoned = 2,
+  kMaxValue = kAbandoned,
+};
+
 // Records the duration of a Gemini session.
 void RecordBWGSessionTime(base::TimeDelta session_duration);
 
+// Records the duration of a Gemini session by type of session.
+void RecordBWGSessionLengthByType(base::TimeDelta session_duration,
+                                  bool is_first_run,
+                                  IOSGeminiSessionType session_type);
+
 // Records when user sees the Gemini entry point impression.
 // Can be called once every 10 minutes to avoid spam logging.
 void RecordGeminiEntryPointImpression();
diff --git a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm
index 3d86bec..3af1779 100644
--- a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm
+++ b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm
@@ -35,6 +35,18 @@
 
 const char kStartupTimeNoFREHistogram[] = "IOS.Gemini.StartupTime.NotFirstRun";
 
+const char kBWGSessionLengthWithPromptHistogram[] =
+    "IOS.Gemini.SessionLength.WithPrompt";
+
+const char kBWGSessionLengthAbandonedHistogram[] =
+    "IOS.Gemini.SessionLength.Abandoned";
+
+const char kBWGSessionLengthFREWithPromptHistogram[] =
+    "IOS.Gemini.SessionLength.FRE.WithPrompt";
+
+const char kBWGSessionLengthFREAbandonedHistogram[] =
+    "IOS.Gemini.SessionLength.FRE.Abandoned";
+
 const char kBWGSessionTimeHistogram[] = "IOS.Gemini.Session.Time";
 
 const char kFirstPromptSubmissionMethodHistogram[] =
@@ -88,6 +100,38 @@
   base::UmaHistogramTimes(kBWGSessionTimeHistogram, session_duration);
 }
 
+void RecordBWGSessionLengthByType(base::TimeDelta session_duration,
+                                  bool is_first_run,
+                                  IOSGeminiSessionType session_type) {
+  if (is_first_run) {
+    switch (session_type) {
+      case IOSGeminiSessionType::kWithPrompt:
+        base::UmaHistogramTimes(kBWGSessionLengthFREWithPromptHistogram,
+                                session_duration);
+        break;
+      case IOSGeminiSessionType::kAbandoned:
+        base::UmaHistogramTimes(kBWGSessionLengthFREAbandonedHistogram,
+                                session_duration);
+        break;
+      case IOSGeminiSessionType::kUnknown:
+        break;
+    }
+  } else {
+    switch (session_type) {
+      case IOSGeminiSessionType::kWithPrompt:
+        base::UmaHistogramTimes(kBWGSessionLengthWithPromptHistogram,
+                                session_duration);
+        break;
+      case IOSGeminiSessionType::kAbandoned:
+        base::UmaHistogramTimes(kBWGSessionLengthAbandonedHistogram,
+                                session_duration);
+        break;
+      case IOSGeminiSessionType::kUnknown:
+        break;
+    }
+  }
+}
+
 void RecordGeminiEntryPointImpression() {
   base::TimeTicks now = base::TimeTicks::Now();
   base::TimeTicks& last_impression_time = GetLastGeminiImpressionTime();
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm b/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm
index 4b8adb6..d25bebb 100644
--- a/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm
+++ b/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm
@@ -92,10 +92,36 @@
                           serverID:(NSString*)serverID {
   [_BWGHandler dismissBWGFlowWithCompletion:nil];
   [self setSessionActive:NO clientID:clientID];
+
+  web::WebState* webState = [self webStateWithClientID:clientID];
+  if (!webState) {
+    return;
+  }
+  // Get the BWGTabHelper from the WebState.
+  BwgTabHelper* BWGTabHelper = BwgTabHelper::FromWebState(webState);
+  // WebState should always be valid as long as the tab is open.
+  if (!BWGTabHelper) {
+    // Early exit if no valid tab helper is found.
+    return;
+  }
+  bool isFirstSession = BWGTabHelper->GetIsFirstRun();
+  BWGTabHelper->SetIsFirstRun(false);
+
   // Record session duration.
   if (!_sessionStartTime.is_null()) {
     base::TimeDelta session_duration =
         base::TimeTicks::Now() - _sessionStartTime;
+
+    // Determine session type.
+    IOSGeminiSessionType session_type;
+    if (_hasSubmittedFirstPrompt) {
+      session_type = IOSGeminiSessionType::kWithPrompt;
+    } else {
+      session_type = IOSGeminiSessionType::kAbandoned;
+    }
+
+    RecordBWGSessionLengthByType(session_duration, isFirstSession,
+                                 session_type);
     RecordBWGSessionTime(session_duration);
     _sessionStartTime = base::TimeTicks();
   }
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.h b/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.h
index 4d52348..881ca97 100644
--- a/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.h
+++ b/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.h
@@ -61,6 +61,12 @@
   // Set the BWG commands handler, used to show/hide the BWG UI.
   void SetBwgCommandsHandler(id<BWGCommands> handler);
 
+  // Sets the state of `is_first_run`.
+  void SetIsFirstRun(bool is_first_run);
+
+  // Gets the state of `is_first_run`.
+  bool GetIsFirstRun();
+
   // WebStateObserver:
   void WasShown(web::WebState* web_state) override;
   void WasHidden(web::WebState* web_state) override;
@@ -116,6 +122,9 @@
   // The observation of the Web State.
   base::ScopedObservation<web::WebState, web::WebStateObserver>
       web_state_observation_{this};
+
+  // Whether this is a first run experience.
+  bool is_first_run_ = false;
 };
 
 #endif  // IOS_CHROME_BROWSER_INTELLIGENCE_BWG_MODEL_BWG_TAB_HELPER_H_
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.mm b/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.mm
index dfc8771..c77d399 100644
--- a/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.mm
+++ b/ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.mm
@@ -82,6 +82,14 @@
   }
 }
 
+void BwgTabHelper::SetIsFirstRun(bool is_first_run) {
+  is_first_run_ = is_first_run;
+}
+
+bool BwgTabHelper::GetIsFirstRun() {
+  return is_first_run_;
+}
+
 bool BwgTabHelper::GetIsBwgSessionActiveInBackground() {
   return is_bwg_session_active_in_background_;
 }
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 4001b79..49e9142 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -2175,6 +2175,39 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.Gemini.SessionLength.FRE.{SessionType}" units="ms"
+    expires_after="2026-02-13">
+  <owner>kanouche@google.com</owner>
+  <owner>bling-alchemy-eng@google.com</owner>
+  <summary>
+    The duration of a Gemini session that happens to be the first run, from when
+    the UI appears to when it is dismissed. This metric is segmented by the type
+    of sessions.
+  </summary>
+  <token key="SessionType">
+    <variant name="Abandoned"
+        summary="Sessions closed without any prompts submitted"/>
+    <variant name="WithPrompt"
+        summary="Sessions where the user submitted at least one prompt"/>
+  </token>
+</histogram>
+
+<histogram name="IOS.Gemini.SessionLength.{SessionType}" units="ms"
+    expires_after="2026-02-13">
+  <owner>kanouche@google.com</owner>
+  <owner>bling-alchemy-eng@google.com</owner>
+  <summary>
+    The duration of a Gemini session, from when the UI appears to when it is
+    dismissed. This metric is segmented by the type of sessions.
+  </summary>
+  <token key="SessionType">
+    <variant name="Abandoned"
+        summary="Sessions closed without any prompts submitted"/>
+    <variant name="WithPrompt"
+        summary="Sessions where the user submitted at least one prompt"/>
+  </token>
+</histogram>
+
 <histogram name="IOS.Gemini.StartupTime.{FirstRunBool}" units="ms"
     expires_after="2026-07-21">
   <owner>nicolasmacbeth@google.com</owner>