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 "ash/system/tray/system_tray_delegate.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chromeos/network/device_state.h"
13 #include "chromeos/network/network_connection_handler.h"
14 #include "chromeos/network/network_state.h"
15 #include "chromeos/network/network_state_handler.h"
16 #include "chromeos/network/shill_property_util.h"
17 #include "grit/ash_resources.h"
18 #include "grit/ash_strings.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/canvas.h"
23 #include "ui/gfx/image/image_skia_operations.h"
24 #include "ui/gfx/image/image_skia_source.h"
25 #include "ui/gfx/rect.h"
26 #include "ui/gfx/size_conversions.h"
28 using chromeos::DeviceState;
29 using chromeos::NetworkConnectionHandler;
30 using chromeos::NetworkHandler;
31 using chromeos::NetworkState;
32 using chromeos::NetworkStateHandler;
33 using chromeos::NetworkTypePattern;
36 namespace network_icon {
40 //------------------------------------------------------------------------------
41 // Struct to pass icon badges to NetworkIconImageSource.
49 const gfx::ImageSkia* top_left;
50 const gfx::ImageSkia* top_right;
51 const gfx::ImageSkia* bottom_left;
52 const gfx::ImageSkia* bottom_right;
55 //------------------------------------------------------------------------------
56 // class used for maintaining a map of network state and images.
57 class NetworkIconImpl {
59 explicit NetworkIconImpl(IconType icon_type);
61 // Determines whether or not the associated network might be dirty and if so
62 // updates and generates the icon. Does nothing if network no longer exists.
63 void Update(const chromeos::NetworkState* network);
65 const gfx::ImageSkia& image() const { return image_; }
68 // Updates |strength_index_| for wireless networks. Returns true if changed.
69 bool UpdateWirelessStrengthIndex(const chromeos::NetworkState* network);
71 // Updates the local state for cellular networks. Returns true if changed.
72 bool UpdateCellularState(const chromeos::NetworkState* network);
74 // Updates the portal state for wireless networks. Returns true if changed.
75 bool UpdatePortalState(const chromeos::NetworkState* network);
77 // Updates the VPN badge. Returns true if changed.
78 bool UpdateVPNBadge();
80 // Gets |badges| based on |network| and the current state.
81 void GetBadges(const NetworkState* network, Badges* badges);
83 // Gets the appropriate icon and badges and composites the image.
84 void GenerateImage(const chromeos::NetworkState* network);
86 // Defines color theme and VPN badging
87 const IconType icon_type_;
89 // Cached state of the network when the icon was last generated.
92 // Cached strength index of the network when the icon was last generated.
95 // Cached technology badge for the network when the icon was last generated.
96 const gfx::ImageSkia* technology_badge_;
98 // Cached vpn badge for the network when the icon was last generated.
99 const gfx::ImageSkia* vpn_badge_;
101 // Cached roaming state of the network when the icon was last generated.
102 std::string roaming_state_;
104 // Cached portal state of the network when the icon was last generated.
105 bool behind_captive_portal_;
107 // Generated icon image.
108 gfx::ImageSkia image_;
110 DISALLOW_COPY_AND_ASSIGN(NetworkIconImpl);
113 //------------------------------------------------------------------------------
114 // Maintain a static (global) icon map. Note: Icons are never destroyed;
115 // it is assumed that a finite and reasonable number of network icons will be
116 // created during a session.
118 typedef std::map<std::string, NetworkIconImpl*> NetworkIconMap;
120 NetworkIconMap* GetIconMapInstance(IconType icon_type, bool create) {
121 typedef std::map<IconType, NetworkIconMap*> IconTypeMap;
122 static IconTypeMap* s_icon_map = NULL;
123 if (s_icon_map == NULL) {
126 s_icon_map = new IconTypeMap;
128 if (s_icon_map->count(icon_type) == 0) {
131 (*s_icon_map)[icon_type] = new NetworkIconMap;
133 return (*s_icon_map)[icon_type];
136 NetworkIconMap* GetIconMap(IconType icon_type) {
137 return GetIconMapInstance(icon_type, true);
140 void PurgeIconMap(IconType icon_type,
141 const std::set<std::string>& network_paths) {
142 NetworkIconMap* icon_map = GetIconMapInstance(icon_type, false);
145 for (NetworkIconMap::iterator loop_iter = icon_map->begin();
146 loop_iter != icon_map->end(); ) {
147 NetworkIconMap::iterator cur_iter = loop_iter++;
148 if (network_paths.count(cur_iter->first) == 0) {
149 delete cur_iter->second;
150 icon_map->erase(cur_iter);
155 //------------------------------------------------------------------------------
156 // Utilities for generating icon images.
158 // 'NONE' will default to ARCS behavior where appropriate (e.g. no network or
159 // if a new type gets added).
166 // Amount to fade icons while connecting.
167 const double kConnectingImageAlpha = 0.5;
169 // Images for strength bars for wired networks.
170 const int kNumBarsImages = 5;
172 // Imagaes for strength arcs for wireless networks.
173 const int kNumArcsImages = 5;
175 // Number of discrete images to use for alpha fade animation
176 const int kNumFadeImages = 10;
178 //------------------------------------------------------------------------------
179 // Classes for generating scaled images.
181 const SkBitmap GetEmptyBitmap(const gfx::Size pixel_size) {
182 typedef std::pair<int, int> SizeKey;
183 typedef std::map<SizeKey, SkBitmap> SizeBitmapMap;
184 static SizeBitmapMap* s_empty_bitmaps = new SizeBitmapMap;
186 SizeKey key(pixel_size.width(), pixel_size.height());
188 SizeBitmapMap::iterator iter = s_empty_bitmaps->find(key);
189 if (iter != s_empty_bitmaps->end())
193 empty.setConfig(SkBitmap::kARGB_8888_Config, key.first, key.second);
195 empty.eraseARGB(0, 0, 0, 0);
196 (*s_empty_bitmaps)[key] = empty;
200 class EmptyImageSource: public gfx::ImageSkiaSource {
202 explicit EmptyImageSource(const gfx::Size& size)
206 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
207 gfx::Size pixel_size = gfx::ToFlooredSize(gfx::ScaleSize(size_, scale));
208 SkBitmap empty_bitmap = GetEmptyBitmap(pixel_size);
209 return gfx::ImageSkiaRep(empty_bitmap, scale);
213 const gfx::Size size_;
215 DISALLOW_COPY_AND_ASSIGN(EmptyImageSource);
218 // This defines how we assemble a network icon.
219 class NetworkIconImageSource : public gfx::ImageSkiaSource {
221 NetworkIconImageSource(const gfx::ImageSkia& icon, const Badges& badges)
225 virtual ~NetworkIconImageSource() {}
227 // TODO(pkotwicz): Figure out what to do when a new image resolution becomes
229 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
230 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale);
231 if (icon_rep.is_null())
232 return gfx::ImageSkiaRep();
233 gfx::Canvas canvas(icon_rep, false);
234 if (badges_.top_left)
235 canvas.DrawImageInt(*badges_.top_left, 0, 0);
236 if (badges_.top_right)
237 canvas.DrawImageInt(*badges_.top_right,
238 icon_.width() - badges_.top_right->width(), 0);
239 if (badges_.bottom_left) {
240 canvas.DrawImageInt(*badges_.bottom_left,
241 0, icon_.height() - badges_.bottom_left->height());
243 if (badges_.bottom_right) {
244 canvas.DrawImageInt(*badges_.bottom_right,
245 icon_.width() - badges_.bottom_right->width(),
246 icon_.height() - badges_.bottom_right->height());
248 return canvas.ExtractImageRep();
252 const gfx::ImageSkia icon_;
253 const Badges badges_;
255 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource);
258 //------------------------------------------------------------------------------
259 // Utilities for extracting icon images.
261 bool IconTypeIsDark(IconType icon_type) {
262 return (icon_type != ICON_TYPE_TRAY);
265 bool IconTypeHasVPNBadge(IconType icon_type) {
266 return (icon_type != ICON_TYPE_LIST);
269 int NumImagesForType(ImageType type) {
270 return (type == BARS) ? kNumBarsImages : kNumArcsImages;
273 gfx::ImageSkia* BaseImageForType(ImageType image_type, IconType icon_type) {
274 gfx::ImageSkia* image;
275 if (image_type == BARS) {
276 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
277 IconTypeIsDark(icon_type) ?
278 IDR_AURA_UBER_TRAY_NETWORK_BARS_DARK :
279 IDR_AURA_UBER_TRAY_NETWORK_BARS_LIGHT);
281 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
282 IconTypeIsDark(icon_type) ?
283 IDR_AURA_UBER_TRAY_NETWORK_ARCS_DARK :
284 IDR_AURA_UBER_TRAY_NETWORK_ARCS_LIGHT);
289 ImageType ImageTypeForNetworkType(const std::string& type) {
290 if (type == shill::kTypeWifi)
292 else if (type == shill::kTypeCellular || type == shill::kTypeWimax)
297 gfx::ImageSkia GetImageForIndex(ImageType image_type,
300 int num_images = NumImagesForType(image_type);
301 if (index < 0 || index >= num_images)
302 return gfx::ImageSkia();
303 gfx::ImageSkia* images = BaseImageForType(image_type, icon_type);
304 int width = images->width();
305 int height = images->height() / num_images;
306 return gfx::ImageSkiaOperations::ExtractSubset(*images,
307 gfx::Rect(0, index * height, width, height));
310 const gfx::ImageSkia GetConnectedImage(const std::string& type,
311 IconType icon_type) {
312 if (type == shill::kTypeVPN) {
313 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
314 IDR_AURA_UBER_TRAY_NETWORK_VPN);
316 ImageType image_type = ImageTypeForNetworkType(type);
317 const int connected_index = NumImagesForType(image_type) - 1;
318 return GetImageForIndex(image_type, icon_type, connected_index);
321 const gfx::ImageSkia GetDisconnectedImage(const std::string& type,
322 IconType icon_type) {
323 if (type == shill::kTypeVPN) {
324 // Note: same as connected image, shouldn't normally be seen.
325 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
326 IDR_AURA_UBER_TRAY_NETWORK_VPN);
328 ImageType image_type = ImageTypeForNetworkType(type);
329 const int disconnected_index = 0;
330 return GetImageForIndex(image_type, icon_type, disconnected_index);
333 gfx::ImageSkia* ConnectingWirelessImage(ImageType image_type,
336 static gfx::ImageSkia* s_bars_images_dark[kNumBarsImages - 1];
337 static gfx::ImageSkia* s_bars_images_light[kNumBarsImages - 1];
338 static gfx::ImageSkia* s_arcs_images_dark[kNumArcsImages - 1];
339 static gfx::ImageSkia* s_arcs_images_light[kNumArcsImages - 1];
340 int image_count = NumImagesForType(image_type) - 1;
341 int index = animation * nextafter(static_cast<float>(image_count), 0);
342 index = std::max(std::min(index, image_count - 1), 0);
343 gfx::ImageSkia** images;
344 bool dark = IconTypeIsDark(icon_type);
345 if (image_type == BARS)
346 images = dark ? s_bars_images_dark : s_bars_images_light;
348 images = dark ? s_arcs_images_dark : s_arcs_images_light;
349 if (!images[index]) {
350 // Lazily cache images.
351 gfx::ImageSkia source = GetImageForIndex(image_type, icon_type, index + 1);
352 images[index] = new gfx::ImageSkia(
353 gfx::ImageSkiaOperations::CreateBlendedImage(
354 gfx::ImageSkia(new EmptyImageSource(source.size()), source.size()),
356 kConnectingImageAlpha));
358 return images[index];
361 gfx::ImageSkia* ConnectingVpnImage(double animation) {
362 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0);
363 static gfx::ImageSkia* s_vpn_images[kNumFadeImages];
364 if (!s_vpn_images[index]) {
365 // Lazily cache images.
366 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
367 gfx::ImageSkia* icon = rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN);
368 s_vpn_images[index] = new gfx::ImageSkia(
369 gfx::ImageSkiaOperations::CreateBlendedImage(
370 gfx::ImageSkia(new EmptyImageSource(icon->size()), icon->size()),
374 return s_vpn_images[index];
377 gfx::ImageSkia* ConnectingVpnBadge(double animation) {
378 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0);
379 static gfx::ImageSkia* s_vpn_badges[kNumFadeImages];
380 if (!s_vpn_badges[index]) {
381 // Lazily cache images.
382 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
383 gfx::ImageSkia* icon =
384 rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED); // For size
385 gfx::ImageSkia* badge =
386 rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE);
387 s_vpn_badges[index] = new gfx::ImageSkia(
388 gfx::ImageSkiaOperations::CreateBlendedImage(
389 gfx::ImageSkia(new EmptyImageSource(icon->size()), icon->size()),
393 return s_vpn_badges[index];
396 int StrengthIndex(int strength, int count) {
397 // Return an index in the range [1, count-1].
398 const float findex = (static_cast<float>(strength) / 100.0f) *
399 nextafter(static_cast<float>(count - 1), 0);
400 int index = 1 + static_cast<int>(findex);
401 index = std::max(std::min(index, count - 1), 1);
405 int GetStrengthIndex(const NetworkState* network) {
406 ImageType image_type = ImageTypeForNetworkType(network->type());
407 if (image_type == ARCS)
408 return StrengthIndex(network->signal_strength(), kNumArcsImages);
409 else if (image_type == BARS)
410 return StrengthIndex(network->signal_strength(), kNumBarsImages);
414 const gfx::ImageSkia* BadgeForNetworkTechnology(const NetworkState* network,
415 IconType icon_type) {
416 const int kUnknownBadgeType = -1;
417 int id = kUnknownBadgeType;
418 const std::string& technology = network->network_technology();
419 if (technology == shill::kNetworkTechnologyEvdo) {
420 id = IconTypeIsDark(icon_type) ?
421 IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK :
422 IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT;
423 } else if (technology == shill::kNetworkTechnology1Xrtt) {
424 id = IDR_AURA_UBER_TRAY_NETWORK_1X;
425 } else if (technology == shill::kNetworkTechnologyGprs) {
426 id = IconTypeIsDark(icon_type) ?
427 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK :
428 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT;
429 } else if (technology == shill::kNetworkTechnologyEdge) {
430 id = IconTypeIsDark(icon_type) ?
431 IDR_AURA_UBER_TRAY_NETWORK_EDGE_DARK :
432 IDR_AURA_UBER_TRAY_NETWORK_EDGE_LIGHT;
433 } else if (technology == shill::kNetworkTechnologyUmts) {
434 id = IconTypeIsDark(icon_type) ?
435 IDR_AURA_UBER_TRAY_NETWORK_3G_DARK :
436 IDR_AURA_UBER_TRAY_NETWORK_3G_LIGHT;
437 } else if (technology == shill::kNetworkTechnologyHspa) {
438 id = IconTypeIsDark(icon_type) ?
439 IDR_AURA_UBER_TRAY_NETWORK_HSPA_DARK :
440 IDR_AURA_UBER_TRAY_NETWORK_HSPA_LIGHT;
441 } else if (technology == shill::kNetworkTechnologyHspaPlus) {
442 id = IconTypeIsDark(icon_type) ?
443 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_DARK :
444 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_LIGHT;
445 } else if (technology == shill::kNetworkTechnologyLte) {
446 id = IconTypeIsDark(icon_type) ?
447 IDR_AURA_UBER_TRAY_NETWORK_LTE_DARK :
448 IDR_AURA_UBER_TRAY_NETWORK_LTE_LIGHT;
449 } else if (technology == shill::kNetworkTechnologyLteAdvanced) {
450 id = IconTypeIsDark(icon_type) ?
451 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_DARK :
452 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_LIGHT;
453 } else if (technology == shill::kNetworkTechnologyGsm) {
454 id = IconTypeIsDark(icon_type) ?
455 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK :
456 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT;
458 if (id == kUnknownBadgeType)
461 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id);
464 const gfx::ImageSkia* BadgeForVPN(IconType icon_type) {
465 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
466 IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE);
469 gfx::ImageSkia GetIcon(const NetworkState* network,
471 int strength_index) {
472 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
473 if (network->Matches(NetworkTypePattern::Ethernet())) {
474 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED);
475 } else if (network->Matches(NetworkTypePattern::Wireless())) {
476 DCHECK(strength_index > 0);
477 return GetImageForIndex(
478 ImageTypeForNetworkType(network->type()), icon_type, strength_index);
479 } else if (network->Matches(NetworkTypePattern::VPN())) {
480 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN);
482 LOG(WARNING) << "Request for icon for unsupported type: "
484 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED);
488 //------------------------------------------------------------------------------
489 // Get connecting images
491 gfx::ImageSkia GetConnectingVpnImage(IconType icon_type) {
492 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
493 const NetworkState* connected_network = NULL;
494 if (icon_type == ICON_TYPE_TRAY) {
496 handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
498 double animation = NetworkIconAnimation::GetInstance()->GetAnimation();
500 if (connected_network) {
501 gfx::ImageSkia icon = GetImageForNetwork(connected_network, icon_type);
503 badges.bottom_left = ConnectingVpnBadge(animation);
504 return gfx::ImageSkia(
505 new NetworkIconImageSource(icon, badges), icon.size());
507 gfx::ImageSkia* icon = ConnectingVpnImage(animation);
508 return gfx::ImageSkia(
509 new NetworkIconImageSource(*icon, Badges()), icon->size());
513 gfx::ImageSkia GetConnectingImage(const std::string& network_type,
514 IconType icon_type) {
515 if (network_type == shill::kTypeVPN)
516 return GetConnectingVpnImage(icon_type);
518 ImageType image_type = ImageTypeForNetworkType(network_type);
519 double animation = NetworkIconAnimation::GetInstance()->GetAnimation();
521 gfx::ImageSkia* icon = ConnectingWirelessImage(
522 image_type, icon_type, animation);
523 return gfx::ImageSkia(
524 new NetworkIconImageSource(*icon, Badges()), icon->size());
529 //------------------------------------------------------------------------------
532 NetworkIconImpl::NetworkIconImpl(IconType icon_type)
533 : icon_type_(icon_type),
535 technology_badge_(NULL),
537 behind_captive_portal_(false) {
539 image_ = GetDisconnectedImage(shill::kTypeWifi, icon_type);
542 void NetworkIconImpl::Update(const NetworkState* network) {
544 // Determine whether or not we need to update the icon.
545 bool dirty = image_.isNull();
547 // If the network state has changed, the icon needs updating.
548 if (state_ != network->connection_state()) {
549 state_ = network->connection_state();
553 dirty |= UpdatePortalState(network);
555 if (network->Matches(NetworkTypePattern::Wireless())) {
556 dirty |= UpdateWirelessStrengthIndex(network);
559 if (network->Matches(NetworkTypePattern::Cellular()))
560 dirty |= UpdateCellularState(network);
562 if (IconTypeHasVPNBadge(icon_type_) &&
563 network->Matches(NetworkTypePattern::NonVirtual())) {
564 dirty |= UpdateVPNBadge();
568 // Set the icon and badges based on the network and generate the image.
569 GenerateImage(network);
573 bool NetworkIconImpl::UpdateWirelessStrengthIndex(const NetworkState* network) {
574 int index = GetStrengthIndex(network);
575 if (index != strength_index_) {
576 strength_index_ = index;
582 bool NetworkIconImpl::UpdateCellularState(const NetworkState* network) {
584 const gfx::ImageSkia* technology_badge =
585 BadgeForNetworkTechnology(network, icon_type_);
586 if (technology_badge != technology_badge_) {
587 technology_badge_ = technology_badge;
590 std::string roaming_state = network->roaming();
591 if (roaming_state != roaming_state_) {
592 roaming_state_ = roaming_state;
598 bool NetworkIconImpl::UpdatePortalState(const NetworkState* network) {
599 bool behind_captive_portal = false;
601 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
602 behind_captive_portal =
603 delegate->IsNetworkBehindCaptivePortal(network->path());
606 if (behind_captive_portal == behind_captive_portal_)
608 behind_captive_portal_ = behind_captive_portal;
612 bool NetworkIconImpl::UpdateVPNBadge() {
613 const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
614 ConnectedNetworkByType(NetworkTypePattern::VPN());
615 if (vpn && vpn_badge_ == NULL) {
616 vpn_badge_ = BadgeForVPN(icon_type_);
618 } else if (!vpn && vpn_badge_ != NULL) {
625 void NetworkIconImpl::GetBadges(const NetworkState* network, Badges* badges) {
627 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
628 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
630 const std::string& type = network->type();
631 if (type == shill::kTypeWifi) {
632 if (network->security() != shill::kSecurityNone &&
633 IconTypeIsDark(icon_type_)) {
634 badges->bottom_right = rb.GetImageSkiaNamed(
635 IDR_AURA_UBER_TRAY_NETWORK_SECURE_DARK);
637 } else if (type == shill::kTypeWimax) {
638 technology_badge_ = rb.GetImageSkiaNamed(
639 IconTypeIsDark(icon_type_) ?
640 IDR_AURA_UBER_TRAY_NETWORK_4G_DARK :
641 IDR_AURA_UBER_TRAY_NETWORK_4G_LIGHT);
642 } else if (type == shill::kTypeCellular) {
643 if (network->roaming() == shill::kRoamingStateRoaming) {
644 // For networks that are always in roaming don't show roaming badge.
645 const DeviceState* device =
646 handler->GetDeviceState(network->device_path());
647 LOG_IF(WARNING, !device) << "Could not find device state for "
648 << network->device_path();
649 if (!device || !device->provider_requires_roaming()) {
650 badges->bottom_right = rb.GetImageSkiaNamed(
651 IconTypeIsDark(icon_type_) ?
652 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_DARK :
653 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_LIGHT);
657 if (!network->IsConnectingState()) {
658 badges->top_left = technology_badge_;
659 badges->bottom_left = vpn_badge_;
662 if (behind_captive_portal_) {
663 gfx::ImageSkia* badge = rb.GetImageSkiaNamed(
664 IconTypeIsDark(icon_type_) ?
665 IDR_AURA_UBER_TRAY_NETWORK_PORTAL_DARK :
666 IDR_AURA_UBER_TRAY_NETWORK_PORTAL_LIGHT);
667 badges->bottom_right = badge;
671 void NetworkIconImpl::GenerateImage(const NetworkState* network) {
673 gfx::ImageSkia icon = GetIcon(network, icon_type_, strength_index_);
675 GetBadges(network, &badges);
676 image_ = gfx::ImageSkia(
677 new NetworkIconImageSource(icon, badges), icon.size());
680 //------------------------------------------------------------------------------
683 gfx::ImageSkia GetImageForNetwork(const NetworkState* network,
684 IconType icon_type) {
686 // Handle connecting icons.
687 if (network->IsConnectingState())
688 return GetConnectingImage(network->type(), icon_type);
690 // Find or add the icon.
691 NetworkIconMap* icon_map = GetIconMap(icon_type);
692 NetworkIconImpl* icon;
693 NetworkIconMap::iterator iter = icon_map->find(network->path());
694 if (iter == icon_map->end()) {
695 icon = new NetworkIconImpl(icon_type);
696 icon_map->insert(std::make_pair(network->path(), icon));
701 // Update and return the icon's image.
702 icon->Update(network);
703 return icon->image();
706 gfx::ImageSkia GetImageForConnectedNetwork(IconType icon_type,
707 const std::string& network_type) {
708 return GetConnectedImage(network_type, icon_type);
711 gfx::ImageSkia GetImageForConnectingNetwork(IconType icon_type,
712 const std::string& network_type) {
713 return GetConnectingImage(network_type, icon_type);
716 gfx::ImageSkia GetImageForDisconnectedNetwork(IconType icon_type,
717 const std::string& network_type) {
718 return GetDisconnectedImage(network_type, icon_type);
721 base::string16 GetLabelForNetwork(const chromeos::NetworkState* network,
722 IconType icon_type) {
724 std::string activation_state = network->activation_state();
725 if (icon_type == ICON_TYPE_LIST) {
726 // Show "<network>: [Connecting|Activating]..."
727 if (network->IsConnectingState()) {
728 return l10n_util::GetStringFUTF16(
729 IDS_ASH_STATUS_TRAY_NETWORK_LIST_CONNECTING,
730 base::UTF8ToUTF16(network->name()));
732 if (activation_state == shill::kActivationStateActivating) {
733 return l10n_util::GetStringFUTF16(
734 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING,
735 base::UTF8ToUTF16(network->name()));
737 // Show "Activate <network>" in list view only.
738 if (activation_state == shill::kActivationStateNotActivated ||
739 activation_state == shill::kActivationStatePartiallyActivated) {
740 return l10n_util::GetStringFUTF16(
741 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE,
742 base::UTF8ToUTF16(network->name()));
745 // Show "[Connected to|Connecting to|Activating] <network>" (non-list view).
746 if (network->IsConnectedState()) {
747 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED,
748 base::UTF8ToUTF16(network->name()));
750 if (network->IsConnectingState()) {
751 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING,
752 base::UTF8ToUTF16(network->name()));
754 if (activation_state == shill::kActivationStateActivating) {
755 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING,
756 base::UTF8ToUTF16(network->name()));
760 // Otherwise just show the network name or 'Ethernet'.
761 if (network->Matches(NetworkTypePattern::Ethernet())) {
762 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET);
764 return base::UTF8ToUTF16(network->name());
768 int GetCellularUninitializedMsg() {
769 static base::Time s_uninitialized_state_time;
770 static int s_uninitialized_msg(0);
772 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
773 if (handler->GetTechnologyState(NetworkTypePattern::Mobile())
774 == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) {
775 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR;
776 s_uninitialized_state_time = base::Time::Now();
777 return s_uninitialized_msg;
778 } else if (handler->GetScanningByType(NetworkTypePattern::Mobile())) {
779 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_CELLULAR_SCANNING;
780 s_uninitialized_state_time = base::Time::Now();
781 return s_uninitialized_msg;
783 // There can be a delay between leaving the Initializing state and when
784 // a Cellular device shows up, so keep showing the initializing
785 // animation for a bit to avoid flashing the disconnect icon.
786 const int kInitializingDelaySeconds = 1;
787 base::TimeDelta dtime = base::Time::Now() - s_uninitialized_state_time;
788 if (dtime.InSeconds() < kInitializingDelaySeconds)
789 return s_uninitialized_msg;
793 void GetDefaultNetworkImageAndLabel(IconType icon_type,
794 gfx::ImageSkia* image,
795 base::string16* label,
797 NetworkStateHandler* state_handler =
798 NetworkHandler::Get()->network_state_handler();
799 NetworkConnectionHandler* connect_handler =
800 NetworkHandler::Get()->network_connection_handler();
801 const NetworkState* connected_network =
802 state_handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
803 const NetworkState* connecting_network =
804 state_handler->ConnectingNetworkByType(NetworkTypePattern::Wireless());
805 if (!connecting_network && icon_type == ICON_TYPE_TRAY) {
807 state_handler->ConnectingNetworkByType(NetworkTypePattern::VPN());
810 const NetworkState* network;
811 // If we are connecting to a network, and there is either no connected
812 // network, or the connection was user requested, use the connecting
814 if (connecting_network &&
815 (!connected_network ||
816 connect_handler->HasConnectingNetwork(connecting_network->path()))) {
817 network = connecting_network;
819 network = connected_network;
822 // Don't show ethernet in the tray
823 if (icon_type == ICON_TYPE_TRAY && network &&
824 network->Matches(NetworkTypePattern::Ethernet())) {
825 *image = gfx::ImageSkia();
831 // If no connecting network, check if we are activating a network.
832 const NetworkState* mobile_network =
833 state_handler->FirstNetworkByType(NetworkTypePattern::Mobile());
834 if (mobile_network && (mobile_network->activation_state() ==
835 shill::kActivationStateActivating)) {
836 network = mobile_network;
840 // If no connecting network, check for cellular initializing.
841 int uninitialized_msg = GetCellularUninitializedMsg();
842 if (uninitialized_msg != 0) {
843 *image = GetImageForConnectingNetwork(icon_type, shill::kTypeCellular);
845 *label = l10n_util::GetStringUTF16(uninitialized_msg);
848 // Otherwise show the disconnected wifi icon.
849 *image = GetImageForDisconnectedNetwork(icon_type, shill::kTypeWifi);
851 *label = l10n_util::GetStringUTF16(
852 IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED);
858 *animating = network->IsConnectingState();
859 // Get icon and label for connected or connecting network.
860 *image = GetImageForNetwork(network, icon_type);
862 *label = GetLabelForNetwork(network, icon_type);
865 void PurgeNetworkIconCache() {
866 NetworkStateHandler::NetworkStateList networks;
867 NetworkHandler::Get()->network_state_handler()->GetNetworkList(&networks);
868 std::set<std::string> network_paths;
869 for (NetworkStateHandler::NetworkStateList::iterator iter = networks.begin();
870 iter != networks.end(); ++iter) {
871 network_paths.insert((*iter)->path());
873 PurgeIconMap(ICON_TYPE_TRAY, network_paths);
874 PurgeIconMap(ICON_TYPE_DEFAULT_VIEW, network_paths);
875 PurgeIconMap(ICON_TYPE_LIST, network_paths);
878 } // namespace network_icon