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 "ash/system/cast/tray_cast.h" | 5 #include "ash/system/cast/tray_cast.h" |
6 | 6 |
7 #include "ash/session/session_state_delegate.h" | 7 #include "ash/session/session_state_delegate.h" |
8 #include "ash/shelf/shelf_types.h" | 8 #include "ash/shelf/shelf_types.h" |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "ash/system/chromeos/screen_security/screen_tray_item.h" | 10 #include "ash/system/chromeos/screen_security/screen_tray_item.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "ui/views/controls/button/button.h" | 29 #include "ui/views/controls/button/button.h" |
30 #include "ui/views/controls/image_view.h" | 30 #include "ui/views/controls/image_view.h" |
31 #include "ui/views/controls/label.h" | 31 #include "ui/views/controls/label.h" |
32 #include "ui/views/layout/box_layout.h" | 32 #include "ui/views/layout/box_layout.h" |
33 #include "ui/views/layout/fill_layout.h" | 33 #include "ui/views/layout/fill_layout.h" |
34 | 34 |
35 namespace ash { | 35 namespace ash { |
36 | 36 |
37 namespace { | 37 namespace { |
38 const int kStopButtonRightPadding = 18; | 38 const int kStopButtonRightPadding = 18; |
| 39 |
| 40 // Returns the active CastConfigDelegate instance. |
| 41 ash::CastConfigDelegate* GetCastConfigDelegate() { |
| 42 return ash::Shell::GetInstance() |
| 43 ->system_tray_delegate() |
| 44 ->GetCastConfigDelegate(); |
| 45 } |
39 } // namespace | 46 } // namespace |
40 | 47 |
41 namespace tray { | 48 namespace tray { |
42 | 49 |
43 // This view is displayed in the system tray when the cast extension is active. | 50 // This view is displayed in the system tray when the cast extension is active. |
44 // It asks the user if they want to cast the desktop. If they click on the | 51 // It asks the user if they want to cast the desktop. If they click on the |
45 // chevron, then a detail view will replace this view where the user will | 52 // chevron, then a detail view will replace this view where the user will |
46 // actually pick the cast receiver. | 53 // actually pick the cast receiver. |
47 class CastSelectDefaultView : public TrayItemMore { | 54 class CastSelectDefaultView : public TrayItemMore { |
48 public: | 55 public: |
49 CastSelectDefaultView(SystemTrayItem* owner, | 56 CastSelectDefaultView(SystemTrayItem* owner, |
50 CastConfigDelegate* cast_config_delegate, | |
51 bool show_more); | 57 bool show_more); |
52 ~CastSelectDefaultView() override; | 58 ~CastSelectDefaultView() override; |
53 | 59 |
54 // Updates the label based on the current set of receivers (if there are or | |
55 // are not any available receivers). | |
56 void UpdateLabel(); | |
57 | |
58 private: | 60 private: |
59 void UpdateLabelCallback( | |
60 const CastConfigDelegate::ReceiversAndActivites& receivers_activities); | |
61 | |
62 CastConfigDelegate* cast_config_delegate_; | |
63 base::WeakPtrFactory<CastSelectDefaultView> weak_ptr_factory_; | |
64 DISALLOW_COPY_AND_ASSIGN(CastSelectDefaultView); | 61 DISALLOW_COPY_AND_ASSIGN(CastSelectDefaultView); |
65 }; | 62 }; |
66 | 63 |
67 CastSelectDefaultView::CastSelectDefaultView( | 64 CastSelectDefaultView::CastSelectDefaultView(SystemTrayItem* owner, |
68 SystemTrayItem* owner, | 65 bool show_more) |
69 CastConfigDelegate* cast_config_delegate, | 66 : TrayItemMore(owner, show_more) { |
70 bool show_more) | |
71 : TrayItemMore(owner, show_more), | |
72 cast_config_delegate_(cast_config_delegate), | |
73 weak_ptr_factory_(this) { | |
74 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 67 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 68 |
| 69 // Update the image and label. |
75 SetImage(rb.GetImageNamed(IDR_AURA_UBER_TRAY_CAST).ToImageSkia()); | 70 SetImage(rb.GetImageNamed(IDR_AURA_UBER_TRAY_CAST).ToImageSkia()); |
76 | 71 base::string16 label = |
77 // We first set a default label before we actually know what the label will | 72 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_DESKTOP); |
78 // be, because it could take awhile before UpdateLabel() actually applies | 73 SetLabel(label); |
79 // the correct label. | 74 SetAccessibleName(label); |
80 SetLabel(rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_NO_DEVICE)); | |
81 UpdateLabel(); | |
82 } | 75 } |
83 | 76 |
84 CastSelectDefaultView::~CastSelectDefaultView() { | 77 CastSelectDefaultView::~CastSelectDefaultView() {} |
85 } | |
86 | |
87 void CastSelectDefaultView::UpdateLabelCallback( | |
88 const CastConfigDelegate::ReceiversAndActivites& receivers_activities) { | |
89 // The label needs to reflect if there are no cast receivers | |
90 const base::string16 label = | |
91 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( | |
92 receivers_activities.empty() ? IDS_ASH_STATUS_TRAY_CAST_NO_DEVICE | |
93 : IDS_ASH_STATUS_TRAY_CAST_DESKTOP); | |
94 SetLabel(label); | |
95 SetAccessibleName(label); | |
96 SetVisible(true); | |
97 } | |
98 | |
99 void CastSelectDefaultView::UpdateLabel() { | |
100 if (cast_config_delegate_ == nullptr || | |
101 cast_config_delegate_->HasCastExtension() == false) | |
102 return; | |
103 | |
104 cast_config_delegate_->GetReceiversAndActivities( | |
105 base::Bind(&CastSelectDefaultView::UpdateLabelCallback, | |
106 weak_ptr_factory_.GetWeakPtr())); | |
107 } | |
108 | 78 |
109 // This view is displayed when the screen is actively being casted; it allows | 79 // This view is displayed when the screen is actively being casted; it allows |
110 // the user to easily stop casting. It fully replaces the | 80 // the user to easily stop casting. It fully replaces the |
111 // |CastSelectDefaultView| view inside of the |CastDuplexView|. | 81 // |CastSelectDefaultView| view inside of the |CastDuplexView|. |
112 class CastCastView : public views::View, public views::ButtonListener { | 82 class CastCastView : public views::View, public views::ButtonListener { |
113 public: | 83 public: |
114 explicit CastCastView(CastConfigDelegate* cast_config_delegate); | 84 CastCastView(); |
115 ~CastCastView() override; | 85 ~CastCastView() override; |
116 | 86 |
117 void StopCasting(); | 87 void StopCasting(); |
118 | 88 |
119 // Updates the label for the stop view to include information about the | 89 // Updates the label for the stop view to include information about the |
120 // current device that is being casted. | 90 // current device that is being casted. |
121 void UpdateLabel(); | 91 void UpdateLabel( |
| 92 const CastConfigDelegate::ReceiversAndActivites& receivers_activities); |
122 | 93 |
123 private: | 94 private: |
124 void UpdateLabelCallback( | |
125 const CastConfigDelegate::ReceiversAndActivites& receivers_activities); | |
126 | |
127 // Overridden from views::View. | 95 // Overridden from views::View. |
128 int GetHeightForWidth(int width) const override; | 96 int GetHeightForWidth(int width) const override; |
129 void Layout() override; | 97 void Layout() override; |
130 | 98 |
131 // Overridden from views::ButtonListener. | 99 // Overridden from views::ButtonListener. |
132 void ButtonPressed(views::Button* sender, const ui::Event& event) override; | 100 void ButtonPressed(views::Button* sender, const ui::Event& event) override; |
133 | 101 |
134 CastConfigDelegate* cast_config_delegate_; | |
135 views::ImageView* icon_; | 102 views::ImageView* icon_; |
136 views::Label* label_; | 103 views::Label* label_; |
137 TrayPopupLabelButton* stop_button_; | 104 TrayPopupLabelButton* stop_button_; |
138 base::WeakPtrFactory<CastCastView> weak_ptr_factory_; | 105 base::WeakPtrFactory<CastCastView> weak_ptr_factory_; |
139 | 106 |
140 DISALLOW_COPY_AND_ASSIGN(CastCastView); | 107 DISALLOW_COPY_AND_ASSIGN(CastCastView); |
141 }; | 108 }; |
142 | 109 |
143 CastCastView::CastCastView(CastConfigDelegate* cast_config_delegate) | 110 CastCastView::CastCastView() : weak_ptr_factory_(this) { |
144 : cast_config_delegate_(cast_config_delegate), weak_ptr_factory_(this) { | |
145 // We will initialize the primary tray view which shows a stop button here. | 111 // We will initialize the primary tray view which shows a stop button here. |
146 | 112 |
147 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); | 113 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); |
148 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | 114 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); |
149 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, | 115 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, |
150 kTrayPopupPaddingHorizontal, 0, | 116 kTrayPopupPaddingHorizontal, 0, |
151 kTrayPopupPaddingBetweenItems)); | 117 kTrayPopupPaddingBetweenItems)); |
152 icon_ = new FixedSizedImageView(0, kTrayPopupItemHeight); | 118 icon_ = new FixedSizedImageView(0, kTrayPopupItemHeight); |
153 icon_->SetImage( | 119 icon_->SetImage( |
154 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAST_ENABLED).ToImageSkia()); | 120 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAST_ENABLED).ToImageSkia()); |
155 AddChildView(icon_); | 121 AddChildView(icon_); |
156 | 122 |
157 // The label which describes both what we are casting (ie, the desktop) and | 123 // The label which describes both what we are casting (ie, the desktop) and |
158 // where we are casting it to. | 124 // where we are casting it to. |
159 label_ = new views::Label; | 125 label_ = new views::Label; |
160 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 126 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
161 label_->SetMultiLine(true); | 127 label_->SetMultiLine(true); |
162 label_->SetText( | 128 label_->SetText( |
163 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN)); | 129 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN)); |
164 AddChildView(label_); | 130 AddChildView(label_); |
165 | 131 |
166 // Add the stop bottom on the far-right. We customize how this stop button is | 132 // Add the stop bottom on the far-right. We customize how this stop button is |
167 // displayed inside of |Layout()|. | 133 // displayed inside of |Layout()|. |
168 base::string16 stop_button_text = | 134 base::string16 stop_button_text = |
169 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( | 135 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( |
170 IDS_ASH_STATUS_TRAY_CAST_STOP); | 136 IDS_ASH_STATUS_TRAY_CAST_STOP); |
171 stop_button_ = new TrayPopupLabelButton(this, stop_button_text); | 137 stop_button_ = new TrayPopupLabelButton(this, stop_button_text); |
172 AddChildView(stop_button_); | 138 AddChildView(stop_button_); |
173 | |
174 UpdateLabel(); | |
175 } | 139 } |
176 | 140 |
177 CastCastView::~CastCastView() { | 141 CastCastView::~CastCastView() { |
178 } | 142 } |
179 | 143 |
180 int CastCastView::GetHeightForWidth(int width) const { | 144 int CastCastView::GetHeightForWidth(int width) const { |
181 // We are reusing the cached label_->bounds() calculation which was | 145 // We are reusing the cached label_->bounds() calculation which was |
182 // done inside of Layout(). Due to the way this object is initialized, | 146 // done inside of Layout(). Due to the way this object is initialized, |
183 // Layout() will always get initially invoked with the dummy text | 147 // Layout() will always get initially invoked with the dummy text |
184 // (which will compute the proper label width) and then when we know | 148 // (which will compute the proper label width) and then when we know |
(...skipping 17 matching lines...) Expand all Loading... |
202 // Adjust the label's bounds in case it got cut off by |stop_button_|. | 166 // Adjust the label's bounds in case it got cut off by |stop_button_|. |
203 if (label_->bounds().Intersects(stop_button_->bounds())) { | 167 if (label_->bounds().Intersects(stop_button_->bounds())) { |
204 gfx::Rect label_bounds = label_->bounds(); | 168 gfx::Rect label_bounds = label_->bounds(); |
205 label_bounds.set_width(stop_button_->x() - kTrayPopupPaddingBetweenItems - | 169 label_bounds.set_width(stop_button_->x() - kTrayPopupPaddingBetweenItems - |
206 label_->x()); | 170 label_->x()); |
207 label_->SetBoundsRect(label_bounds); | 171 label_->SetBoundsRect(label_bounds); |
208 } | 172 } |
209 } | 173 } |
210 | 174 |
211 void CastCastView::StopCasting() { | 175 void CastCastView::StopCasting() { |
212 cast_config_delegate_->StopCasting(); | 176 GetCastConfigDelegate()->StopCasting(); |
213 Shell::GetInstance()->metrics()->RecordUserMetricsAction( | 177 Shell::GetInstance()->metrics()->RecordUserMetricsAction( |
214 ash::UMA_STATUS_AREA_CAST_STOP_CAST); | 178 ash::UMA_STATUS_AREA_CAST_STOP_CAST); |
215 } | 179 } |
216 | 180 |
217 void CastCastView::UpdateLabel() { | 181 void CastCastView::UpdateLabel( |
218 if (cast_config_delegate_ == nullptr || | |
219 cast_config_delegate_->HasCastExtension() == false) | |
220 return; | |
221 | |
222 cast_config_delegate_->GetReceiversAndActivities(base::Bind( | |
223 &CastCastView::UpdateLabelCallback, weak_ptr_factory_.GetWeakPtr())); | |
224 } | |
225 | |
226 void CastCastView::UpdateLabelCallback( | |
227 const CastConfigDelegate::ReceiversAndActivites& receivers_activities) { | 182 const CastConfigDelegate::ReceiversAndActivites& receivers_activities) { |
228 for (auto& i : receivers_activities) { | 183 for (auto& i : receivers_activities) { |
229 const CastConfigDelegate::Receiver receiver = i.second.receiver; | 184 const CastConfigDelegate::Receiver& receiver = i.receiver; |
230 const CastConfigDelegate::Activity activity = i.second.activity; | 185 const CastConfigDelegate::Activity& activity = i.activity; |
231 if (!activity.id.empty()) { | 186 if (!activity.id.empty()) { |
232 // We want to display different labels inside of the title depending on | 187 // We want to display different labels inside of the title depending on |
233 // what we are actually casting - either the desktop, a tab, or a fallback | 188 // what we are actually casting - either the desktop, a tab, or a fallback |
234 // that catches everything else (ie, an extension tab). | 189 // that catches everything else (ie, an extension tab). |
235 if (activity.tab_id == CastConfigDelegate::Activity::TabId::DESKTOP) { | 190 if (activity.tab_id == CastConfigDelegate::Activity::TabId::DESKTOP) { |
236 label_->SetText(l10n_util::GetStringFUTF16( | 191 label_->SetText(l10n_util::GetStringFUTF16( |
237 IDS_ASH_STATUS_TRAY_CAST_CAST_DESKTOP, receiver.name)); | 192 IDS_ASH_STATUS_TRAY_CAST_CAST_DESKTOP, receiver.name)); |
238 } else if (activity.tab_id >= 0) { | 193 } else if (activity.tab_id >= 0) { |
239 label_->SetText(l10n_util::GetStringFUTF16( | 194 label_->SetText(l10n_util::GetStringFUTF16( |
240 IDS_ASH_STATUS_TRAY_CAST_CAST_TAB, activity.title, receiver.name)); | 195 IDS_ASH_STATUS_TRAY_CAST_CAST_TAB, activity.title, receiver.name)); |
(...skipping 13 matching lines...) Expand all Loading... |
254 const ui::Event& event) { | 209 const ui::Event& event) { |
255 DCHECK(sender == stop_button_); | 210 DCHECK(sender == stop_button_); |
256 StopCasting(); | 211 StopCasting(); |
257 } | 212 } |
258 | 213 |
259 // This view by itself does very little. It acts as a front-end for managing | 214 // This view by itself does very little. It acts as a front-end for managing |
260 // which of the two child views (|CastSelectDefaultView| and |CastCastView|) | 215 // which of the two child views (|CastSelectDefaultView| and |CastCastView|) |
261 // is active. | 216 // is active. |
262 class CastDuplexView : public views::View { | 217 class CastDuplexView : public views::View { |
263 public: | 218 public: |
264 CastDuplexView(SystemTrayItem* owner, | 219 CastDuplexView( |
265 CastConfigDelegate* config_delegate, | 220 SystemTrayItem* owner, |
266 bool show_more); | 221 bool show_more, |
| 222 const CastConfigDelegate::ReceiversAndActivites& receivers_activities); |
267 ~CastDuplexView() override; | 223 ~CastDuplexView() override; |
268 | 224 |
269 // Activate either the casting or select view. | 225 // Activate either the casting or select view. |
270 void ActivateCastView(); | 226 void ActivateCastView(); |
271 void ActivateSelectView(); | 227 void ActivateSelectView(); |
272 | 228 |
273 CastSelectDefaultView* select_view() { return select_view_; } | 229 CastSelectDefaultView* select_view() { return select_view_; } |
274 CastCastView* cast_view() { return cast_view_; } | 230 CastCastView* cast_view() { return cast_view_; } |
275 | 231 |
276 private: | 232 private: |
277 // Overridden from views::View. | 233 // Overridden from views::View. |
278 void ChildPreferredSizeChanged(views::View* child) override; | 234 void ChildPreferredSizeChanged(views::View* child) override; |
279 void Layout() override; | 235 void Layout() override; |
280 | 236 |
281 // Only one of |select_view_| or |cast_view_| will be displayed at any given | 237 // Only one of |select_view_| or |cast_view_| will be displayed at any given |
282 // time. This will return the view is being displayed. | 238 // time. This will return the view is being displayed. |
283 views::View* ActiveChildView(); | 239 views::View* ActiveChildView(); |
284 | 240 |
285 CastSelectDefaultView* select_view_; | 241 CastSelectDefaultView* select_view_; |
286 CastCastView* cast_view_; | 242 CastCastView* cast_view_; |
287 | 243 |
288 DISALLOW_COPY_AND_ASSIGN(CastDuplexView); | 244 DISALLOW_COPY_AND_ASSIGN(CastDuplexView); |
289 }; | 245 }; |
290 | 246 |
291 CastDuplexView::CastDuplexView(SystemTrayItem* owner, | 247 CastDuplexView::CastDuplexView( |
292 CastConfigDelegate* config_delegate, | 248 SystemTrayItem* owner, |
293 bool show_more) { | 249 bool show_more, |
294 select_view_ = new CastSelectDefaultView(owner, config_delegate, show_more); | 250 const CastConfigDelegate::ReceiversAndActivites& receivers_activities) { |
295 cast_view_ = new CastCastView(config_delegate); | 251 select_view_ = new CastSelectDefaultView(owner, show_more); |
| 252 cast_view_ = new CastCastView(); |
| 253 cast_view_->UpdateLabel(receivers_activities); |
296 SetLayoutManager(new views::FillLayout()); | 254 SetLayoutManager(new views::FillLayout()); |
297 | 255 |
298 ActivateSelectView(); | 256 ActivateSelectView(); |
299 } | 257 } |
300 | 258 |
301 CastDuplexView::~CastDuplexView() { | 259 CastDuplexView::~CastDuplexView() { |
302 RemoveChildView(ActiveChildView()); | 260 RemoveChildView(ActiveChildView()); |
303 delete select_view_; | 261 delete select_view_; |
304 delete cast_view_; | 262 delete cast_view_; |
305 } | 263 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 SetLayoutManager(new views::BoxLayout(layout, 0, 0, 0)); | 341 SetLayoutManager(new views::BoxLayout(layout, 0, 0, 0)); |
384 Layout(); | 342 Layout(); |
385 } | 343 } |
386 | 344 |
387 // This view displays a list of cast receivers that can be clicked on and casted | 345 // This view displays a list of cast receivers that can be clicked on and casted |
388 // to. It is activated by clicking on the chevron inside of | 346 // to. It is activated by clicking on the chevron inside of |
389 // |CastSelectDefaultView|. | 347 // |CastSelectDefaultView|. |
390 class CastDetailedView : public TrayDetailsView, public ViewClickListener { | 348 class CastDetailedView : public TrayDetailsView, public ViewClickListener { |
391 public: | 349 public: |
392 CastDetailedView(SystemTrayItem* owner, | 350 CastDetailedView(SystemTrayItem* owner, |
393 CastConfigDelegate* cast_config_delegate, | 351 user::LoginStatus login, |
394 user::LoginStatus login); | 352 const CastConfigDelegate::ReceiversAndActivites& |
| 353 receivers_and_activities); |
395 ~CastDetailedView() override; | 354 ~CastDetailedView() override; |
396 | 355 |
397 // Makes the detail view think the view associated with the given receiver_id | 356 // Makes the detail view think the view associated with the given receiver_id |
398 // was clicked. This will start a cast. | 357 // was clicked. This will start a cast. |
399 void SimulateViewClickedForTest(const std::string& receiver_id); | 358 void SimulateViewClickedForTest(const std::string& receiver_id); |
400 | 359 |
| 360 // Updates the list of available receivers. |
| 361 void UpdateReceiverList(const CastConfigDelegate::ReceiversAndActivites& |
| 362 new_receivers_and_activities); |
| 363 |
401 private: | 364 private: |
402 void CreateItems(); | 365 void CreateItems(); |
403 | 366 |
404 void UpdateReceiverList(); | |
405 void UpdateReceiverListCallback( | |
406 const CastConfigDelegate::ReceiversAndActivites& | |
407 new_receivers_and_activities); | |
408 void UpdateReceiverListFromCachedData(); | 367 void UpdateReceiverListFromCachedData(); |
409 views::View* AddToReceiverList( | 368 views::View* AddToReceiverList( |
410 const CastConfigDelegate::ReceiverAndActivity& receiverActivity); | 369 const CastConfigDelegate::ReceiverAndActivity& receiverActivity); |
411 | 370 |
412 void AppendSettingsEntries(); | 371 void AppendSettingsEntries(); |
413 void AppendHeaderEntry(); | 372 void AppendHeaderEntry(); |
414 | 373 |
415 // Overridden from ViewClickListener. | 374 // Overridden from ViewClickListener. |
416 void OnViewClicked(views::View* sender) override; | 375 void OnViewClicked(views::View* sender) override; |
417 | 376 |
418 CastConfigDelegate* cast_config_delegate_; | |
419 user::LoginStatus login_; | 377 user::LoginStatus login_; |
420 views::View* options_ = nullptr; | 378 views::View* options_ = nullptr; |
421 CastConfigDelegate::ReceiversAndActivites receivers_and_activities_; | 379 // A mapping from the receiver id to the receiver/activity data. |
422 // A mapping from the view pointer to the associated activity id | 380 std::map<std::string, CastConfigDelegate::ReceiverAndActivity> |
| 381 receivers_and_activities_; |
| 382 // A mapping from the view pointer to the associated activity id. |
423 std::map<views::View*, std::string> receiver_activity_map_; | 383 std::map<views::View*, std::string> receiver_activity_map_; |
424 base::WeakPtrFactory<CastDetailedView> weak_ptr_factory_; | 384 base::WeakPtrFactory<CastDetailedView> weak_ptr_factory_; |
425 | 385 |
426 DISALLOW_COPY_AND_ASSIGN(CastDetailedView); | 386 DISALLOW_COPY_AND_ASSIGN(CastDetailedView); |
427 }; | 387 }; |
428 | 388 |
429 CastDetailedView::CastDetailedView(SystemTrayItem* owner, | 389 CastDetailedView::CastDetailedView( |
430 CastConfigDelegate* cast_config_delegate, | 390 SystemTrayItem* owner, |
431 user::LoginStatus login) | 391 user::LoginStatus login, |
432 : TrayDetailsView(owner), | 392 const CastConfigDelegate::ReceiversAndActivites& receivers_and_activities) |
433 cast_config_delegate_(cast_config_delegate), | 393 : TrayDetailsView(owner), login_(login), weak_ptr_factory_(this) { |
434 login_(login), | |
435 weak_ptr_factory_(this) { | |
436 CreateItems(); | 394 CreateItems(); |
437 UpdateReceiverList(); | 395 UpdateReceiverList(receivers_and_activities); |
438 } | 396 } |
439 | 397 |
440 CastDetailedView::~CastDetailedView() { | 398 CastDetailedView::~CastDetailedView() { |
441 } | 399 } |
442 | 400 |
443 void CastDetailedView::SimulateViewClickedForTest( | 401 void CastDetailedView::SimulateViewClickedForTest( |
444 const std::string& receiver_id) { | 402 const std::string& receiver_id) { |
445 for (auto& it : receiver_activity_map_) { | 403 for (auto& it : receiver_activity_map_) { |
446 if (it.second == receiver_id) { | 404 if (it.second == receiver_id) { |
447 OnViewClicked(it.first); | 405 OnViewClicked(it.first); |
448 break; | 406 break; |
449 } | 407 } |
450 } | 408 } |
451 } | 409 } |
452 | 410 |
453 void CastDetailedView::CreateItems() { | 411 void CastDetailedView::CreateItems() { |
454 CreateScrollableList(); | 412 CreateScrollableList(); |
455 AppendSettingsEntries(); | 413 AppendSettingsEntries(); |
456 AppendHeaderEntry(); | 414 AppendHeaderEntry(); |
457 } | 415 } |
458 | 416 |
459 void CastDetailedView::UpdateReceiverList() { | 417 void CastDetailedView::UpdateReceiverList( |
460 cast_config_delegate_->GetReceiversAndActivities( | |
461 base::Bind(&CastDetailedView::UpdateReceiverListCallback, | |
462 weak_ptr_factory_.GetWeakPtr())); | |
463 } | |
464 | |
465 void CastDetailedView::UpdateReceiverListCallback( | |
466 const CastConfigDelegate::ReceiversAndActivites& | 418 const CastConfigDelegate::ReceiversAndActivites& |
467 new_receivers_and_activities) { | 419 new_receivers_and_activities) { |
468 // Add/update existing. | 420 // Add/update existing. |
469 for (auto i = new_receivers_and_activities.begin(); | 421 for (auto i = new_receivers_and_activities.begin(); |
470 i != new_receivers_and_activities.end(); ++i) { | 422 i != new_receivers_and_activities.end(); ++i) { |
471 receivers_and_activities_[i->first] = i->second; | 423 receivers_and_activities_[i->receiver.id] = *i; |
472 } | 424 } |
473 // Remove non-existent. | 425 |
474 for (auto i = receivers_and_activities_.begin(); | 426 // Remove non-existent receivers. Removing an element invalidates all existing |
475 i != receivers_and_activities_.end(); ++i) { | 427 // iterators. |
476 if (new_receivers_and_activities.count(i->first) == 0) | 428 auto i = receivers_and_activities_.begin(); |
477 receivers_and_activities_.erase(i->first); | 429 while (i != receivers_and_activities_.end()) { |
| 430 bool has_receiver = false; |
| 431 for (auto receiver : new_receivers_and_activities) { |
| 432 if (i->first == receiver.receiver.id) |
| 433 has_receiver = true; |
| 434 } |
| 435 |
| 436 if (has_receiver) |
| 437 ++i; |
| 438 else |
| 439 i = receivers_and_activities_.erase(i); |
478 } | 440 } |
479 | 441 |
480 // Update UI. | 442 // Update UI. |
481 UpdateReceiverListFromCachedData(); | 443 UpdateReceiverListFromCachedData(); |
482 Layout(); | 444 Layout(); |
483 } | 445 } |
484 | 446 |
485 void CastDetailedView::UpdateReceiverListFromCachedData() { | 447 void CastDetailedView::UpdateReceiverListFromCachedData() { |
486 // Remove all of the existing views. | 448 // Remove all of the existing views. |
487 receiver_activity_map_.clear(); | 449 receiver_activity_map_.clear(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 | 493 |
532 AddChildView(container); | 494 AddChildView(container); |
533 options_ = container; | 495 options_ = container; |
534 } | 496 } |
535 | 497 |
536 void CastDetailedView::AppendHeaderEntry() { | 498 void CastDetailedView::AppendHeaderEntry() { |
537 CreateSpecialRow(IDS_ASH_STATUS_TRAY_CAST, this); | 499 CreateSpecialRow(IDS_ASH_STATUS_TRAY_CAST, this); |
538 } | 500 } |
539 | 501 |
540 void CastDetailedView::OnViewClicked(views::View* sender) { | 502 void CastDetailedView::OnViewClicked(views::View* sender) { |
| 503 ash::CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate(); |
| 504 |
541 if (sender == footer()->content()) { | 505 if (sender == footer()->content()) { |
542 TransitionToDefaultView(); | 506 TransitionToDefaultView(); |
543 } else if (sender == options_) { | 507 } else if (sender == options_) { |
544 cast_config_delegate_->LaunchCastOptions(); | 508 cast_config_delegate->LaunchCastOptions(); |
545 } else { | 509 } else { |
546 // Find the receiver we are going to cast to | 510 // Find the receiver we are going to cast to |
547 auto it = receiver_activity_map_.find(sender); | 511 auto it = receiver_activity_map_.find(sender); |
548 if (it != receiver_activity_map_.end()) { | 512 if (it != receiver_activity_map_.end()) { |
549 cast_config_delegate_->CastToReceiver(it->second); | 513 cast_config_delegate->CastToReceiver(it->second); |
550 Shell::GetInstance()->metrics()->RecordUserMetricsAction( | 514 Shell::GetInstance()->metrics()->RecordUserMetricsAction( |
551 ash::UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST); | 515 ash::UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST); |
552 } | 516 } |
553 } | 517 } |
554 } | 518 } |
555 | 519 |
556 } // namespace tray | 520 } // namespace tray |
557 | 521 |
558 TrayCast::TrayCast(SystemTray* system_tray) | 522 TrayCast::TrayCast(SystemTray* system_tray) |
559 : SystemTrayItem(system_tray), | 523 : SystemTrayItem(system_tray), |
560 cast_config_delegate_(ash::Shell::GetInstance() | |
561 ->system_tray_delegate() | |
562 ->GetCastConfigDelegate()), | |
563 weak_ptr_factory_(this) { | 524 weak_ptr_factory_(this) { |
564 Shell::GetInstance()->AddShellObserver(this); | 525 Shell::GetInstance()->AddShellObserver(this); |
565 } | 526 } |
566 | 527 |
567 TrayCast::~TrayCast() { | 528 TrayCast::~TrayCast() { |
568 Shell::GetInstance()->RemoveShellObserver(this); | 529 Shell::GetInstance()->RemoveShellObserver(this); |
569 } | 530 } |
570 | 531 |
571 void TrayCast::StartCastForTest(const std::string& receiver_id) { | 532 void TrayCast::StartCastForTest(const std::string& receiver_id) { |
572 if (detailed_ != nullptr) | 533 if (detailed_ != nullptr) |
(...skipping 11 matching lines...) Expand all Loading... |
584 views::View* TrayCast::CreateTrayView(user::LoginStatus status) { | 545 views::View* TrayCast::CreateTrayView(user::LoginStatus status) { |
585 CHECK(tray_ == nullptr); | 546 CHECK(tray_ == nullptr); |
586 tray_ = new tray::CastTrayView(this); | 547 tray_ = new tray::CastTrayView(this); |
587 tray_->SetVisible(is_casting_); | 548 tray_->SetVisible(is_casting_); |
588 return tray_; | 549 return tray_; |
589 } | 550 } |
590 | 551 |
591 views::View* TrayCast::CreateDefaultView(user::LoginStatus status) { | 552 views::View* TrayCast::CreateDefaultView(user::LoginStatus status) { |
592 CHECK(default_ == nullptr); | 553 CHECK(default_ == nullptr); |
593 | 554 |
594 default_ = new tray::CastDuplexView(this, cast_config_delegate_, | 555 if (HasCastExtension()) { |
595 status != user::LOGGED_IN_LOCKED); | 556 ash::CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate(); |
| 557 |
| 558 // We add the cast listener here instead of in the ctor for two reasons: |
| 559 // - The ctor gets called too early in the initialization cycle (at least |
| 560 // for the tests); the correct profile hasn't been setup yet. |
| 561 // - The listener is only added if there is a cast extension. If the call |
| 562 // below were in the ctor, then the cast tray item would not appear if the |
| 563 // user installed the extension in an existing session. |
| 564 if (!device_update_subscription_) { |
| 565 device_update_subscription_ = |
| 566 cast_config_delegate->RegisterDeviceUpdateObserver(base::Bind( |
| 567 &TrayCast::OnReceiversUpdated, weak_ptr_factory_.GetWeakPtr())); |
| 568 } |
| 569 |
| 570 // The extension updates its view model whenever the popup is opened, so we |
| 571 // probably should as well. |
| 572 cast_config_delegate->RequestDeviceRefresh(); |
| 573 } |
| 574 |
| 575 default_ = new tray::CastDuplexView(this, status != user::LOGGED_IN_LOCKED, |
| 576 receivers_and_activities_); |
596 default_->set_id(TRAY_VIEW); | 577 default_->set_id(TRAY_VIEW); |
597 default_->select_view()->set_id(SELECT_VIEW); | 578 default_->select_view()->set_id(SELECT_VIEW); |
598 default_->cast_view()->set_id(CAST_VIEW); | 579 default_->cast_view()->set_id(CAST_VIEW); |
599 | 580 |
600 UpdatePrimaryView(); | 581 UpdatePrimaryView(); |
601 return default_; | 582 return default_; |
602 } | 583 } |
603 | 584 |
604 views::View* TrayCast::CreateDetailedView(user::LoginStatus status) { | 585 views::View* TrayCast::CreateDetailedView(user::LoginStatus status) { |
605 Shell::GetInstance()->metrics()->RecordUserMetricsAction( | 586 Shell::GetInstance()->metrics()->RecordUserMetricsAction( |
606 ash::UMA_STATUS_AREA_DETAILED_CAST_VIEW); | 587 ash::UMA_STATUS_AREA_DETAILED_CAST_VIEW); |
607 CHECK(detailed_ == nullptr); | 588 CHECK(detailed_ == nullptr); |
608 detailed_ = new tray::CastDetailedView(this, cast_config_delegate_, status); | 589 detailed_ = |
| 590 new tray::CastDetailedView(this, status, receivers_and_activities_); |
609 return detailed_; | 591 return detailed_; |
610 } | 592 } |
611 | 593 |
612 void TrayCast::DestroyTrayView() { | 594 void TrayCast::DestroyTrayView() { |
613 tray_ = nullptr; | 595 tray_ = nullptr; |
614 } | 596 } |
615 | 597 |
616 void TrayCast::DestroyDefaultView() { | 598 void TrayCast::DestroyDefaultView() { |
617 default_ = nullptr; | 599 default_ = nullptr; |
618 } | 600 } |
619 | 601 |
620 void TrayCast::DestroyDetailedView() { | 602 void TrayCast::DestroyDetailedView() { |
621 detailed_ = nullptr; | 603 detailed_ = nullptr; |
622 } | 604 } |
623 | 605 |
624 bool TrayCast::HasCastExtension() { | 606 bool TrayCast::HasCastExtension() { |
625 return cast_config_delegate_ != nullptr && | 607 ash::CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate(); |
626 cast_config_delegate_->HasCastExtension(); | 608 return cast_config_delegate != nullptr && |
| 609 cast_config_delegate->HasCastExtension(); |
627 } | 610 } |
628 | 611 |
629 void TrayCast::UpdateCachedReceiverState( | 612 void TrayCast::OnReceiversUpdated( |
630 const CastConfigDelegate::ReceiversAndActivites& receivers_activities) { | 613 const CastConfigDelegate::ReceiversAndActivites& receivers_activities) { |
631 has_cast_receivers_ = !receivers_activities.empty(); | 614 receivers_and_activities_ = receivers_activities; |
632 if (default_) | 615 |
633 default_->SetVisible(has_cast_receivers_); | 616 if (default_) { |
| 617 bool has_receivers = !receivers_and_activities_.empty(); |
| 618 default_->SetVisible(has_receivers); |
| 619 default_->cast_view()->UpdateLabel(receivers_and_activities_); |
| 620 } |
| 621 if (detailed_) |
| 622 detailed_->UpdateReceiverList(receivers_and_activities_); |
634 } | 623 } |
635 | 624 |
636 void TrayCast::UpdatePrimaryView() { | 625 void TrayCast::UpdatePrimaryView() { |
637 if (HasCastExtension()) { | 626 if (HasCastExtension()) { |
638 if (default_) { | 627 if (default_) { |
639 if (is_casting_) { | 628 if (is_casting_) |
640 default_->ActivateCastView(); | 629 default_->ActivateCastView(); |
641 } else { | 630 else |
642 default_->ActivateSelectView(); | 631 default_->ActivateSelectView(); |
643 | |
644 // We only want to show the select view if we have a receiver we can | |
645 // cast to. To prevent showing the tray item and then hiding it some | |
646 // short time after, we cache if we have any receivers. We set our | |
647 // default visibility to true if we do have a receiver, false otherwise. | |
648 default_->SetVisible(has_cast_receivers_); | |
649 cast_config_delegate_->GetReceiversAndActivities( | |
650 base::Bind(&TrayCast::UpdateCachedReceiverState, | |
651 weak_ptr_factory_.GetWeakPtr())); | |
652 } | |
653 } | 632 } |
654 | 633 |
655 if (tray_) | 634 if (tray_) |
656 tray_->SetVisible(is_casting_); | 635 tray_->SetVisible(is_casting_); |
657 } else { | 636 } else { |
658 if (default_) | 637 if (default_) |
659 default_->SetVisible(false); | 638 default_->SetVisible(false); |
660 if (tray_) | 639 if (tray_) |
661 tray_->SetVisible(false); | 640 tray_->SetVisible(false); |
662 } | 641 } |
663 } | 642 } |
664 | 643 |
665 void TrayCast::OnCastingSessionStartedOrStopped(bool started) { | 644 void TrayCast::OnCastingSessionStartedOrStopped(bool started) { |
666 is_casting_ = started; | 645 is_casting_ = started; |
667 UpdatePrimaryView(); | 646 UpdatePrimaryView(); |
668 } | 647 } |
669 | 648 |
670 void TrayCast::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { | 649 void TrayCast::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { |
671 if (tray_) | 650 if (tray_) |
672 tray_->UpdateAlignment(alignment); | 651 tray_->UpdateAlignment(alignment); |
673 } | 652 } |
674 | 653 |
675 } // namespace ash | 654 } // namespace ash |
OLD | NEW |