Skip to content

Commit 48eaa14

Browse files
pkotwiczChromium LUCI CQ
authored and
Chromium LUCI CQ
committed
[FedCM] Add metric for reason account picker was dismissed
This CL adds a UMA histogram which tracks the reason that the FedCM account picker was dismissed. BUG=1343857 Change-Id: Ia2f1d27d3c811149b8d1ad98cf8ac2f740191c70 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3774541 Reviewed-by: Yi Gu <yigu@chromium.org> Reviewed-by: John Abd-El-Malek <jam@chromium.org> Commit-Queue: Peter Kotwicz <pkotwicz@chromium.org> Cr-Commit-Position: refs/heads/main@{#1027117}
1 parent 959c5c2 commit 48eaa14

26 files changed

+234
-140
lines changed

chrome/browser/ui/android/webid/BUILD.gn

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ android_library("public_java") {
1313
"//url:gurl_java",
1414
]
1515

16+
srcjar_deps = [ ":java_enums_srcjar" ]
17+
1618
sources = [
1719
"java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionComponent.java",
1820
"java/src/org/chromium/chrome/browser/ui/android/webid/data/Account.java",
@@ -29,3 +31,7 @@ generate_jni("jni_headers") {
2931
"java/src/org/chromium/chrome/browser/ui/android/webid/data/IdentityProviderMetadata.java",
3032
]
3133
}
34+
35+
java_cpp_enum("java_enums_srcjar") {
36+
sources = [ "//content/public/browser/identity_request_dialog_controller.h" ]
37+
}

chrome/browser/ui/android/webid/account_selection_view_android.cc

+6-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "chrome/browser/ui/android/webid/jni_headers/ClientIdMetadata_jni.h"
1616
#include "chrome/browser/ui/android/webid/jni_headers/IdentityProviderMetadata_jni.h"
1717
#include "chrome/browser/ui/webid/account_selection_view.h"
18+
#include "content/public/browser/identity_request_dialog_controller.h"
1819
#include "ui/android/color_utils_android.h"
1920
#include "ui/android/view_android.h"
2021
#include "ui/android/window_android.h"
@@ -28,6 +29,7 @@ using base::android::ConvertJavaStringToUTF8;
2829
using base::android::ConvertUTF8ToJavaString;
2930
using base::android::JavaParamRef;
3031
using base::android::ScopedJavaLocalRef;
32+
using DismissReason = content::IdentityRequestDialogController::DismissReason;
3133

3234
namespace {
3335

@@ -123,7 +125,7 @@ void AccountSelectionViewAndroid::Show(
123125
// It's possible that the constructor cannot access the bottom sheet clank
124126
// component. That case may be temporary but we can't let users in a
125127
// waiting state so report that AccountSelectionView is dismissed instead.
126-
delegate_->OnDismiss(/* should_embargo=*/false);
128+
delegate_->OnDismiss(DismissReason::OTHER);
127129
return;
128130
}
129131

@@ -152,13 +154,13 @@ void AccountSelectionViewAndroid::OnAccountSelected(
152154
env, account_string_fields, account_picture_url, is_sign_in));
153155
}
154156

