File: fedcm_modal_dialog_view.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (187 lines) | stat: -rw-r--r-- 6,359 bytes parent folder | download | duplicates (5)
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
// 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/views/webid/fedcm_modal_dialog_view.h"

#include <algorithm>

#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/url_formatter/elide_url.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/browser/identity_request_dialog_controller.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/table_layout.h"

namespace webid {
namespace {

gfx::Rect ComputePopupWindowBounds(gfx::Rect source_window_bounds) {
  constexpr int kPopupWindowWidth = 500;
  constexpr int kPopupWindowPreferredHeight = 600;
  int popup_window_height =
      std::min(kPopupWindowPreferredHeight,
               static_cast<int>(source_window_bounds.height() * 0.8));
  int x_coordinate = source_window_bounds.x() +
                     ((source_window_bounds.width() - kPopupWindowWidth) / 2);
  int y_coordinate =
      source_window_bounds.y() +
      ((source_window_bounds.height() - popup_window_height) / 2);
  return gfx::Rect(x_coordinate, y_coordinate, kPopupWindowWidth,
                   popup_window_height);
}

}  // namespace

FedCmModalDialogView::FedCmModalDialogView(
    content::WebContents* web_contents,
    FedCmModalDialogView::Observer* observer)
    : source_window_(web_contents), observer_(observer) {}

FedCmModalDialogView::~FedCmModalDialogView() = default;

content::WebContents* FedCmModalDialogView::ShowPopupWindow(
    const GURL& url,
    bool user_close_cancels_flow) {
  user_close_cancels_flow_ = user_close_cancels_flow;
  // TODO(crbug.com/333933012): This is a hack for testing purposes. Add a
  // factory method to initialize FedCmModalDialogView.
  if (popup_window_) {
    return popup_window_;
  }

  if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
    UMA_HISTOGRAM_ENUMERATION(
        "Blink.FedCm.IdpSigninStatus.ShowPopupWindowResult",
        ShowPopupWindowResult::kFailedByInvalidUrl);

    return nullptr;
  }

  content::OpenURLParams params(
      url, content::Referrer(), WindowOpenDisposition::NEW_POPUP,
      ui::PAGE_TRANSITION_AUTO_TOPLEVEL, /*is_renderer_initiated=*/false);
  popup_window_ = source_window_->GetDelegate()->OpenURLFromTab(
      source_window_, params, /*navigation_handle_callback=*/{});

  if (!popup_window_) {
    UMA_HISTOGRAM_ENUMERATION(
        "Blink.FedCm.IdpSigninStatus.ShowPopupWindowResult",
        ShowPopupWindowResult::kFailedForOtherReasons);

    return nullptr;
  }

  ResizeAndFocusPopupWindow();
  Observe(popup_window_);

  UMA_HISTOGRAM_ENUMERATION("Blink.FedCm.IdpSigninStatus.ShowPopupWindowResult",
                            ShowPopupWindowResult::kSuccess);

  return popup_window_;
}

void FedCmModalDialogView::ClosePopupWindow() {
  if (!popup_window_) {
    return;
  }

  std::string histogram_name =
      active_mode_sheet_type_ == webid::SheetType::LOADING
          ? "Blink.FedCm.Button.LoadingStatePopupInteraction"
          : "Blink.FedCm.Button.UseOtherAccountPopupInteraction";
  PopupInteraction metric =
      num_lost_focus_ > 0
          ? PopupInteraction::kLosesFocusAndIdpInitiatedClose
          : PopupInteraction::kNeverLosesFocusAndIdpInitiatedClose;
  if (!popup_interaction_metric_recorded_) {
    base::UmaHistogramEnumeration(histogram_name, metric);
    popup_interaction_metric_recorded_ = true;
  }

  // Store this in a local variable to avoid triggering the dangling pointer
  // detector.
  content::WebContents* popup = popup_window_;
  popup_window_ = nullptr;
  popup->Close();

  UMA_HISTOGRAM_ENUMERATION(
      "Blink.FedCm.IdpSigninStatus.ClosePopupWindowReason",
      FedCmModalDialogView::ClosePopupWindowReason::kIdpInitiatedClose);
}

void FedCmModalDialogView::ResizeAndFocusPopupWindow() {
  CHECK(popup_window_);

  gfx::Rect popup_window_bounds =
      ComputePopupWindowBounds(source_window_->GetContainerBounds());
  if (custom_y_position_) {
    popup_window_bounds.set_y(*custom_y_position_);
  }
  popup_window_->GetDelegate()->SetContentsBounds(popup_window_,
                                                  popup_window_bounds);
  popup_window_->GetDelegate()->ActivateContents(popup_window_);
}

void FedCmModalDialogView::WebContentsDestroyed() {
  std::string histogram_name =
      active_mode_sheet_type_ == webid::SheetType::LOADING
          ? "Blink.FedCm.Button.LoadingStatePopupInteraction"
          : "Blink.FedCm.Button.UseOtherAccountPopupInteraction";
  // Closing the window causes the focus to be lost so `num_lost_focus_` is at
  // least 1.
  PopupInteraction metric =
      num_lost_focus_ > 1
          ? PopupInteraction::kLosesFocusAndPopupWindowDestroyed
          : PopupInteraction::kNeverLosesFocusAndPopupWindowDestroyed;
  if (!popup_interaction_metric_recorded_) {
    base::UmaHistogramEnumeration(histogram_name, metric);
    popup_interaction_metric_recorded_ = true;
  }

  // The popup window is going away, make sure we don't keep a dangling pointer.
  // This should happen before notifying the observer, where `this` will be
  // destroyed.
  popup_window_ = nullptr;

  // Let the observer know that the pop-up window has been destroyed.
  if (observer_) {
    observer_->OnPopupWindowDestroyed();
  }

  UMA_HISTOGRAM_ENUMERATION(
      "Blink.FedCm.IdpSigninStatus.ClosePopupWindowReason",
      FedCmModalDialogView::ClosePopupWindowReason::kPopupWindowDestroyed);
}

void FedCmModalDialogView::SetCustomYPosition(int y) {
  custom_y_position_ = y;
}

void FedCmModalDialogView::SetActiveModeSheetType(webid::SheetType sheet_type) {
  active_mode_sheet_type_ = sheet_type;
}

bool FedCmModalDialogView::UserCloseCancelsFlow() {
  return user_close_cancels_flow_;
}

void FedCmModalDialogView::OnWebContentsLostFocus(
    content::RenderWidgetHost* render_widget_host) {
  ++num_lost_focus_;
}

void FedCmModalDialogView::ResetObserver() {
  observer_ = nullptr;
}

FedCmModalDialogView::Observer* FedCmModalDialogView::GetObserverForTesting() {
  return observer_;
}

}  // namespace webid