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.
5 #include "ash/system/chromeos/network/network_icon.h"
8 #include "ash/system/chromeos/network/network_icon_animation.h"
9 #include "ash/system/chromeos/network/network_icon_animation_observer.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chromeos/network/device_state.h"
12 #include "chromeos/network/network_connection_handler.h"
13 #include "chromeos/network/network_state.h"
14 #include "chromeos/network/network_state_handler.h"
15 #include "chromeos/network/shill_property_util.h"
16 #include "grit/ash_resources.h"
17 #include "grit/ash_strings.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/base/resource/resource_bundle.h"
21 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/image/image_skia_operations.h"
23 #include "ui/gfx/image/image_skia_source.h"
24 #include "ui/gfx/rect.h"
25 #include "ui/gfx/size_conversions.h"
27 using chromeos::DeviceState;
28 using chromeos::NetworkConnectionHandler;
29 using chromeos::NetworkHandler;
30 using chromeos::NetworkState;
31 using chromeos::NetworkStateHandler;
32 using chromeos::NetworkTypePattern;
35 namespace network_icon {
39 //------------------------------------------------------------------------------
40 // Struct to pass icon badges to NetworkIconImageSource.
48 const gfx::ImageSkia* top_left;
49 const gfx::ImageSkia* top_right;
50 const gfx::ImageSkia* bottom_left;
51 const gfx::ImageSkia* bottom_right;
54 //------------------------------------------------------------------------------
55 // class used for maintaining a map of network state and images.
56 class NetworkIconImpl {
58 explicit NetworkIconImpl(IconType icon_type);
60 // Determines whether or not the associated network might be dirty and if so
61 // updates and generates the icon. Does nothing if network no longer exists.
62 void Update(const chromeos::NetworkState* network);
64 const gfx::ImageSkia& image() const { return image_; }
67 // Updates |strength_index_| for wireless networks. Returns true if changed.
68 bool UpdateWirelessStrengthIndex(const chromeos::NetworkState* network);
70 // Updates the local state for cellular networks. Returns true if changed.
71 bool UpdateCellularState(const chromeos::NetworkState* network);
73 // Updates the VPN badge. Returns true if changed.
74 bool UpdateVPNBadge();
76 // Gets |badges| based on |network| and the current state.
77 void GetBadges(const NetworkState* network, Badges* badges);
79 // Gets the appropriate icon and badges and composites the image.
80 void GenerateImage(const chromeos::NetworkState* network);
82 // Defines color theme and VPN badging
83 const IconType icon_type_;
85 // Cached state of the network when the icon was last generated.
88 // Cached strength index of the network when the icon was last generated.
91 // Cached technology badge for the network when the icon was last generated.
92 const gfx::ImageSkia* technology_badge_;
94 // Cached vpn badge for the network when the icon was last generated.
95 const gfx::ImageSkia* vpn_badge_;
97 // Cached roaming state of the network when the icon was last generated.
98 std::string roaming_state_;
100 // Generated icon image.
101 gfx::ImageSkia image_;
103 DISALLOW_COPY_AND_ASSIGN(NetworkIconImpl);
106 //------------------------------------------------------------------------------
107 // Maintain a static (global) icon map. Note: Icons are never destroyed;
108 // it is assumed that a finite and reasonable number of network icons will be
109 // created during a session.
111 typedef std::map<std::string, NetworkIconImpl*> NetworkIconMap;
113 NetworkIconMap* GetIconMapInstance(IconType icon_type, bool create) {
114 typedef std::map<IconType, NetworkIconMap*> IconTypeMap;
115 static IconTypeMap* s_icon_map = NULL;
116 if (s_icon_map == NULL) {
119 s_icon_map = new IconTypeMap;
121 if (s_icon_map->count(icon_type) == 0) {
124 (*s_icon_map)[icon_type] = new NetworkIconMap;
126 return (*s_icon_map)[icon_type];
129 NetworkIconMap* GetIconMap(IconType icon_type) {
130 return GetIconMapInstance(icon_type, true);
133 void PurgeIconMap(IconType icon_type,
134 const std::set<std::string>& network_paths) {
135 NetworkIconMap* icon_map = GetIconMapInstance(icon_type, false);
138 for (NetworkIconMap::iterator loop_iter = icon_map->begin();
139 loop_iter != icon_map->end(); ) {
140 NetworkIconMap::iterator cur_iter = loop_iter++;
141 if (network_paths.count(cur_iter->first) == 0) {
142 delete cur_iter->second;
143 icon_map->erase(cur_iter);
148 //------------------------------------------------------------------------------
149 // Utilities for generating icon images.
151 // 'NONE' will default to ARCS behavior where appropriate (e.g. no network or
152 // if a new type gets added).
159 // Amount to fade icons while connecting.
160 const double kConnectingImageAlpha = 0.5;
162 // Images for strength bars for wired networks.
163 const int kNumBarsImages = 5;
165 // Imagaes for strength arcs for wireless networks.
166 const int kNumArcsImages = 5;
168 // Number of discrete images to use for alpha fade animation
169 const int kNumFadeImages = 10;
171 //------------------------------------------------------------------------------
172 // Classes for generating scaled images.
174 const SkBitmap GetEmptyBitmap(const gfx::Size pixel_size) {
175 typedef std::pair<int, int> SizeKey;
176 typedef std::map<SizeKey, SkBitmap> SizeBitmapMap;
177 static SizeBitmapMap* s_empty_bitmaps = new SizeBitmapMap;
179 SizeKey key(pixel_size.width(), pixel_size.height());
181 SizeBitmapMap::iterator iter = s_empty_bitmaps->find(key);
182 if (iter != s_empty_bitmaps->end())
186 empty.setConfig(SkBitmap::kARGB_8888_Config, key.first, key.second);
188 empty.eraseARGB(0, 0, 0, 0);
189 (*s_empty_bitmaps)[key] = empty;
193 class EmptyImageSource: public gfx::ImageSkiaSource {
195 explicit EmptyImageSource(const gfx::Size& size)
199 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
200 gfx::Size pixel_size = gfx::ToFlooredSize(gfx::ScaleSize(size_, scale));
201 SkBitmap empty_bitmap = GetEmptyBitmap(pixel_size);
202 return gfx::ImageSkiaRep(empty_bitmap, scale);
206 const gfx::Size size_;
208 DISALLOW_COPY_AND_ASSIGN(EmptyImageSource);
211 // This defines how we assemble a network icon.
212 class NetworkIconImageSource : public gfx::ImageSkiaSource {
214 NetworkIconImageSource(const gfx::ImageSkia& icon, const Badges& badges)
218 virtual ~NetworkIconImageSource() {}
220 // TODO(pkotwicz): Figure out what to do when a new image resolution becomes
222 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
223 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale);
224 if (icon_rep.is_null())
225 return gfx::ImageSkiaRep();
226 gfx::Canvas canvas(icon_rep, false);
227 if (badges_.top_left)
228 canvas.DrawImageInt(*badges_.top_left, 0, 0);
229 if (badges_.top_right)
230 canvas.DrawImageInt(*badges_.top_right,
231 icon_.width() - badges_.top_right->width(), 0);
232 if (badges_.bottom_left) {
233 canvas.DrawImageInt(*badges_.bottom_left,
234 0, icon_.height() - badges_.bottom_left->height());
236 if (badges_.bottom_right) {
237 canvas.DrawImageInt(*badges_.bottom_right,
238 icon_.width() - badges_.bottom_right->width(),
239 icon_.height() - badges_.bottom_right->height());
241 return canvas.ExtractImageRep();
245 const gfx::ImageSkia icon_;
246 const Badges badges_;
248 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource);
251 //------------------------------------------------------------------------------
252 // Utilities for extracting icon images.
254 bool IconTypeIsDark(IconType icon_type) {
255 return (icon_type != ICON_TYPE_TRAY);
258 bool IconTypeHasVPNBadge(IconType icon_type) {
259 return (icon_type != ICON_TYPE_LIST);
262 int NumImagesForType(ImageType type) {
263 return (type == BARS) ? kNumBarsImages : kNumArcsImages;
266 gfx::ImageSkia* BaseImageForType(ImageType image_type, IconType icon_type) {
267 gfx::ImageSkia* image;
268 if (image_type == BARS) {
269 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
270 IconTypeIsDark(icon_type) ?
271 IDR_AURA_UBER_TRAY_NETWORK_BARS_DARK :
272 IDR_AURA_UBER_TRAY_NETWORK_BARS_LIGHT);
274 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
275 IconTypeIsDark(icon_type) ?
276 IDR_AURA_UBER_TRAY_NETWORK_ARCS_DARK :
277 IDR_AURA_UBER_TRAY_NETWORK_ARCS_LIGHT);
282 ImageType ImageTypeForNetworkType(const std::string& type) {
283 if (type == shill::kTypeWifi)
285 else if (type == shill::kTypeCellular || type == shill::kTypeWimax)
290 gfx::ImageSkia GetImageForIndex(ImageType image_type,
293 int num_images = NumImagesForType(image_type);
294 if (index < 0 || index >= num_images)
295 return gfx::ImageSkia();
296 gfx::ImageSkia* images = BaseImageForType(image_type, icon_type);
297 int width = images->width();
298 int height = images->height() / num_images;
299 return gfx::ImageSkiaOperations::ExtractSubset(*images,
300 gfx::Rect(0, index * height, width, height));
303 const gfx::ImageSkia GetConnectedImage(const std::string& type,
304 IconType icon_type) {
305 if (type == shill::kTypeVPN) {
306 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
307 IDR_AURA_UBER_TRAY_NETWORK_VPN);
309 ImageType image_type = ImageTypeForNetworkType(type);
310 const int connected_index = NumImagesForType(image_type) - 1;
311 return GetImageForIndex(image_type, icon_type, connected_index);
314 const gfx::ImageSkia GetDisconnectedImage(const std::string& type,
315 IconType icon_type) {
316 if (type == shill::kTypeVPN) {
317 // Note: same as connected image, shouldn't normally be seen.
318 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
319 IDR_AURA_UBER_TRAY_NETWORK_VPN);
321 ImageType image_type = ImageTypeForNetworkType(type);
322 const int disconnected_index = 0;
323 return GetImageForIndex(image_type, icon_type, disconnected_index);
326 gfx::ImageSkia* ConnectingWirelessImage(ImageType image_type,
329 static gfx::ImageSkia* s_bars_images_dark[kNumBarsImages - 1];
330 static gfx::ImageSkia* s_bars_images_light[kNumBarsImages - 1];
331 static gfx::ImageSkia* s_arcs_images_dark[kNumArcsImages - 1];
332 static gfx::ImageSkia* s_arcs_images_light[kNumArcsImages - 1];
333 int image_count = NumImagesForType(image_type) - 1;
334 int index = animation * nextafter(static_cast<float>(image_count), 0);
335 index = std::max(std::min(index, image_count - 1), 0);
336 gfx::ImageSkia** images;
337 bool dark = IconTypeIsDark(icon_type);
338 if (image_type == BARS)
339 images = dark ? s_bars_images_dark : s_bars_images_light;
341 images = dark ? s_arcs_images_dark : s_arcs_images_light;
342 if (!images[index]) {
343 // Lazily cache images.
344 gfx::ImageSkia source = GetImageForIndex(image_type, icon_type, index + 1);
345 images[index] = new gfx::ImageSkia(
346 gfx::ImageSkiaOperations::CreateBlendedImage(
347 gfx::ImageSkia(new EmptyImageSource(source.size()), source.size()),
349 kConnectingImageAlpha));
351 return images[index];
354 gfx::ImageSkia* ConnectingVpnImage(double animation) {
355 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0);
356 static gfx::ImageSkia* s_vpn_images[kNumFadeImages];
357 if (!s_vpn_images[index]) {
358 // Lazily cache images.
359 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
360 gfx::ImageSkia* icon = rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN);
361 s_vpn_images[index] = new gfx::ImageSkia(
362 gfx::ImageSkiaOperations::CreateBlendedImage(
363 gfx::ImageSkia(new EmptyImageSource(icon->size()), icon->size()),
367 return s_vpn_images[index];
370 gfx::ImageSkia* ConnectingVpnBadge(double animation) {
371 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0);
372 static gfx::ImageSkia* s_vpn_badges[kNumFadeImages];
373 if (!s_vpn_badges[index]) {
374 // Lazily cache images.
375 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
376 gfx::ImageSkia* icon =
377 rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED); // For size
378 gfx::ImageSkia* badge =
379 rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE);
380 s_vpn_badges[index] = new gfx::ImageSkia(
381 gfx::ImageSkiaOperations::CreateBlendedImage(
382 gfx::ImageSkia(new EmptyImageSource(icon->size()), icon->size()),
386 return s_vpn_badges[index];
389 int StrengthIndex(int strength, int count) {
390 // Return an index in the range [1, count-1].
391 const float findex = (static_cast<float>(strength) / 100.0f) *
392 nextafter(static_cast<float>(count - 1), 0);
393 int index = 1 + static_cast<int>(findex);
394 index = std::max(std::min(index, count - 1), 1);
398 int GetStrengthIndex(const NetworkState* network) {
399 ImageType image_type = ImageTypeForNetworkType(network->type());
400 if (image_type == ARCS)
401 return StrengthIndex(network->signal_strength(), kNumArcsImages);
402 else if (image_type == BARS)
403 return StrengthIndex(network->signal_strength(), kNumBarsImages);
407 const gfx::ImageSkia* BadgeForNetworkTechnology(const NetworkState* network,
408 IconType icon_type) {
409 const int kUnknownBadgeType = -1;
410 int id = kUnknownBadgeType;
411 const std::string& technology = network->network_technology();
412 if (technology == shill::kNetworkTechnologyEvdo) {
413 id = IconTypeIsDark(icon_type) ?
414 IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK :
415 IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT;
416 } else if (technology == shill::kNetworkTechnology1Xrtt) {
417 id = IDR_AURA_UBER_TRAY_NETWORK_1X;
418 } else if (technology == shill::kNetworkTechnologyGprs) {
419 id = IconTypeIsDark(icon_type) ?
420 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK :
421 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT;
422 } else if (technology == shill::kNetworkTechnologyEdge) {
423 id = IconTypeIsDark(icon_type) ?
424 IDR_AURA_UBER_TRAY_NETWORK_EDGE_DARK :
425 IDR_AURA_UBER_TRAY_NETWORK_EDGE_LIGHT;
426 } else if (technology == shill::kNetworkTechnologyUmts) {
427 id = IconTypeIsDark(icon_type) ?
428 IDR_AURA_UBER_TRAY_NETWORK_3G_DARK :
429 IDR_AURA_UBER_TRAY_NETWORK_3G_LIGHT;
430 } else if (technology == shill::kNetworkTechnologyHspa) {
431 id = IconTypeIsDark(icon_type) ?
432 IDR_AURA_UBER_TRAY_NETWORK_HSPA_DARK :
433 IDR_AURA_UBER_TRAY_NETWORK_HSPA_LIGHT;
434 } else if (technology == shill::kNetworkTechnologyHspaPlus) {
435 id = IconTypeIsDark(icon_type) ?
436 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_DARK :
437 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_LIGHT;
438 } else if (technology == shill::kNetworkTechnologyLte) {
439 id = IconTypeIsDark(icon_type) ?
440 IDR_AURA_UBER_TRAY_NETWORK_LTE_DARK :
441 IDR_AURA_UBER_TRAY_NETWORK_LTE_LIGHT;
442 } else if (technology == shill::kNetworkTechnologyLteAdvanced) {
443 id = IconTypeIsDark(icon_type) ?
444 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_DARK :
445 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_LIGHT;
446 } else if (technology == shill::kNetworkTechnologyGsm) {
447 id = IconTypeIsDark(icon_type) ?
448 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK :
449 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT;
451 if (id == kUnknownBadgeType)
454 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id);
457 const gfx::ImageSkia* BadgeForVPN(IconType icon_type) {
458 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
459 IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE);
462 gfx::ImageSkia GetIcon(const NetworkState* network,
464 int strength_index) {
465 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
466 if (network->Matches(NetworkTypePattern::Ethernet())) {
467 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED);
468 } else if (network->Matches(NetworkTypePattern::Wireless())) {
469 DCHECK(strength_index > 0);
470 return GetImageForIndex(
471 ImageTypeForNetworkType(network->type()), icon_type, strength_index);
472 } else if (network->Matches(NetworkTypePattern::VPN())) {
473 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN);
475 LOG(WARNING) << "Request for icon for unsupported type: "
477 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED);
481 //------------------------------------------------------------------------------
482 // Get connecting images
484 gfx::ImageSkia GetConnectingVpnImage(IconType icon_type) {
485 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
486 const NetworkState* connected_network = NULL;
487 if (icon_type == ICON_TYPE_TRAY) {
489 handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
491 double animation = NetworkIconAnimation::GetInstance()->GetAnimation();
493 if (connected_network) {
494 gfx::ImageSkia icon = GetImageForNetwork(connected_network, icon_type);
496 badges.bottom_left = ConnectingVpnBadge(animation);
497 return gfx::ImageSkia(
498 new NetworkIconImageSource(icon, badges), icon.size());
500 gfx::ImageSkia* icon = ConnectingVpnImage(animation);
501 return gfx::ImageSkia(
502 new NetworkIconImageSource(*icon, Badges()), icon->size());
506 gfx::ImageSkia GetConnectingImage(const std::string& network_type,
507 IconType icon_type) {
508 if (network_type == shill::kTypeVPN)
509 return GetConnectingVpnImage(icon_type);
511 ImageType image_type = ImageTypeForNetworkType(network_type);
512 double animation = NetworkIconAnimation::GetInstance()->GetAnimation();
514 gfx::ImageSkia* icon = ConnectingWirelessImage(
515 image_type, icon_type, animation);
516 return gfx::ImageSkia(
517 new NetworkIconImageSource(*icon, Badges()), icon->size());
522 //------------------------------------------------------------------------------
525 NetworkIconImpl::NetworkIconImpl(IconType icon_type)
526 : icon_type_(icon_type),
528 technology_badge_(NULL),
531 image_ = GetDisconnectedImage(shill::kTypeWifi, icon_type);
534 void NetworkIconImpl::Update(const NetworkState* network) {
536 // Determine whether or not we need to update the icon.
537 bool dirty = image_.isNull();
539 // If the network state has changed, the icon needs updating.
540 if (state_ != network->connection_state()) {
541 state_ = network->connection_state();
545 if (network->Matches(NetworkTypePattern::Wireless()))
546 dirty |= UpdateWirelessStrengthIndex(network);
548 if (network->Matches(NetworkTypePattern::Cellular()))
549 dirty |= UpdateCellularState(network);
551 if (IconTypeHasVPNBadge(icon_type_) &&
552 network->Matches(NetworkTypePattern::NonVirtual())) {
553 dirty |= UpdateVPNBadge();
557 // Set the icon and badges based on the network and generate the image.
558 GenerateImage(network);
562 bool NetworkIconImpl::UpdateWirelessStrengthIndex(const NetworkState* network) {
563 int index = GetStrengthIndex(network);
564 if (index != strength_index_) {
565 strength_index_ = index;
571 bool NetworkIconImpl::UpdateCellularState(const NetworkState* network) {
573 const gfx::ImageSkia* technology_badge =
574 BadgeForNetworkTechnology(network, icon_type_);
575 if (technology_badge != technology_badge_) {
576 technology_badge_ = technology_badge;
579 std::string roaming_state = network->roaming();
580 if (roaming_state != roaming_state_) {
581 roaming_state_ = roaming_state;
587 bool NetworkIconImpl::UpdateVPNBadge() {
588 const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
589 ConnectedNetworkByType(NetworkTypePattern::VPN());
590 if (vpn && vpn_badge_ == NULL) {
591 vpn_badge_ = BadgeForVPN(icon_type_);
593 } else if (!vpn && vpn_badge_ != NULL) {
600 void NetworkIconImpl::GetBadges(const NetworkState* network, Badges* badges) {
602 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
603 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
605 const std::string& type = network->type();
606 if (type == shill::kTypeWifi) {
607 if (network->security() != shill::kSecurityNone &&
608 IconTypeIsDark(icon_type_)) {
609 badges->bottom_right = rb.GetImageSkiaNamed(
610 IDR_AURA_UBER_TRAY_NETWORK_SECURE_DARK);
612 } else if (type == shill::kTypeWimax) {
613 technology_badge_ = rb.GetImageSkiaNamed(
614 IconTypeIsDark(icon_type_) ?
615 IDR_AURA_UBER_TRAY_NETWORK_4G_DARK :
616 IDR_AURA_UBER_TRAY_NETWORK_4G_LIGHT);
617 } else if (type == shill::kTypeCellular) {
618 if (network->roaming() == shill::kRoamingStateRoaming) {
619 // For networks that are always in roaming don't show roaming badge.
620 const DeviceState* device =
621 handler->GetDeviceState(network->device_path());
622 LOG_IF(WARNING, !device) << "Could not find device state for "
623 << network->device_path();
624 if (!device || !device->provider_requires_roaming()) {
625 badges->bottom_right = rb.GetImageSkiaNamed(
626 IconTypeIsDark(icon_type_) ?
627 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_DARK :
628 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_LIGHT);
632 if (!network->IsConnectingState()) {
633 badges->top_left = technology_badge_;
634 badges->bottom_left = vpn_badge_;
638 void NetworkIconImpl::GenerateImage(const NetworkState* network) {
640 gfx::ImageSkia icon = GetIcon(network, icon_type_, strength_index_);
642 GetBadges(network, &badges);
643 image_ = gfx::ImageSkia(
644 new NetworkIconImageSource(icon, badges), icon.size());
647 //------------------------------------------------------------------------------
650 gfx::ImageSkia GetImageForNetwork(const NetworkState* network,
651 IconType icon_type) {
653 // Handle connecting icons.
654 if (network->IsConnectingState())
655 return GetConnectingImage(network->type(), icon_type);
657 // Find or add the icon.
658 NetworkIconMap* icon_map = GetIconMap(icon_type);
659 NetworkIconImpl* icon;
660 NetworkIconMap::iterator iter = icon_map->find(network->path());
661 if (iter == icon_map->end()) {
662 icon = new NetworkIconImpl(icon_type);
663 icon_map->insert(std::make_pair(network->path(), icon));
668 // Update and return the icon's image.
669 icon->Update(network);
670 return icon->image();
673 gfx::ImageSkia GetImageForConnectedNetwork(IconType icon_type,
674 const std::string& network_type) {
675 return GetConnectedImage(network_type, icon_type);
678 gfx::ImageSkia GetImageForConnectingNetwork(IconType icon_type,
679 const std::string& network_type) {
680 return GetConnectingImage(network_type, icon_type);
683 gfx::ImageSkia GetImageForDisconnectedNetwork(IconType icon_type,
684 const std::string& network_type) {
685 return GetDisconnectedImage(network_type, icon_type);
688 base::string16 GetLabelForNetwork(const chromeos::NetworkState* network,
689 IconType icon_type) {
691 std::string activation_state = network->activation_state();
692 if (icon_type == ICON_TYPE_LIST) {
693 // Show "<network>: [Connecting|Activating]..."
694 if (network->IsConnectingState()) {
695 return l10n_util::GetStringFUTF16(
696 IDS_ASH_STATUS_TRAY_NETWORK_LIST_CONNECTING,
697 UTF8ToUTF16(network->name()));
699 if (activation_state == shill::kActivationStateActivating) {
700 return l10n_util::GetStringFUTF16(
701 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING,
702 UTF8ToUTF16(network->name()));
704 // Show "Activate <network>" in list view only.
705 if (activation_state == shill::kActivationStateNotActivated ||
706 activation_state == shill::kActivationStatePartiallyActivated) {
707 return l10n_util::GetStringFUTF16(
708 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE,
709 UTF8ToUTF16(network->name()));
712 // Show "[Connected to|Connecting to|Activating] <network>" (non-list view).
713 if (network->IsConnectedState()) {
714 return l10n_util::GetStringFUTF16(
715 IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, UTF8ToUTF16(network->name()));
717 if (network->IsConnectingState()) {
718 return l10n_util::GetStringFUTF16(
719 IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING, UTF8ToUTF16(network->name()));
721 if (activation_state == shill::kActivationStateActivating) {
722 return l10n_util::GetStringFUTF16(
723 IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING, UTF8ToUTF16(network->name()));
727 // Otherwise just show the network name or 'Ethernet'.
728 if (network->Matches(NetworkTypePattern::Ethernet())) {
729 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET);
731 return UTF8ToUTF16(network->name());
735 int GetCellularUninitializedMsg() {
736 static base::Time s_uninitialized_state_time;
737 static int s_uninitialized_msg(0);
739 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
740 if (handler->GetTechnologyState(NetworkTypePattern::Mobile())
741 == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) {
742 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR;
743 s_uninitialized_state_time = base::Time::Now();
744 return s_uninitialized_msg;
745 } else if (handler->GetScanningByType(NetworkTypePattern::Mobile())) {
746 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_CELLULAR_SCANNING;
747 s_uninitialized_state_time = base::Time::Now();
748 return s_uninitialized_msg;
750 // There can be a delay between leaving the Initializing state and when
751 // a Cellular device shows up, so keep showing the initializing
752 // animation for a bit to avoid flashing the disconnect icon.
753 const int kInitializingDelaySeconds = 1;
754 base::TimeDelta dtime = base::Time::Now() - s_uninitialized_state_time;
755 if (dtime.InSeconds() < kInitializingDelaySeconds)
756 return s_uninitialized_msg;
760 void GetDefaultNetworkImageAndLabel(IconType icon_type,
761 gfx::ImageSkia* image,
762 base::string16* label,
764 NetworkStateHandler* state_handler =
765 NetworkHandler::Get()->network_state_handler();
766 NetworkConnectionHandler* connect_handler =
767 NetworkHandler::Get()->network_connection_handler();
768 const NetworkState* connected_network =
769 state_handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
770 const NetworkState* connecting_network =
771 state_handler->ConnectingNetworkByType(NetworkTypePattern::Wireless());
772 if (!connecting_network && icon_type == ICON_TYPE_TRAY) {
774 state_handler->ConnectingNetworkByType(NetworkTypePattern::VPN());
777 const NetworkState* network;
778 // If we are connecting to a network, and there is either no connected
779 // network, or the connection was user requested, use the connecting
781 if (connecting_network &&
782 (!connected_network ||
783 connect_handler->HasConnectingNetwork(connecting_network->path()))) {
784 network = connecting_network;
786 network = connected_network;
789 // Don't show ethernet in the tray
790 if (icon_type == ICON_TYPE_TRAY && network &&
791 network->Matches(NetworkTypePattern::Ethernet())) {
792 *image = gfx::ImageSkia();
798 // If no connecting network, check if we are activating a network.
799 const NetworkState* mobile_network =
800 state_handler->FirstNetworkByType(NetworkTypePattern::Mobile());
801 if (mobile_network && (mobile_network->activation_state() ==
802 shill::kActivationStateActivating)) {
803 network = mobile_network;
807 // If no connecting network, check for cellular initializing.
808 int uninitialized_msg = GetCellularUninitializedMsg();
809 if (uninitialized_msg != 0) {
810 *image = GetImageForConnectingNetwork(icon_type, shill::kTypeCellular);
812 *label = l10n_util::GetStringUTF16(uninitialized_msg);
815 // Otherwise show the disconnected wifi icon.
816 *image = GetImageForDisconnectedNetwork(icon_type, shill::kTypeWifi);
818 *label = l10n_util::GetStringUTF16(
819 IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED);
825 *animating = network->IsConnectingState();
826 // Get icon and label for connected or connecting network.
827 *image = GetImageForNetwork(network, icon_type);
829 *label = GetLabelForNetwork(network, icon_type);
832 void PurgeNetworkIconCache() {
833 NetworkStateHandler::NetworkStateList networks;
834 NetworkHandler::Get()->network_state_handler()->GetNetworkList(&networks);
835 std::set<std::string> network_paths;
836 for (NetworkStateHandler::NetworkStateList::iterator iter = networks.begin();
837 iter != networks.end(); ++iter) {
838 network_paths.insert((*iter)->path());
840 PurgeIconMap(ICON_TYPE_TRAY, network_paths);
841 PurgeIconMap(ICON_TYPE_DEFAULT_VIEW, network_paths);
842 PurgeIconMap(ICON_TYPE_LIST, network_paths);
845 } // namespace network_icon