| 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 |