File: cast_dialog_view.h

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 (221 lines) | stat: -rw-r--r-- 8,139 bytes parent folder | download | duplicates (4)
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
// Copyright 2018 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_MEDIA_ROUTER_CAST_DIALOG_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_CAST_DIALOG_VIEW_H_

#include <memory>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chrome/browser/ui/media_router/cast_dialog_controller.h"
#include "chrome/browser/ui/views/controls/hover_button.h"
#include "chrome/browser/ui/views/media_router/cast_dialog_access_code_cast_button.h"
#include "chrome/browser/ui/views/media_router/cast_dialog_metrics.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/menus/simple_menu_model.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/md_text_button_with_down_arrow.h"
#include "ui/views/controls/menu/menu_runner.h"

class Profile;

namespace media_router {

class CastDialogSinkView;
enum class MediaRouterDialogActivationLocation;
struct UIMediaSink;

// View component of the Cast dialog that allows users to start and stop Casting
// to devices. The list of devices used to populate the dialog is supplied by
// CastDialogModel.
class CastDialogView : public views::BubbleDialogDelegateView,
                       public CastDialogController::Observer,
                       public ui::SimpleMenuModel::Delegate {
  METADATA_HEADER(CastDialogView, views::BubbleDialogDelegateView)

 public:
  class Observer : public base::CheckedObserver {
   public:
    virtual void OnDialogModelUpdated(CastDialogView* dialog_view) = 0;
    virtual void OnDialogWillClose(CastDialogView* dialog_view) = 0;
  };

  enum SourceType { kTab, kDesktop };

  CastDialogView(views::View* anchor_view,
                 views::BubbleBorder::Arrow anchor_position,
                 CastDialogController* controller,
                 Profile* profile,
                 const base::Time& start_time,
                 MediaRouterDialogActivationLocation activation_location,
                 actions::ActionItem* action_item = nullptr);
  ~CastDialogView() override;
  CastDialogView(const CastDialogView&) = delete;
  CastDialogView& operator=(const CastDialogView&) = delete;

  // views::WidgetDelegate:
  std::u16string GetWindowTitle() const override;

  // CastDialogController::Observer:
  void OnModelUpdated(const CastDialogModel& model) override;
  void OnControllerDestroying() override;

  // ui::SimpleMenuModel::Delegate:
  bool IsCommandIdChecked(int command_id) const override;
  bool IsCommandIdEnabled(int command_id) const override;
  void ExecuteCommand(int command_id, int event_flags) override;

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // If the dialog loses focus during a test and closes, the test can
  // fail unexpectedly. This method prevents that by keeping the dialog from
  // closing on blur.
  void KeepShownForTesting();

  // Called by tests.
  const std::vector<raw_ptr<CastDialogSinkView, DanglingUntriaged>>&
  sink_views_for_test() const {
    return sink_views_;
  }
  views::ScrollView* scroll_view_for_test() { return scroll_view_; }
  views::View* no_sinks_view_for_test() { return no_sinks_view_; }
  views::View* permission_rejected_view_for_test() {
    return permission_rejected_view_;
  }
  views::Button* sources_button_for_test() { return sources_button_; }
  HoverButton* access_code_cast_button_for_test() {
    return access_code_cast_button_;
  }
  ui::SimpleMenuModel* sources_menu_model_for_test() {
    return sources_menu_model_.get();
  }
  views::MenuRunner* sources_menu_runner_for_test() {
    return sources_menu_runner_.get();
  }

 private:
  // TODO(crbug.com/1346127): Remove friend classes.
  friend class CastDialogViewTest;
  friend class MediaRouterCastUiForTest;
  FRIEND_TEST_ALL_PREFIXES(CastDialogViewTest, DisableUnsupportedSinks);
  FRIEND_TEST_ALL_PREFIXES(CastDialogViewTest, ShowAndHideDialog);
  FRIEND_TEST_ALL_PREFIXES(CastDialogViewTest, ShowSourcesMenu);

  // views::BubbleDialogDelegateView:
  void Init() override;
  void WindowClosing() override;

  void ShowAccessCodeCastDialog();
  void MaybeShowAccessCodeCastButton();

  void ShowNoSinksView();
  void ShowPermissionRejectedView();
  void ShowScrollView();
  void ResetViews();

  // Applies the stored scroll state.
  void RestoreSinkListState();

  // Populates the scroll view containing sinks using the data in |model|.
  void PopulateScrollView(const std::vector<UIMediaSink>& sinks);

  void InitializeSourcesButton();

  // Shows the sources menu that allows the user to choose a source to cast.
  void ShowSourcesMenu();

  // Stores |source| as the source to be used when user selects a sink to start
  // casting, and updates the UI to reflect the selection.
  void SelectSource(SourceType source);

  void SinkPressed(size_t index);
  void IssuePressed(size_t index);
  void StopPressed(size_t index);
  void FreezePressed(size_t index);

  void MaybeSizeToContents();

  // Returns the cast mode that is selected in the sources menu and supported by
  // |sink|. Returns nullopt if no such cast mode exists.
  std::optional<MediaCastMode> GetCastModeToUse(const UIMediaSink& sink) const;

  // Disables sink buttons for sinks that do not support the currently selected
  // source.
  void DisableUnsupportedSinks();

  // Posts a delayed task to record the number of sinks shown with the metrics
  // recorder.
  void RecordSinkCountWithDelay();

  // Records the number of sinks shown with the metrics recorder.
  void RecordSinkCount();

  // Returns true iff feature is turned on and the access code casting policy
  // has been enabled for this user.
  bool IsAccessCodeCastingEnabled() const;

  // Title shown at the top of the dialog.
  std::u16string dialog_title_;

  // The source selected in the sources menu. This defaults to "tab"
  // (presentation or tab mirroring). "Tab" is represented by a single item in
  // the sources menu.
  SourceType selected_source_ = SourceType::kTab;

  // Contains references to sink views in the order they appear.
  std::vector<raw_ptr<CastDialogSinkView, DanglingUntriaged>> sink_views_;

  raw_ptr<CastDialogController> controller_;

  // ScrollView containing the list of sink buttons.
  raw_ptr<views::ScrollView> scroll_view_ = nullptr;

  // View shown while there are no sinks.
  raw_ptr<views::View> no_sinks_view_ = nullptr;
  raw_ptr<views::View> permission_rejected_view_ = nullptr;

  const raw_ptr<Profile> profile_;

  // How much |scroll_view_| is scrolled downwards in pixels. Whenever the sink
  // list is updated the scroll position gets reset, so we must manually restore
  // it to this value.
  int scroll_position_ = 0;

  // The access code cast button allows the user to add a cast device through
  // the chrome://access-code-cast dialog.
  raw_ptr<CastDialogAccessCodeCastButton> access_code_cast_button_ = nullptr;

  // The sources menu allows the user to choose a source to cast.
  raw_ptr<views::MdTextButtonWithDownArrow> sources_button_ = nullptr;
  std::unique_ptr<ui::SimpleMenuModel> sources_menu_model_;
  std::unique_ptr<views::MenuRunner> sources_menu_runner_;

  // Records UMA metrics for the dialog's behavior.
  CastDialogMetrics metrics_;

  // The action item tied to this dialog and its anchor view.
  // Used to handle bubble re-opening issues with Pinned Toolbar Buttons.
  const raw_ptr<actions::ActionItem> action_item_ = nullptr;

  // The sink that the user has selected to cast to. If the user is using
  // multiple sinks at the same time, the last activated sink is used.
  std::optional<size_t> selected_sink_index_;

  base::ObserverList<Observer> observers_;

  // When this is set to true, the dialog does not close on blur.
  bool keep_shown_for_testing_ = false;

  base::WeakPtrFactory<CastDialogView> weak_factory_{this};
};

}  // namespace media_router

#endif  // CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_CAST_DIALOG_VIEW_H_