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 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_VIEW_H_
#include <optional>
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "build/buildflag.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/profiles/profile_picker.h"
#include "chrome/browser/ui/views/profiles/profile_management_types.h"
#include "chrome/browser/ui/views/profiles/profile_picker_web_contents_host.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "components/user_education/common/feature_promo/feature_promo_controller.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget_delegate.h"
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
class ProfilePickerDiceSignInToolbar;
#endif
class Profile;
class ScopedProfileKeepAlive;
class ProfileManagementFlowController;
class ProfilePickerFlowController;
class ProfilePickerFeaturePromoController;
class ForceSigninUIError;
namespace content {
struct ContextMenuParams;
class NavigationHandle;
class RenderFrameHost;
class WebContents;
} // namespace content
// Dialog widget that contains the Desktop Profile picker webui.
class ProfilePickerView : public views::WidgetDelegateView,
public ProfilePickerWebContentsHost,
public content::WebContentsDelegate,
public web_modal::WebContentsModalDialogHost,
public ui::AcceleratorProvider {
METADATA_HEADER(ProfilePickerView, views::WidgetDelegateView)
public:
ProfilePickerView(const ProfilePickerView&) = delete;
ProfilePickerView& operator=(const ProfilePickerView&) = delete;
// Updates the parameters. This calls existing callbacks with error values,
// and requires `ProfilePicker::Params::CanReusePickerWindow()` to be true.
void UpdateParams(ProfilePicker::Params&& params);
// ProfilePickerWebContentsHost:
void ShowScreen(content::WebContents* contents,
const GURL& url,
base::OnceClosure navigation_finished_closure) override;
void ShowScreenInPickerContents(
const GURL& url,
base::OnceClosure navigation_finished_closure) override;
bool ShouldUseDarkColors() const override;
content::WebContents* GetPickerContents() const override;
web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
override;
content::WebContentsDelegate* GetWebContentsDelegate() override;
void Reset(StepSwitchFinishedCallback callback) override;
void ShowForceSigninErrorDialog(const ForceSigninUIError& error,
bool success) override;
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
void SetNativeToolbarVisible(bool visible) override;
bool IsNativeToolbarVisibleForTesting() const;
SkColor GetPreferredBackgroundColor() const override;
#endif
// content::WebContentsDelegate:
bool HandleKeyboardEvent(content::WebContents* source,
const input::NativeWebKeyboardEvent& event) override;
bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) override;
// web_modal::WebContentsModalDialogHost
gfx::NativeView GetHostView() const override;
gfx::Point GetDialogPosition(const gfx::Size& size) override;
gfx::Size GetMaximumDialogSize() override;
void AddObserver(web_modal::ModalDialogHostObserver* observer) override;
void RemoveObserver(web_modal::ModalDialogHostObserver* observer) override;
// views::WidgetDelegateView:
void WindowClosing() override;
views::ClientView* CreateClientView(views::Widget* widget) override;
views::View* GetContentsView() override;
std::u16string GetAccessibleWindowTitle() const override;
gfx::Size CalculatePreferredSize(
const views::SizeBounds& available_size) const override;
gfx::Size GetMinimumSize() const override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
// ui::AcceleratorProvider
bool GetAcceleratorForCommandId(int command_id,
ui::Accelerator* accelerator) const override;
// Exposed for testing
enum State {
// The view has just been created.
kNotStarted = 0,
// The view received a request to be displayed, but nothing has been shown
// yet.
kInitializing = 1,
// The view is currently shown.
kDisplayed = 2,
// The view received a request to close, and will be deleted shortly.
kClosing = 3
};
State state_for_testing() { return state_; }
protected:
// To display the Profile picker, use ProfilePicker::Show().
explicit ProfilePickerView(ProfilePicker::Params&& params);
~ProfilePickerView() override;
// Displays the profile picker.
void Display();
// Creates a `ProfileManagementFlowController` to drive the flow for which
// this profile picker is being shown.
virtual std::unique_ptr<ProfileManagementFlowController> CreateFlowController(
Profile* picker_profile,
ClearHostClosure clear_host_callback);
private:
friend class ProfilePicker;
FRIEND_TEST_ALL_PREFIXES(ProfilePickerCreationFlowBrowserTest,
CreateForceSignedInProfile);
class NavigationFinishedObserver : public content::WebContentsObserver {
public:
NavigationFinishedObserver(const GURL& requested_url,
base::OnceClosure closure,
content::WebContents* contents);
NavigationFinishedObserver(const NavigationFinishedObserver&) = delete;
NavigationFinishedObserver& operator=(const NavigationFinishedObserver&) =
delete;
~NavigationFinishedObserver() override;
// content::WebContentsObserver:
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
private:
const GURL requested_url_;
base::OnceClosure closure_;
};
// If the picker needs to be re-opened, this function schedules the reopening,
// closes the picker and return true. Otherwise, it returns false.
bool MaybeReopen(ProfilePicker::Params& params);
// Closes the profile picker.
void Clear();
// On picker profile creation success, it initializes the view.
void OnPickerProfileCreated(Profile* picker_profile);
// Creates and shows the dialog.
void Init(Profile* picker_profile);
// Finalizes the Init (entering the `kDisplayed` state), called along with the
// first time `ShowScreen()`.
void FinishInit();
// Switch to the flow that comes when the user decides to create a profile
// without signing in.
// `profile_color` is the profile's color. It is undefined for the default
// theme.
void SwitchToSignedOutPostIdentityFlow(std::optional<SkColor> profile_color);
// Callback used when the profile is created in the signed out flow.
void OnLocalProfileInitialized(std::optional<SkColor> profile_color,
Profile* profile);
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
// Switches the layout to the sign-in screen (and creates a new profile or
// load an existing one based on the `profile_info` content).
void SwitchToDiceSignIn(ProfilePicker::ProfileInfo profile_info,
StepSwitchFinishedCallback switch_finished_callback);
// Switches the profile picker layout to display the reauth page to the main
// account of the given `profile` if needed. On success the `profile` is
// unlocked and a browser is opend. On failure the user is redirected to the
// profile picker main page with an popup error dialog displayed through
// `on_error_callback`.
void SwitchToReauth(
Profile* profile,
StepSwitchFinishedCallback switch_finished_callback,
base::OnceCallback<void(const ForceSigninUIError&)> on_error_callback);
#endif
// Builds the views hierarchy.
void BuildLayout();
void ShowScreenFinished(
content::WebContents* contents,
base::OnceClosure navigation_finished_closure = base::OnceClosure());
void NavigateBack();
// Register basic keyboard accelerators such as closing the window (Alt-F4
// on Windows).
void ConfigureAccelerators();
ProfilePickerFlowController* GetProfilePickerFlowController() const;
// Returns a closure that can be executed to clear (see
// `ProfilePickerView::Clear()`) the view. Uses a weak pointer internally, so
// it can be called after the view has been destroyed. It is different from
// `ProfilePicker::Hide()` because it only clears this specific instance of
// the picker view, whereas `Hide()` would close any picker view.
ClearHostClosure GetClearClosure();
void UpdateAccessibleNameForRootView(views::WebView*);
// Create the feature promo that manages the IPH logic that can be displayed
// through the Profile Picker.
void InitializeFeaturePromo(Profile* system_profile);
ScopedKeepAlive keep_alive_;
std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive_;
State state_ = State::kNotStarted;
// During destruction, `params_` should stay alive longer than
// `signed_in_flow_` (below) as the flow may want to trigger a callback owned
// by `params_`.
ProfilePicker::Params params_;
// Callback that gets called (if set) when the current window has closed -
// used to reshow the picker (with different params).
base::OnceClosure restart_on_window_closing_;
// A mapping between accelerators and command IDs.
std::map<ui::Accelerator, int> accelerator_table_;
// Handler for unhandled key events from renderer.
views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
// Owned by the view hierarchy.
raw_ptr<views::WebView> web_view_ = nullptr;
// The web contents backed by the picker profile (mostly the system profile).
// This is used for displaying the WebUI pages.
std::unique_ptr<content::WebContents> contents_;
// Observer used for implementing screen switching. Non-null only shorty
// after switching a screen. Must be below all WebContents instances so that
// WebContents outlive this observer.
std::unique_ptr<NavigationFinishedObserver> show_screen_finished_observer_;
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
// Toolbar view displayed on top of the WebView for GAIA sign-in, owned by the
// view hierarchy.
raw_ptr<ProfilePickerDiceSignInToolbar> toolbar_ = nullptr;
#endif
std::unique_ptr<ProfileManagementFlowController> flow_controller_;
// Creation time of the picker, to measure performance on startup. Only set
// when the picker is shown on startup.
base::TimeTicks creation_time_on_startup_;
// Manages IPH promos displayed through the Profile Picker.
std::unique_ptr<ProfilePickerFeaturePromoController> feature_promo_;
base::CallbackListSubscription web_contents_attached_subscription_;
base::WeakPtrFactory<ProfilePickerView> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_VIEW_H_
|