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 |