File: mandatory_reauth_bubble_controller_impl.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (252 lines) | stat: -rw-r--r-- 9,987 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.h"

#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/autofill_bubble_base.h"
#include "chrome/browser/ui/autofill/autofill_bubble_handler.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/grit/generated_resources.h"
#include "components/autofill/core/browser/metrics/payments/mandatory_reauth_metrics.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_android.h"
#include "chrome/browser/mandatory_reauth/android/internal/jni/MandatoryReauthOptInBottomSheetControllerBridge_jni.h"
#else
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#endif  // BUILDFLAG(IS_ANDROID)

namespace autofill {

MandatoryReauthBubbleControllerImpl::MandatoryReauthBubbleControllerImpl(
    content::WebContents* web_contents)
    : AutofillBubbleControllerBase(web_contents),
      content::WebContentsUserData<MandatoryReauthBubbleControllerImpl>(
          *web_contents) {}

MandatoryReauthBubbleControllerImpl::~MandatoryReauthBubbleControllerImpl() {
#if BUILDFLAG(IS_ANDROID)
  // The view is closed by the AutofillBubbleControllerBase base class.
  if (java_controller_bridge_) {
    Java_MandatoryReauthOptInBottomSheetControllerBridge_destroy(
        base::android::AttachCurrentThread(), java_controller_bridge_);
  }
#endif
}

void MandatoryReauthBubbleControllerImpl::ShowBubble(
    base::OnceClosure accept_mandatory_reauth_callback,
    base::OnceClosure cancel_mandatory_reauth_callback,
    base::RepeatingClosure close_mandatory_reauth_callback) {
  if (bubble_view()) {
    return;
  }

  is_reshow_ = false;
  accept_mandatory_reauth_callback_ =
      std::move(accept_mandatory_reauth_callback);
  cancel_mandatory_reauth_callback_ =
      std::move(cancel_mandatory_reauth_callback);
  close_mandatory_reauth_callback_ = std::move(close_mandatory_reauth_callback);
  current_bubble_type_ = MandatoryReauthBubbleType::kOptIn;
  autofill_metrics::LogMandatoryReauthOptInBubbleOffer(
      autofill_metrics::MandatoryReauthOptInBubbleOffer::kShown,
      /*is_reshow=*/false);

  Show();
}

void MandatoryReauthBubbleControllerImpl::ReshowBubble() {
  // Don't show the bubble if it's already visible.
  if (bubble_view()) {
    return;
  }

  is_reshow_ = true;
  if (current_bubble_type_ == MandatoryReauthBubbleType::kOptIn) {
    // Callbacks are verified here, but not the following else if block, because
    // they can only be invoked from the opt-in bubble.
    CHECK(accept_mandatory_reauth_callback_ &&
          cancel_mandatory_reauth_callback_ &&
          close_mandatory_reauth_callback_);
    autofill_metrics::LogMandatoryReauthOptInBubbleOffer(
        autofill_metrics::MandatoryReauthOptInBubbleOffer::kShown,
        /*is_reshow=*/true);
  } else if (current_bubble_type_ == MandatoryReauthBubbleType::kConfirmation) {
    // The confirmation bubble cannot be minimized, so it's safe to increment
    // the shown metric when it is reshown, which is the way it transitions
    // from opt-in to confirmation.
    autofill_metrics::LogMandatoryReauthOptInConfirmationBubbleMetric(
        autofill_metrics::MandatoryReauthOptInConfirmationBubbleMetric::kShown);
  }

  Show();
}

std::u16string MandatoryReauthBubbleControllerImpl::GetWindowTitle() const {
  switch (current_bubble_type_) {
    case MandatoryReauthBubbleType::kOptIn:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_MANDATORY_REAUTH_OPT_IN_TITLE);
    case MandatoryReauthBubbleType::kConfirmation:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_MANDATORY_REAUTH_CONFIRMATION_TITLE);
    case MandatoryReauthBubbleType::kInactive:
      return std::u16string();
  }
}

std::u16string MandatoryReauthBubbleControllerImpl::GetAcceptButtonText()
    const {
  return l10n_util::GetStringUTF16(IDS_AUTOFILL_MANDATORY_REAUTH_OPT_IN_ACCEPT);
}

std::u16string MandatoryReauthBubbleControllerImpl::GetCancelButtonText()
    const {
  return l10n_util::GetStringUTF16(
      IDS_AUTOFILL_MANDATORY_REAUTH_OPT_IN_NO_THANKS);
}

std::u16string MandatoryReauthBubbleControllerImpl::GetExplanationText() const {
  switch (current_bubble_type_) {
    case MandatoryReauthBubbleType::kOptIn:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_MANDATORY_REAUTH_OPT_IN_EXPLANATION);
    case MandatoryReauthBubbleType::kConfirmation:
      return l10n_util::GetStringUTF16(
          IDS_AUTOFILL_MANDATORY_REAUTH_CONFIRMATION_EXPLANATION);
    case MandatoryReauthBubbleType::kInactive:
      return std::u16string();
  }
}

