File: cast_toolbar_button_controller.h

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 (142 lines) | stat: -rw-r--r-- 5,678 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
// Copyright 2016 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_TOOLBAR_CAST_CAST_TOOLBAR_BUTTON_CONTROLLER_H_
#define CHROME_BROWSER_UI_TOOLBAR_CAST_CAST_TOOLBAR_BUTTON_CONTROLLER_H_

#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/profiles/profile.h"
#include "chrome/browser/ui/toolbar/cast/cast_contextual_menu.h"
#include "components/media_router/browser/issues_observer.h"
#include "components/media_router/browser/media_routes_observer.h"
#include "components/prefs/pref_change_registrar.h"

// Controller for the Cast toolbar icon that determines when to show and hide
// icon. There should be one instance of this class per profile, and it should
// only be used on the UI thread.
class CastToolbarButtonController : public media_router::IssuesObserver,
                                    public media_router::MediaRoutesObserver,
                                    public CastContextualMenu::Observer {
 public:
  // TODO(takumif): CastToolbarIcon is the only Observer implementation.
  // Observer should be renamed to make it clear that it is responsible for
  // changing icon states when its methods are called.
  class Observer {
   public:
    virtual ~Observer() = default;

    virtual void ShowIcon() {}
    virtual void HideIcon() {}
    // TODO(crbug.com/40588598): Use the common code path to show and hide
    // the icon's inkdrop.
    // This is called when the icon should enter pressed state.
    virtual void ActivateIcon() {}
    // This is called when the icon should enter unpressed state.
    virtual void DeactivateIcon() {}
  };

  explicit CastToolbarButtonController(Profile* profile);
  // Constructor for injecting dependencies in tests.
  CastToolbarButtonController(Profile* profile,
                              media_router::MediaRouter* router);

  CastToolbarButtonController(const CastToolbarButtonController&) = delete;
  CastToolbarButtonController& operator=(const CastToolbarButtonController&) =
      delete;

  ~CastToolbarButtonController() override;

  // Whether the media router action is shown by an administrator policy.
  static bool IsActionShownByPolicy(Profile* profile);

  // Gets and sets the preference for whether the media router action should be
  // pinned to the toolbar/overflow menu.
  static bool GetAlwaysShowActionPref(Profile* profile);
  static void SetAlwaysShowActionPref(Profile* profile, bool always_show);

  // media_router::IssuesObserver:
  void OnIssue(const media_router::Issue& issue) override;
  void OnIssuesCleared() override;

  // media_router::MediaRoutesObserver:
  void OnRoutesUpdated(
      const std::vector<media_router::MediaRoute>& routes) override;

  // Called when a Media Router dialog is shown or hidden, and updates the
  // visibility of the action icon. Overridden in tests.
  virtual void OnDialogShown();
  virtual void OnDialogHidden();

  // CastContextualMenu::Observer:
  void OnContextMenuShown() override;
  void OnContextMenuHidden() override;

  // Updates the icon for all browsers with the same profile.
  void UpdateIcon();

  // On Windows (with a right click) and Chrome OS (with touch), pressing the
  // toolbar icon makes the dialog disappear, but the context menu does not
  // appear until mouse/touch release. These methods ensure that the icon is
  // still shown at mouse/touch release so that the context menu can be shown.
  void KeepIconShownOnPressed();
  void MaybeHideIconOnReleased();

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

  // Returns |true| if the Media Router action should be present on the toolbar
  // or the overflow menu.
  bool ShouldEnableAction() const;

  bool GetHasLocalDisplayRouteForTesting() { return has_local_display_route_; }
  bool GetHasIssueForTesting() { return has_issue_; }

 private:
  friend class CastToolbarButtonControllerUnitTest;

  // Adds or removes the Cast icon to/from the toolbar if necessary,
  // depending on whether or not we have issues, local routes or a dialog.
  virtual void MaybeToggleIconVisibility();

  // Updates the kActionMediaRouterToggleMediaRemoting ActionItem based on
  // changes to the pref.
  void UpdateToggleMediaRouterRemotingAction();

  // The profile |this| is associated with. There should be one instance of this
  // class per profile.
  const raw_ptr<Profile> profile_;

  bool has_issue_ = false;
  bool has_local_display_route_ = false;

  // Whether the media router action is shown by an administrator policy.
  bool shown_by_policy_;

  // The number of dialogs that are currently open.
  size_t dialog_count_ = 0;

  // Whether the Cast toolbar icon is showing a context menu. The toolbar icon
  // should not be hidden while a context menu is shown.
  bool context_menu_shown_ = false;

  // On Windows (with the right mouse button) and on Chrome OS (with touch),
  // when the user presses the toolbar icon, the dialog gets hidden, but the
  // context menu is not shown until mouse/touch release. If the icon is
  // ephemeral, it gets hidden on press and can't show the context menu. So we
  // must keep the icon shown while the right click or touch is held.
  bool keep_visible_for_right_click_or_hold_ = false;

  PrefChangeRegistrar pref_change_registrar_;

  base::ObserverList<Observer>::Unchecked observers_;

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

#endif  // CHROME_BROWSER_UI_TOOLBAR_CAST_CAST_TOOLBAR_BUTTON_CONTROLLER_H_