Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: ash/common/system/chromeos/network/network_state_list_detailed_view.cc

Issue 2732813002: chromeos: Move files in //ash/common to //ash, part 1 (Closed)
Patch Set: rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "ash/common/system/chromeos/network/network_state_list_detailed_view.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "ash/common/ash_constants.h"
11 #include "ash/common/material_design/material_design_controller.h"
12 #include "ash/common/system/chromeos/network/network_icon.h"
13 #include "ash/common/system/chromeos/network/network_icon_animation.h"
14 #include "ash/common/system/chromeos/network/network_info.h"
15 #include "ash/common/system/chromeos/network/network_list.h"
16 #include "ash/common/system/chromeos/network/network_list_md.h"
17 #include "ash/common/system/chromeos/network/network_list_view_base.h"
18 #include "ash/common/system/chromeos/network/tray_network_state_observer.h"
19 #include "ash/common/system/chromeos/network/vpn_list_view.h"
20 #include "ash/common/system/networking_config_delegate.h"
21 #include "ash/common/system/tray/fixed_sized_image_view.h"
22 #include "ash/common/system/tray/hover_highlight_view.h"
23 #include "ash/common/system/tray/system_menu_button.h"
24 #include "ash/common/system/tray/system_tray.h"
25 #include "ash/common/system/tray/system_tray_controller.h"
26 #include "ash/common/system/tray/system_tray_delegate.h"
27 #include "ash/common/system/tray/throbber_view.h"
28 #include "ash/common/system/tray/tray_constants.h"
29 #include "ash/common/system/tray/tray_details_view.h"
30 #include "ash/common/system/tray/tray_popup_header_button.h"
31 #include "ash/common/system/tray/tri_view.h"
32 #include "ash/common/wm_shell.h"
33 #include "ash/common/wm_window.h"
34 #include "ash/public/cpp/shell_window_ids.h"
35 #include "ash/resources/grit/ash_resources.h"
36 #include "ash/root_window_controller.h"
37 #include "ash/strings/grit/ash_strings.h"
38 #include "base/command_line.h"
39 #include "base/strings/string_number_conversions.h"
40 #include "base/strings/utf_string_conversions.h"
41 #include "base/threading/thread_task_runner_handle.h"
42 #include "base/time/time.h"
43 #include "chromeos/chromeos_switches.h"
44 #include "chromeos/login/login_state.h"
45 #include "chromeos/network/device_state.h"
46 #include "chromeos/network/managed_network_configuration_handler.h"
47 #include "chromeos/network/network_connect.h"
48 #include "chromeos/network/network_state.h"
49 #include "chromeos/network/network_state_handler.h"
50 #include "third_party/cros_system_api/dbus/service_constants.h"
51 #include "ui/accessibility/ax_node_data.h"
52 #include "ui/base/l10n/l10n_util.h"
53 #include "ui/base/resource/resource_bundle.h"
54 #include "ui/compositor/layer.h"
55 #include "ui/compositor/scoped_layer_animation_settings.h"
56 #include "ui/gfx/text_constants.h"
57 #include "ui/views/bubble/bubble_dialog_delegate.h"
58 #include "ui/views/controls/label.h"
59 #include "ui/views/controls/scroll_view.h"
60 #include "ui/views/layout/box_layout.h"
61 #include "ui/views/layout/fill_layout.h"
62 #include "ui/views/layout/layout_manager.h"
63 #include "ui/views/painter.h"
64 #include "ui/views/widget/widget.h"
65
66 using chromeos::DeviceState;
67 using chromeos::LoginState;
68 using chromeos::NetworkHandler;
69 using chromeos::NetworkState;
70 using chromeos::NetworkStateHandler;
71 using chromeos::NetworkTypePattern;
72
73 namespace ash {
74 namespace tray {
75 namespace {
76
77 bool UseMd() {
78 return MaterialDesignController::IsSystemTrayMenuMaterial();
79 }
80
81 // Delay between scan requests.
82 const int kRequestScanDelaySeconds = 10;
83
84 // Create a label with the font size and color used in the network info bubble.
85 views::Label* CreateInfoBubbleLabel(const base::string16& text) {
86 views::Label* label = new views::Label(text);
87 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
88 label->SetFontList(rb.GetFontList(ui::ResourceBundle::SmallFont));
89 label->SetEnabledColor(SkColorSetARGB(127, 0, 0, 0));
90 return label;
91 }
92
93 // Create a row of labels for the network info bubble.
94 views::View* CreateInfoBubbleLine(const base::string16& text_label,
95 const std::string& text_string) {
96 views::View* view = new views::View;
97 view->SetLayoutManager(
98 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 1));
99 view->AddChildView(CreateInfoBubbleLabel(text_label));
100 view->AddChildView(CreateInfoBubbleLabel(base::UTF8ToUTF16(": ")));
101 view->AddChildView(CreateInfoBubbleLabel(base::UTF8ToUTF16(text_string)));
102 return view;
103 }
104
105 // TODO(varkha): Consolidate with a similar method in tray_bluetooth.cc.
106 void SetupConnectedItemMd(HoverHighlightView* container,
107 const base::string16& text,
108 const gfx::ImageSkia& image) {
109 container->AddIconAndLabels(
110 image, text,
111 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED));
112 TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::CAPTION);
113 style.set_color_style(TrayPopupItemStyle::ColorStyle::CONNECTED);
114 style.SetupLabel(container->sub_text_label());
115 }
116
117 // TODO(varkha): Consolidate with a similar method in tray_bluetooth.cc.
118 void SetupConnectingItemMd(HoverHighlightView* container,
119 const base::string16& text,
120 const gfx::ImageSkia& image) {
121 container->AddIconAndLabels(
122 image, text,
123 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTING));
124 ThrobberView* throbber = new ThrobberView;
125 throbber->Start();
126 container->AddRightView(throbber);
127 }
128
129 } // namespace
130
131 //------------------------------------------------------------------------------
132
133 // A bubble which displays network info.
134 class NetworkStateListDetailedView::InfoBubble
135 : public views::BubbleDialogDelegateView {
136 public:
137 InfoBubble(views::View* anchor,
138 views::View* content,
139 NetworkStateListDetailedView* detailed_view)
140 : views::BubbleDialogDelegateView(anchor, views::BubbleBorder::TOP_RIGHT),
141 detailed_view_(detailed_view) {
142 set_can_activate(false);
143 SetLayoutManager(new views::FillLayout());
144 AddChildView(content);
145 }
146
147 ~InfoBubble() override { detailed_view_->OnInfoBubbleDestroyed(); }
148
149 private:
150 // BubbleDialogDelegateView:
151 int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; }
152
153 void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params,
154 views::Widget* widget) const override {
155 DCHECK(anchor_widget());
156 // Place the bubble in the anchor widget's root window.
157 WmWindow::Get(anchor_widget()->GetNativeWindow())
158 ->GetRootWindowController()
159 ->ConfigureWidgetInitParamsForContainer(
160 widget, kShellWindowId_SettingBubbleContainer, params);
161 params->name = "NetworkStateListDetailedView::InfoBubble";
162 }
163
164 // Not owned.
165 NetworkStateListDetailedView* detailed_view_;
166
167 DISALLOW_COPY_AND_ASSIGN(InfoBubble);
168 };
169
170 //------------------------------------------------------------------------------
171
172 const int kFadeIconMs = 500;
173
174 // A throbber view that fades in/out when shown/hidden.
175 class ScanningThrobber : public ThrobberView {
176 public:
177 ScanningThrobber() {
178 SetPaintToLayer();
179 layer()->SetFillsBoundsOpaquely(false);
180 layer()->SetOpacity(1.0);
181 accessible_name_ =
182 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE);
183 }
184 ~ScanningThrobber() override {}
185
186 // views::View
187 void SetVisible(bool visible) override {
188 layer()->GetAnimator()->StopAnimating(); // Stop any previous animation.
189 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
190 animation.SetTransitionDuration(
191 base::TimeDelta::FromMilliseconds(kFadeIconMs));
192 layer()->SetOpacity(visible ? 1.0 : 0.0);
193 }
194
195 void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
196 node_data->SetName(accessible_name_);
197 node_data->role = ui::AX_ROLE_BUSY_INDICATOR;
198 }
199
200 private:
201 base::string16 accessible_name_;
202
203 DISALLOW_COPY_AND_ASSIGN(ScanningThrobber);
204 };
205
206 //------------------------------------------------------------------------------
207
208 // An image button showing the info icon similar to TrayPopupHeaderButton,
209 // but without the toggle properties, that fades in/out when shown/hidden.
210 class InfoIcon : public views::ImageButton {
211 public:
212 explicit InfoIcon(views::ButtonListener* listener)
213 : views::ImageButton(listener) {
214 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
215 SetImage(
216 STATE_NORMAL,
217 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_NETWORK_INFO).ToImageSkia());
218 SetImage(STATE_HOVERED,
219 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER)
220 .ToImageSkia());
221 SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
222 SetAccessibleName(
223 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_INFO));
224 SetPaintToLayer();
225 layer()->SetFillsBoundsOpaquely(false);
226 layer()->SetOpacity(1.0);
227 }
228
229 ~InfoIcon() override {}
230
231 // views::View
232 gfx::Size GetPreferredSize() const override {
233 return gfx::Size(kTrayPopupItemMinHeight, kTrayPopupItemMinHeight);
234 }
235
236 void SetVisible(bool visible) override {
237 layer()->GetAnimator()->StopAnimating(); // Stop any previous animation.
238 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
239 animation.SetTransitionDuration(
240 base::TimeDelta::FromMilliseconds(kFadeIconMs));
241 layer()->SetOpacity(visible ? 1.0 : 0.0);
242 }
243
244 // views::CustomButton
245 void StateChanged(ButtonState old_state) override {
246 if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
247 set_background(views::Background::CreateSolidBackground(
248 kTrayPopupHoverBackgroundColor));
249 } else {
250 set_background(nullptr);
251 }
252 SchedulePaint();
253 }
254
255 private:
256 DISALLOW_COPY_AND_ASSIGN(InfoIcon);
257 };
258
259 //------------------------------------------------------------------------------
260
261 // Special layout to overlap the scanning throbber and the info button.
262 class InfoThrobberLayout : public views::LayoutManager {
263 public:
264 InfoThrobberLayout() {}
265 ~InfoThrobberLayout() override {}
266
267 // views::LayoutManager
268 void Layout(views::View* host) override {
269 gfx::Size max_size(GetMaxChildSize(host));
270 // Center each child view within |max_size|.
271 for (int i = 0; i < host->child_count(); ++i) {
272 views::View* child = host->child_at(i);
273 if (!child->visible())
274 continue;
275 gfx::Size child_size = child->GetPreferredSize();
276 gfx::Point origin;
277 origin.set_x((max_size.width() - child_size.width()) / 2);
278 origin.set_y((max_size.height() - child_size.height()) / 2);
279 gfx::Rect bounds(origin, child_size);
280 bounds.Inset(-host->GetInsets());
281 child->SetBoundsRect(bounds);
282 }
283 }
284
285 gfx::Size GetPreferredSize(const views::View* host) const override {
286 gfx::Point origin;
287 gfx::Rect rect(origin, GetMaxChildSize(host));
288 rect.Inset(-host->GetInsets());
289 return rect.size();
290 }
291
292 private:
293 gfx::Size GetMaxChildSize(const views::View* host) const {
294 int width = 0, height = 0;
295 for (int i = 0; i < host->child_count(); ++i) {
296 const views::View* child = host->child_at(i);
297 if (!child->visible())
298 continue;
299 gfx::Size child_size = child->GetPreferredSize();
300 width = std::max(width, child_size.width());
301 height = std::max(height, child_size.width());
302 }
303 return gfx::Size(width, height);
304 }
305
306 DISALLOW_COPY_AND_ASSIGN(InfoThrobberLayout);
307 };
308
309 //------------------------------------------------------------------------------
310 // NetworkStateListDetailedView
311
312 NetworkStateListDetailedView::NetworkStateListDetailedView(
313 SystemTrayItem* owner,
314 ListType list_type,
315 LoginStatus login)
316 : NetworkDetailedView(owner),
317 list_type_(list_type),
318 login_(login),
319 prev_wifi_scanning_state_(false),
320 info_icon_(nullptr),
321 info_button_md_(nullptr),
322 settings_button_md_(nullptr),
323 proxy_settings_button_md_(nullptr),
324 info_bubble_(nullptr),
325 scanning_throbber_(nullptr) {
326 if (list_type == LIST_TYPE_VPN) {
327 // Use a specialized class to list VPNs.
328 network_list_view_.reset(new VPNListView(this));
329 } else {
330 // Use a common class to list any other network types.
331 // TODO(varkha): NetworkListViewMd is a temporary fork of NetworkListView.
332 // NetworkListView will go away when Material Design becomes default.
333 // See crbug.com/614453.
334 if (UseMd())
335 network_list_view_.reset(new NetworkListViewMd(this));
336 else
337 network_list_view_.reset(new NetworkListView(this));
338 }
339 }
340
341 NetworkStateListDetailedView::~NetworkStateListDetailedView() {
342 if (info_bubble_)
343 info_bubble_->GetWidget()->CloseNow();
344 }
345
346 void NetworkStateListDetailedView::Update() {
347 UpdateNetworkList();
348 UpdateHeaderButtons();
349 Layout();
350 }
351
352 // Overridden from NetworkDetailedView:
353
354 void NetworkStateListDetailedView::Init() {
355 Reset();
356 info_icon_ = nullptr;
357 info_button_md_ = nullptr;
358 settings_button_md_ = nullptr;
359 proxy_settings_button_md_ = nullptr;
360 scanning_throbber_ = nullptr;
361
362 CreateScrollableList();
363 if (!UseMd())
364 CreateNetworkExtra();
365 CreateTitleRow(list_type_ == ListType::LIST_TYPE_NETWORK
366 ? IDS_ASH_STATUS_TRAY_NETWORK
367 : IDS_ASH_STATUS_TRAY_VPN);
368
369 network_list_view_->set_container(scroll_content());
370 Update();
371
372 if (list_type_ != LIST_TYPE_VPN)
373 CallRequestScan();
374 }
375
376 NetworkDetailedView::DetailedViewType
377 NetworkStateListDetailedView::GetViewType() const {
378 return STATE_LIST_VIEW;
379 }
380
381 void NetworkStateListDetailedView::HandleButtonPressed(views::Button* sender,
382 const ui::Event& event) {
383 if (sender == info_button_md_) {
384 ToggleInfoBubble();
385 return;
386 } else if (sender == settings_button_md_) {
387 ShowSettings();
388 } else if (sender == proxy_settings_button_md_) {
389 WmShell::Get()->system_tray_controller()->ShowProxySettings();
390 }
391
392 if (owner()->system_tray())
393 owner()->system_tray()->CloseSystemBubble();
394 }
395
396 void NetworkStateListDetailedView::HandleViewClicked(views::View* view) {
397 // If the info bubble was visible, close it when some other item is clicked.
398 ResetInfoBubble();
399
400 if (login_ == LoginStatus::LOCKED)
401 return;
402
403 std::string guid;
404 if (!network_list_view_->IsNetworkEntry(view, &guid))
405 return;
406
407 const NetworkState* network =
408 NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid(
409 guid);
410 if (!network || network->IsConnectedState() || network->IsConnectingState()) {
411 WmShell::Get()->RecordUserMetricsAction(
412 list_type_ == LIST_TYPE_VPN
413 ? UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS
414 : UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS);
415 WmShell::Get()->system_tray_controller()->ShowNetworkSettings(
416 network ? network->guid() : std::string());
417 } else {
418 WmShell::Get()->RecordUserMetricsAction(
419 list_type_ == LIST_TYPE_VPN
420 ? UMA_STATUS_AREA_CONNECT_TO_VPN
421 : UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK);
422 chromeos::NetworkConnect::Get()->ConnectToNetworkId(network->guid());
423 }
424 }
425
426 void NetworkStateListDetailedView::CreateExtraTitleRowButtons() {
427 if (login_ == LoginStatus::LOCKED)
428 return;
429
430 DCHECK(!info_button_md_);
431 tri_view()->SetContainerVisible(TriView::Container::END, true);
432
433 info_button_md_ = new SystemMenuButton(
434 this, TrayPopupInkDropStyle::HOST_CENTERED, kSystemMenuInfoIcon,
435 IDS_ASH_STATUS_TRAY_NETWORK_INFO);
436 tri_view()->AddView(TriView::Container::END, info_button_md_);
437
438 if (login_ != LoginStatus::NOT_LOGGED_IN) {
439 DCHECK(!settings_button_md_);
440 settings_button_md_ = new SystemMenuButton(
441 this, TrayPopupInkDropStyle::HOST_CENTERED, kSystemMenuSettingsIcon,
442 IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS);
443
444 // Allow the user to access settings only if user is logged in
445 // and showing settings is allowed. There are situations (supervised user
446 // creation flow) when session is started but UI flow continues within
447 // login UI, i.e., no browser window is yet avaialable.
448 if (!WmShell::Get()->system_tray_delegate()->ShouldShowSettings())
449 settings_button_md_->SetEnabled(false);
450
451 tri_view()->AddView(TriView::Container::END, settings_button_md_);
452 } else {
453 proxy_settings_button_md_ = new SystemMenuButton(
454 this, TrayPopupInkDropStyle::HOST_CENTERED, kSystemMenuSettingsIcon,
455 IDS_ASH_STATUS_TRAY_NETWORK_PROXY_SETTINGS);
456 tri_view()->AddView(TriView::Container::END, proxy_settings_button_md_);
457 }
458 }
459
460 void NetworkStateListDetailedView::ShowSettings() {
461 WmShell::Get()->RecordUserMetricsAction(
462 list_type_ == LIST_TYPE_VPN ? UMA_STATUS_AREA_VPN_SETTINGS_OPENED
463 : UMA_STATUS_AREA_NETWORK_SETTINGS_OPENED);
464 WmShell::Get()->system_tray_controller()->ShowNetworkSettings(std::string());
465 }
466
467 void NetworkStateListDetailedView::CreateNetworkExtra() {
468 DCHECK(!UseMd());
469 }
470
471 void NetworkStateListDetailedView::SetScanningStateForThrobberView(
472 bool is_scanning) {
473 if (UseMd())
474 return;
475
476 // Hide the network info button if the device is scanning for Wi-Fi networks
477 // and display the WiFi scanning indicator.
478 info_icon_->SetVisible(!is_scanning);
479 scanning_throbber_->SetVisible(is_scanning);
480 // Set the element, network info button or the wifi scanning indicator, as
481 // focusable based on which one is active/visible.
482 // NOTE: As we do not want to lose focus from the network info throbber view,
483 // the order of below operation is important.
484 if (is_scanning) {
485 scanning_throbber_->SetFocusBehavior(FocusBehavior::ALWAYS);
486 info_icon_->SetFocusBehavior(FocusBehavior::NEVER);
487 } else {
488 info_icon_->SetFocusBehavior(FocusBehavior::ALWAYS);
489 scanning_throbber_->SetFocusBehavior(FocusBehavior::NEVER);
490 }
491 // If the Network Info view was in focus while this toggle operation was
492 // being performed then the focus should remain on this view.
493 if (info_icon_->HasFocus() && is_scanning)
494 scanning_throbber_->RequestFocus();
495 else if (scanning_throbber_->HasFocus() && !is_scanning)
496 info_icon_->RequestFocus();
497 }
498
499 void NetworkStateListDetailedView::UpdateTechnologyButton(
500 TrayPopupHeaderButton* button,
501 const NetworkTypePattern& technology) {
502 NetworkStateHandler::TechnologyState state =
503 NetworkHandler::Get()->network_state_handler()->GetTechnologyState(
504 technology);
505 if (state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
506 button->SetVisible(false);
507 return;
508 }
509 button->SetVisible(true);
510 if (state == NetworkStateHandler::TECHNOLOGY_AVAILABLE) {
511 button->SetEnabled(true);
512 button->SetToggled(true);
513 } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLED) {
514 button->SetEnabled(true);
515 button->SetToggled(false);
516 } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLING) {
517 button->SetEnabled(false);
518 button->SetToggled(false);
519 } else { // Initializing
520 button->SetEnabled(false);
521 button->SetToggled(true);
522 }
523 }
524
525 void NetworkStateListDetailedView::UpdateNetworkList() {
526 network_list_view_->Update();
527 }
528
529 void NetworkStateListDetailedView::UpdateHeaderButtons() {
530 if (proxy_settings_button_md_) {
531 proxy_settings_button_md_->SetEnabled(
532 NetworkHandler::Get()->network_state_handler()->DefaultNetwork() !=
533 nullptr);
534 }
535 }
536
537 bool NetworkStateListDetailedView::OrderChild(views::View* view, int index) {
538 if (scroll_content()->child_at(index) != view) {
539 scroll_content()->ReorderChildView(view, index);
540 return true;
541 }
542 return false;
543 }
544
545 void NetworkStateListDetailedView::CreateSettingsEntry() {
546 DCHECK(!UseMd());
547 }
548
549 void NetworkStateListDetailedView::ToggleInfoBubble() {
550 if (ResetInfoBubble())
551 return;
552
553 info_bubble_ = new InfoBubble(UseMd() ? info_button_md_ : info_icon_,
554 CreateNetworkInfoView(), this);
555 views::BubbleDialogDelegateView::CreateBubble(info_bubble_)->Show();
556 info_bubble_->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, false);
557 }
558
559 bool NetworkStateListDetailedView::ResetInfoBubble() {
560 if (!info_bubble_)
561 return false;
562 info_bubble_->GetWidget()->Close();
563 info_bubble_ = nullptr;
564 return true;
565 }
566
567 void NetworkStateListDetailedView::OnInfoBubbleDestroyed() {
568 info_bubble_ = nullptr;
569 }
570
571 views::View* NetworkStateListDetailedView::CreateNetworkInfoView() {
572 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
573 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
574
575 std::string ip_address, ipv6_address;
576 const NetworkState* network = handler->DefaultNetwork();
577 if (network) {
578 const DeviceState* device = handler->GetDeviceState(network->device_path());
579 if (device) {
580 ip_address = device->GetIpAddressByType(shill::kTypeIPv4);
581 ipv6_address = device->GetIpAddressByType(shill::kTypeIPv6);
582 }
583 }
584
585 views::View* container = new views::View;
586 container->SetLayoutManager(
587 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
588 container->SetBorder(views::CreateEmptyBorder(0, 5, 0, 5));
589
590 std::string ethernet_address, wifi_address, vpn_address;
591 if (list_type_ != LIST_TYPE_VPN) {
592 ethernet_address = handler->FormattedHardwareAddressForType(
593 NetworkTypePattern::Ethernet());
594 wifi_address =
595 handler->FormattedHardwareAddressForType(NetworkTypePattern::WiFi());
596 } else {
597 vpn_address =
598 handler->FormattedHardwareAddressForType(NetworkTypePattern::VPN());
599 }
600
601 if (!ip_address.empty()) {
602 container->AddChildView(CreateInfoBubbleLine(
603 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_IP), ip_address));
604 }
605 if (!ipv6_address.empty()) {
606 container->AddChildView(CreateInfoBubbleLine(
607 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_IPV6), ipv6_address));
608 }
609 if (!ethernet_address.empty()) {
610 container->AddChildView(CreateInfoBubbleLine(
611 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_ETHERNET),
612 ethernet_address));
613 }
614 if (!wifi_address.empty()) {
615 container->AddChildView(CreateInfoBubbleLine(
616 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_WIFI), wifi_address));
617 }
618 if (!vpn_address.empty()) {
619 container->AddChildView(CreateInfoBubbleLine(
620 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_VPN), vpn_address));
621 }
622
623 // Avoid an empty bubble in the unlikely event that there is no network
624 // information at all.
625 if (!container->has_children()) {
626 container->AddChildView(CreateInfoBubbleLabel(
627 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_NO_NETWORKS)));
628 }
629
630 return container;
631 }
632
633 const gfx::ImageSkia*
634 NetworkStateListDetailedView::GetControlledByExtensionIcon() {
635 // Lazily load the icon from the resource bundle.
636 if (controlled_by_extension_icon_.IsEmpty()) {
637 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
638 controlled_by_extension_icon_ =
639 rb.GetImageNamed(IDR_AURA_UBER_TRAY_NETWORK_CONTROLLED);
640 }
641 DCHECK(!controlled_by_extension_icon_.IsEmpty());
642 return controlled_by_extension_icon_.ToImageSkia();
643 }
644
645 views::View* NetworkStateListDetailedView::CreateControlledByExtensionView(
646 const NetworkInfo& info) {
647 NetworkingConfigDelegate* networking_config_delegate =
648 WmShell::Get()->system_tray_delegate()->GetNetworkingConfigDelegate();
649 if (!networking_config_delegate)
650 return nullptr;
651 std::unique_ptr<const NetworkingConfigDelegate::ExtensionInfo>
652 extension_info =
653 networking_config_delegate->LookUpExtensionForNetwork(info.guid);
654 if (!extension_info)
655 return nullptr;
656
657 // Get the tooltip text.
658 base::string16 tooltip_text = l10n_util::GetStringFUTF16(
659 IDS_ASH_STATUS_TRAY_EXTENSION_CONTROLLED_WIFI,
660 base::UTF8ToUTF16(extension_info->extension_name));
661
662 views::ImageView* controlled_icon =
663 new FixedSizedImageView(kTrayPopupDetailsIconWidth, 0);
664
665 controlled_icon->SetImage(GetControlledByExtensionIcon());
666 controlled_icon->SetTooltipText(tooltip_text);
667 return controlled_icon;
668 }
669
670 void NetworkStateListDetailedView::CallRequestScan() {
671 VLOG(1) << "Requesting Network Scan.";
672 NetworkHandler::Get()->network_state_handler()->RequestScan();
673 // Periodically request a scan while this UI is open.
674 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
675 FROM_HERE,
676 base::Bind(&NetworkStateListDetailedView::CallRequestScan, AsWeakPtr()),
677 base::TimeDelta::FromSeconds(kRequestScanDelaySeconds));
678 }
679
680 void NetworkStateListDetailedView::ToggleMobile() {
681 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
682 bool enabled = handler->IsTechnologyEnabled(NetworkTypePattern::Mobile());
683 chromeos::NetworkConnect::Get()->SetTechnologyEnabled(
684 NetworkTypePattern::Mobile(), !enabled);
685 }
686
687 views::View* NetworkStateListDetailedView::CreateViewForNetwork(
688 const NetworkInfo& info) {
689 HoverHighlightView* container = new HoverHighlightView(this);
690 if (info.connected)
691 SetupConnectedItemMd(container, info.label, info.image);
692 else if (info.connecting)
693 SetupConnectingItemMd(container, info.label, info.image);
694 else
695 container->AddIconAndLabel(info.image, info.label, info.highlight);
696 container->set_tooltip(info.tooltip);
697 if (!UseMd()) {
698 container->SetBorder(
699 views::CreateEmptyBorder(0, kTrayPopupPaddingHorizontal, 0, 0));
700 }
701 views::View* controlled_icon = CreateControlledByExtensionView(info);
702 if (controlled_icon)
703 container->AddChildView(controlled_icon);
704 return container;
705 }
706
707 bool NetworkStateListDetailedView::IsViewHovered(views::View* view) {
708 return static_cast<HoverHighlightView*>(view)->hover();
709 }
710
711 NetworkTypePattern NetworkStateListDetailedView::GetNetworkTypePattern() const {
712 return list_type_ == LIST_TYPE_VPN ? NetworkTypePattern::VPN()
713 : NetworkTypePattern::NonVirtual();
714 }
715
716 void NetworkStateListDetailedView::UpdateViewForNetwork(
717 views::View* view,
718 const NetworkInfo& info) {
719 HoverHighlightView* container = static_cast<HoverHighlightView*>(view);
720 DCHECK(!container->has_children());
721 if (info.connected)
722 SetupConnectedItemMd(container, info.label, info.image);
723 else if (info.connecting)
724 SetupConnectingItemMd(container, info.label, info.image);
725 else
726 container->AddIconAndLabel(info.image, info.label, info.highlight);
727 views::View* controlled_icon = CreateControlledByExtensionView(info);
728 container->set_tooltip(info.tooltip);
729 if (controlled_icon)
730 view->AddChildView(controlled_icon);
731 }
732
733 views::Label* NetworkStateListDetailedView::CreateInfoLabel() {
734 views::Label* label = new views::Label();
735 label->SetBorder(views::CreateEmptyBorder(kTrayPopupPaddingBetweenItems,
736 kTrayPopupPaddingHorizontal,
737 kTrayPopupPaddingBetweenItems, 0));
738 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
739 label->SetEnabledColor(SkColorSetARGB(192, 0, 0, 0));
740 return label;
741 }
742
743 void NetworkStateListDetailedView::OnNetworkEntryClicked(views::View* sender) {
744 HandleViewClicked(sender);
745 }
746
747 void NetworkStateListDetailedView::OnOtherWifiClicked() {
748 WmShell::Get()->RecordUserMetricsAction(
749 UMA_STATUS_AREA_NETWORK_JOIN_OTHER_CLICKED);
750 WmShell::Get()->system_tray_controller()->ShowNetworkCreate(shill::kTypeWifi);
751 }
752
753 void NetworkStateListDetailedView::RelayoutScrollList() {
754 scroller()->Layout();
755 }
756
757 } // namespace tray
758 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698