| Index: ash/system/cast/tray_cast.cc
|
| diff --git a/ash/system/cast/tray_cast.cc b/ash/system/cast/tray_cast.cc
|
| index 6128b430b7179195a0cda1f09930bb75670fa186..5d9a60770eb9c164696abcf127f30d7c7290fbd5 100644
|
| --- a/ash/system/cast/tray_cast.cc
|
| +++ b/ash/system/cast/tray_cast.cc
|
| @@ -36,6 +36,13 @@ namespace ash {
|
|
|
| namespace {
|
| const int kStopButtonRightPadding = 18;
|
| +
|
| +// Returns the active CastConfigDelegate instance.
|
| +ash::CastConfigDelegate* GetCastConfigDelegate() {
|
| + return ash::Shell::GetInstance()
|
| + ->system_tray_delegate()
|
| + ->GetCastConfigDelegate();
|
| +}
|
| } // namespace
|
|
|
| namespace tray {
|
| @@ -47,83 +54,44 @@ namespace tray {
|
| class CastSelectDefaultView : public TrayItemMore {
|
| public:
|
| CastSelectDefaultView(SystemTrayItem* owner,
|
| - CastConfigDelegate* cast_config_delegate,
|
| bool show_more);
|
| ~CastSelectDefaultView() override;
|
|
|
| - // Updates the label based on the current set of receivers (if there are or
|
| - // are not any available receivers).
|
| - void UpdateLabel();
|
| -
|
| private:
|
| - void UpdateLabelCallback(
|
| - const CastConfigDelegate::ReceiversAndActivites& receivers_activities);
|
| -
|
| - CastConfigDelegate* cast_config_delegate_;
|
| - base::WeakPtrFactory<CastSelectDefaultView> weak_ptr_factory_;
|
| DISALLOW_COPY_AND_ASSIGN(CastSelectDefaultView);
|
| };
|
|
|
| -CastSelectDefaultView::CastSelectDefaultView(
|
| - SystemTrayItem* owner,
|
| - CastConfigDelegate* cast_config_delegate,
|
| - bool show_more)
|
| - : TrayItemMore(owner, show_more),
|
| - cast_config_delegate_(cast_config_delegate),
|
| - weak_ptr_factory_(this) {
|
| +CastSelectDefaultView::CastSelectDefaultView(SystemTrayItem* owner,
|
| + bool show_more)
|
| + : TrayItemMore(owner, show_more) {
|
| ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - SetImage(rb.GetImageNamed(IDR_AURA_UBER_TRAY_CAST).ToImageSkia());
|
| -
|
| - // We first set a default label before we actually know what the label will
|
| - // be, because it could take awhile before UpdateLabel() actually applies
|
| - // the correct label.
|
| - SetLabel(rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_NO_DEVICE));
|
| - UpdateLabel();
|
| -}
|
| -
|
| -CastSelectDefaultView::~CastSelectDefaultView() {
|
| -}
|
|
|
| -void CastSelectDefaultView::UpdateLabelCallback(
|
| - const CastConfigDelegate::ReceiversAndActivites& receivers_activities) {
|
| - // The label needs to reflect if there are no cast receivers
|
| - const base::string16 label =
|
| - ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
|
| - receivers_activities.empty() ? IDS_ASH_STATUS_TRAY_CAST_NO_DEVICE
|
| - : IDS_ASH_STATUS_TRAY_CAST_DESKTOP);
|
| + // Update the image and label.
|
| + SetImage(rb.GetImageNamed(IDR_AURA_UBER_TRAY_CAST).ToImageSkia());
|
| + base::string16 label =
|
| + rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_DESKTOP);
|
| SetLabel(label);
|
| SetAccessibleName(label);
|
| - SetVisible(true);
|
| }
|
|
|
| -void CastSelectDefaultView::UpdateLabel() {
|
| - if (cast_config_delegate_ == nullptr ||
|
| - cast_config_delegate_->HasCastExtension() == false)
|
| - return;
|
| -
|
| - cast_config_delegate_->GetReceiversAndActivities(
|
| - base::Bind(&CastSelectDefaultView::UpdateLabelCallback,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| -}
|
| +CastSelectDefaultView::~CastSelectDefaultView() {}
|
|
|
| // This view is displayed when the screen is actively being casted; it allows
|
| // the user to easily stop casting. It fully replaces the
|
| // |CastSelectDefaultView| view inside of the |CastDuplexView|.
|
| class CastCastView : public views::View, public views::ButtonListener {
|
| public:
|
| - explicit CastCastView(CastConfigDelegate* cast_config_delegate);
|
| + CastCastView();
|
| ~CastCastView() override;
|
|
|
| void StopCasting();
|
|
|
| // Updates the label for the stop view to include information about the
|
| // current device that is being casted.
|
| - void UpdateLabel();
|
| -
|
| - private:
|
| - void UpdateLabelCallback(
|
| + void UpdateLabel(
|
| const CastConfigDelegate::ReceiversAndActivites& receivers_activities);
|
|
|
| + private:
|
| // Overridden from views::View.
|
| int GetHeightForWidth(int width) const override;
|
| void Layout() override;
|
| @@ -131,7 +99,6 @@ class CastCastView : public views::View, public views::ButtonListener {
|
| // Overridden from views::ButtonListener.
|
| void ButtonPressed(views::Button* sender, const ui::Event& event) override;
|
|
|
| - CastConfigDelegate* cast_config_delegate_;
|
| views::ImageView* icon_;
|
| views::Label* label_;
|
| TrayPopupLabelButton* stop_button_;
|
| @@ -140,8 +107,7 @@ class CastCastView : public views::View, public views::ButtonListener {
|
| DISALLOW_COPY_AND_ASSIGN(CastCastView);
|
| };
|
|
|
| -CastCastView::CastCastView(CastConfigDelegate* cast_config_delegate)
|
| - : cast_config_delegate_(cast_config_delegate), weak_ptr_factory_(this) {
|
| +CastCastView::CastCastView() : weak_ptr_factory_(this) {
|
| // We will initialize the primary tray view which shows a stop button here.
|
|
|
| set_background(views::Background::CreateSolidBackground(kBackgroundColor));
|
| @@ -170,8 +136,6 @@ CastCastView::CastCastView(CastConfigDelegate* cast_config_delegate)
|
| IDS_ASH_STATUS_TRAY_CAST_STOP);
|
| stop_button_ = new TrayPopupLabelButton(this, stop_button_text);
|
| AddChildView(stop_button_);
|
| -
|
| - UpdateLabel();
|
| }
|
|
|
| CastCastView::~CastCastView() {
|
| @@ -209,25 +173,16 @@ void CastCastView::Layout() {
|
| }
|
|
|
| void CastCastView::StopCasting() {
|
| - cast_config_delegate_->StopCasting();
|
| + GetCastConfigDelegate()->StopCasting();
|
| Shell::GetInstance()->metrics()->RecordUserMetricsAction(
|
| ash::UMA_STATUS_AREA_CAST_STOP_CAST);
|
| }
|
|
|
| -void CastCastView::UpdateLabel() {
|
| - if (cast_config_delegate_ == nullptr ||
|
| - cast_config_delegate_->HasCastExtension() == false)
|
| - return;
|
| -
|
| - cast_config_delegate_->GetReceiversAndActivities(base::Bind(
|
| - &CastCastView::UpdateLabelCallback, weak_ptr_factory_.GetWeakPtr()));
|
| -}
|
| -
|
| -void CastCastView::UpdateLabelCallback(
|
| +void CastCastView::UpdateLabel(
|
| const CastConfigDelegate::ReceiversAndActivites& receivers_activities) {
|
| for (auto& i : receivers_activities) {
|
| - const CastConfigDelegate::Receiver receiver = i.second.receiver;
|
| - const CastConfigDelegate::Activity activity = i.second.activity;
|
| + const CastConfigDelegate::Receiver& receiver = i.receiver;
|
| + const CastConfigDelegate::Activity& activity = i.activity;
|
| if (!activity.id.empty()) {
|
| // We want to display different labels inside of the title depending on
|
| // what we are actually casting - either the desktop, a tab, or a fallback
|
| @@ -261,9 +216,10 @@ void CastCastView::ButtonPressed(views::Button* sender,
|
| // is active.
|
| class CastDuplexView : public views::View {
|
| public:
|
| - CastDuplexView(SystemTrayItem* owner,
|
| - CastConfigDelegate* config_delegate,
|
| - bool show_more);
|
| + CastDuplexView(
|
| + SystemTrayItem* owner,
|
| + bool show_more,
|
| + const CastConfigDelegate::ReceiversAndActivites& receivers_activities);
|
| ~CastDuplexView() override;
|
|
|
| // Activate either the casting or select view.
|
| @@ -288,11 +244,13 @@ class CastDuplexView : public views::View {
|
| DISALLOW_COPY_AND_ASSIGN(CastDuplexView);
|
| };
|
|
|
| -CastDuplexView::CastDuplexView(SystemTrayItem* owner,
|
| - CastConfigDelegate* config_delegate,
|
| - bool show_more) {
|
| - select_view_ = new CastSelectDefaultView(owner, config_delegate, show_more);
|
| - cast_view_ = new CastCastView(config_delegate);
|
| +CastDuplexView::CastDuplexView(
|
| + SystemTrayItem* owner,
|
| + bool show_more,
|
| + const CastConfigDelegate::ReceiversAndActivites& receivers_activities) {
|
| + select_view_ = new CastSelectDefaultView(owner, show_more);
|
| + cast_view_ = new CastCastView();
|
| + cast_view_->UpdateLabel(receivers_activities);
|
| SetLayoutManager(new views::FillLayout());
|
|
|
| ActivateSelectView();
|
| @@ -390,21 +348,22 @@ void CastTrayView::UpdateAlignment(ShelfAlignment alignment) {
|
| class CastDetailedView : public TrayDetailsView, public ViewClickListener {
|
| public:
|
| CastDetailedView(SystemTrayItem* owner,
|
| - CastConfigDelegate* cast_config_delegate,
|
| - user::LoginStatus login);
|
| + user::LoginStatus login,
|
| + const CastConfigDelegate::ReceiversAndActivites&
|
| + receivers_and_activities);
|
| ~CastDetailedView() override;
|
|
|
| // Makes the detail view think the view associated with the given receiver_id
|
| // was clicked. This will start a cast.
|
| void SimulateViewClickedForTest(const std::string& receiver_id);
|
|
|
| + // Updates the list of available receivers.
|
| + void UpdateReceiverList(const CastConfigDelegate::ReceiversAndActivites&
|
| + new_receivers_and_activities);
|
| +
|
| private:
|
| void CreateItems();
|
|
|
| - void UpdateReceiverList();
|
| - void UpdateReceiverListCallback(
|
| - const CastConfigDelegate::ReceiversAndActivites&
|
| - new_receivers_and_activities);
|
| void UpdateReceiverListFromCachedData();
|
| views::View* AddToReceiverList(
|
| const CastConfigDelegate::ReceiverAndActivity& receiverActivity);
|
| @@ -415,26 +374,25 @@ class CastDetailedView : public TrayDetailsView, public ViewClickListener {
|
| // Overridden from ViewClickListener.
|
| void OnViewClicked(views::View* sender) override;
|
|
|
| - CastConfigDelegate* cast_config_delegate_;
|
| user::LoginStatus login_;
|
| views::View* options_ = nullptr;
|
| - CastConfigDelegate::ReceiversAndActivites receivers_and_activities_;
|
| - // A mapping from the view pointer to the associated activity id
|
| + // A mapping from the receiver id to the receiver/activity data.
|
| + std::map<std::string, CastConfigDelegate::ReceiverAndActivity>
|
| + receivers_and_activities_;
|
| + // A mapping from the view pointer to the associated activity id.
|
| std::map<views::View*, std::string> receiver_activity_map_;
|
| base::WeakPtrFactory<CastDetailedView> weak_ptr_factory_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(CastDetailedView);
|
| };
|
|
|
| -CastDetailedView::CastDetailedView(SystemTrayItem* owner,
|
| - CastConfigDelegate* cast_config_delegate,
|
| - user::LoginStatus login)
|
| - : TrayDetailsView(owner),
|
| - cast_config_delegate_(cast_config_delegate),
|
| - login_(login),
|
| - weak_ptr_factory_(this) {
|
| +CastDetailedView::CastDetailedView(
|
| + SystemTrayItem* owner,
|
| + user::LoginStatus login,
|
| + const CastConfigDelegate::ReceiversAndActivites& receivers_and_activities)
|
| + : TrayDetailsView(owner), login_(login), weak_ptr_factory_(this) {
|
| CreateItems();
|
| - UpdateReceiverList();
|
| + UpdateReceiverList(receivers_and_activities);
|
| }
|
|
|
| CastDetailedView::~CastDetailedView() {
|
| @@ -456,25 +414,29 @@ void CastDetailedView::CreateItems() {
|
| AppendHeaderEntry();
|
| }
|
|
|
| -void CastDetailedView::UpdateReceiverList() {
|
| - cast_config_delegate_->GetReceiversAndActivities(
|
| - base::Bind(&CastDetailedView::UpdateReceiverListCallback,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| -}
|
| -
|
| -void CastDetailedView::UpdateReceiverListCallback(
|
| +void CastDetailedView::UpdateReceiverList(
|
| const CastConfigDelegate::ReceiversAndActivites&
|
| new_receivers_and_activities) {
|
| // Add/update existing.
|
| for (auto i = new_receivers_and_activities.begin();
|
| i != new_receivers_and_activities.end(); ++i) {
|
| - receivers_and_activities_[i->first] = i->second;
|
| + receivers_and_activities_[i->receiver.id] = *i;
|
| }
|
| - // Remove non-existent.
|
| - for (auto i = receivers_and_activities_.begin();
|
| - i != receivers_and_activities_.end(); ++i) {
|
| - if (new_receivers_and_activities.count(i->first) == 0)
|
| - receivers_and_activities_.erase(i->first);
|
| +
|
| + // Remove non-existent receivers. Removing an element invalidates all existing
|
| + // iterators.
|
| + auto i = receivers_and_activities_.begin();
|
| + while (i != receivers_and_activities_.end()) {
|
| + bool has_receiver = false;
|
| + for (auto receiver : new_receivers_and_activities) {
|
| + if (i->first == receiver.receiver.id)
|
| + has_receiver = true;
|
| + }
|
| +
|
| + if (has_receiver)
|
| + ++i;
|
| + else
|
| + i = receivers_and_activities_.erase(i);
|
| }
|
|
|
| // Update UI.
|
| @@ -538,15 +500,17 @@ void CastDetailedView::AppendHeaderEntry() {
|
| }
|
|
|
| void CastDetailedView::OnViewClicked(views::View* sender) {
|
| + ash::CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate();
|
| +
|
| if (sender == footer()->content()) {
|
| TransitionToDefaultView();
|
| } else if (sender == options_) {
|
| - cast_config_delegate_->LaunchCastOptions();
|
| + cast_config_delegate->LaunchCastOptions();
|
| } else {
|
| // Find the receiver we are going to cast to
|
| auto it = receiver_activity_map_.find(sender);
|
| if (it != receiver_activity_map_.end()) {
|
| - cast_config_delegate_->CastToReceiver(it->second);
|
| + cast_config_delegate->CastToReceiver(it->second);
|
| Shell::GetInstance()->metrics()->RecordUserMetricsAction(
|
| ash::UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST);
|
| }
|
| @@ -557,9 +521,6 @@ void CastDetailedView::OnViewClicked(views::View* sender) {
|
|
|
| TrayCast::TrayCast(SystemTray* system_tray)
|
| : SystemTrayItem(system_tray),
|
| - cast_config_delegate_(ash::Shell::GetInstance()
|
| - ->system_tray_delegate()
|
| - ->GetCastConfigDelegate()),
|
| weak_ptr_factory_(this) {
|
| Shell::GetInstance()->AddShellObserver(this);
|
| }
|
| @@ -591,8 +552,28 @@ views::View* TrayCast::CreateTrayView(user::LoginStatus status) {
|
| views::View* TrayCast::CreateDefaultView(user::LoginStatus status) {
|
| CHECK(default_ == nullptr);
|
|
|
| - default_ = new tray::CastDuplexView(this, cast_config_delegate_,
|
| - status != user::LOGGED_IN_LOCKED);
|
| + if (HasCastExtension()) {
|
| + ash::CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate();
|
| +
|
| + // We add the cast listener here instead of in the ctor for two reasons:
|
| + // - The ctor gets called too early in the initialization cycle (at least
|
| + // for the tests); the correct profile hasn't been setup yet.
|
| + // - The listener is only added if there is a cast extension. If the call
|
| + // below were in the ctor, then the cast tray item would not appear if the
|
| + // user installed the extension in an existing session.
|
| + if (!device_update_subscription_) {
|
| + device_update_subscription_ =
|
| + cast_config_delegate->RegisterDeviceUpdateObserver(base::Bind(
|
| + &TrayCast::OnReceiversUpdated, weak_ptr_factory_.GetWeakPtr()));
|
| + }
|
| +
|
| + // The extension updates its view model whenever the popup is opened, so we
|
| + // probably should as well.
|
| + cast_config_delegate->RequestDeviceRefresh();
|
| + }
|
| +
|
| + default_ = new tray::CastDuplexView(this, status != user::LOGGED_IN_LOCKED,
|
| + receivers_and_activities_);
|
| default_->set_id(TRAY_VIEW);
|
| default_->select_view()->set_id(SELECT_VIEW);
|
| default_->cast_view()->set_id(CAST_VIEW);
|
| @@ -605,7 +586,8 @@ views::View* TrayCast::CreateDetailedView(user::LoginStatus status) {
|
| Shell::GetInstance()->metrics()->RecordUserMetricsAction(
|
| ash::UMA_STATUS_AREA_DETAILED_CAST_VIEW);
|
| CHECK(detailed_ == nullptr);
|
| - detailed_ = new tray::CastDetailedView(this, cast_config_delegate_, status);
|
| + detailed_ =
|
| + new tray::CastDetailedView(this, status, receivers_and_activities_);
|
| return detailed_;
|
| }
|
|
|
| @@ -622,34 +604,31 @@ void TrayCast::DestroyDetailedView() {
|
| }
|
|
|
| bool TrayCast::HasCastExtension() {
|
| - return cast_config_delegate_ != nullptr &&
|
| - cast_config_delegate_->HasCastExtension();
|
| + ash::CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate();
|
| + return cast_config_delegate != nullptr &&
|
| + cast_config_delegate->HasCastExtension();
|
| }
|
|
|
| -void TrayCast::UpdateCachedReceiverState(
|
| +void TrayCast::OnReceiversUpdated(
|
| const CastConfigDelegate::ReceiversAndActivites& receivers_activities) {
|
| - has_cast_receivers_ = !receivers_activities.empty();
|
| - if (default_)
|
| - default_->SetVisible(has_cast_receivers_);
|
| + receivers_and_activities_ = receivers_activities;
|
| +
|
| + if (default_) {
|
| + bool has_receivers = !receivers_and_activities_.empty();
|
| + default_->SetVisible(has_receivers);
|
| + default_->cast_view()->UpdateLabel(receivers_and_activities_);
|
| + }
|
| + if (detailed_)
|
| + detailed_->UpdateReceiverList(receivers_and_activities_);
|
| }
|
|
|
| void TrayCast::UpdatePrimaryView() {
|
| if (HasCastExtension()) {
|
| if (default_) {
|
| - if (is_casting_) {
|
| + if (is_casting_)
|
| default_->ActivateCastView();
|
| - } else {
|
| + else
|
| default_->ActivateSelectView();
|
| -
|
| - // We only want to show the select view if we have a receiver we can
|
| - // cast to. To prevent showing the tray item and then hiding it some
|
| - // short time after, we cache if we have any receivers. We set our
|
| - // default visibility to true if we do have a receiver, false otherwise.
|
| - default_->SetVisible(has_cast_receivers_);
|
| - cast_config_delegate_->GetReceiversAndActivities(
|
| - base::Bind(&TrayCast::UpdateCachedReceiverState,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| - }
|
| }
|
|
|
| if (tray_)
|
|
|