blob: 70dd7a63b968fffc29f7b7f1b3211c4dcab71960 [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.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.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);
}
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(connection_status_string_);
node_data->role = ax::mojom::Role::kButton;
}
views::View* NetworkTrayView::GetTooltipHandlerForPoint(
const gfx::Point& point) {
return GetLocalBounds().Contains(point) ? this : nullptr;
}
bool NetworkTrayView::GetTooltipText(const gfx::Point& p,
base::string16* tooltip) const {
if (connection_status_tooltip_.empty())
return false;
*tooltip = connection_status_tooltip_;
return true;
}
void NetworkTrayView::NetworkIconChanged() {
UpdateNetworkStateHandlerIcon();
UpdateConnectionStatus(GetConnectedNetwork(), false /* notify_a11y */);
}
void NetworkTrayView::OnSessionStateChanged(
session_manager::SessionState state) {
UpdateNetworkStateHandlerIcon();
}
void NetworkTrayView::NetworkStateChanged(bool notify_a11y) {
UpdateNetworkStateHandlerIcon();
UpdateConnectionStatus(GetConnectedNetwork(), notify_a11y);
}
NetworkTrayView::NetworkTrayView(
Shelf* shelf,
std::unique_ptr<NetworkTrayIconStrategy> network_tray_icon_strategy)
: TrayItemView(shelf),
network_state_observer_(std::make_unique<TrayNetworkStateObserver>(this)),
network_tray_icon_strategy_(std::move(network_tray_icon_strategy)) {
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;
base::string16 new_connection_status_string;
if (connected_network) {
new_connection_status_string = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED,
base::UTF8ToUTF16(connected_network->name()));
// Retrieve the string describing the signal strength, if it is applicable
// to |connected_network|.
base::string16 signal_strength_string;
switch (network_icon::GetSignalStrengthForNetwork(connected_network)) {
case SignalStrength::NONE:
case SignalStrength::NOT_WIRELESS:
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;
}
if (!signal_strength_string.empty()) {
new_connection_status_string = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED_ACCESSIBLE,
base::UTF8ToUTF16(connected_network->name()), signal_strength_string);
}
connection_status_tooltip_ = new_connection_status_string;
} else {
new_connection_status_string = l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED_A11Y);
// Use shorter desription like "Disconnected" instead of "disconnected from
// netrowk" 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);
}
if (new_connection_status_string != connection_status_string_) {
connection_status_string_ = new_connection_status_string;
if (notify_a11y && !connection_status_string_.empty())
NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
image_view()->SetAccessibleName(connection_status_string_);
}
}
} // namespace tray
} // namespace ash