blob: bbe373ba83ba50136c09bf1c047c333ca44e9b21 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/network/network_tray_view.h"
#include <utility>
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/network/network_icon.h"
#include "ash/system/network/network_icon_animation.h"
#include "ash/system/network/network_tray_icon_strategy.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/image_view.h"
using chromeos::NetworkHandler;
using chromeos::NetworkState;
using chromeos::NetworkStateHandler;
using chromeos::NetworkTypePattern;
namespace ash {
namespace tray {
const NetworkState* GetConnectedNetwork() {
NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
return handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
}
NetworkTrayView::~NetworkTrayView() {
network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
Shell::Get()->system_tray_model()->network_observer()->RemoveObserver(this);
}
NetworkTrayView* NetworkTrayView::CreateForDefault(Shelf* shelf) {
return new NetworkTrayView(
shelf, std::make_unique<DefaultNetworkTrayIconStrategy>());
}
NetworkTrayView* NetworkTrayView::CreateForMobile(Shelf* shelf) {
return new NetworkTrayView(shelf,
std::make_unique<MobileNetworkTrayIconStrategy>());
}
NetworkTrayView* NetworkTrayView::CreateForSingleIcon(Shelf* shelf) {
return new NetworkTrayView(shelf,
std::make_unique<SingleNetworkTrayIconStrategy>());
}
const char* NetworkTrayView::GetClassName() const {
return "NetworkTrayView";
}
void NetworkTrayView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->SetName(accessible_name_);
node_data->SetDescription(accessible_description_);
node_data->role = ax::mojom::Role::kButton;
}
views::View* NetworkTrayView::GetTooltipHandlerForPoint(
const gfx::Point& point) {
return GetLocalBounds().Contains(point) ? this : nullptr;
}
base::string16 NetworkTrayView::GetTooltipText(const gfx::Point& p) const {
return connection_status_tooltip_;
}
void NetworkTrayView::NetworkIconChanged() {
UpdateNetworkStateHandlerIcon();
UpdateConnectionStatus(GetConnectedNetwork(), false /* notify_a11y */);
}
void NetworkTrayView::OnSessionStateChanged(
session_manager::SessionState state) {
UpdateNetworkStateHandlerIcon();
}
void NetworkTrayView::ActiveNetworkStateChanged() {
UpdateNetworkStateHandlerIcon();
UpdateConnectionStatus(GetConnectedNetwork(), true /* notify _a11y */);
}
void NetworkTrayView::NetworkListChanged() {
UpdateNetworkStateHandlerIcon();
UpdateConnectionStatus(GetConnectedNetwork(), false /* notify_a11y */);
}
NetworkTrayView::NetworkTrayView(
Shelf* shelf,
std::unique_ptr<NetworkTrayIconStrategy> network_tray_icon_strategy)
: TrayItemView(shelf),
network_tray_icon_strategy_(std::move(network_tray_icon_strategy)) {
Shell::Get()->system_tray_model()->network_observer()->AddObserver(this);
CreateImageView();
UpdateNetworkStateHandlerIcon();
UpdateConnectionStatus(GetConnectedNetwork(), true /* notify_a11y */);
}
void NetworkTrayView::UpdateIcon(bool tray_icon_visible,
const gfx::ImageSkia& image) {
image_view()->SetImage(image);
SetVisible(tray_icon_visible);
SchedulePaint();
}
void NetworkTrayView::UpdateNetworkStateHandlerIcon() {
bool animating = false;
gfx::ImageSkia image =
network_tray_icon_strategy_->GetNetworkIcon(&animating);
bool show_in_tray = !image.isNull();
UpdateIcon(show_in_tray, image);
if (animating)
network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
else
network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
}
void NetworkTrayView::UpdateConnectionStatus(
const NetworkState* connected_network,
bool notify_a11y) {
using SignalStrength = network_icon::SignalStrength;
if (connected_network) {
base::string16 new_accessible_name = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED,
base::UTF8ToUTF16(connected_network->name()));
if (connected_network->Matches(NetworkTypePattern::Wireless())) {
// Retrieve the string describing the signal strength, if it is applicable
// to |connected_network|.
base::string16 signal_strength_string;
switch (network_icon::GetSignalStrength(
connected_network->signal_strength())) {
case SignalStrength::NONE:
break;
case SignalStrength::WEAK:
signal_strength_string = l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_WEAK);
break;
case SignalStrength::MEDIUM:
signal_strength_string = l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_MEDIUM);
break;
case SignalStrength::STRONG:
signal_strength_string = l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_STRONG);
break;
}
accessible_description_ = signal_strength_string;
if (!signal_strength_string.empty()) {
connection_status_tooltip_ = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED_ACCESSIBLE,
base::UTF8ToUTF16(connected_network->name()),
signal_strength_string);
} else {
// Use shorter description like "Disconnected" instead of "disconnected
// from network" for the tooltip, because the visual icon tells that
// this is about the network status.
connection_status_tooltip_ = l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_TOOLTIP);
}
} else {
accessible_description_.clear();
}
if (accessible_name_ == new_accessible_name)
return;
accessible_name_ = new_accessible_name;
if (notify_a11y && !accessible_name_.empty())
NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
}
}
} // namespace tray
} // namespace ash