| OLD | NEW |
| (Empty) |
| 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 "ui/chromeos/network/network_icon.h" | |
| 6 | |
| 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/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" | |
| 26 | |
| 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; | |
| 34 | |
| 35 namespace ui { | |
| 36 namespace network_icon { | |
| 37 | |
| 38 namespace { | |
| 39 | |
| 40 //------------------------------------------------------------------------------ | |
| 41 // Struct to pass icon badges to NetworkIconImageSource. | |
| 42 struct Badges { | |
| 43 Badges() | |
| 44 : top_left(NULL), | |
| 45 top_right(NULL), | |
| 46 bottom_left(NULL), | |
| 47 bottom_right(NULL) { | |
| 48 } | |
| 49 const gfx::ImageSkia* top_left; | |
| 50 const gfx::ImageSkia* top_right; | |
| 51 const gfx::ImageSkia* bottom_left; | |
| 52 const gfx::ImageSkia* bottom_right; | |
| 53 }; | |
| 54 | |
| 55 //------------------------------------------------------------------------------ | |
| 56 // class used for maintaining a map of network state and images. | |
| 57 class NetworkIconImpl { | |
| 58 public: | |
| 59 NetworkIconImpl(const std::string& path, IconType icon_type); | |
| 60 | |
| 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); | |
| 64 | |
| 65 // Returns the cached image url for |image_| based on |scale_factor|. | |
| 66 const std::string& GetImageUrl(float scale_factor); | |
| 67 | |
| 68 const gfx::ImageSkia& image() const { return image_; } | |
| 69 | |
| 70 private: | |
| 71 typedef std::map<float, std::string> ImageUrlMap; | |
| 72 | |
| 73 // Updates |strength_index_| for wireless networks. Returns true if changed. | |
| 74 bool UpdateWirelessStrengthIndex(const chromeos::NetworkState* network); | |
| 75 | |
| 76 // Updates the local state for cellular networks. Returns true if changed. | |
| 77 bool UpdateCellularState(const chromeos::NetworkState* network); | |
| 78 | |
| 79 // Updates the portal state for wireless networks. Returns true if changed. | |
| 80 bool UpdatePortalState(const chromeos::NetworkState* network); | |
| 81 | |
| 82 // Updates the VPN badge. Returns true if changed. | |
| 83 bool UpdateVPNBadge(); | |
| 84 | |
| 85 // Gets |badges| based on |network| and the current state. | |
| 86 void GetBadges(const NetworkState* network, Badges* badges); | |
| 87 | |
| 88 // Gets the appropriate icon and badges and composites the image. | |
| 89 void GenerateImage(const chromeos::NetworkState* network); | |
| 90 | |
| 91 // Network path, used for debugging. | |
| 92 std::string network_path_; | |
| 93 | |
| 94 // Defines color theme and VPN badging | |
| 95 const IconType icon_type_; | |
| 96 | |
| 97 // Cached state of the network when the icon was last generated. | |
| 98 std::string state_; | |
| 99 | |
| 100 // Cached strength index of the network when the icon was last generated. | |
| 101 int strength_index_; | |
| 102 | |
| 103 // Cached technology badge for the network when the icon was last generated. | |
| 104 const gfx::ImageSkia* technology_badge_; | |
| 105 | |
| 106 // Cached vpn badge for the network when the icon was last generated. | |
| 107 const gfx::ImageSkia* vpn_badge_; | |
| 108 | |
| 109 // Cached roaming state of the network when the icon was last generated. | |
| 110 std::string roaming_state_; | |
| 111 | |
| 112 // Cached portal state of the network when the icon was last generated. | |
| 113 bool behind_captive_portal_; | |
| 114 | |
| 115 // Generated icon image. | |
| 116 gfx::ImageSkia image_; | |
| 117 | |
| 118 // Map of cached image urls by scale factor. Cleared whenever image_ is | |
| 119 // generated. | |
| 120 ImageUrlMap image_urls_; | |
| 121 | |
| 122 DISALLOW_COPY_AND_ASSIGN(NetworkIconImpl); | |
| 123 }; | |
| 124 | |
| 125 //------------------------------------------------------------------------------ | |
| 126 // Maintain a static (global) icon map. Note: Icons are never destroyed; | |
| 127 // it is assumed that a finite and reasonable number of network icons will be | |
| 128 // created during a session. | |
| 129 | |
| 130 typedef std::map<std::string, NetworkIconImpl*> NetworkIconMap; | |
| 131 | |
| 132 NetworkIconMap* GetIconMapInstance(IconType icon_type, bool create) { | |
| 133 typedef std::map<IconType, NetworkIconMap*> IconTypeMap; | |
| 134 static IconTypeMap* s_icon_map = NULL; | |
| 135 if (s_icon_map == NULL) { | |
| 136 if (!create) | |
| 137 return NULL; | |
| 138 s_icon_map = new IconTypeMap; | |
| 139 } | |
| 140 if (s_icon_map->count(icon_type) == 0) { | |
| 141 if (!create) | |
| 142 return NULL; | |
| 143 (*s_icon_map)[icon_type] = new NetworkIconMap; | |
| 144 } | |
| 145 return (*s_icon_map)[icon_type]; | |
| 146 } | |
| 147 | |
| 148 NetworkIconMap* GetIconMap(IconType icon_type) { | |
| 149 return GetIconMapInstance(icon_type, true); | |
| 150 } | |
| 151 | |
| 152 void PurgeIconMap(IconType icon_type, | |
| 153 const std::set<std::string>& network_paths) { | |
| 154 NetworkIconMap* icon_map = GetIconMapInstance(icon_type, false); | |
| 155 if (!icon_map) | |
| 156 return; | |
| 157 for (NetworkIconMap::iterator loop_iter = icon_map->begin(); | |
| 158 loop_iter != icon_map->end(); ) { | |
| 159 NetworkIconMap::iterator cur_iter = loop_iter++; | |
| 160 if (network_paths.count(cur_iter->first) == 0) { | |
| 161 delete cur_iter->second; | |
| 162 icon_map->erase(cur_iter); | |
| 163 } | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 //------------------------------------------------------------------------------ | |
| 168 // Utilities for generating icon images. | |
| 169 | |
| 170 // 'NONE' will default to ARCS behavior where appropriate (e.g. no network or | |
| 171 // if a new type gets added). | |
| 172 enum ImageType { | |
| 173 ARCS, | |
| 174 BARS, | |
| 175 NONE | |
| 176 }; | |
| 177 | |
| 178 // Amount to fade icons while connecting. | |
| 179 const double kConnectingImageAlpha = 0.5; | |
| 180 | |
| 181 // Images for strength bars for wired networks. | |
| 182 const int kNumBarsImages = 5; | |
| 183 | |
| 184 // Imagaes for strength arcs for wireless networks. | |
| 185 const int kNumArcsImages = 5; | |
| 186 | |
| 187 // Number of discrete images to use for alpha fade animation | |
| 188 const int kNumFadeImages = 10; | |
| 189 | |
| 190 //------------------------------------------------------------------------------ | |
| 191 // Classes for generating scaled images. | |
| 192 | |
| 193 const SkBitmap GetEmptyBitmap(const gfx::Size pixel_size) { | |
| 194 typedef std::pair<int, int> SizeKey; | |
| 195 typedef std::map<SizeKey, SkBitmap> SizeBitmapMap; | |
| 196 static SizeBitmapMap* s_empty_bitmaps = new SizeBitmapMap; | |
| 197 | |
| 198 SizeKey key(pixel_size.width(), pixel_size.height()); | |
| 199 | |
| 200 SizeBitmapMap::iterator iter = s_empty_bitmaps->find(key); | |
| 201 if (iter != s_empty_bitmaps->end()) | |
| 202 return iter->second; | |
| 203 | |
| 204 SkBitmap empty; | |
| 205 empty.allocN32Pixels(key.first, key.second); | |
| 206 empty.eraseARGB(0, 0, 0, 0); | |
| 207 (*s_empty_bitmaps)[key] = empty; | |
| 208 return empty; | |
| 209 } | |
| 210 | |
| 211 class EmptyImageSource: public gfx::ImageSkiaSource { | |
| 212 public: | |
| 213 explicit EmptyImageSource(const gfx::Size& size) | |
| 214 : size_(size) { | |
| 215 } | |
| 216 | |
| 217 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE { | |
| 218 gfx::Size pixel_size = gfx::ToFlooredSize(gfx::ScaleSize(size_, scale)); | |
| 219 SkBitmap empty_bitmap = GetEmptyBitmap(pixel_size); | |
| 220 return gfx::ImageSkiaRep(empty_bitmap, scale); | |
| 221 } | |
| 222 | |
| 223 private: | |
| 224 const gfx::Size size_; | |
| 225 | |
| 226 DISALLOW_COPY_AND_ASSIGN(EmptyImageSource); | |
| 227 }; | |
| 228 | |
| 229 // This defines how we assemble a network icon. | |
| 230 class NetworkIconImageSource : public gfx::ImageSkiaSource { | |
| 231 public: | |
| 232 NetworkIconImageSource(const gfx::ImageSkia& icon, const Badges& badges) | |
| 233 : icon_(icon), | |
| 234 badges_(badges) { | |
| 235 } | |
| 236 virtual ~NetworkIconImageSource() {} | |
| 237 | |
| 238 // TODO(pkotwicz): Figure out what to do when a new image resolution becomes | |
| 239 // available. | |
| 240 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE { | |
| 241 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale); | |
| 242 if (icon_rep.is_null()) | |
| 243 return gfx::ImageSkiaRep(); | |
| 244 gfx::Canvas canvas(icon_rep, false); | |
| 245 if (badges_.top_left) | |
| 246 canvas.DrawImageInt(*badges_.top_left, 0, 0); | |
| 247 if (badges_.top_right) | |
| 248 canvas.DrawImageInt(*badges_.top_right, | |
| 249 icon_.width() - badges_.top_right->width(), 0); | |
| 250 if (badges_.bottom_left) { | |
| 251 canvas.DrawImageInt(*badges_.bottom_left, | |
| 252 0, icon_.height() - badges_.bottom_left->height()); | |
| 253 } | |
| 254 if (badges_.bottom_right) { | |
| 255 canvas.DrawImageInt(*badges_.bottom_right, | |
| 256 icon_.width() - badges_.bottom_right->width(), | |
| 257 icon_.height() - badges_.bottom_right->height()); | |
| 258 } | |
| 259 return canvas.ExtractImageRep(); | |
| 260 } | |
| 261 | |
| 262 private: | |
| 263 const gfx::ImageSkia icon_; | |
| 264 const Badges badges_; | |
| 265 | |
| 266 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource); | |
| 267 }; | |
| 268 | |
| 269 //------------------------------------------------------------------------------ | |
| 270 // Utilities for extracting icon images. | |
| 271 | |
| 272 // A struct used for caching image urls. | |
| 273 struct ImageIdForNetworkType { | |
| 274 ImageIdForNetworkType(IconType icon_type, | |
| 275 const std::string& network_type, | |
| 276 float scale_factor) : | |
| 277 icon_type(icon_type), | |
| 278 network_type(network_type), | |
| 279 scale_factor(scale_factor) {} | |
| 280 bool operator<(const ImageIdForNetworkType& other) const { | |
| 281 if (icon_type != other.icon_type) | |
| 282 return icon_type < other.icon_type; | |
| 283 if (network_type != other.network_type) | |
| 284 return network_type < other.network_type; | |
| 285 return scale_factor < other.scale_factor; | |
| 286 } | |
| 287 IconType icon_type; | |
| 288 std::string network_type; | |
| 289 float scale_factor; | |
| 290 }; | |
| 291 | |
| 292 typedef std::map<ImageIdForNetworkType, std::string> ImageIdUrlMap; | |
| 293 | |
| 294 bool IconTypeIsDark(IconType icon_type) { | |
| 295 return (icon_type != ICON_TYPE_TRAY); | |
| 296 } | |
| 297 | |
| 298 bool IconTypeHasVPNBadge(IconType icon_type) { | |
| 299 return (icon_type != ICON_TYPE_LIST); | |
| 300 } | |
| 301 | |
| 302 int NumImagesForType(ImageType type) { | |
| 303 return (type == BARS) ? kNumBarsImages : kNumArcsImages; | |
| 304 } | |
| 305 | |
| 306 gfx::ImageSkia* BaseImageForType(ImageType image_type, IconType icon_type) { | |
| 307 gfx::ImageSkia* image; | |
| 308 if (image_type == BARS) { | |
| 309 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 310 IconTypeIsDark(icon_type) ? | |
| 311 IDR_AURA_UBER_TRAY_NETWORK_BARS_DARK : | |
| 312 IDR_AURA_UBER_TRAY_NETWORK_BARS_LIGHT); | |
| 313 } else { | |
| 314 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 315 IconTypeIsDark(icon_type) ? | |
| 316 IDR_AURA_UBER_TRAY_NETWORK_ARCS_DARK : | |
| 317 IDR_AURA_UBER_TRAY_NETWORK_ARCS_LIGHT); | |
| 318 } | |
| 319 return image; | |
| 320 } | |
| 321 | |
| 322 ImageType ImageTypeForNetworkType(const std::string& type) { | |
| 323 if (type == shill::kTypeWifi) | |
| 324 return ARCS; | |
| 325 else if (type == shill::kTypeCellular || type == shill::kTypeWimax) | |
| 326 return BARS; | |
| 327 return NONE; | |
| 328 } | |
| 329 | |
| 330 gfx::ImageSkia GetImageForIndex(ImageType image_type, | |
| 331 IconType icon_type, | |
| 332 int index) { | |
| 333 int num_images = NumImagesForType(image_type); | |
| 334 if (index < 0 || index >= num_images) | |
| 335 return gfx::ImageSkia(); | |
| 336 gfx::ImageSkia* images = BaseImageForType(image_type, icon_type); | |
| 337 int width = images->width(); | |
| 338 int height = images->height() / num_images; | |
| 339 return gfx::ImageSkiaOperations::ExtractSubset(*images, | |
| 340 gfx::Rect(0, index * height, width, height)); | |
| 341 } | |
| 342 | |
| 343 const gfx::ImageSkia GetConnectedImage(IconType icon_type, | |
| 344 const std::string& network_type) { | |
| 345 if (network_type == shill::kTypeVPN) { | |
| 346 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 347 IDR_AURA_UBER_TRAY_NETWORK_VPN); | |
| 348 } | |
| 349 ImageType image_type = ImageTypeForNetworkType(network_type); | |
| 350 const int connected_index = NumImagesForType(image_type) - 1; | |
| 351 return GetImageForIndex(image_type, icon_type, connected_index); | |
| 352 } | |
| 353 | |
| 354 const gfx::ImageSkia GetDisconnectedImage(IconType icon_type, | |
| 355 const std::string& network_type) { | |
| 356 if (network_type == shill::kTypeVPN) { | |
| 357 // Note: same as connected image, shouldn't normally be seen. | |
| 358 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 359 IDR_AURA_UBER_TRAY_NETWORK_VPN); | |
| 360 } | |
| 361 ImageType image_type = ImageTypeForNetworkType(network_type); | |
| 362 const int disconnected_index = 0; | |
| 363 return GetImageForIndex(image_type, icon_type, disconnected_index); | |
| 364 } | |
| 365 | |
| 366 gfx::ImageSkia* ConnectingWirelessImage(ImageType image_type, | |
| 367 IconType icon_type, | |
| 368 double animation) { | |
| 369 static gfx::ImageSkia* s_bars_images_dark[kNumBarsImages - 1]; | |
| 370 static gfx::ImageSkia* s_bars_images_light[kNumBarsImages - 1]; | |
| 371 static gfx::ImageSkia* s_arcs_images_dark[kNumArcsImages - 1]; | |
| 372 static gfx::ImageSkia* s_arcs_images_light[kNumArcsImages - 1]; | |
| 373 int image_count = NumImagesForType(image_type) - 1; | |
| 374 int index = animation * nextafter(static_cast<float>(image_count), 0); | |
| 375 index = std::max(std::min(index, image_count - 1), 0); | |
| 376 gfx::ImageSkia** images; | |
| 377 bool dark = IconTypeIsDark(icon_type); | |
| 378 if (image_type == BARS) | |
| 379 images = dark ? s_bars_images_dark : s_bars_images_light; | |
| 380 else | |
| 381 images = dark ? s_arcs_images_dark : s_arcs_images_light; | |
| 382 if (!images[index]) { | |
| 383 // Lazily cache images. | |
| 384 gfx::ImageSkia source = GetImageForIndex(image_type, icon_type, index + 1); | |
| 385 images[index] = new gfx::ImageSkia( | |
| 386 gfx::ImageSkiaOperations::CreateBlendedImage( | |
| 387 gfx::ImageSkia(new EmptyImageSource(source.size()), source.size()), | |
| 388 source, | |
| 389 kConnectingImageAlpha)); | |
| 390 } | |
| 391 return images[index]; | |
| 392 } | |
| 393 | |
| 394 gfx::ImageSkia* ConnectingVpnImage(double animation) { | |
| 395 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0); | |
| 396 static gfx::ImageSkia* s_vpn_images[kNumFadeImages]; | |
| 397 if (!s_vpn_images[index]) { | |
| 398 // Lazily cache images. | |
| 399 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 400 gfx::ImageSkia* icon = rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN); | |
| 401 s_vpn_images[index] = new gfx::ImageSkia( | |
| 402 gfx::ImageSkiaOperations::CreateBlendedImage( | |
| 403 gfx::ImageSkia(new EmptyImageSource(icon->size()), icon->size()), | |
| 404 *icon, | |
| 405 animation)); | |
| 406 } | |
| 407 return s_vpn_images[index]; | |
| 408 } | |
| 409 | |
| 410 gfx::ImageSkia* ConnectingVpnBadge(double animation) { | |
| 411 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0); | |
| 412 static gfx::ImageSkia* s_vpn_badges[kNumFadeImages]; | |
| 413 if (!s_vpn_badges[index]) { | |
| 414 // Lazily cache images. | |
| 415 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 416 gfx::ImageSkia* icon = | |
| 417 rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED); // For size | |
| 418 gfx::ImageSkia* badge = | |
| 419 rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE); | |
| 420 s_vpn_badges[index] = new gfx::ImageSkia( | |
| 421 gfx::ImageSkiaOperations::CreateBlendedImage( | |
| 422 gfx::ImageSkia(new EmptyImageSource(icon->size()), icon->size()), | |
| 423 *badge, | |
| 424 animation)); | |
| 425 } | |
| 426 return s_vpn_badges[index]; | |
| 427 } | |
| 428 | |
| 429 int StrengthIndex(int strength, int count) { | |
| 430 // Return an index in the range [1, count-1]. | |
| 431 const float findex = (static_cast<float>(strength) / 100.0f) * | |
| 432 nextafter(static_cast<float>(count - 1), 0); | |
| 433 int index = 1 + static_cast<int>(findex); | |
| 434 index = std::max(std::min(index, count - 1), 1); | |
| 435 return index; | |
| 436 } | |
| 437 | |
| 438 int GetStrengthIndex(const NetworkState* network) { | |
| 439 ImageType image_type = ImageTypeForNetworkType(network->type()); | |
| 440 if (image_type == ARCS) | |
| 441 return StrengthIndex(network->signal_strength(), kNumArcsImages); | |
| 442 else if (image_type == BARS) | |
| 443 return StrengthIndex(network->signal_strength(), kNumBarsImages); | |
| 444 return 0; | |
| 445 } | |
| 446 | |
| 447 const gfx::ImageSkia* BadgeForNetworkTechnology(const NetworkState* network, | |
| 448 IconType icon_type) { | |
| 449 const int kUnknownBadgeType = -1; | |
| 450 int id = kUnknownBadgeType; | |
| 451 const std::string& technology = network->network_technology(); | |
| 452 if (technology == shill::kNetworkTechnologyEvdo) { | |
| 453 id = IconTypeIsDark(icon_type) ? | |
| 454 IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK : | |
| 455 IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT; | |
| 456 } else if (technology == shill::kNetworkTechnology1Xrtt) { | |
| 457 id = IDR_AURA_UBER_TRAY_NETWORK_1X; | |
| 458 } else if (technology == shill::kNetworkTechnologyGprs) { | |
| 459 id = IconTypeIsDark(icon_type) ? | |
| 460 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK : | |
| 461 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT; | |
| 462 } else if (technology == shill::kNetworkTechnologyEdge) { | |
| 463 id = IconTypeIsDark(icon_type) ? | |
| 464 IDR_AURA_UBER_TRAY_NETWORK_EDGE_DARK : | |
| 465 IDR_AURA_UBER_TRAY_NETWORK_EDGE_LIGHT; | |
| 466 } else if (technology == shill::kNetworkTechnologyUmts) { | |
| 467 id = IconTypeIsDark(icon_type) ? | |
| 468 IDR_AURA_UBER_TRAY_NETWORK_3G_DARK : | |
| 469 IDR_AURA_UBER_TRAY_NETWORK_3G_LIGHT; | |
| 470 } else if (technology == shill::kNetworkTechnologyHspa) { | |
| 471 id = IconTypeIsDark(icon_type) ? | |
| 472 IDR_AURA_UBER_TRAY_NETWORK_HSPA_DARK : | |
| 473 IDR_AURA_UBER_TRAY_NETWORK_HSPA_LIGHT; | |
| 474 } else if (technology == shill::kNetworkTechnologyHspaPlus) { | |
| 475 id = IconTypeIsDark(icon_type) ? | |
| 476 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_DARK : | |
| 477 IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_LIGHT; | |
| 478 } else if (technology == shill::kNetworkTechnologyLte) { | |
| 479 id = IconTypeIsDark(icon_type) ? | |
| 480 IDR_AURA_UBER_TRAY_NETWORK_LTE_DARK : | |
| 481 IDR_AURA_UBER_TRAY_NETWORK_LTE_LIGHT; | |
| 482 } else if (technology == shill::kNetworkTechnologyLteAdvanced) { | |
| 483 id = IconTypeIsDark(icon_type) ? | |
| 484 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_DARK : | |
| 485 IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_LIGHT; | |
| 486 } else if (technology == shill::kNetworkTechnologyGsm) { | |
| 487 id = IconTypeIsDark(icon_type) ? | |
| 488 IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK : | |
| 489 IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT; | |
| 490 } | |
| 491 if (id == kUnknownBadgeType) | |
| 492 return NULL; | |
| 493 else | |
| 494 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id); | |
| 495 } | |
| 496 | |
| 497 const gfx::ImageSkia* BadgeForVPN(IconType icon_type) { | |
| 498 return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 499 IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE); | |
| 500 } | |
| 501 | |
| 502 gfx::ImageSkia GetIcon(const NetworkState* network, | |
| 503 IconType icon_type, | |
| 504 int strength_index) { | |
| 505 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 506 if (network->Matches(NetworkTypePattern::Ethernet())) { | |
| 507 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED); | |
| 508 } else if (network->Matches(NetworkTypePattern::Wireless())) { | |
| 509 DCHECK(strength_index > 0); | |
| 510 return GetImageForIndex( | |
| 511 ImageTypeForNetworkType(network->type()), icon_type, strength_index); | |
| 512 } else if (network->Matches(NetworkTypePattern::VPN())) { | |
| 513 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN); | |
| 514 } else { | |
| 515 LOG(WARNING) << "Request for icon for unsupported type: " | |
| 516 << network->type(); | |
| 517 return *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED); | |
| 518 } | |
| 519 } | |
| 520 | |
| 521 //------------------------------------------------------------------------------ | |
| 522 // Get connecting images | |
| 523 | |
| 524 gfx::ImageSkia GetConnectingVpnImage(IconType icon_type) { | |
| 525 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); | |
| 526 const NetworkState* connected_network = NULL; | |
| 527 if (icon_type == ICON_TYPE_TRAY) { | |
| 528 connected_network = | |
| 529 handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual()); | |
| 530 } | |
| 531 double animation = NetworkIconAnimation::GetInstance()->GetAnimation(); | |
| 532 | |
| 533 if (connected_network) { | |
| 534 gfx::ImageSkia icon = GetImageForNetwork(connected_network, icon_type); | |
| 535 Badges badges; | |
| 536 badges.bottom_left = ConnectingVpnBadge(animation); | |
| 537 return gfx::ImageSkia( | |
| 538 new NetworkIconImageSource(icon, badges), icon.size()); | |
| 539 } else { | |
| 540 gfx::ImageSkia* icon = ConnectingVpnImage(animation); | |
| 541 return gfx::ImageSkia( | |
| 542 new NetworkIconImageSource(*icon, Badges()), icon->size()); | |
| 543 } | |
| 544 } | |
| 545 | |
| 546 gfx::ImageSkia GetConnectingImage(IconType icon_type, | |
| 547 const std::string& network_type) { | |
| 548 if (network_type == shill::kTypeVPN) | |
| 549 return GetConnectingVpnImage(icon_type); | |
| 550 | |
| 551 ImageType image_type = ImageTypeForNetworkType(network_type); | |
| 552 double animation = NetworkIconAnimation::GetInstance()->GetAnimation(); | |
| 553 | |
| 554 gfx::ImageSkia* icon = ConnectingWirelessImage( | |
| 555 image_type, icon_type, animation); | |
| 556 return gfx::ImageSkia( | |
| 557 new NetworkIconImageSource(*icon, Badges()), icon->size()); | |
| 558 } | |
| 559 | |
| 560 std::string GetConnectingImageUrl(IconType icon_type, | |
| 561 const std::string& network_type, | |
| 562 float scale_factor) { | |
| 563 // Caching the connecting image is complicated and we will never draw more | |
| 564 // than a few per frame, so just generate the image url each time. | |
| 565 gfx::ImageSkia image = GetConnectingImage(icon_type, network_type); | |
| 566 gfx::ImageSkiaRep image_rep = image.GetRepresentation(scale_factor); | |
| 567 return webui::GetBitmapDataUrl(image_rep.sk_bitmap()); | |
| 568 } | |
| 569 | |
| 570 } // namespace | |
| 571 | |
| 572 //------------------------------------------------------------------------------ | |
| 573 // NetworkIconImpl | |
| 574 | |
| 575 NetworkIconImpl::NetworkIconImpl(const std::string& path, IconType icon_type) | |
| 576 : network_path_(path), | |
| 577 icon_type_(icon_type), | |
| 578 strength_index_(-1), | |
| 579 technology_badge_(NULL), | |
| 580 vpn_badge_(NULL), | |
| 581 behind_captive_portal_(false) { | |
| 582 // Default image | |
| 583 image_ = GetDisconnectedImage(icon_type, shill::kTypeWifi); | |
| 584 } | |
| 585 | |
| 586 void NetworkIconImpl::Update(const NetworkState* network) { | |
| 587 DCHECK(network); | |
| 588 // Determine whether or not we need to update the icon. | |
| 589 bool dirty = image_.isNull(); | |
| 590 | |
| 591 // If the network state has changed, the icon needs updating. | |
| 592 if (state_ != network->connection_state()) { | |
| 593 state_ = network->connection_state(); | |
| 594 dirty = true; | |
| 595 } | |
| 596 | |
| 597 dirty |= UpdatePortalState(network); | |
| 598 | |
| 599 if (network->Matches(NetworkTypePattern::Wireless())) { | |
| 600 dirty |= UpdateWirelessStrengthIndex(network); | |
| 601 } | |
| 602 | |
| 603 if (network->Matches(NetworkTypePattern::Cellular())) | |
| 604 dirty |= UpdateCellularState(network); | |
| 605 | |
| 606 if (IconTypeHasVPNBadge(icon_type_) && | |
| 607 network->Matches(NetworkTypePattern::NonVirtual())) { | |
| 608 dirty |= UpdateVPNBadge(); | |
| 609 } | |
| 610 | |
| 611 if (dirty) { | |
| 612 // Set the icon and badges based on the network and generate the image. | |
| 613 GenerateImage(network); | |
| 614 } | |
| 615 } | |
| 616 | |
| 617 bool NetworkIconImpl::UpdateWirelessStrengthIndex(const NetworkState* network) { | |
| 618 int index = GetStrengthIndex(network); | |
| 619 if (index != strength_index_) { | |
| 620 strength_index_ = index; | |
| 621 return true; | |
| 622 } | |
| 623 return false; | |
| 624 } | |
| 625 | |
| 626 bool NetworkIconImpl::UpdateCellularState(const NetworkState* network) { | |
| 627 bool dirty = false; | |
| 628 const gfx::ImageSkia* technology_badge = | |
| 629 BadgeForNetworkTechnology(network, icon_type_); | |
| 630 if (technology_badge != technology_badge_) { | |
| 631 technology_badge_ = technology_badge; | |
| 632 dirty = true; | |
| 633 } | |
| 634 std::string roaming_state = network->roaming(); | |
| 635 if (roaming_state != roaming_state_) { | |
| 636 roaming_state_ = roaming_state; | |
| 637 dirty = true; | |
| 638 } | |
| 639 return dirty; | |
| 640 } | |
| 641 | |
| 642 bool NetworkIconImpl::UpdatePortalState(const NetworkState* network) { | |
| 643 bool behind_captive_portal = false; | |
| 644 if (network) { | |
| 645 NetworkPortalDetector::CaptivePortalState state = | |
| 646 NetworkPortalDetector::Get()->GetCaptivePortalState(network->path()); | |
| 647 behind_captive_portal = | |
| 648 state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL; | |
| 649 } | |
| 650 | |
| 651 if (behind_captive_portal == behind_captive_portal_) | |
| 652 return false; | |
| 653 behind_captive_portal_ = behind_captive_portal; | |
| 654 return true; | |
| 655 } | |
| 656 | |
| 657 bool NetworkIconImpl::UpdateVPNBadge() { | |
| 658 const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> | |
| 659 ConnectedNetworkByType(NetworkTypePattern::VPN()); | |
| 660 if (vpn && vpn_badge_ == NULL) { | |
| 661 vpn_badge_ = BadgeForVPN(icon_type_); | |
| 662 return true; | |
| 663 } else if (!vpn && vpn_badge_ != NULL) { | |
| 664 vpn_badge_ = NULL; | |
| 665 return true; | |
| 666 } | |
| 667 return false; | |
| 668 } | |
| 669 | |
| 670 void NetworkIconImpl::GetBadges(const NetworkState* network, Badges* badges) { | |
| 671 DCHECK(network); | |
| 672 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 673 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); | |
| 674 | |
| 675 const std::string& type = network->type(); | |
| 676 if (type == shill::kTypeWifi) { | |
| 677 if (network->security() != shill::kSecurityNone && | |
| 678 IconTypeIsDark(icon_type_)) { | |
| 679 badges->bottom_right = rb.GetImageSkiaNamed( | |
| 680 IDR_AURA_UBER_TRAY_NETWORK_SECURE_DARK); | |
| 681 } | |
| 682 } else if (type == shill::kTypeWimax) { | |
| 683 technology_badge_ = rb.GetImageSkiaNamed( | |
| 684 IconTypeIsDark(icon_type_) ? | |
| 685 IDR_AURA_UBER_TRAY_NETWORK_4G_DARK : | |
| 686 IDR_AURA_UBER_TRAY_NETWORK_4G_LIGHT); | |
| 687 } else if (type == shill::kTypeCellular) { | |
| 688 if (network->roaming() == shill::kRoamingStateRoaming) { | |
| 689 // For networks that are always in roaming don't show roaming badge. | |
| 690 const DeviceState* device = | |
| 691 handler->GetDeviceState(network->device_path()); | |
| 692 LOG_IF(WARNING, !device) << "Could not find device state for " | |
| 693 << network->device_path(); | |
| 694 if (!device || !device->provider_requires_roaming()) { | |
| 695 badges->bottom_right = rb.GetImageSkiaNamed( | |
| 696 IconTypeIsDark(icon_type_) ? | |
| 697 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_DARK : | |
| 698 IDR_AURA_UBER_TRAY_NETWORK_ROAMING_LIGHT); | |
| 699 } | |
| 700 } | |
| 701 } | |
| 702 if (!network->IsConnectingState()) { | |
| 703 badges->top_left = technology_badge_; | |
| 704 badges->bottom_left = vpn_badge_; | |
| 705 } | |
| 706 | |
| 707 if (behind_captive_portal_) { | |
| 708 gfx::ImageSkia* badge = rb.GetImageSkiaNamed( | |
| 709 IconTypeIsDark(icon_type_) ? | |
| 710 IDR_AURA_UBER_TRAY_NETWORK_PORTAL_DARK : | |
| 711 IDR_AURA_UBER_TRAY_NETWORK_PORTAL_LIGHT); | |
| 712 badges->bottom_right = badge; | |
| 713 } | |
| 714 } | |
| 715 | |
| 716 void NetworkIconImpl::GenerateImage(const NetworkState* network) { | |
| 717 DCHECK(network); | |
| 718 gfx::ImageSkia icon = GetIcon(network, icon_type_, strength_index_); | |
| 719 Badges badges; | |
| 720 GetBadges(network, &badges); | |
| 721 image_ = gfx::ImageSkia( | |
| 722 new NetworkIconImageSource(icon, badges), icon.size()); | |
| 723 image_urls_.clear(); | |
| 724 } | |
| 725 | |
| 726 const std::string& NetworkIconImpl::GetImageUrl(float scale_factor) { | |
| 727 ImageUrlMap::iterator iter = image_urls_.find(scale_factor); | |
| 728 if (iter != image_urls_.end()) | |
| 729 return iter->second; | |
| 730 | |
| 731 VLOG(2) << "Generating bitmap URL for: " << network_path_; | |
| 732 gfx::ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); | |
| 733 iter = image_urls_.insert(std::make_pair( | |
| 734 scale_factor, webui::GetBitmapDataUrl(image_rep.sk_bitmap()))).first; | |
| 735 return iter->second; | |
| 736 } | |
| 737 | |
| 738 namespace { | |
| 739 | |
| 740 NetworkIconImpl* FindAndUpdateImageImpl(const NetworkState* network, | |
| 741 IconType icon_type) { | |
| 742 // Find or add the icon. | |
| 743 NetworkIconMap* icon_map = GetIconMap(icon_type); | |
| 744 NetworkIconImpl* icon; | |
| 745 NetworkIconMap::iterator iter = icon_map->find(network->path()); | |
| 746 if (iter == icon_map->end()) { | |
| 747 icon = new NetworkIconImpl(network->path(), icon_type); | |
| 748 icon_map->insert(std::make_pair(network->path(), icon)); | |
| 749 } else { | |
| 750 icon = iter->second; | |
| 751 } | |
| 752 | |
| 753 // Update and return the icon's image. | |
| 754 icon->Update(network); | |
| 755 return icon; | |
| 756 } | |
| 757 | |
| 758 } // namespace | |
| 759 | |
| 760 //------------------------------------------------------------------------------ | |
| 761 // Public interface | |
| 762 | |
| 763 gfx::ImageSkia GetImageForNetwork(const NetworkState* network, | |
| 764 IconType icon_type) { | |
| 765 DCHECK(network); | |
| 766 if (!network->visible()) | |
| 767 return GetDisconnectedImage(icon_type, network->type()); | |
| 768 | |
| 769 if (network->IsConnectingState()) | |
| 770 return GetConnectingImage(icon_type, network->type()); | |
| 771 | |
| 772 NetworkIconImpl* icon = FindAndUpdateImageImpl(network, icon_type); | |
| 773 return icon->image(); | |
| 774 } | |
| 775 | |
| 776 std::string GetImageUrlForNetwork(const NetworkState* network, | |
| 777 IconType icon_type, | |
| 778 float scale_factor) { | |
| 779 DCHECK(network); | |
| 780 // Handle connecting icons. | |
| 781 if (network->IsConnectingState()) | |
| 782 return GetConnectingImageUrl(icon_type, network->type(), scale_factor); | |
| 783 | |
| 784 NetworkIconImpl* icon = FindAndUpdateImageImpl(network, icon_type); | |
| 785 return icon->GetImageUrl(scale_factor); | |
| 786 } | |
| 787 | |
| 788 gfx::ImageSkia GetImageForConnectedNetwork(IconType icon_type, | |
| 789 const std::string& network_type) { | |
| 790 return GetConnectedImage(icon_type, network_type); | |
| 791 } | |
| 792 | |
| 793 gfx::ImageSkia GetImageForConnectingNetwork(IconType icon_type, | |
| 794 const std::string& network_type) { | |
| 795 return GetConnectingImage(icon_type, network_type); | |
| 796 } | |
| 797 | |
| 798 gfx::ImageSkia GetImageForDisconnectedNetwork(IconType icon_type, | |
| 799 const std::string& network_type) { | |
| 800 return GetDisconnectedImage(icon_type, network_type); | |
| 801 } | |
| 802 | |
| 803 base::string16 GetLabelForNetwork(const chromeos::NetworkState* network, | |
| 804 IconType icon_type) { | |
| 805 DCHECK(network); | |
| 806 std::string activation_state = network->activation_state(); | |
| 807 if (icon_type == ICON_TYPE_LIST) { | |
| 808 // Show "<network>: [Connecting|Activating]..." | |
| 809 if (network->IsConnectingState()) { | |
| 810 return l10n_util::GetStringFUTF16( | |
| 811 IDS_ASH_STATUS_TRAY_NETWORK_LIST_CONNECTING, | |
| 812 base::UTF8ToUTF16(network->name())); | |
| 813 } | |
| 814 if (activation_state == shill::kActivationStateActivating) { | |
| 815 return l10n_util::GetStringFUTF16( | |
| 816 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING, | |
| 817 base::UTF8ToUTF16(network->name())); | |
| 818 } | |
| 819 // Show "Activate <network>" in list view only. | |
| 820 if (activation_state == shill::kActivationStateNotActivated || | |
| 821 activation_state == shill::kActivationStatePartiallyActivated) { | |
| 822 return l10n_util::GetStringFUTF16( | |
| 823 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE, | |
| 824 base::UTF8ToUTF16(network->name())); | |
| 825 } | |
| 826 } else { | |
| 827 // Show "[Connected to|Connecting to|Activating] <network>" (non-list view). | |
| 828 if (network->IsConnectedState()) { | |
| 829 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, | |
| 830 base::UTF8ToUTF16(network->name())); | |
| 831 } | |
| 832 if (network->IsConnectingState()) { | |
| 833 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING, | |
| 834 base::UTF8ToUTF16(network->name())); | |
| 835 } | |
| 836 if (activation_state == shill::kActivationStateActivating) { | |
| 837 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING, | |
| 838 base::UTF8ToUTF16(network->name())); | |
| 839 } | |
| 840 } | |
| 841 | |
| 842 // Otherwise just show the network name or 'Ethernet'. | |
| 843 if (network->Matches(NetworkTypePattern::Ethernet())) { | |
| 844 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET); | |
| 845 } else { | |
| 846 return base::UTF8ToUTF16(network->name()); | |
| 847 } | |
| 848 } | |
| 849 | |
| 850 int GetCellularUninitializedMsg() { | |
| 851 static base::Time s_uninitialized_state_time; | |
| 852 static int s_uninitialized_msg(0); | |
| 853 | |
| 854 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); | |
| 855 if (handler->GetTechnologyState(NetworkTypePattern::Mobile()) | |
| 856 == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) { | |
| 857 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR; | |
| 858 s_uninitialized_state_time = base::Time::Now(); | |
| 859 return s_uninitialized_msg; | |
| 860 } else if (handler->GetScanningByType(NetworkTypePattern::Mobile())) { | |
| 861 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_CELLULAR_SCANNING; | |
| 862 s_uninitialized_state_time = base::Time::Now(); | |
| 863 return s_uninitialized_msg; | |
| 864 } | |
| 865 // There can be a delay between leaving the Initializing state and when | |
| 866 // a Cellular device shows up, so keep showing the initializing | |
| 867 // animation for a bit to avoid flashing the disconnect icon. | |
| 868 const int kInitializingDelaySeconds = 1; | |
| 869 base::TimeDelta dtime = base::Time::Now() - s_uninitialized_state_time; | |
| 870 if (dtime.InSeconds() < kInitializingDelaySeconds) | |
| 871 return s_uninitialized_msg; | |
| 872 return 0; | |
| 873 } | |
| 874 | |
| 875 void GetDefaultNetworkImageAndLabel(IconType icon_type, | |
| 876 gfx::ImageSkia* image, | |
| 877 base::string16* label, | |
| 878 bool* animating) { | |
| 879 NetworkStateHandler* state_handler = | |
| 880 NetworkHandler::Get()->network_state_handler(); | |
| 881 NetworkConnectionHandler* connect_handler = | |
| 882 NetworkHandler::Get()->network_connection_handler(); | |
| 883 const NetworkState* connected_network = | |
| 884 state_handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual()); | |
| 885 const NetworkState* connecting_network = | |
| 886 state_handler->ConnectingNetworkByType(NetworkTypePattern::Wireless()); | |
| 887 if (!connecting_network && icon_type == ICON_TYPE_TRAY) { | |
| 888 connecting_network = | |
| 889 state_handler->ConnectingNetworkByType(NetworkTypePattern::VPN()); | |
| 890 } | |
| 891 | |
| 892 const NetworkState* network; | |
| 893 // If we are connecting to a network, and there is either no connected | |
| 894 // network, or the connection was user requested, use the connecting | |
| 895 // network. | |
| 896 if (connecting_network && | |
| 897 (!connected_network || | |
| 898 connect_handler->HasConnectingNetwork(connecting_network->path()))) { | |
| 899 network = connecting_network; | |
| 900 } else { | |
| 901 network = connected_network; | |
| 902 } | |
| 903 | |
| 904 // Don't show ethernet in the tray | |
| 905 if (icon_type == ICON_TYPE_TRAY && network && | |
| 906 network->Matches(NetworkTypePattern::Ethernet())) { | |
| 907 *image = gfx::ImageSkia(); | |
| 908 *animating = false; | |
| 909 return; | |
| 910 } | |
| 911 | |
| 912 if (!network) { | |
| 913 // If no connecting network, check if we are activating a network. | |
| 914 const NetworkState* mobile_network = | |
| 915 state_handler->FirstNetworkByType(NetworkTypePattern::Mobile()); | |
| 916 if (mobile_network && (mobile_network->activation_state() == | |
| 917 shill::kActivationStateActivating)) { | |
| 918 network = mobile_network; | |
| 919 } | |
| 920 } | |
| 921 if (!network) { | |
| 922 // If no connecting network, check for cellular initializing. | |
| 923 int uninitialized_msg = GetCellularUninitializedMsg(); | |
| 924 if (uninitialized_msg != 0) { | |
| 925 *image = GetImageForConnectingNetwork(icon_type, shill::kTypeCellular); | |
| 926 if (label) | |
| 927 *label = l10n_util::GetStringUTF16(uninitialized_msg); | |
| 928 *animating = true; | |
| 929 } else { | |
| 930 // Otherwise show the disconnected wifi icon. | |
| 931 *image = GetImageForDisconnectedNetwork(icon_type, shill::kTypeWifi); | |
| 932 if (label) { | |
| 933 *label = l10n_util::GetStringUTF16( | |
| 934 IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED); | |
| 935 } | |
| 936 *animating = false; | |
| 937 } | |
| 938 return; | |
| 939 } | |
| 940 *animating = network->IsConnectingState(); | |
| 941 // Get icon and label for connected or connecting network. | |
| 942 *image = GetImageForNetwork(network, icon_type); | |
| 943 if (label) | |
| 944 *label = GetLabelForNetwork(network, icon_type); | |
| 945 } | |
| 946 | |
| 947 void PurgeNetworkIconCache() { | |
| 948 NetworkStateHandler::NetworkStateList networks; | |
| 949 NetworkHandler::Get()->network_state_handler()->GetVisibleNetworkList( | |
| 950 &networks); | |
| 951 std::set<std::string> network_paths; | |
| 952 for (NetworkStateHandler::NetworkStateList::iterator iter = networks.begin(); | |
| 953 iter != networks.end(); ++iter) { | |
| 954 network_paths.insert((*iter)->path()); | |
| 955 } | |
| 956 PurgeIconMap(ICON_TYPE_TRAY, network_paths); | |
| 957 PurgeIconMap(ICON_TYPE_DEFAULT_VIEW, network_paths); | |
| 958 PurgeIconMap(ICON_TYPE_LIST, network_paths); | |
| 959 } | |
| 960 | |
| 961 } // namespace network_icon | |
| 962 } // namespace ui | |
| OLD | NEW |