| 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/macros.h" | |
| 8 #include "base/strings/utf_string_conversions.h" | |
| 9 #include "chromeos/network/device_state.h" | |
| 10 #include "chromeos/network/network_connection_handler.h" | |
| 11 #include "chromeos/network/network_state.h" | |
| 12 #include "chromeos/network/network_state_handler.h" | |
| 13 #include "chromeos/network/portal_detector/network_portal_detector.h" | |
| 14 #include "grit/ui_chromeos_resources.h" | |
| 15 #include "grit/ui_chromeos_strings.h" | |
| 16 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 17 #include "third_party/skia/include/core/SkPaint.h" | |
| 18 #include "third_party/skia/include/core/SkPath.h" | |
| 19 #include "ui/base/l10n/l10n_util.h" | |
| 20 #include "ui/base/resource/resource_bundle.h" | |
| 21 #include "ui/base/webui/web_ui_util.h" | |
| 22 #include "ui/chromeos/material_design_icon_controller.h" | |
| 23 #include "ui/chromeos/network/network_icon_animation.h" | |
| 24 #include "ui/chromeos/network/network_icon_animation_observer.h" | |
| 25 #include "ui/gfx/canvas.h" | |
| 26 #include "ui/gfx/color_palette.h" | |
| 27 #include "ui/gfx/geometry/insets.h" | |
| 28 #include "ui/gfx/geometry/rect.h" | |
| 29 #include "ui/gfx/geometry/size_conversions.h" | |
| 30 #include "ui/gfx/image/canvas_image_source.h" | |
| 31 #include "ui/gfx/image/image_skia_operations.h" | |
| 32 #include "ui/gfx/image/image_skia_source.h" | |
| 33 #include "ui/gfx/paint_vector_icon.h" | |
| 34 #include "ui/gfx/skia_util.h" | |
| 35 #include "ui/gfx/vector_icons_public.h" | |
| 36 | |
| 37 using chromeos::DeviceState; | |
| 38 using chromeos::NetworkConnectionHandler; | |
| 39 using chromeos::NetworkHandler; | |
| 40 using chromeos::NetworkPortalDetector; | |
| 41 using chromeos::NetworkState; | |
| 42 using chromeos::NetworkStateHandler; | |
| 43 using chromeos::NetworkTypePattern; | |
| 44 | |
| 45 namespace ui { | |
| 46 namespace network_icon { | |
| 47 | |
| 48 namespace { | |
| 49 | |
| 50 // Constants for offseting the badge displayed on top of the signal strength | |
| 51 // icon. The badge will extend outside of the base icon bounds by these amounts. | |
| 52 // Only used for MD. All values are in dp. | |
| 53 | |
| 54 // The badge offsets are different depending on whether the icon is in the tray | |
| 55 // or menu. | |
| 56 const int kTrayIconBadgeOffset = 3; | |
| 57 const int kMenuIconBadgeOffset = 2; | |
| 58 | |
| 59 // TODO(estade): use kTrayIconSize. See crbug.com/623987 | |
| 60 const int kTrayIconSide = 16; | |
| 61 | |
| 62 bool UseMd() { | |
| 63 return md_icon_controller::UseMaterialDesignNetworkIcons(); | |
| 64 } | |
| 65 | |
| 66 //------------------------------------------------------------------------------ | |
| 67 // Struct to pass icon badges to NetworkIconImageSource. | |
| 68 struct Badges { | |
| 69 gfx::ImageSkia top_left; | |
| 70 gfx::ImageSkia top_right; | |
| 71 gfx::ImageSkia bottom_left; | |
| 72 gfx::ImageSkia bottom_right; | |
| 73 }; | |
| 74 | |
| 75 //------------------------------------------------------------------------------ | |
| 76 // class used for maintaining a map of network state and images. | |
| 77 class NetworkIconImpl { | |
| 78 public: | |
| 79 NetworkIconImpl(const std::string& path, IconType icon_type); | |
| 80 | |
| 81 // Determines whether or not the associated network might be dirty and if so | |
| 82 // updates and generates the icon. Does nothing if network no longer exists. | |
| 83 void Update(const chromeos::NetworkState* network); | |
| 84 | |
| 85 const gfx::ImageSkia& image() const { return image_; } | |
| 86 | |
| 87 private: | |
| 88 // Updates |strength_index_| for wireless networks. Returns true if changed. | |
| 89 bool UpdateWirelessStrengthIndex(const chromeos::NetworkState* network); | |
| 90 | |
| 91 // Updates the local state for cellular networks. Returns true if changed. | |
| 92 bool UpdateCellularState(const chromeos::NetworkState* network); | |
| 93 | |
| 94 // Updates the portal state for wireless networks. Returns true if changed. | |
| 95 bool UpdatePortalState(const chromeos::NetworkState* network); | |
| 96 | |
| 97 // Updates the VPN badge. Returns true if changed. | |
| 98 bool UpdateVPNBadge(); | |
| 99 | |
| 100 // Gets |badges| based on |network| and the current state. | |
| 101 void GetBadges(const NetworkState* network, Badges* badges); | |
| 102 | |
| 103 // Gets the appropriate icon and badges and composites the image. | |
| 104 void GenerateImage(const chromeos::NetworkState* network); | |
| 105 | |
| 106 // Network path, used for debugging. | |
| 107 std::string network_path_; | |
| 108 | |
| 109 // Defines color theme and VPN badging | |
| 110 const IconType icon_type_; | |
| 111 | |
| 112 // Cached state of the network when the icon was last generated. | |
| 113 std::string state_; | |
| 114 | |
| 115 // Cached strength index of the network when the icon was last generated. | |
| 116 int strength_index_; | |
| 117 | |
| 118 // Cached technology badge for the network when the icon was last generated. | |
| 119 gfx::ImageSkia technology_badge_; | |
| 120 | |
| 121 // Cached vpn badge for the network when the icon was last generated. | |
| 122 gfx::ImageSkia vpn_badge_; | |
| 123 | |
| 124 // Cached roaming state of the network when the icon was last generated. | |
| 125 std::string roaming_state_; | |
| 126 | |
| 127 // Cached portal state of the network when the icon was last generated. | |
| 128 bool behind_captive_portal_; | |
| 129 | |
| 130 // Generated icon image. | |
| 131 gfx::ImageSkia image_; | |
| 132 | |
| 133 DISALLOW_COPY_AND_ASSIGN(NetworkIconImpl); | |
| 134 }; | |
| 135 | |
| 136 //------------------------------------------------------------------------------ | |
| 137 // Maintain a static (global) icon map. Note: Icons are never destroyed; | |
| 138 // it is assumed that a finite and reasonable number of network icons will be | |
| 139 // created during a session. | |
| 140 | |
| 141 typedef std::map<std::string, NetworkIconImpl*> NetworkIconMap; | |
| 142 | |
| 143 NetworkIconMap* GetIconMapInstance(IconType icon_type, bool create) { | |
| 144 typedef std::map<IconType, NetworkIconMap*> IconTypeMap; | |
| 145 static IconTypeMap* s_icon_map = nullptr; | |
| 146 if (s_icon_map == nullptr) { | |
| 147 if (!create) | |
| 148 return nullptr; | |
| 149 s_icon_map = new IconTypeMap; | |
| 150 } | |
| 151 if (s_icon_map->count(icon_type) == 0) { | |
| 152 if (!create) | |
| 153 return nullptr; | |
| 154 (*s_icon_map)[icon_type] = new NetworkIconMap; | |
| 155 } | |
| 156 return (*s_icon_map)[icon_type]; | |
| 157 } | |
| 158 | |
| 159 NetworkIconMap* GetIconMap(IconType icon_type) { | |
| 160 return GetIconMapInstance(icon_type, true); | |
| 161 } | |
| 162 | |
| 163 void PurgeIconMap(IconType icon_type, | |
| 164 const std::set<std::string>& network_paths) { | |
| 165 NetworkIconMap* icon_map = GetIconMapInstance(icon_type, false); | |
| 166 if (!icon_map) | |
| 167 return; | |
| 168 for (NetworkIconMap::iterator loop_iter = icon_map->begin(); | |
| 169 loop_iter != icon_map->end(); ) { | |
| 170 NetworkIconMap::iterator cur_iter = loop_iter++; | |
| 171 if (network_paths.count(cur_iter->first) == 0) { | |
| 172 delete cur_iter->second; | |
| 173 icon_map->erase(cur_iter); | |
| 174 } | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 //------------------------------------------------------------------------------ | |
| 179 // Utilities for generating icon images. | |
| 180 | |
| 181 // 'NONE' will default to ARCS behavior where appropriate (e.g. no network or | |
| 182 // if a new type gets added). | |
| 183 enum ImageType { | |
| 184 ARCS, | |
| 185 BARS, | |
| 186 NONE | |
| 187 }; | |
| 188 | |
| 189 // Amount to fade icons while connecting. | |
| 190 const double kConnectingImageAlpha = 0.5; | |
| 191 | |
| 192 // Images for strength arcs for wireless networks or strength bars for cellular | |
| 193 // networks. | |
| 194 const int kNumNetworkImages = 5; | |
| 195 | |
| 196 // Number of discrete images to use for alpha fade animation | |
| 197 const int kNumFadeImages = 10; | |
| 198 | |
| 199 SkColor GetDefaultColorForIconType(IconType icon_type) { | |
| 200 // TODO(estade): use kTrayIconColor and kMenuIconColor. | |
| 201 return icon_type == ICON_TYPE_TRAY ? SK_ColorWHITE : gfx::kChromeIconGrey; | |
| 202 } | |
| 203 | |
| 204 bool IconTypeIsDark(IconType icon_type) { | |
| 205 return (icon_type != ICON_TYPE_TRAY); | |
| 206 } | |
| 207 | |
| 208 bool IconTypeHasVPNBadge(IconType icon_type) { | |
| 209 return (icon_type != ICON_TYPE_LIST); | |
| 210 } | |
| 211 | |
| 212 // This defines how we assemble a network icon. | |
| 213 class NetworkIconImageSource : public gfx::CanvasImageSource { | |
| 214 public: | |
| 215 NetworkIconImageSource(const gfx::ImageSkia& icon, const Badges& badges) | |
| 216 : CanvasImageSource(icon.size(), false), icon_(icon), badges_(badges) {} | |
| 217 ~NetworkIconImageSource() override {} | |
| 218 | |
| 219 // TODO(pkotwicz): Figure out what to do when a new image resolution becomes | |
| 220 // available. | |
| 221 void Draw(gfx::Canvas* canvas) override { | |
| 222 canvas->DrawImageInt(icon_, 0, 0); | |
| 223 | |
| 224 if (!badges_.top_left.isNull()) | |
| 225 canvas->DrawImageInt(badges_.top_left, 0, 0); | |
| 226 if (!badges_.top_right.isNull()) | |
| 227 canvas->DrawImageInt(badges_.top_right, | |
| 228 icon_.width() - badges_.top_right.width(), 0); | |
| 229 if (!badges_.bottom_left.isNull()) { | |
| 230 canvas->DrawImageInt(badges_.bottom_left, 0, | |
| 231 icon_.height() - badges_.bottom_left.height()); | |
| 232 } | |
| 233 if (!badges_.bottom_right.isNull()) { | |
| 234 canvas->DrawImageInt(badges_.bottom_right, | |
| 235 icon_.width() - badges_.bottom_right.width(), | |
| 236 icon_.height() - badges_.bottom_right.height()); | |
| 237 } | |
| 238 } | |
| 239 | |
| 240 private: | |
| 241 const gfx::ImageSkia icon_; | |
| 242 const Badges badges_; | |
| 243 | |
| 244 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource); | |
| 245 }; | |
| 246 | |
| 247 // This defines how we assemble a network icon. | |
| 248 class NetworkIconImageSourceMd : public gfx::CanvasImageSource { | |
| 249 public: | |
| 250 static gfx::ImageSkia CreateImage(const gfx::ImageSkia& icon, | |
| 251 const Badges& badges) { | |
| 252 auto source = new NetworkIconImageSourceMd(icon, badges); | |
| 253 return gfx::ImageSkia(source, source->size()); | |
| 254 } | |
| 255 | |
| 256 // gfx::CanvasImageSource: | |
| 257 void Draw(gfx::Canvas* canvas) override { | |
| 258 const int width = size().width(); | |
| 259 const int height = size().height(); | |
| 260 | |
| 261 // The base icon is centered in both dimensions. | |
| 262 const int icon_y = (height - icon_.height()) / 2; | |
| 263 canvas->DrawImageInt(icon_, (width - icon_.width()) / 2, icon_y); | |
| 264 | |
| 265 // The badges are flush against the edges of the canvas, except at the top, | |
| 266 // where the badge is only 1dp higher than the base image. | |
| 267 const int top_badge_y = icon_y - 1; | |
| 268 if (!badges_.top_left.isNull()) | |
| 269 canvas->DrawImageInt(badges_.top_left, 0, top_badge_y); | |
| 270 if (!badges_.top_right.isNull()) { | |
| 271 canvas->DrawImageInt(badges_.top_right, width - badges_.top_right.width(), | |
| 272 top_badge_y); | |
| 273 } | |
| 274 if (!badges_.bottom_left.isNull()) { | |
| 275 canvas->DrawImageInt(badges_.bottom_left, 0, | |
| 276 height - badges_.bottom_left.height()); | |
| 277 } | |
| 278 if (!badges_.bottom_right.isNull()) { | |
| 279 canvas->DrawImageInt(badges_.bottom_right, | |
| 280 width - badges_.bottom_right.width(), | |
| 281 height - badges_.bottom_right.height()); | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 bool HasRepresentationAtAllScales() const override { return true; } | |
| 286 | |
| 287 private: | |
| 288 NetworkIconImageSourceMd(const gfx::ImageSkia& icon, const Badges& badges) | |
| 289 : CanvasImageSource(GetSizeForBaseIconSize(icon.size()), false), | |
| 290 icon_(icon), | |
| 291 badges_(badges) {} | |
| 292 ~NetworkIconImageSourceMd() override {} | |
| 293 | |
| 294 static gfx::Size GetSizeForBaseIconSize(const gfx::Size& base_icon_size) { | |
| 295 gfx::Size size = base_icon_size; | |
| 296 const int badge_offset = base_icon_size.width() == kTrayIconSide | |
| 297 ? kTrayIconBadgeOffset | |
| 298 : kMenuIconBadgeOffset; | |
| 299 size.Enlarge(badge_offset * 2, badge_offset * 2); | |
| 300 return size; | |
| 301 } | |
| 302 | |
| 303 const gfx::ImageSkia icon_; | |
| 304 const Badges badges_; | |
| 305 | |
| 306 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSourceMd); | |
| 307 }; | |
| 308 | |
| 309 // Depicts a given signal strength using arcs (e.g. for WiFi connections) or | |
| 310 // bars (e.g. for cell connections). | |
| 311 class SignalStrengthImageSource : public gfx::CanvasImageSource { | |
| 312 public: | |
| 313 SignalStrengthImageSource(ImageType image_type, | |
| 314 IconType icon_type, | |
| 315 int signal_strength) | |
| 316 : CanvasImageSource(GetSizeForIconType(icon_type), false), | |
| 317 image_type_(image_type), | |
| 318 icon_type_(icon_type), | |
| 319 color_(GetDefaultColorForIconType(icon_type_)), | |
| 320 signal_strength_(signal_strength) { | |
| 321 if (image_type_ == NONE) | |
| 322 image_type_ = ARCS; | |
| 323 | |
| 324 DCHECK_GE(signal_strength, 0); | |
| 325 DCHECK_LT(signal_strength, kNumNetworkImages); | |
| 326 } | |
| 327 ~SignalStrengthImageSource() override {} | |
| 328 | |
| 329 void set_color(SkColor color) { color_ = color; } | |
| 330 | |
| 331 // gfx::CanvasImageSource: | |
| 332 void Draw(gfx::Canvas* canvas) override { | |
| 333 if (image_type_ == ARCS) | |
| 334 DrawArcs(canvas); | |
| 335 else | |
| 336 DrawBars(canvas); | |
| 337 } | |
| 338 | |
| 339 bool HasRepresentationAtAllScales() const override { | |
| 340 return true; | |
| 341 } | |
| 342 | |
| 343 private: | |
| 344 static gfx::Size GetSizeForIconType(IconType icon_type) { | |
| 345 return icon_type == ICON_TYPE_TRAY | |
| 346 ? gfx::Size(kTrayIconSide, kTrayIconSide) | |
| 347 // TODO(estade): use kMenuIconSize instead of 20. | |
| 348 : gfx::Size(20, 20); | |
| 349 } | |
| 350 | |
| 351 void DrawArcs(gfx::Canvas* canvas) { | |
| 352 gfx::RectF oval_bounds((gfx::Rect(size()))); | |
| 353 oval_bounds.Inset(gfx::Insets(kIconInset)); | |
| 354 // Double the width and height. The new midpoint should be the former | |
| 355 // bottom center. | |
| 356 oval_bounds.Inset(-oval_bounds.width() / 2, 0, -oval_bounds.width() / 2, | |
| 357 -oval_bounds.height()); | |
| 358 | |
| 359 const SkScalar kAngleAboveHorizontal = 51.f; | |
| 360 const SkScalar kStartAngle = 180.f + kAngleAboveHorizontal; | |
| 361 const SkScalar kSweepAngle = 180.f - 2 * kAngleAboveHorizontal; | |
| 362 | |
| 363 SkPaint paint; | |
| 364 paint.setAntiAlias(true); | |
| 365 paint.setStyle(SkPaint::kFill_Style); | |
| 366 // Background. Skip drawing for full signal. | |
| 367 if (signal_strength_ != kNumNetworkImages - 1) { | |
| 368 paint.setColor(SkColorSetA(color_, kBgAlpha)); | |
| 369 canvas->sk_canvas()->drawArc(gfx::RectFToSkRect(oval_bounds), kStartAngle, | |
| 370 kSweepAngle, true, paint); | |
| 371 } | |
| 372 // Foreground (signal strength). | |
| 373 if (signal_strength_ != 0) { | |
| 374 paint.setColor(color_); | |
| 375 // Percent of the height of the background wedge that we draw the | |
| 376 // foreground wedge, indexed by signal strength. | |
| 377 static const float kWedgeHeightPercentages[] = {0.f, 0.375f, 0.5833f, | |
| 378 0.75f, 1.f}; | |
| 379 const float wedge_percent = kWedgeHeightPercentages[signal_strength_]; | |
| 380 oval_bounds.Inset( | |
| 381 gfx::InsetsF((oval_bounds.height() / 2) * (1.f - wedge_percent))); | |
| 382 canvas->sk_canvas()->drawArc(gfx::RectFToSkRect(oval_bounds), kStartAngle, | |
| 383 kSweepAngle, true, paint); | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 void DrawBars(gfx::Canvas* canvas) { | |
| 388 // Undo the canvas's device scaling and round values to the nearest whole | |
| 389 // number so we can draw on exact pixel boundaries. | |
| 390 const float dsf = canvas->UndoDeviceScaleFactor(); | |
| 391 auto scale = [dsf](SkScalar dimension) { | |
| 392 return std::round(dimension * dsf); | |
| 393 }; | |
| 394 | |
| 395 // Length of short side of an isosceles right triangle, in dip. | |
| 396 const SkScalar kFullTriangleSide = | |
| 397 SkIntToScalar(size().width()) - kIconInset * 2; | |
| 398 | |
| 399 auto make_triangle = [scale, kFullTriangleSide](SkScalar side) { | |
| 400 SkPath triangle; | |
| 401 triangle.moveTo(scale(kIconInset), scale(kIconInset + kFullTriangleSide)); | |
| 402 triangle.rLineTo(scale(side), 0); | |
| 403 triangle.rLineTo(0, -scale(side)); | |
| 404 triangle.close(); | |
| 405 return triangle; | |
| 406 }; | |
| 407 | |
| 408 SkPaint paint; | |
| 409 paint.setAntiAlias(true); | |
| 410 paint.setStyle(SkPaint::kFill_Style); | |
| 411 // Background. Skip drawing for full signal. | |
| 412 if (signal_strength_ != kNumNetworkImages - 1) { | |
| 413 paint.setColor(SkColorSetA(color_, kBgAlpha)); | |
| 414 canvas->DrawPath(make_triangle(kFullTriangleSide), paint); | |
| 415 } | |
| 416 // Foreground (signal strength). | |
| 417 if (signal_strength_ != 0) { | |
| 418 paint.setColor(color_); | |
| 419 // As a percentage of the bg triangle, the length of one of the short | |
| 420 // sides of the fg triangle, indexed by signal strength. | |
| 421 static const float kTriangleSidePercents[] = {0.f, 0.5f, 0.625f, 0.75f, | |
| 422 1.f}; | |
| 423 canvas->DrawPath(make_triangle(kTriangleSidePercents[signal_strength_] * | |
| 424 kFullTriangleSide), | |
| 425 paint); | |
| 426 } | |
| 427 } | |
| 428 | |
| 429 ImageType image_type_; | |
| 430 IconType icon_type_; | |
| 431 SkColor color_; | |
| 432 | |
| 433 // On a scale of 0 to kNum{Arcs,Bars}Images - 1, how connected we are. | |
| 434 int signal_strength_; | |
| 435 | |
| 436 // Padding between outside of icon and edge of the canvas, in dp. This value | |
| 437 // stays the same regardless of the canvas size (which depends on | |
| 438 // |icon_type_|). | |
| 439 static constexpr int kIconInset = 2; | |
| 440 | |
| 441 // TODO(estade): share this alpha with other things in ash (battery, etc.). | |
| 442 // See crbug.com/623987 and crbug.com/632827 | |
| 443 static constexpr int kBgAlpha = 0x4D; | |
| 444 | |
| 445 DISALLOW_COPY_AND_ASSIGN(SignalStrengthImageSource); | |
| 446 }; | |
| 447 | |
| 448 //------------------------------------------------------------------------------ | |
| 449 // Utilities for extracting icon images. | |
| 450 | |
| 451 gfx::ImageSkia* BaseImageForType(ImageType image_type, IconType icon_type) { | |
| 452 gfx::ImageSkia* image; | |
| 453 if (image_type == BARS) { | |
| 454 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 455 IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_BARS_DARK | |
| 456 : IDR_AURA_UBER_TRAY_NETWORK_BARS_LIGHT); | |
| 457 } else { | |
| 458 image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 459 IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_ARCS_DARK | |
| 460 : IDR_AURA_UBER_TRAY_NETWORK_ARCS_LIGHT); | |
| 461 } | |
| 462 return image; | |
| 463 } | |
| 464 | |
| 465 ImageType ImageTypeForNetworkType(const std::string& type) { | |
| 466 if (type == shill::kTypeWifi) | |
| 467 return ARCS; | |
| 468 else if (type == shill::kTypeCellular || type == shill::kTypeWimax) | |
| 469 return BARS; | |
| 470 return NONE; | |
| 471 } | |
| 472 | |
| 473 gfx::ImageSkia GetImageForIndex(ImageType image_type, | |
| 474 IconType icon_type, | |
| 475 int index) { | |
| 476 if (UseMd()) { | |
| 477 gfx::CanvasImageSource* source = | |
| 478 new SignalStrengthImageSource(image_type, icon_type, index); | |
| 479 return gfx::ImageSkia(source, source->size()); | |
| 480 } | |
| 481 | |
| 482 if (index < 0 || index >= kNumNetworkImages) | |
| 483 return gfx::ImageSkia(); | |
| 484 gfx::ImageSkia* images = BaseImageForType(image_type, icon_type); | |
| 485 int width = images->width(); | |
| 486 int height = images->height() / kNumNetworkImages; | |
| 487 return gfx::ImageSkiaOperations::ExtractSubset(*images, | |
| 488 gfx::Rect(0, index * height, width, height)); | |
| 489 } | |
| 490 | |
| 491 const gfx::ImageSkia GetDisconnectedImage(IconType icon_type, | |
| 492 const std::string& network_type) { | |
| 493 DCHECK_NE(shill::kTypeVPN, network_type); | |
| 494 ImageType image_type = ImageTypeForNetworkType(network_type); | |
| 495 const int disconnected_index = 0; | |
| 496 return GetImageForIndex(image_type, icon_type, disconnected_index); | |
| 497 } | |
| 498 | |
| 499 gfx::ImageSkia* ConnectingWirelessImage(ImageType image_type, | |
| 500 IconType icon_type, | |
| 501 double animation) { | |
| 502 static const int kImageCount = kNumNetworkImages - 1; | |
| 503 static gfx::ImageSkia* s_bars_images_dark[kImageCount]; | |
| 504 static gfx::ImageSkia* s_bars_images_light[kImageCount]; | |
| 505 static gfx::ImageSkia* s_arcs_images_dark[kImageCount]; | |
| 506 static gfx::ImageSkia* s_arcs_images_light[kImageCount]; | |
| 507 int index = animation * nextafter(static_cast<float>(kImageCount), 0); | |
| 508 index = std::max(std::min(index, kImageCount - 1), 0); | |
| 509 gfx::ImageSkia** images; | |
| 510 bool dark = IconTypeIsDark(icon_type); | |
| 511 if (image_type == BARS) | |
| 512 images = dark ? s_bars_images_dark : s_bars_images_light; | |
| 513 else | |
| 514 images = dark ? s_arcs_images_dark : s_arcs_images_light; | |
| 515 if (!images[index]) { | |
| 516 // Lazily cache images. | |
| 517 // TODO(estade): should the alpha be applied in SignalStrengthImageSource? | |
| 518 gfx::ImageSkia source = GetImageForIndex(image_type, icon_type, index + 1); | |
| 519 images[index] = | |
| 520 new gfx::ImageSkia(gfx::ImageSkiaOperations::CreateTransparentImage( | |
| 521 source, kConnectingImageAlpha)); | |
| 522 } | |
| 523 return images[index]; | |
| 524 } | |
| 525 | |
| 526 gfx::ImageSkia ConnectingVpnImage(double animation) { | |
| 527 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0); | |
| 528 static gfx::ImageSkia* s_vpn_images[kNumFadeImages]; | |
| 529 if (!s_vpn_images[index]) { | |
| 530 // Lazily cache images. | |
| 531 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 532 gfx::ImageSkia* icon = rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_VPN); | |
| 533 s_vpn_images[index] = new gfx::ImageSkia( | |
| 534 gfx::ImageSkiaOperations::CreateTransparentImage(*icon, animation)); | |
| 535 } | |
| 536 return *s_vpn_images[index]; | |
| 537 } | |
| 538 | |
| 539 gfx::ImageSkia ConnectingVpnBadge(double animation, IconType icon_type) { | |
| 540 int index = animation * nextafter(static_cast<float>(kNumFadeImages), 0); | |
| 541 static gfx::ImageSkia* s_vpn_badges[kNumFadeImages]; | |
| 542 if (!s_vpn_badges[index]) { | |
| 543 // Lazily cache images. | |
| 544 gfx::ImageSkia badge = | |
| 545 UseMd() ? gfx::CreateVectorIcon(gfx::VectorIconId::NETWORK_BADGE_VPN, | |
| 546 GetDefaultColorForIconType(icon_type)) | |
| 547 : *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 548 IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE); | |
| 549 s_vpn_badges[index] = new gfx::ImageSkia( | |
| 550 gfx::ImageSkiaOperations::CreateTransparentImage(badge, animation)); | |
| 551 } | |
| 552 return *s_vpn_badges[index]; | |
| 553 } | |
| 554 | |
| 555 int StrengthIndex(int strength) { | |
| 556 // Return an index in the range [1, kNumNetworkImages - 1]. | |
| 557 const float findex = (static_cast<float>(strength) / 100.0f) * | |
| 558 nextafter(static_cast<float>(kNumNetworkImages - 1), 0); | |
| 559 int index = 1 + static_cast<int>(findex); | |
| 560 index = std::max(std::min(index, kNumNetworkImages - 1), 1); | |
| 561 return index; | |
| 562 } | |
| 563 | |
| 564 gfx::ImageSkia BadgeForNetworkTechnology(const NetworkState* network, | |
| 565 IconType icon_type) { | |
| 566 const std::string& technology = network->network_technology(); | |
| 567 if (UseMd()) { | |
| 568 gfx::VectorIconId id = gfx::VectorIconId::VECTOR_ICON_NONE; | |
| 569 if (technology == shill::kNetworkTechnologyEvdo) { | |
| 570 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_EVDO; | |
| 571 } else if (technology == shill::kNetworkTechnology1Xrtt) { | |
| 572 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_1X; | |
| 573 } else if (technology == shill::kNetworkTechnologyGprs || | |
| 574 technology == shill::kNetworkTechnologyGsm) { | |
| 575 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_GPRS; | |
| 576 } else if (technology == shill::kNetworkTechnologyEdge) { | |
| 577 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_EDGE; | |
| 578 } else if (technology == shill::kNetworkTechnologyUmts) { | |
| 579 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_3G; | |
| 580 } else if (technology == shill::kNetworkTechnologyHspa) { | |
| 581 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_HSPA; | |
| 582 } else if (technology == shill::kNetworkTechnologyHspaPlus) { | |
| 583 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_HSPA_PLUS; | |
| 584 } else if (technology == shill::kNetworkTechnologyLte) { | |
| 585 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_LTE; | |
| 586 } else if (technology == shill::kNetworkTechnologyLteAdvanced) { | |
| 587 id = gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_LTE_ADVANCED; | |
| 588 } else { | |
| 589 return gfx::ImageSkia(); | |
| 590 } | |
| 591 return gfx::CreateVectorIcon(id, GetDefaultColorForIconType(icon_type)); | |
| 592 } | |
| 593 | |
| 594 int id = -1; | |
| 595 if (technology == shill::kNetworkTechnologyEvdo) { | |
| 596 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK | |
| 597 : IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT; | |
| 598 } else if (technology == shill::kNetworkTechnology1Xrtt) { | |
| 599 id = IDR_AURA_UBER_TRAY_NETWORK_1X; | |
| 600 } else if (technology == shill::kNetworkTechnologyGprs) { | |
| 601 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK | |
| 602 : IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT; | |
| 603 } else if (technology == shill::kNetworkTechnologyEdge) { | |
| 604 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_EDGE_DARK | |
| 605 : IDR_AURA_UBER_TRAY_NETWORK_EDGE_LIGHT; | |
| 606 } else if (technology == shill::kNetworkTechnologyUmts) { | |
| 607 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_3G_DARK | |
| 608 : IDR_AURA_UBER_TRAY_NETWORK_3G_LIGHT; | |
| 609 } else if (technology == shill::kNetworkTechnologyHspa) { | |
| 610 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_HSPA_DARK | |
| 611 : IDR_AURA_UBER_TRAY_NETWORK_HSPA_LIGHT; | |
| 612 } else if (technology == shill::kNetworkTechnologyHspaPlus) { | |
| 613 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_DARK | |
| 614 : IDR_AURA_UBER_TRAY_NETWORK_HSPA_PLUS_LIGHT; | |
| 615 } else if (technology == shill::kNetworkTechnologyLte) { | |
| 616 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_LTE_DARK | |
| 617 : IDR_AURA_UBER_TRAY_NETWORK_LTE_LIGHT; | |
| 618 } else if (technology == shill::kNetworkTechnologyLteAdvanced) { | |
| 619 id = IconTypeIsDark(icon_type) | |
| 620 ? IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_DARK | |
| 621 : IDR_AURA_UBER_TRAY_NETWORK_LTE_ADVANCED_LIGHT; | |
| 622 } else if (technology == shill::kNetworkTechnologyGsm) { | |
| 623 id = IconTypeIsDark(icon_type) ? IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK | |
| 624 : IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT; | |
| 625 } else { | |
| 626 return gfx::ImageSkia(); | |
| 627 } | |
| 628 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id); | |
| 629 } | |
| 630 | |
| 631 gfx::ImageSkia GetIcon(const NetworkState* network, | |
| 632 IconType icon_type, | |
| 633 int strength_index) { | |
| 634 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 635 if (network->Matches(NetworkTypePattern::Ethernet())) { | |
| 636 DCHECK_NE(ICON_TYPE_TRAY, icon_type); | |
| 637 return UseMd() ? gfx::CreateVectorIcon( | |
| 638 gfx::VectorIconId::NETWORK_ETHERNET, | |
| 639 GetDefaultColorForIconType(ICON_TYPE_LIST)) | |
| 640 : *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_WIRED); | |
| 641 } else if (network->Matches(NetworkTypePattern::Wireless())) { | |
| 642 DCHECK(strength_index > 0); | |
| 643 return GetImageForIndex(ImageTypeForNetworkType(network->type()), icon_type, | |
| 644 strength_index); | |
| 645 } else if (network->Matches(NetworkTypePattern::VPN())) { | |
| 646 DCHECK_NE(ICON_TYPE_TRAY, icon_type); | |
| 647 return GetVpnImage(); | |
| 648 } | |
| 649 | |
| 650 NOTREACHED() << "Request for icon for unsupported type: " << network->type(); | |
| 651 return gfx::ImageSkia(); | |
| 652 } | |
| 653 | |
| 654 //------------------------------------------------------------------------------ | |
| 655 // Get connecting images | |
| 656 | |
| 657 gfx::ImageSkia GetConnectingVpnImage(IconType icon_type) { | |
| 658 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); | |
| 659 const NetworkState* connected_network = nullptr; | |
| 660 if (icon_type == ICON_TYPE_TRAY) { | |
| 661 connected_network = | |
| 662 handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual()); | |
| 663 } | |
| 664 double animation = NetworkIconAnimation::GetInstance()->GetAnimation(); | |
| 665 | |
| 666 gfx::ImageSkia icon; | |
| 667 Badges badges; | |
| 668 if (connected_network) { | |
| 669 icon = GetImageForNetwork(connected_network, icon_type); | |
| 670 badges.bottom_left = ConnectingVpnBadge(animation, icon_type); | |
| 671 } else { | |
| 672 icon = ConnectingVpnImage(animation); | |
| 673 } | |
| 674 return UseMd() ? NetworkIconImageSourceMd::CreateImage(icon, badges) | |
| 675 : gfx::ImageSkia(new NetworkIconImageSource(icon, badges), | |
| 676 icon.size()); | |
| 677 } | |
| 678 | |
| 679 gfx::ImageSkia GetConnectingImage(IconType icon_type, | |
| 680 const std::string& network_type) { | |
| 681 if (network_type == shill::kTypeVPN) | |
| 682 return GetConnectingVpnImage(icon_type); | |
| 683 | |
| 684 ImageType image_type = ImageTypeForNetworkType(network_type); | |
| 685 double animation = NetworkIconAnimation::GetInstance()->GetAnimation(); | |
| 686 | |
| 687 gfx::ImageSkia* icon = ConnectingWirelessImage( | |
| 688 image_type, icon_type, animation); | |
| 689 return UseMd() ? NetworkIconImageSourceMd::CreateImage(*icon, Badges()) | |
| 690 : gfx::ImageSkia(new NetworkIconImageSource(*icon, Badges()), | |
| 691 icon->size()); | |
| 692 } | |
| 693 | |
| 694 } // namespace | |
| 695 | |
| 696 //------------------------------------------------------------------------------ | |
| 697 // NetworkIconImpl | |
| 698 | |
| 699 NetworkIconImpl::NetworkIconImpl(const std::string& path, IconType icon_type) | |
| 700 : network_path_(path), | |
| 701 icon_type_(icon_type), | |
| 702 strength_index_(-1), | |
| 703 behind_captive_portal_(false) { | |
| 704 // Default image | |
| 705 image_ = GetDisconnectedImage(icon_type, shill::kTypeWifi); | |
| 706 } | |
| 707 | |
| 708 void NetworkIconImpl::Update(const NetworkState* network) { | |
| 709 DCHECK(network); | |
| 710 // Determine whether or not we need to update the icon. | |
| 711 bool dirty = image_.isNull(); | |
| 712 | |
| 713 // If the network state has changed, the icon needs updating. | |
| 714 if (state_ != network->connection_state()) { | |
| 715 state_ = network->connection_state(); | |
| 716 dirty = true; | |
| 717 } | |
| 718 | |
| 719 dirty |= UpdatePortalState(network); | |
| 720 | |
| 721 if (network->Matches(NetworkTypePattern::Wireless())) { | |
| 722 dirty |= UpdateWirelessStrengthIndex(network); | |
| 723 } | |
| 724 | |
| 725 if (network->Matches(NetworkTypePattern::Cellular())) | |
| 726 dirty |= UpdateCellularState(network); | |
| 727 | |
| 728 if (IconTypeHasVPNBadge(icon_type_) && | |
| 729 network->Matches(NetworkTypePattern::NonVirtual())) { | |
| 730 dirty |= UpdateVPNBadge(); | |
| 731 } | |
| 732 | |
| 733 if (dirty) { | |
| 734 // Set the icon and badges based on the network and generate the image. | |
| 735 GenerateImage(network); | |
| 736 } | |
| 737 } | |
| 738 | |
| 739 bool NetworkIconImpl::UpdateWirelessStrengthIndex(const NetworkState* network) { | |
| 740 int index = StrengthIndex(network->signal_strength()); | |
| 741 if (index != strength_index_) { | |
| 742 strength_index_ = index; | |
| 743 return true; | |
| 744 } | |
| 745 return false; | |
| 746 } | |
| 747 | |
| 748 bool NetworkIconImpl::UpdateCellularState(const NetworkState* network) { | |
| 749 bool dirty = false; | |
| 750 const gfx::ImageSkia technology_badge = | |
| 751 BadgeForNetworkTechnology(network, icon_type_); | |
| 752 if (!technology_badge.BackedBySameObjectAs(technology_badge_)) { | |
| 753 technology_badge_ = technology_badge; | |
| 754 dirty = true; | |
| 755 } | |
| 756 std::string roaming_state = network->roaming(); | |
| 757 if (roaming_state != roaming_state_) { | |
| 758 roaming_state_ = roaming_state; | |
| 759 dirty = true; | |
| 760 } | |
| 761 return dirty; | |
| 762 } | |
| 763 | |
| 764 bool NetworkIconImpl::UpdatePortalState(const NetworkState* network) { | |
| 765 bool behind_captive_portal = false; | |
| 766 if (network && chromeos::network_portal_detector::IsInitialized()) { | |
| 767 NetworkPortalDetector::CaptivePortalState state = | |
| 768 chromeos::network_portal_detector::GetInstance()->GetCaptivePortalState( | |
| 769 network->guid()); | |
| 770 behind_captive_portal = | |
| 771 state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL; | |
| 772 } | |
| 773 | |
| 774 if (behind_captive_portal == behind_captive_portal_) | |
| 775 return false; | |
| 776 behind_captive_portal_ = behind_captive_portal; | |
| 777 return true; | |
| 778 } | |
| 779 | |
| 780 bool NetworkIconImpl::UpdateVPNBadge() { | |
| 781 const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> | |
| 782 ConnectedNetworkByType(NetworkTypePattern::VPN()); | |
| 783 if (vpn && vpn_badge_.isNull()) { | |
| 784 vpn_badge_ = | |
| 785 UseMd() ? gfx::CreateVectorIcon(gfx::VectorIconId::NETWORK_BADGE_VPN, | |
| 786 GetDefaultColorForIconType(icon_type_)) | |
| 787 : *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 788 IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE); | |
| 789 return true; | |
| 790 } | |
| 791 if (!vpn && !vpn_badge_.isNull()) { | |
| 792 vpn_badge_ = gfx::ImageSkia(); | |
| 793 return true; | |
| 794 } | |
| 795 return false; | |
| 796 } | |
| 797 | |
| 798 void NetworkIconImpl::GetBadges(const NetworkState* network, Badges* badges) { | |
| 799 DCHECK(network); | |
| 800 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 801 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); | |
| 802 | |
| 803 const std::string& type = network->type(); | |
| 804 const SkColor icon_color = GetDefaultColorForIconType(icon_type_); | |
| 805 if (type == shill::kTypeWifi) { | |
| 806 if (network->security_class() != shill::kSecurityNone && | |
| 807 IconTypeIsDark(icon_type_)) { | |
| 808 badges->bottom_right = | |
| 809 UseMd() | |
| 810 ? gfx::CreateVectorIcon(gfx::VectorIconId::NETWORK_BADGE_SECURE, | |
| 811 icon_color) | |
| 812 : *rb.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_NETWORK_SECURE_DARK); | |
| 813 } | |
| 814 } else if (type == shill::kTypeWimax) { | |
| 815 technology_badge_ = | |
| 816 UseMd() | |
| 817 ? gfx::CreateVectorIcon( | |
| 818 gfx::VectorIconId::NETWORK_BADGE_TECHNOLOGY_4G, icon_color) | |
| 819 : *rb.GetImageSkiaNamed(IconTypeIsDark(icon_type_) | |
| 820 ? IDR_AURA_UBER_TRAY_NETWORK_4G_DARK | |
| 821 : IDR_AURA_UBER_TRAY_NETWORK_4G_LIGHT); | |
| 822 } else if (type == shill::kTypeCellular) { | |
| 823 if (network->roaming() == shill::kRoamingStateRoaming) { | |
| 824 // For networks that are always in roaming don't show roaming badge. | |
| 825 const DeviceState* device = | |
| 826 handler->GetDeviceState(network->device_path()); | |
| 827 LOG_IF(WARNING, !device) << "Could not find device state for " | |
| 828 << network->device_path(); | |
| 829 if (!device || !device->provider_requires_roaming()) { | |
| 830 badges->bottom_right = | |
| 831 UseMd() ? gfx::CreateVectorIcon( | |
| 832 gfx::VectorIconId::NETWORK_BADGE_ROAMING, icon_color) | |
| 833 : *rb.GetImageSkiaNamed( | |
| 834 IconTypeIsDark(icon_type_) | |
| 835 ? IDR_AURA_UBER_TRAY_NETWORK_ROAMING_DARK | |
| 836 : IDR_AURA_UBER_TRAY_NETWORK_ROAMING_LIGHT); | |
| 837 } | |
| 838 } | |
| 839 } | |
| 840 if (!network->IsConnectingState()) { | |
| 841 badges->top_left = technology_badge_; | |
| 842 badges->bottom_left = vpn_badge_; | |
| 843 } | |
| 844 | |
| 845 if (behind_captive_portal_) { | |
| 846 badges->bottom_right = | |
| 847 UseMd() | |
| 848 ? gfx::CreateVectorIcon( | |
| 849 gfx::VectorIconId::NETWORK_BADGE_CAPTIVE_PORTAL, icon_color) | |
| 850 : *rb.GetImageSkiaNamed( | |
| 851 IconTypeIsDark(icon_type_) | |
| 852 ? IDR_AURA_UBER_TRAY_NETWORK_PORTAL_DARK | |
| 853 : IDR_AURA_UBER_TRAY_NETWORK_PORTAL_LIGHT); | |
| 854 } | |
| 855 } | |
| 856 | |
| 857 void NetworkIconImpl::GenerateImage(const NetworkState* network) { | |
| 858 DCHECK(network); | |
| 859 gfx::ImageSkia icon = GetIcon(network, icon_type_, strength_index_); | |
| 860 Badges badges; | |
| 861 GetBadges(network, &badges); | |
| 862 image_ = UseMd() ? NetworkIconImageSourceMd::CreateImage(icon, badges) | |
| 863 : gfx::ImageSkia(new NetworkIconImageSource(icon, badges), | |
| 864 icon.size()); | |
| 865 } | |
| 866 | |
| 867 namespace { | |
| 868 | |
| 869 NetworkIconImpl* FindAndUpdateImageImpl(const NetworkState* network, | |
| 870 IconType icon_type) { | |
| 871 // Find or add the icon. | |
| 872 NetworkIconMap* icon_map = GetIconMap(icon_type); | |
| 873 NetworkIconImpl* icon; | |
| 874 NetworkIconMap::iterator iter = icon_map->find(network->path()); | |
| 875 if (iter == icon_map->end()) { | |
| 876 icon = new NetworkIconImpl(network->path(), icon_type); | |
| 877 icon_map->insert(std::make_pair(network->path(), icon)); | |
| 878 } else { | |
| 879 icon = iter->second; | |
| 880 } | |
| 881 | |
| 882 // Update and return the icon's image. | |
| 883 icon->Update(network); | |
| 884 return icon; | |
| 885 } | |
| 886 | |
| 887 } // namespace | |
| 888 | |
| 889 //------------------------------------------------------------------------------ | |
| 890 // Public interface | |
| 891 | |
| 892 gfx::ImageSkia GetImageForNetwork(const NetworkState* network, | |
| 893 IconType icon_type) { | |
| 894 DCHECK(network); | |
| 895 if (!network->visible()) | |
| 896 return GetDisconnectedImage(icon_type, network->type()); | |
| 897 | |
| 898 if (network->IsConnectingState()) | |
| 899 return GetConnectingImage(icon_type, network->type()); | |
| 900 | |
| 901 NetworkIconImpl* icon = FindAndUpdateImageImpl(network, icon_type); | |
| 902 return icon->image(); | |
| 903 } | |
| 904 | |
| 905 gfx::ImageSkia GetImageForConnectedMobileNetwork() { | |
| 906 ImageType image_type = ImageTypeForNetworkType(shill::kTypeWifi); | |
| 907 const IconType icon_type = ICON_TYPE_LIST; | |
| 908 const int connected_index = kNumNetworkImages - 1; | |
| 909 return GetImageForIndex(image_type, icon_type, connected_index); | |
| 910 } | |
| 911 | |
| 912 gfx::ImageSkia GetImageForDisconnectedCellNetwork() { | |
| 913 return GetDisconnectedImage(ICON_TYPE_LIST, shill::kTypeCellular); | |
| 914 } | |
| 915 | |
| 916 gfx::ImageSkia GetImageForNewWifiNetwork(SkColor icon_color, | |
| 917 SkColor badge_color) { | |
| 918 SignalStrengthImageSource* source = | |
| 919 new SignalStrengthImageSource(ImageTypeForNetworkType(shill::kTypeWifi), | |
| 920 ICON_TYPE_LIST, kNumNetworkImages - 1); | |
| 921 source->set_color(icon_color); | |
| 922 gfx::ImageSkia icon = gfx::ImageSkia(source, source->size()); | |
| 923 Badges badges; | |
| 924 badges.bottom_right = gfx::CreateVectorIcon( | |
| 925 gfx::VectorIconId::NETWORK_BADGE_ADD_OTHER, badge_color); | |
| 926 return NetworkIconImageSourceMd::CreateImage(icon, badges); | |
| 927 } | |
| 928 | |
| 929 gfx::ImageSkia GetVpnImage() { | |
| 930 return UseMd() | |
| 931 ? gfx::CreateVectorIcon(gfx::VectorIconId::NETWORK_VPN, | |
| 932 GetDefaultColorForIconType(ICON_TYPE_LIST)) | |
| 933 : *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 934 IDR_AURA_UBER_TRAY_NETWORK_VPN); | |
| 935 } | |
| 936 | |
| 937 base::string16 GetLabelForNetwork(const chromeos::NetworkState* network, | |
| 938 IconType icon_type) { | |
| 939 DCHECK(network); | |
| 940 std::string activation_state = network->activation_state(); | |
| 941 if (icon_type == ICON_TYPE_LIST) { | |
| 942 // Show "<network>: [Connecting|Activating|Reconnecting]..." | |
| 943 if (network->IsReconnecting()) { | |
| 944 return l10n_util::GetStringFUTF16( | |
| 945 IDS_ASH_STATUS_TRAY_NETWORK_LIST_RECONNECTING, | |
| 946 base::UTF8ToUTF16(network->name())); | |
| 947 } | |
| 948 if (network->IsConnectingState()) { | |
| 949 return l10n_util::GetStringFUTF16( | |
| 950 IDS_ASH_STATUS_TRAY_NETWORK_LIST_CONNECTING, | |
| 951 base::UTF8ToUTF16(network->name())); | |
| 952 } | |
| 953 if (activation_state == shill::kActivationStateActivating) { | |
| 954 return l10n_util::GetStringFUTF16( | |
| 955 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING, | |
| 956 base::UTF8ToUTF16(network->name())); | |
| 957 } | |
| 958 // Show "Activate <network>" in list view only. | |
| 959 if (activation_state == shill::kActivationStateNotActivated || | |
| 960 activation_state == shill::kActivationStatePartiallyActivated) { | |
| 961 return l10n_util::GetStringFUTF16( | |
| 962 IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE, | |
| 963 base::UTF8ToUTF16(network->name())); | |
| 964 } | |
| 965 } else { | |
| 966 // Show "[Connected to|Connecting to|Activating|Reconnecting to] <network>" | |
| 967 // (non-list view). | |
| 968 if (network->IsReconnecting()) { | |
| 969 return l10n_util::GetStringFUTF16( | |
| 970 IDS_ASH_STATUS_TRAY_NETWORK_RECONNECTING, | |
| 971 base::UTF8ToUTF16(network->name())); | |
| 972 } | |
| 973 if (network->IsConnectedState()) { | |
| 974 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, | |
| 975 base::UTF8ToUTF16(network->name())); | |
| 976 } | |
| 977 if (network->IsConnectingState()) { | |
| 978 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING, | |
| 979 base::UTF8ToUTF16(network->name())); | |
| 980 } | |
| 981 if (activation_state == shill::kActivationStateActivating) { | |
| 982 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING, | |
| 983 base::UTF8ToUTF16(network->name())); | |
| 984 } | |
| 985 } | |
| 986 | |
| 987 // Otherwise just show the network name or 'Ethernet'. | |
| 988 if (network->Matches(NetworkTypePattern::Ethernet())) { | |
| 989 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET); | |
| 990 } else { | |
| 991 return base::UTF8ToUTF16(network->name()); | |
| 992 } | |
| 993 } | |
| 994 | |
| 995 int GetCellularUninitializedMsg() { | |
| 996 static base::Time s_uninitialized_state_time; | |
| 997 static int s_uninitialized_msg(0); | |
| 998 | |
| 999 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); | |
| 1000 if (handler->GetTechnologyState(NetworkTypePattern::Mobile()) | |
| 1001 == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) { | |
| 1002 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR; | |
| 1003 s_uninitialized_state_time = base::Time::Now(); | |
| 1004 return s_uninitialized_msg; | |
| 1005 } else if (handler->GetScanningByType(NetworkTypePattern::Mobile())) { | |
| 1006 s_uninitialized_msg = IDS_ASH_STATUS_TRAY_CELLULAR_SCANNING; | |
| 1007 s_uninitialized_state_time = base::Time::Now(); | |
| 1008 return s_uninitialized_msg; | |
| 1009 } | |
| 1010 // There can be a delay between leaving the Initializing state and when | |
| 1011 // a Cellular device shows up, so keep showing the initializing | |
| 1012 // animation for a bit to avoid flashing the disconnect icon. | |
| 1013 const int kInitializingDelaySeconds = 1; | |
| 1014 base::TimeDelta dtime = base::Time::Now() - s_uninitialized_state_time; | |
| 1015 if (dtime.InSeconds() < kInitializingDelaySeconds) | |
| 1016 return s_uninitialized_msg; | |
| 1017 return 0; | |
| 1018 } | |
| 1019 | |
| 1020 void GetDefaultNetworkImageAndLabel(IconType icon_type, | |
| 1021 gfx::ImageSkia* image, | |
| 1022 base::string16* label, | |
| 1023 bool* animating) { | |
| 1024 NetworkStateHandler* state_handler = | |
| 1025 NetworkHandler::Get()->network_state_handler(); | |
| 1026 NetworkConnectionHandler* connect_handler = | |
| 1027 NetworkHandler::Get()->network_connection_handler(); | |
| 1028 const NetworkState* connected_network = | |
| 1029 state_handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual()); | |
| 1030 const NetworkState* connecting_network = | |
| 1031 state_handler->ConnectingNetworkByType(NetworkTypePattern::Wireless()); | |
| 1032 if (!connecting_network && icon_type == ICON_TYPE_TRAY) { | |
| 1033 connecting_network = | |
| 1034 state_handler->ConnectingNetworkByType(NetworkTypePattern::VPN()); | |
| 1035 } | |
| 1036 | |
| 1037 const NetworkState* network; | |
| 1038 // If we are connecting to a network, and there is either no connected | |
| 1039 // network, or the connection was user requested, or shill triggered a | |
| 1040 // reconnection, use the connecting network. | |
| 1041 if (connecting_network && | |
| 1042 (!connected_network || connecting_network->IsReconnecting() || | |
| 1043 connect_handler->HasConnectingNetwork(connecting_network->path()))) { | |
| 1044 network = connecting_network; | |
| 1045 } else { | |
| 1046 network = connected_network; | |
| 1047 } | |
| 1048 | |
| 1049 // Don't show ethernet in the tray | |
| 1050 if (icon_type == ICON_TYPE_TRAY && network && | |
| 1051 network->Matches(NetworkTypePattern::Ethernet())) { | |
| 1052 *image = gfx::ImageSkia(); | |
| 1053 *animating = false; | |
| 1054 return; | |
| 1055 } | |
| 1056 | |
| 1057 if (!network) { | |
| 1058 // If no connecting network, check if we are activating a network. | |
| 1059 const NetworkState* mobile_network = | |
| 1060 state_handler->FirstNetworkByType(NetworkTypePattern::Mobile()); | |
| 1061 if (mobile_network && (mobile_network->activation_state() == | |
| 1062 shill::kActivationStateActivating)) { | |
| 1063 network = mobile_network; | |
| 1064 } | |
| 1065 } | |
| 1066 if (!network) { | |
| 1067 // If no connecting network, check for cellular initializing. | |
| 1068 int uninitialized_msg = GetCellularUninitializedMsg(); | |
| 1069 if (uninitialized_msg != 0) { | |
| 1070 *image = GetConnectingImage(icon_type, shill::kTypeCellular); | |
| 1071 if (label) | |
| 1072 *label = l10n_util::GetStringUTF16(uninitialized_msg); | |
| 1073 *animating = true; | |
| 1074 } else { | |
| 1075 // Otherwise show the disconnected wifi icon. | |
| 1076 *image = GetDisconnectedImage(icon_type, shill::kTypeWifi); | |
| 1077 if (label) { | |
| 1078 *label = l10n_util::GetStringUTF16( | |
| 1079 IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED); | |
| 1080 } | |
| 1081 *animating = false; | |
| 1082 } | |
| 1083 return; | |
| 1084 } | |
| 1085 *animating = network->IsConnectingState(); | |
| 1086 // Get icon and label for connected or connecting network. | |
| 1087 *image = GetImageForNetwork(network, icon_type); | |
| 1088 if (label) | |
| 1089 *label = GetLabelForNetwork(network, icon_type); | |
| 1090 } | |
| 1091 | |
| 1092 void PurgeNetworkIconCache() { | |
| 1093 NetworkStateHandler::NetworkStateList networks; | |
| 1094 NetworkHandler::Get()->network_state_handler()->GetVisibleNetworkList( | |
| 1095 &networks); | |
| 1096 std::set<std::string> network_paths; | |
| 1097 for (NetworkStateHandler::NetworkStateList::iterator iter = networks.begin(); | |
| 1098 iter != networks.end(); ++iter) { | |
| 1099 network_paths.insert((*iter)->path()); | |
| 1100 } | |
| 1101 PurgeIconMap(ICON_TYPE_TRAY, network_paths); | |
| 1102 PurgeIconMap(ICON_TYPE_DEFAULT_VIEW, network_paths); | |
| 1103 PurgeIconMap(ICON_TYPE_LIST, network_paths); | |
| 1104 } | |
| 1105 | |
| 1106 } // namespace network_icon | |
| 1107 } // namespace ui | |
| OLD | NEW |