tray_network.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ash/system/chromeos/network/tray_network.h" 6 7#include "ash/ash_switches.h" 8#include "ash/shell.h" 9#include "ash/system/chromeos/network/network_icon_animation.h" 10#include "ash/system/chromeos/network/network_state_list_detailed_view.h" 11#include "ash/system/chromeos/network/tray_network_state_observer.h" 12#include "ash/system/tray/system_tray.h" 13#include "ash/system/tray/system_tray_delegate.h" 14#include "ash/system/tray/system_tray_notifier.h" 15#include "ash/system/tray/tray_constants.h" 16#include "ash/system/tray/tray_item_more.h" 17#include "ash/system/tray/tray_item_view.h" 18#include "ash/system/tray/tray_utils.h" 19#include "base/command_line.h" 20#include "base/strings/utf_string_conversions.h" 21#include "chromeos/network/network_state.h" 22#include "chromeos/network/network_state_handler.h" 23#include "chromeos/network/shill_property_util.h" 24#include "grit/ash_resources.h" 25#include "grit/ash_strings.h" 26#include "third_party/cros_system_api/dbus/service_constants.h" 27#include "ui/base/accessibility/accessible_view_state.h" 28#include "ui/base/l10n/l10n_util.h" 29#include "ui/base/resource/resource_bundle.h" 30#include "ui/views/controls/image_view.h" 31#include "ui/views/controls/link.h" 32#include "ui/views/controls/link_listener.h" 33#include "ui/views/layout/box_layout.h" 34#include "ui/views/widget/widget.h" 35 36using chromeos::NetworkHandler; 37using chromeos::NetworkState; 38using chromeos::NetworkStateHandler; 39using chromeos::NetworkTypePattern; 40 41namespace ash { 42namespace internal { 43 44namespace tray { 45 46class NetworkTrayView : public TrayItemView, 47 public network_icon::AnimationObserver { 48 public: 49 explicit NetworkTrayView(TrayNetwork* network_tray) 50 : TrayItemView(network_tray), 51 network_tray_(network_tray) { 52 SetLayoutManager( 53 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); 54 55 image_view_ = new views::ImageView; 56 AddChildView(image_view_); 57 58 UpdateNetworkStateHandlerIcon(); 59 } 60 61 virtual ~NetworkTrayView() { 62 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); 63 } 64 65 virtual const char* GetClassName() const OVERRIDE { 66 return "NetworkTrayView"; 67 } 68 69 void UpdateNetworkStateHandlerIcon() { 70 NetworkStateHandler* handler = 71 NetworkHandler::Get()->network_state_handler(); 72 gfx::ImageSkia image; 73 base::string16 name; 74 bool animating = false; 75 network_icon::GetDefaultNetworkImageAndLabel( 76 network_icon::ICON_TYPE_TRAY, &image, &name, &animating); 77 bool show_in_tray = !image.isNull(); 78 UpdateIcon(show_in_tray, image); 79 if (animating) 80 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this); 81 else 82 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); 83 // Update accessibility. 84 const NetworkState* connected_network = 85 handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual()); 86 if (connected_network) 87 UpdateConnectionStatus(UTF8ToUTF16(connected_network->name()), true); 88 else 89 UpdateConnectionStatus(base::string16(), false); 90 } 91 92 // views::View override. 93 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE { 94 state->name = connection_status_string_; 95 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; 96 } 97 98 // network_icon::AnimationObserver 99 virtual void NetworkIconChanged() OVERRIDE { 100 UpdateNetworkStateHandlerIcon(); 101 } 102 103 private: 104 // Updates connection status and notifies accessibility event when necessary. 105 void UpdateConnectionStatus(const base::string16& network_name, 106 bool connected) { 107 base::string16 new_connection_status_string; 108 if (connected) { 109 new_connection_status_string = l10n_util::GetStringFUTF16( 110 IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, network_name); 111 } 112 if (new_connection_status_string != connection_status_string_) { 113 connection_status_string_ = new_connection_status_string; 114 if(!connection_status_string_.empty()) 115 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_ALERT, true); 116 } 117 } 118 119 void UpdateIcon(bool tray_icon_visible, const gfx::ImageSkia& image) { 120 image_view_->SetImage(image); 121 SetVisible(tray_icon_visible); 122 SchedulePaint(); 123 } 124 125 TrayNetwork* network_tray_; 126 views::ImageView* image_view_; 127 base::string16 connection_status_string_; 128 129 DISALLOW_COPY_AND_ASSIGN(NetworkTrayView); 130}; 131 132class NetworkDefaultView : public TrayItemMore, 133 public network_icon::AnimationObserver { 134 public: 135 NetworkDefaultView(TrayNetwork* network_tray, bool show_more) 136 : TrayItemMore(network_tray, show_more), 137 network_tray_(network_tray) { 138 Update(); 139 } 140 141 virtual ~NetworkDefaultView() { 142 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); 143 } 144 145 void Update() { 146 gfx::ImageSkia image; 147 base::string16 label; 148 bool animating = false; 149 network_icon::GetDefaultNetworkImageAndLabel( 150 network_icon::ICON_TYPE_DEFAULT_VIEW, &image, &label, &animating); 151 if (animating) 152 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this); 153 else 154 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); 155 SetImage(&image); 156 SetLabel(label); 157 SetAccessibleName(label); 158 } 159 160 // network_icon::AnimationObserver 161 virtual void NetworkIconChanged() OVERRIDE { 162 Update(); 163 } 164 165 private: 166 TrayNetwork* network_tray_; 167 168 DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView); 169}; 170 171class NetworkWifiDetailedView : public NetworkDetailedView { 172 public: 173 explicit NetworkWifiDetailedView(SystemTrayItem* owner) 174 : NetworkDetailedView(owner) { 175 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 176 kTrayPopupPaddingHorizontal, 177 10, 178 kTrayPopupPaddingBetweenItems)); 179 image_view_ = new views::ImageView; 180 AddChildView(image_view_); 181 182 label_view_ = new views::Label(); 183 label_view_->SetMultiLine(true); 184 label_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 185 AddChildView(label_view_); 186 187 Update(); 188 } 189 190 virtual ~NetworkWifiDetailedView() { 191 } 192 193 // Overridden from NetworkDetailedView: 194 195 virtual void Init() OVERRIDE { 196 } 197 198 virtual NetworkDetailedView::DetailedViewType GetViewType() const OVERRIDE { 199 return NetworkDetailedView::WIFI_VIEW; 200 } 201 202 virtual void ManagerChanged() OVERRIDE { 203 Update(); 204 } 205 206 virtual void NetworkListChanged() OVERRIDE { 207 Update(); 208 } 209 210 virtual void NetworkServiceChanged( 211 const chromeos::NetworkState* network) OVERRIDE { 212 } 213 214 private: 215 virtual void Layout() OVERRIDE { 216 // Center both views vertically. 217 views::View::Layout(); 218 image_view_->SetY( 219 (height() - image_view_->GetPreferredSize().height()) / 2); 220 label_view_->SetY( 221 (height() - label_view_->GetPreferredSize().height()) / 2); 222 } 223 224 void Update() { 225 bool wifi_enabled = 226 NetworkHandler::Get()->network_state_handler()->IsTechnologyEnabled( 227 NetworkTypePattern::WiFi()); 228 const int image_id = wifi_enabled ? 229 IDR_AURA_UBER_TRAY_WIFI_ENABLED : IDR_AURA_UBER_TRAY_WIFI_DISABLED; 230 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 231 image_view_->SetImage(bundle.GetImageNamed(image_id).ToImageSkia()); 232 233 const int string_id = wifi_enabled ? 234 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED : 235 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED; 236 label_view_->SetText(bundle.GetLocalizedString(string_id)); 237 label_view_->SizeToFit(kTrayPopupMinWidth - 238 kTrayPopupPaddingHorizontal * 2 - kTrayPopupPaddingBetweenItems - 239 kTrayPopupDetailsIconWidth); 240 } 241 242 views::ImageView* image_view_; 243 views::Label* label_view_; 244 245 DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView); 246}; 247 248} // namespace tray 249 250TrayNetwork::TrayNetwork(SystemTray* system_tray) 251 : SystemTrayItem(system_tray), 252 tray_(NULL), 253 default_(NULL), 254 detailed_(NULL), 255 request_wifi_view_(false) { 256 network_state_observer_.reset(new TrayNetworkStateObserver(this)); 257 Shell::GetInstance()->system_tray_notifier()->AddNetworkObserver(this); 258} 259 260TrayNetwork::~TrayNetwork() { 261 Shell::GetInstance()->system_tray_notifier()->RemoveNetworkObserver(this); 262} 263 264views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) { 265 CHECK(tray_ == NULL); 266 if (!chromeos::NetworkHandler::IsInitialized()) 267 return NULL; 268 tray_ = new tray::NetworkTrayView(this); 269 return tray_; 270} 271 272views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) { 273 CHECK(default_ == NULL); 274 if (!chromeos::NetworkHandler::IsInitialized()) 275 return NULL; 276 CHECK(tray_ != NULL); 277 default_ = new tray::NetworkDefaultView( 278 this, status != user::LOGGED_IN_LOCKED); 279 return default_; 280} 281 282views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) { 283 CHECK(detailed_ == NULL); 284 if (!chromeos::NetworkHandler::IsInitialized()) 285 return NULL; 286 if (request_wifi_view_) { 287 detailed_ = new tray::NetworkWifiDetailedView(this); 288 request_wifi_view_ = false; 289 } else { 290 detailed_ = new tray::NetworkStateListDetailedView( 291 this, tray::NetworkStateListDetailedView::LIST_TYPE_NETWORK, status); 292 detailed_->Init(); 293 } 294 return detailed_; 295} 296 297void TrayNetwork::DestroyTrayView() { 298 tray_ = NULL; 299} 300 301void TrayNetwork::DestroyDefaultView() { 302 default_ = NULL; 303} 304 305void TrayNetwork::DestroyDetailedView() { 306 detailed_ = NULL; 307} 308 309void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) { 310} 311 312void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { 313 if (tray_) 314 SetTrayImageItemBorder(tray_, alignment); 315} 316 317void TrayNetwork::RequestToggleWifi() { 318 // This will always be triggered by a user action (e.g. keyboard shortcut) 319 if (!detailed_ || 320 detailed_->GetViewType() == tray::NetworkDetailedView::WIFI_VIEW) { 321 request_wifi_view_ = true; 322 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false); 323 } 324 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 325 bool enabled = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi()); 326 handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(), 327 !enabled, 328 chromeos::network_handler::ErrorCallback()); 329} 330 331void TrayNetwork::NetworkStateChanged(bool list_changed) { 332 if (tray_) 333 tray_->UpdateNetworkStateHandlerIcon(); 334 if (default_) 335 default_->Update(); 336 if (detailed_) { 337 if (list_changed) 338 detailed_->NetworkListChanged(); 339 else 340 detailed_->ManagerChanged(); 341 } 342} 343 344void TrayNetwork::NetworkServiceChanged(const chromeos::NetworkState* network) { 345 if (detailed_) 346 detailed_->NetworkServiceChanged(network); 347} 348 349} // namespace internal 350} // namespace ash 351