155-
void AccountSelectionViewAndroid::OnDismiss(JNIEnv* env, bool should_embargo) {
156-
delegate_->OnDismiss(should_embargo);
157+
void AccountSelectionViewAndroid::OnDismiss(JNIEnv* env, jint dismiss_reason) {
158+
delegate_->OnDismiss(static_cast<DismissReason>(dismiss_reason));
157159
}
158160

159161
void AccountSelectionViewAndroid::OnAutoSignInCancelled(JNIEnv* env) {
160162
// TODO(yigu): Alternatively we could fall back to manual sign in flow.
161-
delegate_->OnDismiss(/*should_embargo=*/false);
163+
delegate_->OnDismiss(DismissReason::OTHER);
162164
}
163165

164166
bool AccountSelectionViewAndroid::RecreateJavaObject() {

chrome/browser/ui/android/webid/account_selection_view_android.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class AccountSelectionViewAndroid : public AccountSelectionView {
3232
const base::android::JavaParamRef<jobjectArray>& account_string_fields,
3333
const base::android::JavaParamRef<jobject>& account_picture_url,
3434
bool is_sign_in);
35-
void OnDismiss(JNIEnv* env, bool should_embargo);
35+
void OnDismiss(JNIEnv* env, jint dismiss_reason);
3636
void OnAutoSignInCancelled(JNIEnv* env);
3737

3838
private:

chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.chromium.chrome.browser.ui.android.webid.data.IdentityProviderMetadata;
1717
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
1818
import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
19+
import org.chromium.content.webid.IdentityRequestDialogDismissReason;
1920
import org.chromium.ui.base.WindowAndroid;
2021
import org.chromium.url.GURL;
2122

@@ -91,9 +92,9 @@ private void showAccounts(String rpForDisplay, String idpForDisplay, Account[] a
9192
}
9293

9394
@Override
94-
public void onDismissed(boolean shouldEmbargo) {
95+
public void onDismissed(@IdentityRequestDialogDismissReason int dismissReason) {
9596
if (mNativeView != 0) {
96-
AccountSelectionBridgeJni.get().onDismiss(mNativeView, shouldEmbargo);
97+
AccountSelectionBridgeJni.get().onDismiss(mNativeView, dismissReason);
9798
}
9899
}
99100

@@ -122,7 +123,8 @@ public void onAutoSignInCancelled() {
122123
interface Natives {
123124
void onAccountSelected(long nativeAccountSelectionViewAndroid, String[] accountFields,
124125
GURL accountPictureUrl, boolean isSignedIn);
125-
void onDismiss(long nativeAccountSelectionViewAndroid, boolean shouldEmbargo);
126+
void onDismiss(long nativeAccountSelectionViewAndroid,
127+
@IdentityRequestDialogDismissReason int dismissReason);
126128
void onAutoSignInCancelled(long nativeAccountSelectionViewAndroid);
127129
}
128130
}

chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.chromium.chrome.browser.ui.android.webid.data.IdentityProviderMetadata;
6060
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
6161
import org.chromium.components.image_fetcher.ImageFetcher;
62+
import org.chromium.content.webid.IdentityRequestDialogDismissReason;
6263
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
6364
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
6465
import org.chromium.ui.modelutil.PropertyKey;
@@ -341,7 +342,7 @@ public void testCallsDelegateAndHidesOnSingleAccountDismiss() {
341342
mMediator.showAccounts(TEST_ETLD_PLUS_ONE, TEST_ETLD_PLUS_ONE_1, Arrays.asList(ANA),
342343
IDP_METADATA, CLIENT_ID_METADATA, false);
343344
pressBack();
344-
verify(mMockDelegate).onDismissed(/*shouldEmbargo=*/false);
345+
verify(mMockDelegate).onDismissed(IdentityRequestDialogDismissReason.OTHER);
345346
assertTrue(mMediator.wasDismissed());
346347
}
347348

@@ -351,7 +352,7 @@ public void testCallsDelegateAndHidesOnAccountPickerDismiss() {
351352
mMediator.showAccounts(TEST_ETLD_PLUS_ONE, TEST_ETLD_PLUS_ONE_1, Arrays.asList(ANA, BOB),
352353
IDP_METADATA, CLIENT_ID_METADATA, false);
353354
pressBack();
354-
verify(mMockDelegate).onDismissed(/*shouldEmbargo=*/false);
355+
verify(mMockDelegate).onDismissed(IdentityRequestDialogDismissReason.OTHER);
355356
assertTrue(mMediator.wasDismissed());
356357
}
357358

@@ -444,7 +445,7 @@ public void testCallsDelegateAndHidesOnlyOnceWithAutoSignIn() {
444445
mMediator.showAccounts(TEST_ETLD_PLUS_ONE, TEST_ETLD_PLUS_ONE_1, Arrays.asList(ANA),
445446
IDP_METADATA, CLIENT_ID_METADATA, true);
446447
pressBack();
447-
verify(mMockDelegate).onDismissed(/*shouldEmbargo=*/false);
448+
verify(mMockDelegate).onDismissed(IdentityRequestDialogDismissReason.OTHER);
448449
verifyNoMoreInteractions(mMockDelegate);
449450
assertTrue(mMediator.wasDismissed());
450451
// The delayed task should not call delegate after user dismissing.
@@ -486,7 +487,7 @@ public void testShowVerifySheet() {
486487
private void pressBack() {
487488
if (mBottomSheetContent.handleBackPress()) return;
488489

489-
mMediator.onDismissed(/*shouldEmbargo=*/false);
490+
mMediator.onDismissed(IdentityRequestDialogDismissReason.OTHER);
490491
}
491492

492493
private int countAllItems() {

chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionIntegrationTest.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
5959
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState;
6060
import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
61+
import org.chromium.content.webid.IdentityRequestDialogDismissReason;
6162
import org.chromium.url.GURL;
6263
import org.chromium.url.JUnitTestGURLs;
6364

@@ -143,7 +144,7 @@ public void testBackDismissesAndCallsCallback() {
143144

144145
Espresso.pressBack();
145146

146-
waitForEvent(mMockBridge).onDismissed(/*shouldEmbargo=*/false);
147+
waitForEvent(mMockBridge).onDismissed(IdentityRequestDialogDismissReason.OTHER);
147148
verify(mMockBridge, never()).onAccountSelected(any());
148149
}
149150

@@ -209,7 +210,7 @@ public void testDismissedIfUnableToShow() throws Exception {
209210
mAccountSelection.showAccounts(EXAMPLE_ETLD_PLUS_ONE, TEST_ETLD_PLUS_ONE_1,
210211
Arrays.asList(ANA, BOB), IDP_METADATA, mClientIdMetadata, false);
211212
});
212-
waitForEvent(mMockBridge).onDismissed(/*shouldEmbargo=*/false);
213+
waitForEvent(mMockBridge).onDismissed(IdentityRequestDialogDismissReason.OTHER);
213214
verify(mMockBridge, never()).onAccountSelected(any());
214215
Espresso.onView(withText("Another bottom sheet content")).check(matches(isDisplayed()));
215216

chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java

+11-9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
2828
import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
2929
import org.chromium.components.image_fetcher.ImageFetcher;
30+
import org.chromium.content.webid.IdentityRequestDialogDismissReason;
3031
import org.chromium.ui.KeyboardVisibilityDelegate;
3132
import org.chromium.ui.KeyboardVisibilityDelegate.KeyboardVisibilityListener;
3233
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
@@ -77,7 +78,7 @@ class AccountSelectionMediator {
7778
@Override
7879
public void keyboardVisibilityChanged(boolean isShowing) {
7980
if (isShowing) {
80-
onDismissed(/*shouldEmbargo=*/false);
81+
onDismissed(IdentityRequestDialogDismissReason.VIRTUAL_KEYBOARD_SHOWN);
8182
}
8283
}
8384
};
@@ -106,10 +107,11 @@ public void onSheetClosed(@BottomSheetController.StateChangeReason int reason) {
106107

107108
if (mWasDismissed) return;
108109

109-
// Dismissing the FedCM bottom sheet via {@link StateChangeReason#SWIPE} is more
110-
// intentional than other methods such as {@link StateChangeReason#OMNIBOX_FOCUS}.
111-
onDismissed(/*shouldEmbargo=*/(
112-
reason == BottomSheetController.StateChangeReason.SWIPE));
110+
@IdentityRequestDialogDismissReason
111+
int dismissReason = (reason == BottomSheetController.StateChangeReason.SWIPE)
112+
? IdentityRequestDialogDismissReason.SWIPE
113+
: IdentityRequestDialogDismissReason.OTHER;
114+
onDismissed(dismissReason);
113115
}
114116
};
115117
}
@@ -130,7 +132,7 @@ private void handleBackPress() {
130132
private PropertyModel createHeaderItem(HeaderType headerType, String rpForDisplay,
131133
String idpForDisplay, IdentityProviderMetadata idpMetadata) {
132134
Runnable closeOnClickRunnable = () -> {
133-
onDismissed(/*shouldEmbargo=*/true);
135+
onDismissed(IdentityRequestDialogDismissReason.CLOSE_BUTTON);
134136

135137
RecordHistogram.recordBooleanHistogram(
136138
"Blink.FedCm.CloseVerifySheet.Android", mHeaderType == HeaderType.VERIFY);
@@ -273,7 +275,7 @@ private void showContent() {
273275
KeyboardVisibilityDelegate.getInstance().addKeyboardVisibilityListener(
274276
mKeyboardVisibilityListener);
275277
} else {
276-
onDismissed(/*shouldEmbargo=*/false);
278+
onDismissed(IdentityRequestDialogDismissReason.OTHER);
277279
}
278280
}
279281

@@ -329,9 +331,9 @@ void onAccountSelected(Account selectedAccount) {
329331
updateBackPressBehavior();
330332
}
331333

332-
void onDismissed(boolean shouldEmbargo) {
334+
void onDismissed(@IdentityRequestDialogDismissReason int dismissReason) {
333335
hideContent();
334-
mDelegate.onDismissed(shouldEmbargo);
336+
mDelegate.onDismissed(dismissReason);
335337
}
336338

337339
void onAutoSignInCancelled() {

chrome/browser/ui/android/webid/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionComponent.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.chromium.chrome.browser.ui.android.webid.data.Account;
88
import org.chromium.chrome.browser.ui.android.webid.data.ClientIdMetadata;
99
import org.chromium.chrome.browser.ui.android.webid.data.IdentityProviderMetadata;
10+
import org.chromium.content.webid.IdentityRequestDialogDismissReason;
1011

1112
import java.util.List;
1213

@@ -30,7 +31,7 @@ interface Delegate {
3031
* Called when the user dismisses the AccountSelectionComponent. Not called if a suggestion
3132
* was selected.
3233
*/
33-
void onDismissed(boolean shouldEmbargo);
34+
void onDismissed(@IdentityRequestDialogDismissReason int dismissReason);
3435

3536
/**
3637
* Called when the user cancels auto sign in.

chrome/browser/ui/views/webid/fake_delegate.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ class FakeDelegate : public AccountSelectionView::Delegate {
1818

1919
void OnAccountSelected(const Account& account) override {}
2020

21-
void OnDismiss(bool should_embargo) override {}
21+
void OnDismiss(content::IdentityRequestDialogController::DismissReason
22+
dismiss_reason) override {}
2223

2324
// AccountSelectionView::Delegate
2425
gfx::NativeView GetNativeView() override;

chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc

+11-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "chrome/browser/ui/views/frame/top_container_view.h"
1212
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
1313

14+
using DismissReason = content::IdentityRequestDialogController::DismissReason;
15+
1416
// static
1517
std::unique_ptr<AccountSelectionView> AccountSelectionView::Create(
1618
AccountSelectionView::Delegate* delegate) {
@@ -106,9 +108,12 @@ void FedCmAccountSelectionView::OnTabStripModelChanged(
106108
}
107109

108110
void FedCmAccountSelectionView::OnWidgetDestroying(views::Widget* widget) {
109-
bool should_embargo = (bubble_widget_->closed_reason() ==
110-
views::Widget::ClosedReason::kCloseButtonClicked);
111-
OnDismiss(should_embargo);
111+
DismissReason dismiss_reason =
112+
(bubble_widget_->closed_reason() ==
113+
views::Widget::ClosedReason::kCloseButtonClicked)
114+
? DismissReason::CLOSE_BUTTON
115+
: DismissReason::OTHER;
116+
OnDismiss(dismiss_reason);
112117
}
113118

114119
void FedCmAccountSelectionView::OnAccountSelected(
@@ -122,16 +127,16 @@ void FedCmAccountSelectionView::Close() {
122127
return;
123128

124129
bubble_widget_->Close();
125-
OnDismiss(/*should_embargo=*/false);
130+
OnDismiss(DismissReason::OTHER);
126131
}
127132

128-
void FedCmAccountSelectionView::OnDismiss(bool should_embargo) {
133+
void FedCmAccountSelectionView::OnDismiss(DismissReason dismiss_reason) {
129134
if (!bubble_widget_)
130135
return;
131136

132137
bubble_widget_->RemoveObserver(this);
133138
bubble_widget_.reset();
134139

135140
if (notify_delegate_of_dismiss_)
136-
delegate_->OnDismiss(should_embargo);
141+
delegate_->OnDismiss(dismiss_reason);
137142
}

chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ class FedCmAccountSelectionView : public AccountSelectionView,
5858
// Closes the widget and notifies the delegate.
5959
void Close();
6060

61-
// Notify the delegate that the widget was closed.
62-
// |should_embargo| indicates whether the FedCM API should be embargoed due
63-
// to the user explicitly dismissing the dialog.
64-
void OnDismiss(bool should_embargo);
61+
// Notify the delegate that the widget was closed with reason
62+
// `dismiss_reason`.
63+
void OnDismiss(
64+
content::IdentityRequestDialogController::DismissReason dismiss_reason);
6565

6666
// Whether to notify the delegate when the widget is closed.
6767
bool notify_delegate_of_dismiss_{true};

chrome/browser/ui/webid/account_selection_view.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ class AccountSelectionView {
2828
virtual ~Delegate() = default;
2929
// Informs the controller that the user has made a selection.
3030
virtual void OnAccountSelected(const Account& account) = 0;
31-
// Informs the controller that the user has dismissed the sheet.
32-
// |should_embargo| indicates whether the FedCM API should be embargoed due
33-
// to the user explicitly dismissing the FedCM account picker.
34-
virtual void OnDismiss(bool should_embargo) = 0;
31+
// Informs the controller that the user has dismissed the sheet with reason
32+
// `dismiss_reason`.
33+
virtual void OnDismiss(
34+
content::IdentityRequestDialogController::DismissReason
35+
dismiss_reason) = 0;
3536
// The web page view containing the focused field.
3637
virtual gfx::NativeView GetNativeView() = 0;
3738
// The WebContents for the page.

chrome/browser/ui/webid/identity_dialog_controller.cc

+10-6
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ void IdentityDialogController::ShowAccountsDialog(
5252
const content::IdentityProviderMetadata& idp_metadata,
5353
const content::ClientIdData& client_data,
5454
content::IdentityRequestAccount::SignInMode sign_in_mode,
55-
AccountSelectionCallback on_selected) {
55+
AccountSelectionCallback on_selected,
56+
DismissCallback dismiss_callback) {
5657
// IDP scheme is expected to always be `https://`.
5758
CHECK(idp_url.SchemeIs(url::kHttpsScheme));
5859
rp_web_contents_ = rp_web_contents;
5960
on_account_selection_ = std::move(on_selected);
61+
on_dismiss_ = std::move(dismiss_callback);
6062
std::string rp_for_display =
6163
FormatUrlForDisplay(rp_web_contents_->GetLastCommittedURL());
6264
std::string idp_for_display = FormatUrlForDisplay(idp_url);
@@ -68,18 +70,20 @@ void IdentityDialogController::ShowAccountsDialog(
6870
}
6971

7072
void IdentityDialogController::OnAccountSelected(const Account& account) {
73+
on_dismiss_.Reset();
7174
std::move(on_account_selection_)
7275
.Run(account.id,
7376
account.login_state ==
74-
content::IdentityRequestAccount::LoginState::kSignIn,
75-
/* should_embargo=*/false);
77+
content::IdentityRequestAccount::LoginState::kSignIn);
7678
}
7779

78-
void IdentityDialogController::OnDismiss(bool should_embargo) {
80+
void IdentityDialogController::OnDismiss(DismissReason dismiss_reason) {
7981
// |OnDismiss| can be called after |OnAccountSelected| which sets the callback
8082
// to null.
81-
if (on_account_selection_)
82-
std::move(on_account_selection_).Run(std::string(), false, should_embargo);
83+
if (on_dismiss_) {
84+
on_account_selection_.Reset();
85+
std::move(on_dismiss_).Run(dismiss_reason);
86+
}
8387
}
8488

8589
gfx::NativeView IdentityDialogController::GetNativeView() {

0 commit comments

Comments
 (0)