OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/toolbar/media_router_action.h" | 5 #include "chrome/browser/ui/toolbar/media_router_action.h" |
6 | 6 |
7 #include "base/metrics/user_metrics.h" | 7 #include "base/metrics/user_metrics.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "chrome/browser/media/router/issue.h" | 9 #include "chrome/browser/media/router/issue.h" |
10 #include "chrome/browser/media/router/media_route.h" | 10 #include "chrome/browser/media/router/media_route.h" |
11 #include "chrome/browser/media/router/media_router.h" | 11 #include "chrome/browser/media/router/media_router.h" |
12 #include "chrome/browser/media/router/media_router_factory.h" | 12 #include "chrome/browser/media/router/media_router_factory.h" |
13 #include "chrome/browser/media/router/media_router_metrics.h" | 13 #include "chrome/browser/media/router/media_router_metrics.h" |
14 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
15 #include "chrome/browser/ui/browser.h" | 15 #include "chrome/browser/ui/browser.h" |
16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 16 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
17 #include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h" | 17 #include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h" |
18 #include "chrome/browser/ui/toolbar/media_router_action_platform_delegate.h" | 18 #include "chrome/browser/ui/toolbar/media_router_action_platform_delegate.h" |
19 #include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h" | 19 #include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h" |
20 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" | |
21 #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_im
pl.h" | 20 #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_im
pl.h" |
22 #include "chrome/common/pref_names.h" | |
23 #include "chrome/grit/generated_resources.h" | 21 #include "chrome/grit/generated_resources.h" |
24 #include "components/prefs/pref_service.h" | |
25 #include "components/prefs/pref_service_factory.h" | |
26 #include "grit/theme_resources.h" | |
27 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
28 #include "ui/gfx/color_palette.h" | 23 #include "ui/gfx/color_palette.h" |
29 #include "ui/gfx/image/image_skia.h" | 24 #include "ui/gfx/image/image_skia.h" |
30 #include "ui/gfx/paint_vector_icon.h" | 25 #include "ui/gfx/paint_vector_icon.h" |
31 | 26 |
32 using media_router::MediaRouterDialogControllerImpl; | 27 using media_router::MediaRouterDialogControllerImpl; |
33 | 28 |
34 namespace { | 29 namespace { |
35 | 30 |
36 media_router::MediaRouter* GetMediaRouter(Browser* browser) { | 31 media_router::MediaRouter* GetMediaRouter(Browser* browser) { |
37 return media_router::MediaRouterFactory::GetApiForBrowserContext( | 32 return media_router::MediaRouterFactory::GetApiForBrowserContext( |
38 browser->profile()); | 33 browser->profile()); |
39 } | 34 } |
40 | 35 |
41 } // namespace | 36 } // namespace |
42 | 37 |
43 MediaRouterAction::MediaRouterAction(Browser* browser, | 38 MediaRouterAction::MediaRouterAction(Browser* browser, |
44 ToolbarActionsBar* toolbar_actions_bar) | 39 ToolbarActionsBar* toolbar_actions_bar) |
45 : media_router::IssuesObserver(GetMediaRouter(browser)), | 40 : media_router::IssuesObserver(GetMediaRouter(browser)), |
46 media_router::MediaRoutesObserver(GetMediaRouter(browser)), | 41 media_router::MediaRoutesObserver(GetMediaRouter(browser)), |
47 current_icon_(gfx::VectorIconId::MEDIA_ROUTER_IDLE), | 42 current_icon_(gfx::VectorIconId::MEDIA_ROUTER_IDLE), |
48 has_local_display_route_(false), | 43 has_local_display_route_(false), |
49 has_dialog_(false), | |
50 delegate_(nullptr), | 44 delegate_(nullptr), |
51 browser_(browser), | 45 browser_(browser), |
52 toolbar_actions_bar_(toolbar_actions_bar), | 46 toolbar_actions_bar_(toolbar_actions_bar), |
53 platform_delegate_(MediaRouterActionPlatformDelegate::Create(browser)), | 47 platform_delegate_(MediaRouterActionPlatformDelegate::Create(browser)), |
54 contextual_menu_(browser, this), | 48 contextual_menu_(browser), |
55 tab_strip_model_observer_(this), | 49 tab_strip_model_observer_(this), |
56 toolbar_actions_bar_observer_(this), | |
57 weak_ptr_factory_(this) { | 50 weak_ptr_factory_(this) { |
58 DCHECK(browser_); | 51 DCHECK(browser_); |
59 DCHECK(toolbar_actions_bar_); | 52 DCHECK(toolbar_actions_bar_); |
60 tab_strip_model_observer_.Add(browser_->tab_strip_model()); | 53 tab_strip_model_observer_.Add(browser_->tab_strip_model()); |
61 toolbar_actions_bar_observer_.Add(toolbar_actions_bar_); | 54 |
62 RegisterObserver(); | 55 RegisterObserver(); |
63 } | 56 } |
64 | 57 |
65 MediaRouterAction::~MediaRouterAction() { | 58 MediaRouterAction::~MediaRouterAction() { |
66 UnregisterObserver(); | 59 UnregisterObserver(); |
67 } | 60 } |
68 | 61 |
69 std::string MediaRouterAction::GetId() const { | 62 std::string MediaRouterAction::GetId() const { |
70 return ComponentToolbarActionsFactory::kMediaRouterActionId; | 63 return ComponentToolbarActionsFactory::kMediaRouterActionId; |
71 } | 64 } |
72 | 65 |
73 void MediaRouterAction::SetDelegate(ToolbarActionViewDelegate* delegate) { | 66 void MediaRouterAction::SetDelegate(ToolbarActionViewDelegate* delegate) { |
74 delegate_ = delegate; | 67 delegate_ = delegate; |
75 | 68 |
76 // Updates the current dialog state if |delegate_| is non-null and has | 69 // Updates the current popup state if |delegate_| is non-null and has |
77 // WebContents ready. | 70 // WebContents ready. |
78 // In cases such as opening a new browser window, SetDelegate() will be | 71 // In cases such as opening a new browser window, SetDelegate() will be |
79 // called before the WebContents is set. In those cases, we update the dialog | 72 // called before the WebContents is set. In those cases, we update the popup |
80 // state when ActiveTabChanged() is called. | 73 // state when ActiveTabChanged() is called. |
81 if (delegate_ && delegate_->GetCurrentWebContents()) | 74 if (delegate_ && delegate_->GetCurrentWebContents()) |
82 UpdateDialogState(); | 75 UpdatePopupState(); |
83 } | 76 } |
84 | 77 |
85 gfx::Image MediaRouterAction::GetIcon(content::WebContents* web_contents, | 78 gfx::Image MediaRouterAction::GetIcon(content::WebContents* web_contents, |
86 const gfx::Size& size) { | 79 const gfx::Size& size) { |
87 // Color is defined in the icon. | 80 // Color is defined in the icon. |
88 return gfx::Image( | 81 return gfx::Image( |
89 gfx::CreateVectorIcon(current_icon_, gfx::kPlaceholderColor)); | 82 gfx::CreateVectorIcon(current_icon_, gfx::kPlaceholderColor)); |
90 } | 83 } |
91 | 84 |
92 base::string16 MediaRouterAction::GetActionName() const { | 85 base::string16 MediaRouterAction::GetActionName() const { |
(...skipping 20 matching lines...) Expand all Loading... |
113 return false; | 106 return false; |
114 } | 107 } |
115 | 108 |
116 bool MediaRouterAction::HasPopup( | 109 bool MediaRouterAction::HasPopup( |
117 content::WebContents* web_contents) const { | 110 content::WebContents* web_contents) const { |
118 return true; | 111 return true; |
119 } | 112 } |
120 | 113 |
121 void MediaRouterAction::HidePopup() { | 114 void MediaRouterAction::HidePopup() { |
122 GetMediaRouterDialogController()->HideMediaRouterDialog(); | 115 GetMediaRouterDialogController()->HideMediaRouterDialog(); |
| 116 OnPopupHidden(); |
123 } | 117 } |
124 | 118 |
125 gfx::NativeView MediaRouterAction::GetPopupNativeView() { | 119 gfx::NativeView MediaRouterAction::GetPopupNativeView() { |
126 return nullptr; | 120 return nullptr; |
127 } | 121 } |
128 | 122 |
129 ui::MenuModel* MediaRouterAction::GetContextMenu() { | 123 ui::MenuModel* MediaRouterAction::GetContextMenu() { |
130 return contextual_menu_.menu_model(); | 124 return contextual_menu_.menu_model(); |
131 } | 125 } |
132 | 126 |
133 bool MediaRouterAction::ExecuteAction(bool by_user) { | 127 bool MediaRouterAction::ExecuteAction(bool by_user) { |
134 base::RecordAction(base::UserMetricsAction("MediaRouter_Icon_Click")); | 128 base::RecordAction(base::UserMetricsAction("MediaRouter_Icon_Click")); |
135 | 129 |
136 if (GetMediaRouterDialogController()->IsShowingMediaRouterDialog()) { | 130 if (GetMediaRouterDialogController()->IsShowingMediaRouterDialog()) { |
137 GetMediaRouterDialogController()->HideMediaRouterDialog(); | 131 GetMediaRouterDialogController()->HideMediaRouterDialog(); |
138 return false; | 132 return false; |
139 } | 133 } |
140 | 134 |
141 GetMediaRouterDialogController()->ShowMediaRouterDialog(); | 135 GetMediaRouterDialogController()->ShowMediaRouterDialog(); |
142 if (GetPlatformDelegate()) { | 136 if (GetPlatformDelegate()) { |
143 media_router::MediaRouterMetrics::RecordMediaRouterDialogOrigin( | 137 media_router::MediaRouterMetrics::RecordMediaRouterDialogOrigin( |
144 GetPlatformDelegate()->CloseOverflowMenuIfOpen() ? | 138 GetPlatformDelegate()->CloseOverflowMenuIfOpen() ? |
145 media_router::MediaRouterDialogOpenOrigin::OVERFLOW_MENU : | 139 media_router::MediaRouterDialogOpenOrigin::OVERFLOW_MENU : |
146 media_router::MediaRouterDialogOpenOrigin::TOOLBAR); | 140 media_router::MediaRouterDialogOpenOrigin::TOOLBAR); |
147 } | 141 } |
148 return true; | 142 return true; |
149 } | 143 } |
150 | 144 |
151 void MediaRouterAction::UpdateState() { | 145 void MediaRouterAction::UpdateState() { |
152 DCHECK(delegate_); | 146 if (delegate_) |
153 delegate_->UpdateState(); | 147 delegate_->UpdateState(); |
154 } | 148 } |
155 | 149 |
156 bool MediaRouterAction::DisabledClickOpensMenu() const { | 150 bool MediaRouterAction::DisabledClickOpensMenu() const { |
157 return false; | 151 return false; |
158 } | 152 } |
159 | 153 |
160 void MediaRouterAction::OnIssueUpdated(const media_router::Issue* issue) { | 154 void MediaRouterAction::OnIssueUpdated(const media_router::Issue* issue) { |
161 issue_.reset(issue ? new media_router::Issue(*issue) : nullptr); | 155 issue_.reset(issue ? new media_router::Issue(*issue) : nullptr); |
162 | 156 |
163 MaybeUpdateIcon(); | 157 MaybeUpdateIcon(); |
164 } | 158 } |
165 | 159 |
166 void MediaRouterAction::OnRoutesUpdated( | 160 void MediaRouterAction::OnRoutesUpdated( |
167 const std::vector<media_router::MediaRoute>& routes, | 161 const std::vector<media_router::MediaRoute>& routes, |
168 const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) { | 162 const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) { |
169 has_local_display_route_ = | 163 has_local_display_route_ = |
170 std::find_if(routes.begin(), routes.end(), | 164 std::find_if(routes.begin(), routes.end(), |
171 [](const media_router::MediaRoute& route) { | 165 [](const media_router::MediaRoute& route) { |
172 return route.is_local() && route.for_display(); | 166 return route.is_local() && route.for_display(); |
173 }) != routes.end(); | 167 }) != routes.end(); |
174 MaybeUpdateIcon(); | 168 MaybeUpdateIcon(); |
175 MaybeRemoveAction(); | |
176 } | 169 } |
177 | 170 |
178 void MediaRouterAction::ActiveTabChanged(content::WebContents* old_contents, | 171 void MediaRouterAction::ActiveTabChanged(content::WebContents* old_contents, |
179 content::WebContents* new_contents, | 172 content::WebContents* new_contents, |
180 int index, | 173 int index, |
181 int reason) { | 174 int reason) { |
182 UpdateDialogState(); | 175 UpdatePopupState(); |
183 MaybeRemoveAction(); | |
184 } | 176 } |
185 | 177 |
186 void MediaRouterAction::OnToolbarActionsBarAnimationEnded() { | 178 void MediaRouterAction::OnPopupHidden() { |
187 // Depress the action if the dialog is shown, release it otherwise. | 179 if (delegate_) |
188 DCHECK(delegate_); | 180 delegate_->OnPopupClosed(); |
189 if (GetMediaRouterDialogController()->IsShowingMediaRouterDialog()) | |
190 OnDialogShown(); | |
191 } | 181 } |
192 | 182 |
193 void MediaRouterAction::OnDialogHidden() { | 183 void MediaRouterAction::OnPopupShown() { |
194 if (has_dialog_) { | 184 // We depress the action regardless of whether ExecuteAction() was user |
195 has_dialog_ = false; | 185 // initiated. |
196 DCHECK(delegate_); | 186 if (delegate_) |
197 delegate_->OnPopupClosed(); | 187 delegate_->OnPopupShown(true); |
198 } | |
199 } | 188 } |
200 | 189 |
201 void MediaRouterAction::OnDialogShown() { | 190 void MediaRouterAction::UpdatePopupState() { |
202 if (!has_dialog_) { | |
203 has_dialog_ = true; | |
204 DCHECK(delegate_); | |
205 // We depress the action regardless of whether ExecuteAction() was user | |
206 // initiated. | |
207 delegate_->OnPopupShown(true); | |
208 } | |
209 } | |
210 | |
211 void MediaRouterAction::ToggleVisibilityPreference() { | |
212 browser_->profile()->GetPrefs()->SetBoolean( | |
213 prefs::kMediaRouterAlwaysShowActionIcon, !ShouldAlwaysShowIcon()); | |
214 MaybeRemoveAction(); | |
215 } | |
216 | |
217 void MediaRouterAction::UpdateDialogState() { | |
218 MediaRouterDialogControllerImpl* controller = | 191 MediaRouterDialogControllerImpl* controller = |
219 GetMediaRouterDialogController(); | 192 GetMediaRouterDialogController(); |
220 | 193 |
221 if (!controller) | 194 if (!controller) |
222 return; | 195 return; |
223 | 196 |
224 // |controller| keeps track of |this| if |this| was created with the browser | 197 // When each browser window is created, its toolbar creates a |
225 // window or ephemerally by activating the Cast functionality. If |this| was | 198 // MediaRouterAction that is only destroyed when the browser window is torn |
226 // created in overflow mode, it will be destroyed when the overflow menu is | 199 // down. |controller| will keep track of that instance. If |this| was created |
227 // closed. If SetMediaRouterAction() was previously called, this is a no-op. | 200 // in overflow mode, it will be destroyed when the overflow menu is closed. |
| 201 // If SetMediaRouterAction() was previously called, this is a no-op. |
228 if (!toolbar_actions_bar_->in_overflow_mode()) | 202 if (!toolbar_actions_bar_->in_overflow_mode()) |
229 controller->SetMediaRouterAction(weak_ptr_factory_.GetWeakPtr()); | 203 controller->SetMediaRouterAction(weak_ptr_factory_.GetWeakPtr()); |
230 | 204 |
231 // Update the button in case the pressed state is out of sync with dialog | 205 // Update the button in case the pressed state is out of sync with dialog |
232 // visibility. If we just added the ephemeral icon to the toolbar and need to | 206 // visibility. |
233 // depress it, we do that in |OnToolbarActionsBarAnimationEnded|. | 207 if (controller->IsShowingMediaRouterDialog()) |
234 DCHECK(delegate_); | 208 OnPopupShown(); |
235 if (ShouldAlwaysShowIcon() && controller->IsShowingMediaRouterDialog()) | 209 else |
236 OnDialogShown(); | 210 OnPopupHidden(); |
237 else if (!controller->IsShowingMediaRouterDialog()) | |
238 OnDialogHidden(); | |
239 } | 211 } |
240 | 212 |
241 MediaRouterDialogControllerImpl* | 213 MediaRouterDialogControllerImpl* |
242 MediaRouterAction::GetMediaRouterDialogController() { | 214 MediaRouterAction::GetMediaRouterDialogController() { |
243 DCHECK(delegate_); | 215 DCHECK(delegate_); |
244 content::WebContents* web_contents = delegate_->GetCurrentWebContents(); | 216 content::WebContents* web_contents = delegate_->GetCurrentWebContents(); |
245 DCHECK(web_contents); | 217 DCHECK(web_contents); |
246 return MediaRouterDialogControllerImpl::GetOrCreateForWebContents( | 218 return MediaRouterDialogControllerImpl::GetOrCreateForWebContents( |
247 web_contents); | 219 web_contents); |
248 } | 220 } |
249 | 221 |
250 MediaRouterActionPlatformDelegate* MediaRouterAction::GetPlatformDelegate() { | 222 MediaRouterActionPlatformDelegate* MediaRouterAction::GetPlatformDelegate() { |
251 return platform_delegate_.get(); | 223 return platform_delegate_.get(); |
252 } | 224 } |
253 | 225 |
254 void MediaRouterAction::MaybeUpdateIcon() { | 226 void MediaRouterAction::MaybeUpdateIcon() { |
255 gfx::VectorIconId new_icon = GetCurrentIcon(); | 227 gfx::VectorIconId new_icon = GetCurrentIcon(); |
256 | 228 |
257 // Update the current state if it has changed. | 229 // Update the current state if it has changed. |
258 if (new_icon != current_icon_) { | 230 if (new_icon != current_icon_) { |
259 current_icon_ = new_icon; | 231 current_icon_ = new_icon; |
260 | 232 |
261 // Tell the associated view to update its icon to reflect the change made | 233 // Tell the associated view to update its icon to reflect the change made |
262 // above. | 234 // above. |
263 UpdateState(); | 235 if (delegate_) |
| 236 delegate_->UpdateState(); |
264 } | 237 } |
265 } | 238 } |
266 | 239 |
267 void MediaRouterAction::MaybeRemoveAction() { | |
268 if (!ShouldAlwaysShowIcon() && | |
269 !GetMediaRouterDialogController()->IsShowingMediaRouterDialog() && | |
270 !has_local_display_route_) { | |
271 // Warning: |this| can be deleted here. | |
272 ToolbarActionsModel::Get(browser_->profile()) | |
273 ->RemoveComponentAction(GetId()); | |
274 } | |
275 } | |
276 | |
277 bool MediaRouterAction::ShouldAlwaysShowIcon() { | |
278 PrefService* pref_service = browser_->profile()->GetPrefs(); | |
279 return pref_service->GetBoolean(prefs::kMediaRouterAlwaysShowActionIcon); | |
280 } | |
281 | |
282 gfx::VectorIconId MediaRouterAction::GetCurrentIcon() const { | 240 gfx::VectorIconId MediaRouterAction::GetCurrentIcon() const { |
283 // Highest priority is to indicate whether there's an issue. | 241 // Highest priority is to indicate whether there's an issue. |
284 if (issue_) { | 242 if (issue_) { |
285 if (issue_->severity() == media_router::Issue::FATAL) | 243 if (issue_->severity() == media_router::Issue::FATAL) |
286 return gfx::VectorIconId::MEDIA_ROUTER_ERROR; | 244 return gfx::VectorIconId::MEDIA_ROUTER_ERROR; |
287 if (issue_->severity() == media_router::Issue::WARNING) | 245 if (issue_->severity() == media_router::Issue::WARNING) |
288 return gfx::VectorIconId::MEDIA_ROUTER_WARNING; | 246 return gfx::VectorIconId::MEDIA_ROUTER_WARNING; |
289 } | 247 } |
290 | 248 |
291 return has_local_display_route_ ? gfx::VectorIconId::MEDIA_ROUTER_ACTIVE | 249 return has_local_display_route_ ? gfx::VectorIconId::MEDIA_ROUTER_ACTIVE |
292 : gfx::VectorIconId::MEDIA_ROUTER_IDLE; | 250 : gfx::VectorIconId::MEDIA_ROUTER_IDLE; |
293 } | 251 } |
294 | |
295 base::WeakPtr<MediaRouterAction> MediaRouterAction::GetWeakPtr() { | |
296 return weak_ptr_factory_.GetWeakPtr(); | |
297 } | |
OLD | NEW |