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 "ui/chromeos/network/network_icon.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chromeos/network/device_state.h"
9 #include "chromeos/network/network_connection_handler.h"
10 #include "chromeos/network/network_state.h"
11 #include "chromeos/network/network_state_handler.h"
12 #include "chromeos/network/portal_detector/network_portal_detector.h"
13 #include "grit/ui_chromeos_resources.h"
14 #include "grit/ui_chromeos_strings.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/base/resource/resource_bundle.h"
18 #include "ui/base/webui/web_ui_util.h"
19 #include "ui/chromeos/network/network_icon_animation.h"
20 #include "ui/chromeos/network/network_icon_animation_observer.h"
21 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/geometry/rect.h"
23 #include "ui/gfx/geometry/size_conversions.h"
24 #include "ui/gfx/image/image_skia_operations.h"
25 #include "ui/gfx/image/image_skia_source.h"
27 using chromeos::DeviceState
;
28 using chromeos::NetworkConnectionHandler
;
29 using chromeos::NetworkHandler
;
30 using chromeos::NetworkPortalDetector
;
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 NetworkIconImpl(const std::string
& path
, 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 // Network path, used for debugging.
87 std::string network_path_
;
89 // Defines color theme and VPN badging
90 const IconType icon_type_
;
92 // Cached state of the network when the icon was last generated.
95 // Cached strength index of the network when the icon was last generated.
98 // Cached technology badge for the network when the icon was last generated.
99 const gfx::ImageSkia
* technology_badge_
;
101 // Cached vpn badge for the network when the icon was last generated.
102 const gfx::ImageSkia
* vpn_badge_
;
104 // Cached roaming state of the network when the icon was last generated.
105 std::string roaming_state_
;
107 // Cached portal state of the network when the icon was last generated.
108 bool behind_captive_portal_
;
110 // Generated icon image.
111 gfx::ImageSkia image_
;
113 DISALLOW_COPY_AND_ASSIGN(NetworkIconImpl
);
116 //------------------------------------------------------------------------------
117 // Maintain a static (global) icon map. Note: Icons are never destroyed;
118 // it is assumed that a finite and reasonable number of network icons will be
119 // created during a session.
121 typedef std::map
<std::string
, NetworkIconImpl
*> NetworkIconMap
;
123 NetworkIconMap
* GetIconMapInstance(IconType icon_type
, bool create
) {
124 typedef std::map
<IconType
, NetworkIconMap
*> IconTypeMap
;
125 static IconTypeMap
* s_icon_map
= NULL
;
126 if (s_icon_map
== NULL
) {
129 s_icon_map
= new IconTypeMap
;
131 if (s_icon_map
->count(icon_type
) == 0) {
134 (*s_icon_map
)[icon_type
] = new NetworkIconMap
;
136 return (*s_icon_map
)[icon_type
];
139 NetworkIconMap
* GetIconMap(IconType icon_type
) {
140 return GetIconMapInstance(icon_type
, true);
143 void PurgeIconMap(IconType icon_type
,
144 const std::set
<std::string
>& network_paths
) {
145 NetworkIconMap
* icon_map
= GetIconMapInstance(icon_type
, false);
148 for (NetworkIconMap::iterator loop_iter
= icon_map
->begin();
149 loop_iter
!= icon_map
->end(); ) {
150 NetworkIconMap::iterator cur_iter
= loop_iter
++;
151 if (network_paths
.count(cur_iter
->first
) == 0) {
152 delete cur_iter
->second
;
153 icon_map
->erase(cur_iter
);
158 //------------------------------------------------------------------------------
159 // Utilities for generating icon images.
161 // 'NONE' will default to ARCS behavior where appropriate (e.g. no network or
162 // if a new type gets added).
169 // Amount to fade icons while connecting.
170 const double kConnectingImageAlpha
= 0.5;
172 // Images for strength bars for wired networks.
173 const int kNumBarsImages
= 5;
175 // Imagaes for strength arcs for wireless networks.
176 const int kNumArcsImages
= 5;
178 // Number of discrete images to use for alpha fade animation
179 const int kNumFadeImages
= 10;
181 //------------------------------------------------------------------------------
182 // Classes for generating scaled images.
184 const SkBitmap
GetEmptyBitmap(const gfx::Size pixel_size
) {
185 typedef std::pair
<int, int> SizeKey
;
186 typedef std::map
<SizeKey
, SkBitmap
> SizeBitmapMap
;
187 static SizeBitmapMap
* s_empty_bitmaps
= new SizeBitmapMap
;
189 SizeKey
key(pixel_size
.width(), pixel_size
.height());
191 SizeBitmapMap::iterator iter
= s_empty_bitmaps
->find(key
);
192 if (iter
!= s_empty_bitmaps
->end())
196 empty
.allocN32Pixels(key
.first
, key
.second
);
197 empty
.eraseARGB(0, 0, 0, 0);
198 (*s_empty_bitmaps
)[key
] = empty
;
202 class EmptyImageSource
: public gfx::ImageSkiaSource
{
204 explicit EmptyImageSource(const gfx::Size
& size
)
208 gfx::ImageSkiaRep
GetImageForScale(float scale
) override
{
209 gfx::Size pixel_size
= gfx::ToFlooredSize(gfx::ScaleSize(size_
, scale
));
210 SkBitmap empty_bitmap
= GetEmptyBitmap(pixel_size
);
211 return gfx::ImageSkiaRep(empty_bitmap
, scale
);
215 const gfx::Size size_
;
217 DISALLOW_COPY_AND_ASSIGN(EmptyImageSource
);
220 // This defines how we assemble a network icon.
221 class NetworkIconImageSource
: public gfx::ImageSkiaSource
{
223 NetworkIconImageSource(const gfx::ImageSkia
& icon
, const Badges
& badges
)
227 ~NetworkIconImageSource() override
{}
229 // TODO(pkotwicz): Figure out what to do when a new image resolution becomes
231 gfx::ImageSkiaRep
GetImageForScale(float scale
) override
{
232 gfx::ImageSkiaRep icon_rep
= icon_
.GetRepresentation(scale
);
233 if (icon_rep
.is_null())
234 return gfx::ImageSkiaRep();
235 gfx::Canvas
canvas(icon_rep
, false);
236 if (badges_
.top_left
)
237 canvas
.DrawImageInt(*badges_
.top_left
, 0, 0);
238 if (badges_
.top_right
)
239 canvas
.DrawImageInt(*badges_
.top_right
,
240 icon_
.width() - badges_
.top_right
->width(), 0);
241 if (badges_
.bottom_left
) {
242 canvas
.DrawImageInt(*badges_
.bottom_left
,
243 0, icon_
.height() - badges_
.bottom_left
->height());
245 if (badges_
.bottom_right
) {
246 canvas
.DrawImageInt(*badges_
.bottom_right
,
247 icon_
.width() - badges_
.bottom_right
->width(),
248 icon_
.height() - badges_
.bottom_right
->height());
250 return canvas
.ExtractImageRep();
254 const gfx::ImageSkia icon_
;
255 const Badges badges_
;
257 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource
);
260 //------------------------------------------------------------------------------
261 // Utilities for extracting icon images.
263 bool IconTypeIsDark(IconType icon_type
) {
264 return (icon_type
!= ICON_TYPE_TRAY
);
267 bool IconTypeHasVPNBadge(IconType icon_type
) {
268 return (icon_type
!= ICON_TYPE_LIST
);
271 int NumImagesForType(ImageType type
) {
272 return (type
== BARS
) ? kNumBarsImages
: kNumArcsImages
;
275 gfx::ImageSkia
* BaseImageForType(ImageType image_type
, IconType icon_type
) {
276 gfx::ImageSkia
* image
;
277 if (image_type
== BARS
) {
278 image
= ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
279 IconTypeIsDark(icon_type
) ?
280 IDR_AURA_UBER_TRAY_NETWORK_BARS_DARK
:
281 IDR_AURA_UBER_TRAY_NETWORK_BARS_LIGHT
);
283 image
= ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
284 IconTypeIsDark(icon_type
) ?
285 IDR_AURA_UBER_TRAY_NETWORK_ARCS_DARK
:
286 IDR_AURA_UBER_TRAY_NETWORK_ARCS_LIGHT
);
291 ImageType
ImageTypeForNetworkType(const std::string
& type
) {
292 if (type
== shill::kTypeWifi
)
294 else if (type
== shill::kTypeCellular
|| type
== shill::kTypeWimax
)
299 gfx::ImageSkia
GetImageForIndex(ImageType image_type
,
302 int num_images
= NumImagesForType(image_type
);
303 if (index
< 0 || index
>= num_images
)
304 return gfx::ImageSkia();
305 gfx::ImageSkia
* images
= BaseImageForType(image_type
, icon_type
);
306 int width
= images
->width();
307 int height
= images
->height() / num_images
;
308 return gfx::ImageSkiaOperations::ExtractSubset(*images
,
309 gfx::Rect(0, index
* height
, width
, height
));
312 const gfx::ImageSkia
GetConnectedImage(IconType icon_type
,
313 const std::string
& network_type
) {
314 if (network_type
== shill::kTypeVPN
) {
315 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
316 IDR_AURA_UBER_TRAY_NETWORK_VPN
);
318 ImageType image_type
= ImageTypeForNetworkType(network_type
);
319 const int connected_index
= NumImagesForType(image_type
) - 1;
320 return GetImageForIndex(image_type
, icon_type
, connected_index
);
323 const gfx::ImageSkia
GetDisconnectedImage(IconType icon_type
,
324 const std::string
& network_type
) {
325 if (network_type
== shill::kTypeVPN
) {
326 // Note: same as connected image, shouldn't normally be seen.
327 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
328 IDR_AURA_UBER_TRAY_NETWORK_VPN
);
330 ImageType image_type
= ImageTypeForNetworkType(network_type
);
331 const int disconnected_index
= 0;
332 return GetImageForIndex(image_type
, icon_type
, disconnected_index
);
335 gfx::ImageSkia
* ConnectingWirelessImage(ImageType image_type
,
338 static gfx::ImageSkia
* s_bars_images_dark
[kNumBarsImages
- 1];
339 static gfx::ImageSkia
* s_bars_images_light
[kNumBarsImages
- 1];
340 static gfx::ImageSkia
* s_arcs_images_dark
[kNumArcsImages
- 1];
341 static gfx::ImageSkia
* s_arcs_images_light
[kNumArcsImages
- 1];
342 int image_count
= NumImagesForType(image_type
) - 1;
343 int index
= animation
* nextafter(static_cast<float>(image_count
), 0);
344 index
= std::max(std::min(index
, image_count
- 1), 0);
345 gfx::ImageSkia
** images
;
346 bool dark
= IconTypeIsDark(icon_type
);
347 if (image_type
== BARS
)
348 images
= dark
? s_bars_images_dark
: s_bars_images_light
;
350 images
= dark
? s_arcs_images_dark
: s_arcs_images_light
;
351 if (!images
[index
]) {
352 // Lazily cache images.
353 gfx::ImageSkia source
= GetImageForIndex(image_type
, icon_type
, index
+ 1);
354 images
[index
] = new gfx::ImageSkia(
355 gfx::ImageSkiaOperations::CreateBlendedImage(
356 gfx::ImageSkia(new EmptyImageSource(source
.size()), source
.size()),
358 kConnectingImageAlpha
));
360 return images
[index
];
363 gfx::ImageSkia
* ConnectingVpnImage(double animation
) {
364 int index
= animation
* nextafter(static_cast<float>(kNumFadeImages
), 0);
365 static gfx::ImageSkia
* s_vpn_images
[kNumFadeImages
];
366 if (!s_vpn_images
[index
]) {
367 // Lazily cache images.
368 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
369 gfx::ImageSkia
* icon
= rb
.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN
);
370 s_vpn_images
[index
] = new gfx::ImageSkia(
371 gfx::ImageSkiaOperations::CreateBlendedImage(
372 gfx::ImageSkia(new EmptyImageSource(icon
->size()), icon
->size()),
376 return s_vpn_images
[index
];
379 gfx::ImageSkia
* ConnectingVpnBadge(double animation
) {
380 int index
= animation
* nextafter(static_cast<float>(kNumFadeImages
), 0);
381 static gfx::ImageSkia
* s_vpn_badges
[kNumFadeImages
];
382 if (!s_vpn_badges
[index
]) {
383 // Lazily cache images.
384 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
385 gfx::ImageSkia
* icon
=
386 rb
.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED
); // For size
387 gfx::ImageSkia
* badge
=
388 rb
.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE
);
389 s_vpn_badges
[index
] = new gfx::ImageSkia(
390 gfx::ImageSkiaOperations::CreateBlendedImage(
391 gfx::ImageSkia(new EmptyImageSource(icon
->size()), icon
->size()),
395 return s_vpn_badges
[index
];
398 int StrengthIndex(int strength
, int count
) {
399 // Return an index in the range [1, count-1].
400 const float findex
= (static_cast<float>(strength
) / 100.0f
) *
401 nextafter(static_cast<float>(count
- 1), 0);
402 int index
= 1 + static_cast<int>(findex
);
403 index
= std::max(std::min(index
, count
- 1), 1);
407 int GetStrengthIndex(const NetworkState
* network
) {
408 ImageType image_type
= ImageTypeForNetworkType(network
->type());
409 if (image_type
== ARCS
)
410 return StrengthIndex(network
->signal_strength(), kNumArcsImages
);
411 else if (image_type
== BARS
)
412 return StrengthIndex(network
->signal_strength(), kNumBarsImages
);
416 const gfx::ImageSkia
* BadgeForNetworkTechnology(const NetworkState
* network
,
417 IconType icon_type
) {
418 const int kUnknownBadgeType
= -1;
419 int id
= kUnknownBadgeType
;
420 const std::string
& technology
= network
->network_technology();
421 if (technology
== shill::kNetworkTechnologyEvdo
) {
422 id
= IconTypeIsDark(icon_type
) ?
423 IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK
:
424 IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT
;
425 } else if (technology
== shill::kNetworkTechnology1Xrtt
) {
426 id
= IDR_AURA_UBER_TRAY_NETWORK_1X
;
427 } else if (technology
== shill::kNetworkTechnologyGprs
) {
428 id
= IconTypeIsDark(icon_type
) ?
429 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK
:
430 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT
;
431 } else if (technology
== shill::kNetworkTechnologyEdge
) {
432 id
= IconTypeIsDark(icon_type
) ?
433 IDR_AURA_UBER_TRAY_NETWORK_EDGE_DARK
:
434 IDR_AURA_UBER_TRAY_NETWORK_EDGE_LIGHT
;
435 } else if (technology
== shill::kNetworkTechnologyUmts
) {
436 id
= IconTypeIsDark(icon_type
) ?
437 IDR_AURA_UBER_TRAY_NETWORK_3G_DARK
:
438 IDR_AURA_UBER_TRAY_NETWORK_3G_LIGHT
;
439 } else if (technology
== shill::kNetworkTechnologyHspa
) {
440 id
= IconTypeIsDark(icon_type
) ?
441 IDR_AURA_UBER_TRAY_NETWORK_HSPA_DARK
:
442 IDR_AURA_UBER_TRAY_NETWORK_HSPA_LIGHT
;
443 } else if (technology
== shill::kNetworkTechnologyHspaPlus
) {
444 id
= IconTypeIsDark(icon_type
) ?
445 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_DARK
:
446 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_LIGHT
;
447 } else if (technology
== shill::kNetworkTechnologyLte
) {
448 id
= IconTypeIsDark(icon_type
) ?
449 IDR_AURA_UBER_TRAY_NETWORK_LTE_DARK
:
450 IDR_AURA_UBER_TRAY_NETWORK_LTE_LIGHT
;
451 } else if (technology
== shill::kNetworkTechnologyLteAdvanced
) {
452 id
= IconTypeIsDark(icon_type
) ?
453 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_DARK
:
454 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_LIGHT
;
455 } else if (technology
== shill::kNetworkTechnologyGsm
) {
456 id
= IconTypeIsDark(icon_type
) ?
457 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK
:
458 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT
;
460 if (id
== kUnknownBadgeType
)
463 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id
);
466 const gfx::ImageSkia
* BadgeForVPN(IconType icon_type
) {
467 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
468 IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE
);
471 gfx::ImageSkia
GetIcon(const NetworkState
* network
,
473 int strength_index
) {
474 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
475 if (network
->Matches(NetworkTypePattern::Ethernet())) {
476 return *rb
.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED
);
477 } else if (network
->Matches(NetworkTypePattern::Wireless())) {
478 DCHECK(strength_index
> 0);
479 return GetImageForIndex(
480 ImageTypeForNetworkType(network
->type()), icon_type
, strength_index
);
481 } else if (network
->Matches(NetworkTypePattern::VPN())) {
482 return *rb
.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN
);
484 LOG(WARNING
) << "Request for icon for unsupported type: "
486 return *rb
.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED
);
490 //------------------------------------------------------------------------------
491 // Get connecting images
493 gfx::ImageSkia
GetConnectingVpnImage(IconType icon_type
) {
494 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
495 const NetworkState
* connected_network
= NULL
;
496 if (icon_type
== ICON_TYPE_TRAY
) {
498 handler
->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
500 double animation
= NetworkIconAnimation::GetInstance()->GetAnimation();
502 if (connected_network
) {
503 gfx::ImageSkia icon
= GetImageForNetwork(connected_network
, icon_type
);
505 badges
.bottom_left
= ConnectingVpnBadge(animation
);
506 return gfx::ImageSkia(
507 new NetworkIconImageSource(icon
, badges
), icon
.size());
509 gfx::ImageSkia
* icon
= ConnectingVpnImage(animation
);
510 return gfx::ImageSkia(
511 new NetworkIconImageSource(*icon
, Badges()), icon
->size());
515 gfx::ImageSkia
GetConnectingImage(IconType icon_type
,
516 const std::string
& network_type
) {
517 if (network_type
== shill::kTypeVPN
)
518 return GetConnectingVpnImage(icon_type
);
520 ImageType image_type
= ImageTypeForNetworkType(network_type
);
521 double animation
= NetworkIconAnimation::GetInstance()->GetAnimation();
523 gfx::ImageSkia
* icon
= ConnectingWirelessImage(
524 image_type
, icon_type
, animation
);
525 return gfx::ImageSkia(
526 new NetworkIconImageSource(*icon
, Badges()), icon
->size());
531 //------------------------------------------------------------------------------
534 NetworkIconImpl::NetworkIconImpl(const std::string
& path
, IconType icon_type
)
535 : network_path_(path
),
536 icon_type_(icon_type
),
538 technology_badge_(NULL
),
540 behind_captive_portal_(false) {
542 image_
= GetDisconnectedImage(icon_type
, shill::kTypeWifi
);
545 void NetworkIconImpl::Update(const NetworkState
* network
) {
547 // Determine whether or not we need to update the icon.
548 bool dirty
= image_
.isNull();
550 // If the network state has changed, the icon needs updating.
551 if (state_
!= network
->connection_state()) {
552 state_
= network
->connection_state();
556 dirty
|= UpdatePortalState(network
);
558 if (network
->Matches(NetworkTypePattern::Wireless())) {
559 dirty
|= UpdateWirelessStrengthIndex(network
);
562 if (network
->Matches(NetworkTypePattern::Cellular()))
563 dirty
|= UpdateCellularState(network
);
565 if (IconTypeHasVPNBadge(icon_type_
) &&
566 network
->Matches(NetworkTypePattern::NonVirtual())) {
567 dirty
|= UpdateVPNBadge();
571 // Set the icon and badges based on the network and generate the image.
572 GenerateImage(network
);
576 bool NetworkIconImpl::UpdateWirelessStrengthIndex(const NetworkState
* network
) {
577 int index
= GetStrengthIndex(network
);
578 if (index
!= strength_index_
) {
579 strength_index_
= index
;
585 bool NetworkIconImpl::UpdateCellularState(const NetworkState
* network
) {
587 const gfx::ImageSkia
* technology_badge
=
588 BadgeForNetworkTechnology(network
, icon_type_
);
589 if (technology_badge
!= technology_badge_
) {
590 technology_badge_
= technology_badge
;
593 std::string roaming_state
= network
->roaming();
594 if (roaming_state
!= roaming_state_
) {
595 roaming_state_
= roaming_state
;
601 bool NetworkIconImpl::UpdatePortalState(const NetworkState
* network
) {
602 bool behind_captive_portal
= false;
603 if (network
&& NetworkPortalDetector::IsInitialized()) {
604 NetworkPortalDetector::CaptivePortalState state
=
605 NetworkPortalDetector::Get()->GetCaptivePortalState(network
->guid());
606 behind_captive_portal
=
607 state
.status
== NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL
;
610 if (behind_captive_portal
== behind_captive_portal_
)
612 behind_captive_portal_
= behind_captive_portal
;
616 bool NetworkIconImpl::UpdateVPNBadge() {
617 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
618 ConnectedNetworkByType(NetworkTypePattern::VPN());
619 if (vpn
&& vpn_badge_
== NULL
) {
620 vpn_badge_
= BadgeForVPN(icon_type_
);
622 } else if (!vpn
&& vpn_badge_
!= NULL
) {
629 void NetworkIconImpl::GetBadges(const NetworkState
* network
, Badges
* badges
) {
631 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
632 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
634 const std::string
& type
= network
->type();
635 if (type
== shill::kTypeWifi
) {
636 if (network
->security_class() != shill::kSecurityNone
&&
637 IconTypeIsDark(icon_type_
)) {
638 badges
->bottom_right
= rb
.GetImageSkiaNamed(
639 IDR_AURA_UBER_TRAY_NETWORK_SECURE_DARK
);
641 } else if (type
== shill::kTypeWimax
) {
642 technology_badge_
= rb
.GetImageSkiaNamed(
643 IconTypeIsDark(icon_type_
) ?
644 IDR_AURA_UBER_TRAY_NETWORK_4G_DARK
:
645 IDR_AURA_UBER_TRAY_NETWORK_4G_LIGHT
);
646 } else if (type
== shill::kTypeCellular
) {
647 if (network
->roaming() == shill::kRoamingStateRoaming
) {
648 // For networks that are always in roaming don't show roaming badge.
649 const DeviceState
* device
=
650 handler
->GetDeviceState(network
->device_path());
651 LOG_IF(WARNING
, !device
) << "Could not find device state for "
652 << network
->device_path();
653 if (!device
|| !device
->provider_requires_roaming()) {
654 badges
->bottom_right
= rb
.GetImageSkiaNamed(
655 IconTypeIsDark(icon_type_
) ?
656 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_DARK
:
657 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_LIGHT
);
661 if (!network
->IsConnectingState()) {
662 badges
->top_left
= technology_badge_
;
663 badges
->bottom_left
= vpn_badge_
;
666 if (behind_captive_portal_
) {
667 gfx::ImageSkia
* badge
= rb
.GetImageSkiaNamed(
668 IconTypeIsDark(icon_type_
) ?
669 IDR_AURA_UBER_TRAY_NETWORK_PORTAL_DARK
:
670 IDR_AURA_UBER_TRAY_NETWORK_PORTAL_LIGHT
);
671 badges
->bottom_right
= badge
;
675 void NetworkIconImpl::GenerateImage(const NetworkState
* network
) {
677 gfx::ImageSkia icon
= GetIcon(network
, icon_type_
, strength_index_
);
679 GetBadges(network
, &badges
);
680 image_
= gfx::ImageSkia(
681 new NetworkIconImageSource(icon
, badges
), icon
.size());
686 NetworkIconImpl
* FindAndUpdateImageImpl(const NetworkState
* network
,
687 IconType icon_type
) {
688 // Find or add the icon.
689 NetworkIconMap
* icon_map
= GetIconMap(icon_type
);
690 NetworkIconImpl
* icon
;
691 NetworkIconMap::iterator iter
= icon_map
->find(network
->path());
692 if (iter
== icon_map
->end()) {
693 icon
= new NetworkIconImpl(network
->path(), icon_type
);
694 icon_map
->insert(std::make_pair(network
->path(), icon
));
699 // Update and return the icon's image.
700 icon
->Update(network
);
706 //------------------------------------------------------------------------------
709 gfx::ImageSkia
GetImageForNetwork(const NetworkState
* network
,
710 IconType icon_type
) {
712 if (!network
->visible())
713 return GetDisconnectedImage(icon_type
, network
->type());
715 if (network
->IsConnectingState())
716 return GetConnectingImage(icon_type
, network
->type());
718 NetworkIconImpl
* icon
= FindAndUpdateImageImpl(network
, icon_type
);
719 return icon
->image();
722 gfx::ImageSkia
GetImageForConnectedNetwork(IconType icon_type
,
723 const std::string
& network_type
) {
724 return GetConnectedImage(icon_type
, network_type
);
727 gfx::ImageSkia
GetImageForConnectingNetwork(IconType icon_type
,
728 const std::string
& network_type
) {
729 return GetConnectingImage(icon_type
, network_type
);
732 gfx::ImageSkia
GetImageForDisconnectedNetwork(IconType icon_type
,
733 const std::string
& network_type
) {
734 return GetDisconnectedImage(icon_type
, network_type
);
737 base::string16
GetLabelForNetwork(const chromeos::NetworkState
* network
,
738 IconType icon_type
) {
740 std::string activation_state
= network
->activation_state();
741 if (icon_type
== ICON_TYPE_LIST
) {
742 // Show "<network>: [Connecting|Activating]..."
743 if (network
->IsConnectingState()) {
744 return l10n_util::GetStringFUTF16(
745 IDS_ASH_STATUS_TRAY_NETWORK_LIST_CONNECTING
,
746 base::UTF8ToUTF16(network
->name()));
748 if (activation_state
== shill::kActivationStateActivating
) {
749 return l10n_util::GetStringFUTF16(
750 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING
,
751 base::UTF8ToUTF16(network
->name()));
753 // Show "Activate <network>" in list view only.
754 if (activation_state
== shill::kActivationStateNotActivated
||
755 activation_state
== shill::kActivationStatePartiallyActivated
) {
756 return l10n_util::GetStringFUTF16(
757 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE
,
758 base::UTF8ToUTF16(network
->name()));
761 // Show "[Connected to|Connecting to|Activating] <network>" (non-list view).
762 if (network
->IsConnectedState()) {
763 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED
,
764 base::UTF8ToUTF16(network
->name()));
766 if (network
->IsConnectingState()) {
767 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING
,
768 base::UTF8ToUTF16(network
->name()));
770 if (activation_state
== shill::kActivationStateActivating
) {
771 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING
,
772 base::UTF8ToUTF16(network
->name()));
776 // Otherwise just show the network name or 'Ethernet'.
777 if (network
->Matches(NetworkTypePattern::Ethernet())) {
778 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET
);
780 return base::UTF8ToUTF16(network
->name());
784 int GetCellularUninitializedMsg() {
785 static base::Time s_uninitialized_state_time
;
786 static int s_uninitialized_msg(0);
788 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
789 if (handler
->GetTechnologyState(NetworkTypePattern::Mobile())
790 == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED
) {
791 s_uninitialized_msg
= IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR
;
792 s_uninitialized_state_time
= base::Time::Now();
793 return s_uninitialized_msg
;
794 } else if (handler
->GetScanningByType(NetworkTypePattern::Mobile())) {
795 s_uninitialized_msg
= IDS_ASH_STATUS_TRAY_CELLULAR_SCANNING
;
796 s_uninitialized_state_time
= base::Time::Now();
797 return s_uninitialized_msg
;
799 // There can be a delay between leaving the Initializing state and when
800 // a Cellular device shows up, so keep showing the initializing
801 // animation for a bit to avoid flashing the disconnect icon.
802 const int kInitializingDelaySeconds
= 1;
803 base::TimeDelta dtime
= base::Time::Now() - s_uninitialized_state_time
;
804 if (dtime
.InSeconds() < kInitializingDelaySeconds
)
805 return s_uninitialized_msg
;
809 void GetDefaultNetworkImageAndLabel(IconType icon_type
,
810 gfx::ImageSkia
* image
,
811 base::string16
* label
,
813 NetworkStateHandler
* state_handler
=
814 NetworkHandler::Get()->network_state_handler();
815 NetworkConnectionHandler
* connect_handler
=
816 NetworkHandler::Get()->network_connection_handler();
817 const NetworkState
* connected_network
=
818 state_handler
->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
819 const NetworkState
* connecting_network
=
820 state_handler
->ConnectingNetworkByType(NetworkTypePattern::Wireless());
821 if (!connecting_network
&& icon_type
== ICON_TYPE_TRAY
) {
823 state_handler
->ConnectingNetworkByType(NetworkTypePattern::VPN());
826 const NetworkState
* network
;
827 // If we are connecting to a network, and there is either no connected
828 // network, or the connection was user requested, use the connecting
830 if (connecting_network
&&
831 (!connected_network
||
832 connect_handler
->HasConnectingNetwork(connecting_network
->path()))) {
833 network
= connecting_network
;
835 network
= connected_network
;
838 // Don't show ethernet in the tray
839 if (icon_type
== ICON_TYPE_TRAY
&& network
&&
840 network
->Matches(NetworkTypePattern::Ethernet())) {
841 *image
= gfx::ImageSkia();
847 // If no connecting network, check if we are activating a network.
848 const NetworkState
* mobile_network
=
849 state_handler
->FirstNetworkByType(NetworkTypePattern::Mobile());
850 if (mobile_network
&& (mobile_network
->activation_state() ==
851 shill::kActivationStateActivating
)) {
852 network
= mobile_network
;
856 // If no connecting network, check for cellular initializing.
857 int uninitialized_msg
= GetCellularUninitializedMsg();
858 if (uninitialized_msg
!= 0) {
859 *image
= GetImageForConnectingNetwork(icon_type
, shill::kTypeCellular
);
861 *label
= l10n_util::GetStringUTF16(uninitialized_msg
);
864 // Otherwise show the disconnected wifi icon.
865 *image
= GetImageForDisconnectedNetwork(icon_type
, shill::kTypeWifi
);
867 *label
= l10n_util::GetStringUTF16(
868 IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED
);
874 *animating
= network
->IsConnectingState();
875 // Get icon and label for connected or connecting network.
876 *image
= GetImageForNetwork(network
, icon_type
);
878 *label
= GetLabelForNetwork(network
, icon_type
);
881 void PurgeNetworkIconCache() {
882 NetworkStateHandler::NetworkStateList networks
;
883 NetworkHandler::Get()->network_state_handler()->GetVisibleNetworkList(
885 std::set
<std::string
> network_paths
;
886 for (NetworkStateHandler::NetworkStateList::iterator iter
= networks
.begin();
887 iter
!= networks
.end(); ++iter
) {
888 network_paths
.insert((*iter
)->path());
890 PurgeIconMap(ICON_TYPE_TRAY
, network_paths
);
891 PurgeIconMap(ICON_TYPE_DEFAULT_VIEW
, network_paths
);
892 PurgeIconMap(ICON_TYPE_LIST
, network_paths
);
895 } // namespace network_icon