void MandatoryReauthBubbleControllerImpl::OnBubbleClosed(
    PaymentsUiClosedReason closed_reason) {
  set_bubble_view(nullptr);

// After resetting the raw pointer to the view in the base class, the Android
// view has to be deleted.
#if BUILDFLAG(IS_ANDROID)
  view_android_.reset();
#endif

  if (current_bubble_type_ == MandatoryReauthBubbleType::kOptIn) {
    autofill_metrics::MandatoryReauthOptInBubbleResult metric =
        autofill_metrics::MandatoryReauthOptInBubbleResult::kUnknown;
    switch (closed_reason) {
      case PaymentsUiClosedReason::kAccepted:
        metric = autofill_metrics::MandatoryReauthOptInBubbleResult::kAccepted;
        // We must set the `current_bubble_type_` before running the callback,
        // as the callback is not always asynchronous (for example, in the case
        // where the user is automatically authenticated due to being within a
        // certain grace period of time from the previous authentication). In
        // these cases, we might re-show the opt-in bubble again if we don't set
        // the `current_bubble_type_` first.
        current_bubble_type_ = MandatoryReauthBubbleType::kConfirmation;
        std::move(accept_mandatory_reauth_callback_).Run();
        break;
      case PaymentsUiClosedReason::kCancelled:
        metric = autofill_metrics::MandatoryReauthOptInBubbleResult::kCancelled;
        // We must set the `current_bubble_type_` before running the callback,
        // as the callback is not always asynchronous (for example, in the case
        // where the user is automatically authenticated due to being within a
        // certain grace period of time from the previous authentication). In
        // these cases, we might re-show the opt-in bubble again if we don't set
        // the `current_bubble_type_` first.
        current_bubble_type_ = MandatoryReauthBubbleType::kInactive;
        std::move(cancel_mandatory_reauth_callback_).Run();
        break;
      case PaymentsUiClosedReason::kClosed:
        metric = autofill_metrics::MandatoryReauthOptInBubbleResult::kClosed;
        close_mandatory_reauth_callback_.Run();
        break;
      case PaymentsUiClosedReason::kNotInteracted:
        metric =
            autofill_metrics::MandatoryReauthOptInBubbleResult::kNotInteracted;
        break;
      case PaymentsUiClosedReason::kLostFocus:
        metric = autofill_metrics::MandatoryReauthOptInBubbleResult::kLostFocus;
        break;
      case PaymentsUiClosedReason::kUnknown:
        metric = autofill_metrics::MandatoryReauthOptInBubbleResult::kUnknown;
        break;
    }
    DCHECK(metric !=
           autofill_metrics::MandatoryReauthOptInBubbleResult::kUnknown);
    autofill_metrics::LogMandatoryReauthOptInBubbleResult(metric, is_reshow_);
  } else {
    current_bubble_type_ = MandatoryReauthBubbleType::kInactive;
  }

  UpdatePageActionIcon();
}

#if BUILDFLAG(IS_ANDROID)
void MandatoryReauthBubbleControllerImpl::OnClosed(JNIEnv* env,
                                                   jint closed_reason) {
  OnBubbleClosed(static_cast<autofill::PaymentsUiClosedReason>(closed_reason));
}
#endif

AutofillBubbleBase* MandatoryReauthBubbleControllerImpl::GetBubbleView() {
  return bubble_view();
}

bool MandatoryReauthBubbleControllerImpl::IsIconVisible() {
  return current_bubble_type_ != MandatoryReauthBubbleType::kInactive;
}

MandatoryReauthBubbleType MandatoryReauthBubbleControllerImpl::GetBubbleType()
    const {
  return current_bubble_type_;
}

PageActionIconType
MandatoryReauthBubbleControllerImpl::GetPageActionIconType() {
  return PageActionIconType::kMandatoryReauth;
}

void MandatoryReauthBubbleControllerImpl::DoShowBubble() {
#if BUILDFLAG(IS_ANDROID)
  // The Android view's lifecycle is managed by this controller. We also
  // register it as a raw pointer in the base class to use its closing logic
  // when this controller wants to close it.
  view_android_ =
      MandatoryReauthOptInViewAndroid::CreateAndShow(web_contents(), this);
  if (!view_android_) {
    java_controller_bridge_.Reset();
    return;
  }
  set_bubble_view(view_android_.get());
#else
  Browser* browser = chrome::FindBrowserWithTab(web_contents());
  AutofillBubbleHandler* autofill_bubble_handler =
      browser->window()->GetAutofillBubbleHandler();
  set_bubble_view(autofill_bubble_handler->ShowMandatoryReauthBubble(
      web_contents(), this, /*is_user_gesture=*/false, current_bubble_type_));
#endif  // BUILDFLAG(IS_ANDROID)
}

#if BUILDFLAG(IS_ANDROID)
base::android::ScopedJavaLocalRef<jobject>
MandatoryReauthBubbleControllerImpl::GetJavaControllerBridge() {
  if (!java_controller_bridge_) {
    java_controller_bridge_ =
        Java_MandatoryReauthOptInBottomSheetControllerBridge_create(
            base::android::AttachCurrentThread(),
            reinterpret_cast<intptr_t>(this));
  }
  return base::android::ScopedJavaLocalRef<jobject>(java_controller_bridge_);
}
#endif

WEB_CONTENTS_USER_DATA_KEY_IMPL(MandatoryReauthBubbleControllerImpl);

}  // namespace autofill