| 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/common/system/chromeos/cast/tray_cast.h" | 5 #include "ash/common/system/chromeos/cast/tray_cast.h" |
| 6 | 6 |
| 7 #include "ash/common/material_design/material_design_controller.h" | 7 #include "ash/common/material_design/material_design_controller.h" |
| 8 #include "ash/common/session/session_state_delegate.h" | 8 #include "ash/common/session/session_state_delegate.h" |
| 9 #include "ash/common/shelf/wm_shelf_util.h" | 9 #include "ash/common/shelf/wm_shelf_util.h" |
| 10 #include "ash/common/system/chromeos/screen_security/screen_tray_item.h" | 10 #include "ash/common/system/chromeos/screen_security/screen_tray_item.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #include "ui/views/layout/fill_layout.h" | 39 #include "ui/views/layout/fill_layout.h" |
| 40 | 40 |
| 41 namespace ash { | 41 namespace ash { |
| 42 | 42 |
| 43 namespace { | 43 namespace { |
| 44 | 44 |
| 45 const size_t kMaximumStatusStringLength = 100; | 45 const size_t kMaximumStatusStringLength = 100; |
| 46 | 46 |
| 47 // Returns the active CastConfigDelegate instance. | 47 // Returns the active CastConfigDelegate instance. |
| 48 CastConfigDelegate* GetCastConfigDelegate() { | 48 CastConfigDelegate* GetCastConfigDelegate() { |
| 49 return WmShell::Get()->system_tray_delegate()->GetCastConfigDelegate(); | 49 ash::SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate(); |
| 50 return delegate ? delegate->GetCastConfigDelegate() : nullptr; |
| 50 } | 51 } |
| 51 | 52 |
| 52 // Helper method to elide the given string to the maximum length. If a string is | 53 // Helper method to elide the given string to the maximum length. If a string is |
| 53 // contains user-input and is displayed, we should elide it. | 54 // contains user-input and is displayed, we should elide it. |
| 54 // TODO(jdufault): This does not properly trim unicode characters. We should | 55 // TODO(jdufault): This does not properly trim unicode characters. We should |
| 55 // implement this properly by using views::Label::SetElideBehavior(...). See | 56 // implement this properly by using views::Label::SetElideBehavior(...). See |
| 56 // crbug.com/532496. | 57 // crbug.com/532496. |
| 57 base::string16 ElideString(const base::string16& text) { | 58 base::string16 ElideString(const base::string16& text) { |
| 58 base::string16 elided; | 59 base::string16 elided; |
| 59 gfx::ElideString(text, kMaximumStatusStringLength, &elided); | 60 gfx::ElideString(text, kMaximumStatusStringLength, &elided); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 // This view is displayed when the screen is actively being casted; it allows | 107 // This view is displayed when the screen is actively being casted; it allows |
| 107 // the user to easily stop casting. It fully replaces the | 108 // the user to easily stop casting. It fully replaces the |
| 108 // |CastSelectDefaultView| view inside of the |CastDuplexView|. | 109 // |CastSelectDefaultView| view inside of the |CastDuplexView|. |
| 109 class CastCastView : public ScreenStatusView { | 110 class CastCastView : public ScreenStatusView { |
| 110 public: | 111 public: |
| 111 CastCastView(); | 112 CastCastView(); |
| 112 ~CastCastView() override; | 113 ~CastCastView() override; |
| 113 | 114 |
| 114 void StopCasting(); | 115 void StopCasting(); |
| 115 | 116 |
| 116 const std::string& displayed_route_id() const { return displayed_route_id_; } | 117 const std::string& displayed_route_id() const { return displayed_route_.id; } |
| 117 | 118 |
| 118 // Updates the label for the stop view to include information about the | 119 // Updates the label for the stop view to include information about the |
| 119 // current device that is being casted. | 120 // current device that is being casted. |
| 120 void UpdateLabel(const CastConfigDelegate::SinksAndRoutes& sinks_routes); | 121 void UpdateLabel(const CastConfigDelegate::SinksAndRoutes& sinks_routes); |
| 121 | 122 |
| 122 private: | 123 private: |
| 123 // Overridden from views::ButtonListener. | 124 // Overridden from views::ButtonListener. |
| 124 void ButtonPressed(views::Button* sender, const ui::Event& event) override; | 125 void ButtonPressed(views::Button* sender, const ui::Event& event) override; |
| 125 | 126 |
| 126 // The cast activity id that we are displaying. If the user stops a cast, we | 127 // The cast activity id that we are displaying. If the user stops a cast, we |
| 127 // send this value to the config delegate so that we stop the right cast. | 128 // send this value to the config delegate so that we stop the right cast. |
| 128 std::string displayed_route_id_; | 129 CastConfigDelegate::Route displayed_route_; |
| 129 | 130 |
| 130 DISALLOW_COPY_AND_ASSIGN(CastCastView); | 131 DISALLOW_COPY_AND_ASSIGN(CastCastView); |
| 131 }; | 132 }; |
| 132 | 133 |
| 133 CastCastView::CastCastView() | 134 CastCastView::CastCastView() |
| 134 : ScreenStatusView( | 135 : ScreenStatusView( |
| 135 nullptr, | 136 nullptr, |
| 136 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN), | 137 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN), |
| 137 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_STOP)) { | 138 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_STOP)) { |
| 138 if (MaterialDesignController::IsSystemTrayMenuMaterial()) { | 139 if (MaterialDesignController::IsSystemTrayMenuMaterial()) { |
| 139 icon()->SetImage(GetCastIconForSystemMenu(true)); | 140 icon()->SetImage(GetCastIconForSystemMenu(true)); |
| 140 } else { | 141 } else { |
| 141 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | 142 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); |
| 142 icon()->SetImage( | 143 icon()->SetImage( |
| 143 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAST_ENABLED).ToImageSkia()); | 144 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAST_ENABLED).ToImageSkia()); |
| 144 } | 145 } |
| 145 } | 146 } |
| 146 | 147 |
| 147 CastCastView::~CastCastView() {} | 148 CastCastView::~CastCastView() {} |
| 148 | 149 |
| 149 void CastCastView::StopCasting() { | 150 void CastCastView::StopCasting() { |
| 150 GetCastConfigDelegate()->StopCasting(displayed_route_id_); | 151 GetCastConfigDelegate()->StopCasting(displayed_route_); |
| 151 WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_CAST_STOP_CAST); | 152 WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_CAST_STOP_CAST); |
| 152 } | 153 } |
| 153 | 154 |
| 154 void CastCastView::UpdateLabel( | 155 void CastCastView::UpdateLabel( |
| 155 const CastConfigDelegate::SinksAndRoutes& sinks_routes) { | 156 const CastConfigDelegate::SinksAndRoutes& sinks_routes) { |
| 156 for (auto& i : sinks_routes) { | 157 for (auto& i : sinks_routes) { |
| 157 const CastConfigDelegate::Sink& sink = i.sink; | 158 const CastConfigDelegate::Sink& sink = i.sink; |
| 158 const CastConfigDelegate::Route& route = i.route; | 159 const CastConfigDelegate::Route& route = i.route; |
| 159 | 160 |
| 160 if (!route.id.empty()) { | 161 if (!route.id.empty()) { |
| 161 displayed_route_id_ = route.id; | 162 displayed_route_ = route; |
| 162 | 163 |
| 163 // We want to display different labels inside of the title depending on | 164 // We want to display different labels inside of the title depending on |
| 164 // what we are actually casting - either the desktop, a tab, or a fallback | 165 // what we are actually casting - either the desktop, a tab, or a fallback |
| 165 // that catches everything else (ie, an extension tab). | 166 // that catches everything else (ie, an extension tab). |
| 166 if (route.tab_id == CastConfigDelegate::Route::TabId::DESKTOP) { | 167 switch (route.content_source) { |
| 167 label()->SetText(ElideString(l10n_util::GetStringFUTF16( | 168 case CastConfigDelegate::Route::ContentSource::UNKNOWN: |
| 168 IDS_ASH_STATUS_TRAY_CAST_CAST_DESKTOP, sink.name))); | 169 label()->SetText( |
| 169 } else if (route.tab_id >= 0) { | 170 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN)); |
| 170 label()->SetText(ElideString(l10n_util::GetStringFUTF16( | 171 break; |
| 171 IDS_ASH_STATUS_TRAY_CAST_CAST_TAB, route.title, sink.name))); | 172 case CastConfigDelegate::Route::ContentSource::TAB: |
| 172 } else { | 173 label()->SetText(ElideString(l10n_util::GetStringFUTF16( |
| 173 label()->SetText( | 174 IDS_ASH_STATUS_TRAY_CAST_CAST_TAB, route.title, sink.name))); |
| 174 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN)); | 175 break; |
| 176 case CastConfigDelegate::Route::ContentSource::DESKTOP: |
| 177 label()->SetText(ElideString(l10n_util::GetStringFUTF16( |
| 178 IDS_ASH_STATUS_TRAY_CAST_CAST_DESKTOP, sink.name))); |
| 179 break; |
| 175 } | 180 } |
| 176 | 181 |
| 177 PreferredSizeChanged(); | 182 PreferredSizeChanged(); |
| 178 Layout(); | 183 Layout(); |
| 179 | 184 |
| 180 // If this machine is the source of the activity, then we want to display | 185 // If this machine is the source of the activity, then we want to display |
| 181 // it over any other activity. There can be multiple activities if other | 186 // it over any other activity. There can be multiple activities if other |
| 182 // devices on the network are casting at the same time. | 187 // devices on the network are casting at the same time. |
| 183 if (route.is_local_source) | 188 if (route.is_local_source) |
| 184 break; | 189 break; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 void UpdateReceiverListFromCachedData(); | 331 void UpdateReceiverListFromCachedData(); |
| 327 views::View* AddToReceiverList( | 332 views::View* AddToReceiverList( |
| 328 const CastConfigDelegate::SinkAndRoute& sink_route); | 333 const CastConfigDelegate::SinkAndRoute& sink_route); |
| 329 | 334 |
| 330 // TrayDetailsView: | 335 // TrayDetailsView: |
| 331 void HandleViewClicked(views::View* view) override; | 336 void HandleViewClicked(views::View* view) override; |
| 332 | 337 |
| 333 // A mapping from the receiver id to the receiver/activity data. | 338 // A mapping from the receiver id to the receiver/activity data. |
| 334 std::map<std::string, CastConfigDelegate::SinkAndRoute> sinks_and_routes_; | 339 std::map<std::string, CastConfigDelegate::SinkAndRoute> sinks_and_routes_; |
| 335 // A mapping from the view pointer to the associated activity id. | 340 // A mapping from the view pointer to the associated activity id. |
| 336 std::map<views::View*, std::string> receiver_activity_map_; | 341 std::map<views::View*, CastConfigDelegate::Sink> view_to_sink_map_; |
| 337 | 342 |
| 338 DISALLOW_COPY_AND_ASSIGN(CastDetailedView); | 343 DISALLOW_COPY_AND_ASSIGN(CastDetailedView); |
| 339 }; | 344 }; |
| 340 | 345 |
| 341 CastDetailedView::CastDetailedView( | 346 CastDetailedView::CastDetailedView( |
| 342 SystemTrayItem* owner, | 347 SystemTrayItem* owner, |
| 343 const CastConfigDelegate::SinksAndRoutes& sinks_and_routes) | 348 const CastConfigDelegate::SinksAndRoutes& sinks_routes) |
| 344 : TrayDetailsView(owner) { | 349 : TrayDetailsView(owner) { |
| 345 CreateItems(); | 350 CreateItems(); |
| 346 UpdateReceiverList(sinks_and_routes); | 351 UpdateReceiverList(sinks_routes); |
| 347 } | 352 } |
| 348 | 353 |
| 349 CastDetailedView::~CastDetailedView() {} | 354 CastDetailedView::~CastDetailedView() {} |
| 350 | 355 |
| 351 void CastDetailedView::SimulateViewClickedForTest( | 356 void CastDetailedView::SimulateViewClickedForTest( |
| 352 const std::string& receiver_id) { | 357 const std::string& receiver_id) { |
| 353 for (auto& it : receiver_activity_map_) { | 358 for (const auto& it : view_to_sink_map_) { |
| 354 if (it.second == receiver_id) { | 359 if (it.second.id == receiver_id) { |
| 355 HandleViewClicked(it.first); | 360 HandleViewClicked(it.first); |
| 356 break; | 361 break; |
| 357 } | 362 } |
| 358 } | 363 } |
| 359 } | 364 } |
| 360 | 365 |
| 361 void CastDetailedView::CreateItems() { | 366 void CastDetailedView::CreateItems() { |
| 362 CreateScrollableList(); | 367 CreateScrollableList(); |
| 363 CreateTitleRow(IDS_ASH_STATUS_TRAY_CAST); | 368 CreateTitleRow(IDS_ASH_STATUS_TRAY_CAST); |
| 364 } | 369 } |
| 365 | 370 |
| 366 void CastDetailedView::UpdateReceiverList( | 371 void CastDetailedView::UpdateReceiverList( |
| 367 const CastConfigDelegate::SinksAndRoutes& new_sinks_and_routes) { | 372 const CastConfigDelegate::SinksAndRoutes& sinks_routes) { |
| 368 // Add/update existing. | 373 // Add/update existing. |
| 369 for (auto i = new_sinks_and_routes.begin(); i != new_sinks_and_routes.end(); | 374 for (const auto& it : sinks_routes) |
| 370 ++i) { | 375 sinks_and_routes_[it.sink.id] = it; |
| 371 sinks_and_routes_[i->sink.id] = *i; | |
| 372 } | |
| 373 | 376 |
| 374 // Remove non-existent sinks. Removing an element invalidates all existing | 377 // Remove non-existent sinks. Removing an element invalidates all existing |
| 375 // iterators. | 378 // iterators. |
| 376 auto i = sinks_and_routes_.begin(); | 379 auto i = sinks_and_routes_.begin(); |
| 377 while (i != sinks_and_routes_.end()) { | 380 while (i != sinks_and_routes_.end()) { |
| 378 bool has_receiver = false; | 381 bool has_receiver = false; |
| 379 for (auto receiver : new_sinks_and_routes) { | 382 for (auto receiver : sinks_routes) { |
| 380 if (i->first == receiver.sink.id) | 383 if (i->first == receiver.sink.id) |
| 381 has_receiver = true; | 384 has_receiver = true; |
| 382 } | 385 } |
| 383 | 386 |
| 384 if (has_receiver) | 387 if (has_receiver) |
| 385 ++i; | 388 ++i; |
| 386 else | 389 else |
| 387 i = sinks_and_routes_.erase(i); | 390 i = sinks_and_routes_.erase(i); |
| 388 } | 391 } |
| 389 | 392 |
| 390 // Update UI. | 393 // Update UI. |
| 391 UpdateReceiverListFromCachedData(); | 394 UpdateReceiverListFromCachedData(); |
| 392 Layout(); | 395 Layout(); |
| 393 } | 396 } |
| 394 | 397 |
| 395 void CastDetailedView::UpdateReceiverListFromCachedData() { | 398 void CastDetailedView::UpdateReceiverListFromCachedData() { |
| 396 // Remove all of the existing views. | 399 // Remove all of the existing views. |
| 397 receiver_activity_map_.clear(); | 400 view_to_sink_map_.clear(); |
| 398 scroll_content()->RemoveAllChildViews(true); | 401 scroll_content()->RemoveAllChildViews(true); |
| 399 | 402 |
| 400 // Add a view for each receiver. | 403 // Add a view for each receiver. |
| 401 for (auto& it : sinks_and_routes_) { | 404 for (auto& it : sinks_and_routes_) { |
| 402 const CastConfigDelegate::SinkAndRoute& sink_route = it.second; | 405 const CastConfigDelegate::SinkAndRoute& sink_route = it.second; |
| 403 views::View* container = AddToReceiverList(sink_route); | 406 views::View* container = AddToReceiverList(sink_route); |
| 404 receiver_activity_map_[container] = it.first; | 407 view_to_sink_map_[container] = sink_route.sink; |
| 405 } | 408 } |
| 406 | 409 |
| 407 scroll_content()->SizeToPreferredSize(); | 410 scroll_content()->SizeToPreferredSize(); |
| 408 static_cast<views::View*>(scroller())->Layout(); | 411 static_cast<views::View*>(scroller())->Layout(); |
| 409 } | 412 } |
| 410 | 413 |
| 411 views::View* CastDetailedView::AddToReceiverList( | 414 views::View* CastDetailedView::AddToReceiverList( |
| 412 const CastConfigDelegate::SinkAndRoute& sink_route) { | 415 const CastConfigDelegate::SinkAndRoute& sink_route) { |
| 413 HoverHighlightView* container = new HoverHighlightView(this); | |
| 414 const gfx::ImageSkia image = | 416 const gfx::ImageSkia image = |
| 415 MaterialDesignController::IsSystemTrayMenuMaterial() | 417 MaterialDesignController::IsSystemTrayMenuMaterial() |
| 416 ? gfx::CreateVectorIcon(kSystemMenuCastDeviceIcon, kMenuIconColor) | 418 ? gfx::CreateVectorIcon(kSystemMenuCastDeviceIcon, kMenuIconColor) |
| 417 : *ui::ResourceBundle::GetSharedInstance() | 419 : *ui::ResourceBundle::GetSharedInstance() |
| 418 .GetImageNamed(IDR_AURA_UBER_TRAY_CAST_DEVICE_ICON) | 420 .GetImageNamed(IDR_AURA_UBER_TRAY_CAST_DEVICE_ICON) |
| 419 .ToImageSkia(); | 421 .ToImageSkia(); |
| 420 const base::string16& name = sink_route.sink.name; | 422 |
| 423 HoverHighlightView* container = new HoverHighlightView(this); |
| 421 container->AddIconAndLabelCustomSize( | 424 container->AddIconAndLabelCustomSize( |
| 422 image, name, false, kTrayPopupDetailsIconWidth, | 425 image, sink_route.sink.name, false, kTrayPopupDetailsIconWidth, |
| 423 kTrayPopupPaddingHorizontal, kTrayPopupPaddingBetweenItems); | 426 kTrayPopupPaddingHorizontal, kTrayPopupPaddingBetweenItems); |
| 424 | 427 |
| 425 scroll_content()->AddChildView(container); | 428 scroll_content()->AddChildView(container); |
| 426 return container; | 429 return container; |
| 427 } | 430 } |
| 428 | 431 |
| 429 void CastDetailedView::HandleViewClicked(views::View* view) { | 432 void CastDetailedView::HandleViewClicked(views::View* view) { |
| 430 // Find the receiver we are going to cast to. | 433 // Find the receiver we are going to cast to. |
| 431 auto it = receiver_activity_map_.find(view); | 434 auto it = view_to_sink_map_.find(view); |
| 432 if (it != receiver_activity_map_.end()) { | 435 if (it != view_to_sink_map_.end()) { |
| 433 GetCastConfigDelegate()->CastToSink(it->second); | 436 GetCastConfigDelegate()->CastToSink(it->second); |
| 434 WmShell::Get()->RecordUserMetricsAction( | 437 WmShell::Get()->RecordUserMetricsAction( |
| 435 UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST); | 438 UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST); |
| 436 } | 439 } |
| 437 } | 440 } |
| 438 | 441 |
| 439 } // namespace tray | 442 } // namespace tray |
| 440 | 443 |
| 441 TrayCast::TrayCast(SystemTray* system_tray) | 444 TrayCast::TrayCast(SystemTray* system_tray) |
| 442 : SystemTrayItem(system_tray, UMA_CAST) { | 445 : SystemTrayItem(system_tray, UMA_CAST) { |
| 443 WmShell::Get()->AddShellObserver(this); | 446 WmShell::Get()->AddShellObserver(this); |
| 447 |
| 448 CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate(); |
| 449 if (cast_config_delegate) { |
| 450 cast_config_delegate->AddObserver(this); |
| 451 cast_config_delegate->RequestDeviceRefresh(); |
| 452 } |
| 444 } | 453 } |
| 445 | 454 |
| 446 TrayCast::~TrayCast() { | 455 TrayCast::~TrayCast() { |
| 456 CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate(); |
| 457 if (cast_config_delegate) |
| 458 cast_config_delegate->RemoveObserver(this); |
| 459 |
| 447 WmShell::Get()->RemoveShellObserver(this); | 460 WmShell::Get()->RemoveShellObserver(this); |
| 448 if (added_observer_) | |
| 449 GetCastConfigDelegate()->RemoveObserver(this); | |
| 450 } | 461 } |
| 451 | 462 |
| 452 void TrayCast::StartCastForTest(const std::string& receiver_id) { | 463 void TrayCast::StartCastForTest(const std::string& receiver_id) { |
| 453 if (detailed_ != nullptr) | 464 if (detailed_ != nullptr) |
| 454 detailed_->SimulateViewClickedForTest(receiver_id); | 465 detailed_->SimulateViewClickedForTest(receiver_id); |
| 455 } | 466 } |
| 456 | 467 |
| 457 void TrayCast::StopCastForTest() { | 468 void TrayCast::StopCastForTest() { |
| 458 default_->cast_view()->StopCasting(); | 469 default_->cast_view()->StopCasting(); |
| 459 } | 470 } |
| 460 | 471 |
| 461 const std::string& TrayCast::GetDisplayedCastId() { | 472 const std::string& TrayCast::GetDisplayedCastId() { |
| 462 return default_->cast_view()->displayed_route_id(); | 473 return default_->cast_view()->displayed_route_id(); |
| 463 } | 474 } |
| 464 | 475 |
| 465 const views::View* TrayCast::GetDefaultView() const { | 476 const views::View* TrayCast::GetDefaultView() const { |
| 466 return default_; | 477 return default_; |
| 467 } | 478 } |
| 468 | 479 |
| 469 views::View* TrayCast::CreateTrayView(LoginStatus status) { | 480 views::View* TrayCast::CreateTrayView(LoginStatus status) { |
| 470 CHECK(tray_ == nullptr); | 481 CHECK(tray_ == nullptr); |
| 471 tray_ = new tray::CastTrayView(this); | 482 tray_ = new tray::CastTrayView(this); |
| 472 tray_->SetVisible(is_casting_); | 483 tray_->SetVisible(HasActiveRoute()); |
| 473 return tray_; | 484 return tray_; |
| 474 } | 485 } |
| 475 | 486 |
| 476 views::View* TrayCast::CreateDefaultView(LoginStatus status) { | 487 views::View* TrayCast::CreateDefaultView(LoginStatus status) { |
| 477 CHECK(default_ == nullptr); | 488 CHECK(default_ == nullptr); |
| 478 | 489 |
| 479 CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate(); | |
| 480 if (cast_config_delegate) { | |
| 481 // Add the cast observer here instead of the ctor for two reasons: | |
| 482 // - The ctor gets called too early in the initialization cycle (at least | |
| 483 // for the tests); the correct profile hasn't been setup yet. | |
| 484 // - If we're using the cast extension backend (media router is disabled), | |
| 485 // then the user can install the extension at any point in time. The | |
| 486 // return value of HasCastExtension() can change, so only checking it in | |
| 487 // the ctor isn't enough. | |
| 488 if (!added_observer_) { | |
| 489 cast_config_delegate->AddObserver(this); | |
| 490 added_observer_ = true; | |
| 491 } | |
| 492 | |
| 493 // The extension updates its view model whenever the popup is opened, so we | |
| 494 // probably should as well. | |
| 495 cast_config_delegate->RequestDeviceRefresh(); | |
| 496 } | |
| 497 | |
| 498 default_ = new tray::CastDuplexView(this, status != LoginStatus::LOCKED, | 490 default_ = new tray::CastDuplexView(this, status != LoginStatus::LOCKED, |
| 499 sinks_and_routes_); | 491 sinks_and_routes_); |
| 500 default_->set_id(TRAY_VIEW); | 492 default_->set_id(TRAY_VIEW); |
| 501 default_->select_view()->set_id(SELECT_VIEW); | 493 default_->select_view()->set_id(SELECT_VIEW); |
| 502 default_->cast_view()->set_id(CAST_VIEW); | 494 default_->cast_view()->set_id(CAST_VIEW); |
| 503 | 495 |
| 504 UpdatePrimaryView(); | 496 UpdatePrimaryView(); |
| 505 return default_; | 497 return default_; |
| 506 } | 498 } |
| 507 | 499 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 520 default_ = nullptr; | 512 default_ = nullptr; |
| 521 } | 513 } |
| 522 | 514 |
| 523 void TrayCast::DestroyDetailedView() { | 515 void TrayCast::DestroyDetailedView() { |
| 524 detailed_ = nullptr; | 516 detailed_ = nullptr; |
| 525 } | 517 } |
| 526 | 518 |
| 527 void TrayCast::OnDevicesUpdated( | 519 void TrayCast::OnDevicesUpdated( |
| 528 const CastConfigDelegate::SinksAndRoutes& sinks_routes) { | 520 const CastConfigDelegate::SinksAndRoutes& sinks_routes) { |
| 529 sinks_and_routes_ = sinks_routes; | 521 sinks_and_routes_ = sinks_routes; |
| 522 UpdatePrimaryView(); |
| 530 | 523 |
| 531 if (default_) { | 524 if (default_) { |
| 532 bool has_receivers = !sinks_and_routes_.empty(); | 525 bool has_receivers = !sinks_and_routes_.empty(); |
| 533 default_->SetVisible(has_receivers); | 526 default_->SetVisible(has_receivers); |
| 534 default_->cast_view()->UpdateLabel(sinks_and_routes_); | 527 default_->cast_view()->UpdateLabel(sinks_and_routes_); |
| 535 } | 528 } |
| 536 if (detailed_) | 529 if (detailed_) |
| 537 detailed_->UpdateReceiverList(sinks_and_routes_); | 530 detailed_->UpdateReceiverList(sinks_and_routes_); |
| 538 } | 531 } |
| 539 | 532 |
| 540 void TrayCast::UpdatePrimaryView() { | 533 void TrayCast::UpdatePrimaryView() { |
| 541 if (GetCastConfigDelegate() && !sinks_and_routes_.empty()) { | 534 if (GetCastConfigDelegate() && !sinks_and_routes_.empty()) { |
| 542 if (default_) { | 535 if (default_) { |
| 543 if (is_casting_) | 536 if (HasActiveRoute()) |
| 544 default_->ActivateCastView(); | 537 default_->ActivateCastView(); |
| 545 else | 538 else |
| 546 default_->ActivateSelectView(); | 539 default_->ActivateSelectView(); |
| 547 } | 540 } |
| 548 | 541 |
| 549 if (tray_) | 542 if (tray_) |
| 550 tray_->SetVisible(is_casting_); | 543 tray_->SetVisible(is_mirror_casting_); |
| 551 } else { | 544 } else { |
| 552 if (default_) | 545 if (default_) |
| 553 default_->SetVisible(false); | 546 default_->SetVisible(false); |
| 554 if (tray_) | 547 if (tray_) |
| 555 tray_->SetVisible(false); | 548 tray_->SetVisible(false); |
| 556 } | 549 } |
| 557 } | 550 } |
| 558 | 551 |
| 552 bool TrayCast::HasActiveRoute() { |
| 553 if (is_mirror_casting_) |
| 554 return true; |
| 555 |
| 556 for (const auto& sr : sinks_and_routes_) { |
| 557 if (!sr.route.title.empty()) |
| 558 return true; |
| 559 } |
| 560 |
| 561 return false; |
| 562 } |
| 563 |
| 559 void TrayCast::OnCastingSessionStartedOrStopped(bool started) { | 564 void TrayCast::OnCastingSessionStartedOrStopped(bool started) { |
| 560 is_casting_ = started; | 565 is_mirror_casting_ = started; |
| 561 UpdatePrimaryView(); | 566 UpdatePrimaryView(); |
| 562 } | 567 } |
| 563 | 568 |
| 564 } // namespace ash | 569 } // namespace ash |
| OLD | NEW |