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
|
// Copyright 2022 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_PERMISSIONS_CHIP_CHIP_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_PERMISSIONS_CHIP_CHIP_CONTROLLER_H_
#include <cstddef>
#include <memory>
#include "base/check_is_test.h"
#include "base/functional/callback_helpers.h"
#include "base/timer/timer.h"
#include "chrome/browser/ui/views/permissions/chip/permission_chip_view.h"
#include "components/permissions/permission_prompt.h"
#include "components/permissions/permission_request_manager.h"
#include "components/permissions/permission_util.h"
#include "ui/views/widget/widget_observer.h"
class PermissionPromptChipModel;
class LocationBarView;
class PermissionDashboardView;
class PermissionDashboardController;
// ButtonController that NotifyClick from being called when the
// BubbleOwnerDelegate's bubble is showing. Otherwise the bubble will show again
// immediately after being closed via losing focus.
class BubbleOwnerDelegate {
public:
virtual bool IsBubbleShowing() = 0;
virtual bool IsAnimating() const = 0;
virtual void RestartTimersOnMouseHover() = 0;
};
// This class controls a chip UI view to surface permission related information
// and prompts. For its creation, the controller expects an object of type
// PermissionChipView which should be a child view of another view. No ownership
// is transferred through the creation, and the controller will never destruct
// the PermissionChipView object. The controller and it's view are intended to
// be long-lived.
class ChipController : public permissions::PermissionRequestManager::Observer,
public views::WidgetObserver,
public BubbleOwnerDelegate,
public PermissionChipView::Observer {
public:
ChipController(
LocationBarView* location_bar_view,
PermissionChipView* chip_view,
PermissionDashboardView* permission_dashboard_view = nullptr,
PermissionDashboardController* permission_dashboard_controller = nullptr);
~ChipController() override;
ChipController(const ChipController&) = delete;
ChipController& operator=(const ChipController&) = delete;
// PermissionRequestManager::Observer:
void OnPermissionRequestManagerDestructed() override;
void OnTabVisibilityChanged(content::Visibility visibility) override;
// Called when the currently active permission request was finalized. That
// could be called independently of `OnRequestDecided`.
void OnRequestsFinalized() override;
// Called when currently visible permission prompt was removed. That is called
// independently from `OnRequestsFinalized` and `OnRequestDecided`.
void OnPromptRemoved() override;
// OnBubbleRemoved only triggers when a request chip (bubble) is removed, when
// the user navigates while a confirmation chip is showing, the request is
// already finished and hence OnBubbleRemoved is not triggered. Thus we need
// to handle chip cleanup on navigation events separately.
void OnNavigation(content::NavigationHandle* navigation_handle) override;
// Called when there is a decision for a permission request.
void OnRequestDecided(permissions::PermissionAction permissions) override;
// BubbleOwnerDelegate:
bool IsBubbleShowing() override;
bool IsAnimating() const override;
void RestartTimersOnMouseHover() override;
// WidgetObserver:
void OnWidgetDestroying(views::Widget* widget) override;
void OnWidgetDestroyed(views::Widget* widget) override;
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
// PermissionChipView::Observer
void OnChipVisibilityChanged(bool is_visible) override;
void OnExpandAnimationEnded() override;
void OnCollapseAnimationEnded() override;
// Initializes the permission prompt model as well as the permission request
// manager and observes the prompt bubble.
void InitializePermissionPrompt(
base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate,
base::OnceCallback<void()> = base::DoNothing());
// Displays a permission chip. Call ShowPermissionPrompt() instead to show
// both a chip and a prompt.
void ShowPermissionChip(
base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate);
// Displays a permission prompt using the chip UI.
void ShowPermissionPrompt(
base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate);
// Chip View.
PermissionChipView* chip() { return chip_; }
// Hide and clean up the chip.
void ResetPermissionPromptChip();
// Hide and clean up only if the chip displays a permission request. That
// method is no-op if the confirmation chip is displayed.
void ResetPermissionRequestChip();
bool IsPermissionPromptChipVisible() {
return chip_ && chip_->GetVisible() && permission_prompt_model_;
}
views::Widget* GetBubbleWidget();
PermissionPromptBubbleBaseView* GetPromptBubbleView();
void ClosePermissionPrompt();
void PromptDecided(permissions::PermissionAction action);
PermissionPromptChipModel* permission_prompt_model() {
return permission_prompt_model_.get();
}
bool should_expand_for_testing();
bool is_collapse_timer_running_for_testing() const {
CHECK_IS_TEST();
return collapse_timer_.IsRunning();
}
void fire_collapse_timer_for_testing() {
CHECK_IS_TEST();
collapse_timer_.FireNow();
}
bool is_dismiss_timer_running_for_testing() const {
CHECK_IS_TEST();
return dismiss_timer_.IsRunning();
}
void stop_animation_for_test() {
CHECK_IS_TEST();
chip_->animation_for_testing()->Stop();
OnExpandAnimationEnded();
}
views::View* get_prompt_bubble_view_for_testing() {
CHECK_IS_TEST();
return bubble_tracker_.view();
}
std::optional<permissions::PermissionRequestManager*>
active_permission_request_manager() {
return active_chip_permission_request_manager_;
}
bool is_confirmation_showing() const { return is_confirmation_showing_; }
bool is_waiting_for_confirmation_collapse_for_testing() const {
CHECK_IS_TEST();
return is_waiting_for_confirmation_collapse_;
}
void set_is_bubble_suppressed(bool is_bubble_suppressed) {
is_bubble_suppressed_ = is_bubble_suppressed;
}
void DoNotCollapseForTesting() { do_no_collapse_for_testing_ = true; }
private:
FRIEND_TEST_ALL_PREFIXES(PermissionChipUnitTest, AccessibleName);
bool ShouldWaitForConfirmationToComplete() const;
bool ShouldWaitForLHSIndicatorToCollapse() const;
void AnimateExpand();
// Confirmation chip.
void HandleConfirmation(permissions::PermissionAction permission_action);
void CollapseConfirmation();
// Permission prompt chip functionality.
void AnnouncePermissionRequestForAccessibility(const std::u16string& text);
void CollapsePrompt(bool allow_restart);
// Hides the chip and invalidates the layout.
void HideChip();
void ShowPermissionUi(
base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate);
// Permission prompt bubble functiontionality.
void OpenPermissionPromptBubble();
void ClosePermissionPromptBubbleWithReason(
views::Widget::ClosedReason reason);
void RecordRequestChipButtonPressed(const char* recordKey);
// Event handling.
void ObservePromptBubble();
void OnPromptBubbleDismissed();
void OnPromptExpired();
void OnRequestChipButtonPressed();
// Updates chip icon, text and theme with model.
void SyncChipWithModel();
// Opens the Page Info Dialog.
void ShowPageInfoDialog();
// Actions executed when the user closes the page info dialog.
void OnPageInfoBubbleClosed(views::Widget::ClosedReason closed_reason,
bool reload_prompt);
// Clean up utility.
void RemoveBubbleObserverAndResetTimersAndChipCallbacks();
// Timer functionality.
void StartCollapseTimer();
void StartDismissTimer();
void ResetTimers();
// The location bar view to which the chip is attached.
LocationBarView* GetLocationBarView() { return location_bar_view_; }
bool is_confirmation_showing_ = false;
bool is_waiting_for_confirmation_collapse_ = false;
// `LocationBarView` owns this.
raw_ptr<LocationBarView> location_bar_view_ = nullptr;
// The chip view this controller modifies.
raw_ptr<PermissionChipView> chip_;
// `PermissionDashboardView` is an owner of PermissionChipView.
raw_ptr<PermissionDashboardView> permission_dashboard_view_;
// `PermissionDashboardController` is an owner of this.
raw_ptr<PermissionDashboardController> permission_dashboard_controller_;
// The time when the request chip was displayed.
base::TimeTicks request_chip_shown_time_;
// A timer used to dismiss the permission request after it's been collapsed
// for a while.
base::OneShotTimer dismiss_timer_;
// A timer used to collapse the chip after a delay.
base::OneShotTimer collapse_timer_;
// A timer used to delay showing a prompt if a confirmation chip is being
// displayed.
base::OneShotTimer delay_prompt_timer_;
bool parent_was_visible_when_activation_changed_ = false;
// The model of a permission prompt if one is present.
std::unique_ptr<PermissionPromptChipModel> permission_prompt_model_;
std::optional<permissions::PermissionRequestManager*>
active_chip_permission_request_manager_;
views::ViewTracker bubble_tracker_;
bool is_bubble_suppressed_ = false;
bool do_no_collapse_for_testing_ = false;
// Keep prompt's decision until the prompt's widget is removed.
std::optional<permissions::PermissionAction> prompt_decision_;
base::ScopedClosureRunner disallowed_custom_cursors_scope_;
base::ScopedObservation<PermissionChipView, PermissionChipView::Observer>
observation_{this};
base::WeakPtrFactory<ChipController> weak_factory_{this};
};
#endif // CHROME_BROWSER_UI_VIEWS_PERMISSIONS_CHIP_CHIP_CONTROLLER_H_
|