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

Side by Side Diff: ui/chromeos/network/network_list_md.cc

Issue 2342793005: [ash-md] Adds Wi-Fi header row to system tray network detailed view (Closed)
Patch Set: [ash-md] Materializes system tray network detailed view (comments) Created 4 years, 2 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 2014 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_list_md.h"
6
7 #include <stddef.h>
8
9 #include "base/memory/ptr_util.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
11 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
12 #include "chromeos/dbus/power_manager_client.h"
13 #include "chromeos/login/login_state.h"
14 #include "chromeos/network/managed_network_configuration_handler.h"
15 #include "chromeos/network/network_state.h"
16 #include "chromeos/network/network_state_handler.h"
17 #include "chromeos/network/network_state_handler_observer.h"
18 #include "components/device_event_log/device_event_log.h"
19 #include "grit/ui_chromeos_strings.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/chromeos/network/network_icon.h"
23 #include "ui/chromeos/network/network_icon_animation.h"
24 #include "ui/chromeos/network/network_info.h"
25 #include "ui/chromeos/network/network_list_delegate.h"
26 #include "ui/gfx/font.h"
27 #include "ui/gfx/paint_vector_icon.h"
28 #include "ui/gfx/vector_icons_public.h"
29 #include "ui/views/border.h"
30 #include "ui/views/controls/button/image_button.h"
31 #include "ui/views/controls/button/toggle_button.h"
32 #include "ui/views/controls/label.h"
33 #include "ui/views/layout/box_layout.h"
34 #include "ui/views/view.h"
35
36 using chromeos::LoginState;
37 using chromeos::NetworkHandler;
38 using chromeos::NetworkStateHandler;
39 using chromeos::ManagedNetworkConfigurationHandler;
40 using chromeos::NetworkTypePattern;
41
42 namespace ui {
43
44 namespace {
45
46 const int kWiFiRowHeight = 48;
47 const int kWiFiIconSize = 10;
48 const int kWifiRowVerticalInset = 4;
Evan Stade 2016/09/23 01:22:35 nit: WiFi or Wifi? I would err on the side of Wif
varkha 2016/09/23 04:50:36 Done.
49 const int kWifiRowLeftInset = 18;
50 const int kWifiRowRightInset = 10;
51 const int kWifiRowSeparatorThickness = 1;
52 const int kWifiRowHorizontalSpacing = 0;
Evan Stade 2016/09/23 01:22:35 nit: remove
varkha 2016/09/23 04:50:36 Done.
53 const int kWifiRowVerticalSpacing = 8;
54 const int kWifiRowChildSpacing = 28;
55 const SkColor kWifiRowSeparatorColor = SkColorSetA(SK_ColorBLACK, .12f * 0xFF);
Evan Stade 2016/09/23 01:22:34 I've tended to calculate this out and just put the
varkha 2016/09/23 04:50:35 Done.
56
57 bool IsProhibitedByPolicy(const chromeos::NetworkState* network) {
58 if (!NetworkTypePattern::WiFi().MatchesType(network->type()))
59 return false;
60 if (!LoginState::IsInitialized() || !LoginState::Get()->IsUserLoggedIn())
61 return false;
62 ManagedNetworkConfigurationHandler* managed_configuration_handler =
63 NetworkHandler::Get()->managed_network_configuration_handler();
64 const base::DictionaryValue* global_network_config =
65 managed_configuration_handler->GetGlobalConfigFromPolicy(
66 std::string() /* no username hash, device policy */);
67 bool policy_prohibites_unmanaged = false;
68 if (global_network_config) {
69 global_network_config->GetBooleanWithoutPathExpansion(
70 ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect,
71 &policy_prohibites_unmanaged);
72 }
73 if (!policy_prohibites_unmanaged)
74 return false;
75 return !managed_configuration_handler->FindPolicyByGuidAndProfile(
76 network->guid(), network->profile_path());
77 }
78
79 } // namespace
80
81 class NetworkListViewMd::WiFiHeaderRowView : public views::View {
82 public:
83 WiFiHeaderRowView(views::ButtonListener* listener, bool enabled)
84 : views::View(),
85 listener_(listener),
86 enabled_(enabled),
87 label_(nullptr),
88 toggle_(nullptr),
89 join_(nullptr) {
90 Init();
Evan Stade 2016/09/23 01:37:59 a separate Init function that's called from the ct
varkha 2016/09/23 04:50:36 Done.
91 }
92
93 ~WiFiHeaderRowView() override {}
94
95 void Init() {
96 // TODO(tdanderson): Need to unify this with the generic menu row class.
97 SetBorder(views::Border::CreateSolidSidedBorder(
98 kWifiRowSeparatorThickness, 0, 0, 0, kWifiRowSeparatorColor));
99 views::View* container = new views::View;
100 container->SetBorder(views::Border::CreateEmptyBorder(
101 kWifiRowVerticalInset, kWifiRowLeftInset, kWifiRowVerticalInset,
102 kWifiRowRightInset));
103 views::BoxLayout* layout1 =
Evan Stade 2016/09/23 01:37:59 there's gotta be a better name for this variable
varkha 2016/09/23 04:50:36 Done.
104 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
105 SetLayoutManager(layout1);
106 AddChildView(container);
107 layout1->SetFlexForView(container, 1);
108
109 views::BoxLayout* layout = new views::BoxLayout(
110 views::BoxLayout::kHorizontal, kWifiRowHorizontalSpacing,
111 kWifiRowVerticalSpacing, kWifiRowChildSpacing);
112 container->SetLayoutManager(layout);
113 SkColor color = GetNativeTheme()->GetSystemColor(
114 ui::NativeTheme::kColorId_CallToActionColor);
115 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
116 base::string16 text =
117 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_WIFI);
Evan Stade 2016/09/23 01:37:59 inline?
varkha 2016/09/23 04:50:35 Done.
118 label_ =
119 new views::Label(text, rb.GetFontList(ui::ResourceBundle::BoldFont));
120 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
121 label_->SetEnabledColor(color);
122 container->AddChildView(label_);
123 layout->SetFlexForView(label_, 1);
124
125 join_ = new views::ImageButton(listener_);
126 join_image_ = network_icon::GetImageForHeaderWifiNetwork(
127 SkColorSetA(color, 0xFF / 2), color);
128 join_->SetImage(views::CustomButton::STATE_NORMAL, &join_image_);
129 join_->SetImage(views::CustomButton::STATE_HOVERED, &join_image_);
130 join_->SetImage(views::CustomButton::STATE_PRESSED, &join_image_);
131 join_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
132 views::ImageButton::ALIGN_MIDDLE);
133 join_->SetMinimumImageSize(gfx::Size(kWiFiIconSize, kWiFiIconSize));
134 container->AddChildView(join_);
135
136 toggle_ = new views::ToggleButton(listener_);
137 container->AddChildView(toggle_);
138 SetEnabled(enabled_);
139 }
140
141 void SetEnabled(bool enabled) {
Evan Stade 2016/09/23 01:37:59 this is hiding SetEnabled on views::View (it's too
varkha 2016/09/23 04:50:36 Done.
142 enabled_ = enabled;
143 join_->SetVisible(enabled_);
144 toggle_->SetIsOn(enabled_, true);
145 }
146
147 const views::Button* toggle() const { return toggle_; }
148 const views::Button* join() const { return join_; }
149 bool is_toggled() const { return toggle_->is_on(); }
150
151 // views::View:
152 gfx::Size GetPreferredSize() const override {
153 gfx::Size size = views::View::GetPreferredSize();
154 size.set_height(kWiFiRowHeight);
155 return size;
156 }
157
158 int GetHeightForWidth(int width) const override { return kWiFiRowHeight; }
159
160 void Layout() override {
161 views::View::Layout();
162 toggle_->SizeToPreferredSize();
Evan Stade 2016/09/23 01:37:59 this should not be necessary. Why is it necessary?
varkha 2016/09/23 04:50:35 Yes, thank you!
163 }
164
165 private:
166 views::ButtonListener* listener_;
167 bool enabled_;
168 views::Label* label_;
169 views::ToggleButton* toggle_;
Evan Stade 2016/09/23 01:37:59 nice to see this being used
varkha 2016/09/23 04:50:36 Acknowledged.
170 views::ImageButton* join_;
171 gfx::ImageSkia join_image_;
172
173 DISALLOW_COPY_AND_ASSIGN(WiFiHeaderRowView);
174 };
175
176 // NetworkListViewMd:
177
178 NetworkListViewMd::NetworkListViewMd(NetworkListDelegate* delegate)
179 : delegate_(delegate),
180 no_wifi_networks_view_(nullptr),
181 no_cellular_networks_view_(nullptr),
182 wifi_header_view_(nullptr) {
183 CHECK(delegate_);
184 }
185
186 NetworkListViewMd::~NetworkListViewMd() {
187 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
188 }
189
190 void NetworkListViewMd::Update() {
191 CHECK(container_);
192 NetworkStateHandler::NetworkStateList network_list;
193 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
194 handler->GetVisibleNetworkList(&network_list);
195 UpdateNetworks(network_list);
196 OrderNetworks();
197 UpdateNetworkIcons();
198 UpdateNetworkListInternal();
199 }
200
201 bool NetworkListViewMd::IsNetworkEntry(views::View* view,
202 std::string* service_path) const {
203 std::map<views::View*, std::string>::const_iterator found =
204 network_map_.find(view);
205 if (found == network_map_.end())
206 return false;
207 *service_path = found->second;
208 return true;
209 }
210
211 void NetworkListViewMd::UpdateNetworks(
212 const NetworkStateHandler::NetworkStateList& networks) {
213 SCOPED_NET_LOG_IF_SLOW();
214 network_list_.clear();
215 const NetworkTypePattern pattern = delegate_->GetNetworkTypePattern();
216 for (NetworkStateHandler::NetworkStateList::const_iterator iter =
217 networks.begin();
218 iter != networks.end(); ++iter) {
219 const chromeos::NetworkState* network = *iter;
220 if (!pattern.MatchesType(network->type()))
221 continue;
222 network_list_.push_back(base::MakeUnique<NetworkInfo>(network->path()));
223 }
224 }
225
226 void NetworkListViewMd::OrderNetworks() {
227 struct CompareNetwork {
228 explicit CompareNetwork(NetworkStateHandler* handler) : handler_(handler) {}
229
230 // Returns true if |network1| is less than (i.e. is ordered before)
231 // |network2|.
232 bool operator()(const std::unique_ptr<NetworkInfo>& network1,
233 const std::unique_ptr<NetworkInfo>& network2) {
234 int order1 = GetOrder(handler_->GetNetworkState(network1->service_path));
235 int order2 = GetOrder(handler_->GetNetworkState(network2->service_path));
236 const bool above =
237 (order1 < order2) ||
238 (order1 == order2 && network1->highlight && !network2->highlight) ||
239 (order1 == order2 &&
240 network1->service_path.compare(network2->service_path) < 0);
241 return above;
242 }
243
244 private:
245 static int GetOrder(const chromeos::NetworkState* network) {
246 if (!network)
247 return 999;
248 if (network->Matches(NetworkTypePattern::Ethernet()))
249 return 0;
250 if (network->Matches(NetworkTypePattern::Cellular()))
251 return 1;
252 if (network->Matches(NetworkTypePattern::Mobile()))
253 return 2;
254 if (network->Matches(NetworkTypePattern::WiFi()))
255 return 3;
256 return 4;
257 }
258
259 NetworkStateHandler* handler_;
260 };
261 std::sort(network_list_.begin(), network_list_.end(),
262 CompareNetwork(NetworkHandler::Get()->network_state_handler()));
263 }
264
265 void NetworkListViewMd::UpdateNetworkIcons() {
266 SCOPED_NET_LOG_IF_SLOW();
267 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
268
269 // First, update state for all networks
270 bool animating = false;
271
272 for (auto& info : network_list_) {
273 const chromeos::NetworkState* network =
274 handler->GetNetworkState(info->service_path);
275 if (!network)
276 continue;
277 bool prohibited_by_policy = IsProhibitedByPolicy(network);
278 info->label =
279 network_icon::GetLabelForNetwork(network, network_icon::ICON_TYPE_LIST);
280 info->image =
281 network_icon::GetImageForNetwork(network, network_icon::ICON_TYPE_LIST);
282 info->disable =
283 (network->activation_state() == shill::kActivationStateActivating) ||
284 prohibited_by_policy;
285 info->highlight =
286 network->IsConnectedState() || network->IsConnectingState();
287 info->wifi = network->Matches(NetworkTypePattern::WiFi());
288 if (prohibited_by_policy) {
289 info->tooltip =
290 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED);
291 }
292 if (!animating && network->IsConnectingState())
293 animating = true;
294 }
295 if (animating)
296 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
297 else
298 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
299 }
300
301 void NetworkListViewMd::UpdateNetworkListInternal() {
302 SCOPED_NET_LOG_IF_SLOW();
303 // Get the updated list entries
304 network_map_.clear();
305 std::set<std::string> new_service_paths;
306 bool needs_relayout = UpdateNetworkListEntries(&new_service_paths);
307
308 // Remove old children
309 std::set<std::string> remove_service_paths;
310 for (ServicePathMap::const_iterator it = service_path_map_.begin();
311 it != service_path_map_.end(); ++it) {
312 if (new_service_paths.find(it->first) == new_service_paths.end()) {
313 remove_service_paths.insert(it->first);
314 network_map_.erase(it->second);
315 container_->RemoveChildView(it->second);
316 needs_relayout = true;
317 }
318 }
319
320 for (std::set<std::string>::const_iterator remove_it =
321 remove_service_paths.begin();
322 remove_it != remove_service_paths.end(); ++remove_it) {
323 service_path_map_.erase(*remove_it);
324 }
325
326 if (needs_relayout)
327 HandleRelayout();
328 }
329
330 void NetworkListViewMd::HandleRelayout() {
Evan Stade 2016/09/23 01:22:34 inline this fn?
varkha 2016/09/23 04:50:36 Done.
331 views::View* selected_view = nullptr;
332 for (auto& iter : service_path_map_) {
Evan Stade 2016/09/23 01:22:35 const?
varkha 2016/09/23 04:50:36 Done.
333 if (delegate_->IsViewHovered(iter.second)) {
334 selected_view = iter.second;
335 break;
336 }
337 }
338 container_->SizeToPreferredSize();
339 delegate_->RelayoutScrollList();
340 if (selected_view)
341 container_->ScrollRectToVisible(selected_view->bounds());
342 }
343
344 bool NetworkListViewMd::UpdateNetworkListEntries(
345 std::set<std::string>* new_service_paths) {
346 bool needs_relayout = false;
347 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
348
349 // Insert child views
Evan Stade 2016/09/23 01:22:35 I do not understand this comment
varkha 2016/09/23 04:50:35 See if you like this edit.
350 int index = 0;
351
352 // High-priority networks (not Wi-Fi)
Evan Stade 2016/09/23 01:22:35 nit: final punctuation on all comments (here and m
varkha 2016/09/23 04:50:35 Done.
353 needs_relayout |=
354 UpdateNetworkChildren(new_service_paths, &index, false /* not Wi-Fi */);
355
356 const NetworkTypePattern pattern = delegate_->GetNetworkTypePattern();
357 if (pattern.MatchesPattern(NetworkTypePattern::Cellular())) {
358 // Cellular initializing
359 int message_id = network_icon::GetCellularUninitializedMsg();
360 if (!message_id &&
361 handler->IsTechnologyEnabled(NetworkTypePattern::Mobile()) &&
362 !handler->FirstNetworkByType(NetworkTypePattern::Mobile())) {
363 message_id = IDS_ASH_STATUS_TRAY_NO_CELLULAR_NETWORKS;
364 }
365 needs_relayout |=
Evan Stade 2016/09/23 01:22:35 this use of |= seems kinda treacherous. It doesn't
varkha 2016/09/23 04:50:36 See if you like this more. View::needs_layout() is
Evan Stade 2016/09/23 21:32:12 container()->SetBoundsRect(container()->bounds());
366 UpdateInfoLabel(message_id, index, &no_cellular_networks_view_);
367
368 if (message_id)
369 ++index;
370 }
371
372 if (pattern.MatchesPattern(NetworkTypePattern::WiFi())) {
373 needs_relayout |= UpdateWiFiHeaderRow(
374 handler->IsTechnologyEnabled(NetworkTypePattern::WiFi()), index,
375 &wifi_header_view_);
376 ++index;
Evan Stade 2016/09/23 01:22:35 why is this increment not inlined?
varkha 2016/09/23 04:50:35 Done.
377
378 // "Wifi Enabled / Disabled"
379 int message_id = 0;
380 if (network_list_.empty()) {
381 message_id = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi())
382 ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
383 : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
384 }
385 needs_relayout |=
386 UpdateInfoLabel(message_id, index, &no_wifi_networks_view_);
387 if (message_id)
388 ++index;
389
390 // Wi-Fi networks
391 needs_relayout |=
392 UpdateNetworkChildren(new_service_paths, &index, true /* Wi-Fi */);
393 }
394
395 // No networks or other messages (fallback)
396 if (index == 0) {
397 needs_relayout |= UpdateInfoLabel(IDS_ASH_STATUS_TRAY_NO_NETWORKS, index,
398 &no_wifi_networks_view_);
399 }
400
401 return needs_relayout;
402 }
403
404 bool NetworkListViewMd::UpdateNetworkChildren(
405 std::set<std::string>* new_service_paths,
Evan Stade 2016/09/23 01:22:35 imo this function should return a set. If that set
varkha 2016/09/23 04:50:36 I've left for the Update[...]View methods to worry
406 int* child_index,
Evan Stade 2016/09/23 01:22:35 undocumented in/out param... oof I have no idea w
varkha 2016/09/23 04:50:36 Done.
407 bool wifi) {
408 bool needs_relayout = false;
409 int index = *child_index;
410 for (auto& info : network_list_) {
Evan Stade 2016/09/23 01:22:35 can this be const auto&
varkha 2016/09/23 04:50:35 Done.
411 if (info->wifi != wifi)
412 continue;
413 needs_relayout |= UpdateNetworkChild(index++, info.get());
414 new_service_paths->insert(info->service_path);
415 }
416 *child_index = index;
417 return needs_relayout;
418 }
419
420 bool NetworkListViewMd::UpdateNetworkChild(int index, const NetworkInfo* info) {
421 bool needs_relayout = false;
422 views::View* container = nullptr;
423 ServicePathMap::const_iterator found =
424 service_path_map_.find(info->service_path);
425 if (found == service_path_map_.end()) {
426 container = delegate_->CreateViewForNetwork(*info);
427 container_->AddChildViewAt(container, index);
Evan Stade 2016/09/23 01:22:34 it is really confusing that you have both containe
varkha 2016/09/23 04:50:35 Done.
428 needs_relayout = true;
429 } else {
430 container = found->second;
431 container->RemoveAllChildViews(true);
432 delegate_->UpdateViewForNetwork(container, *info);
433 container->Layout();
434 container->SchedulePaint();
435 needs_relayout = PlaceViewAtIndex(container, index);
436 }
437 if (info->disable)
438 container->SetEnabled(false);
439 network_map_[container] = info->service_path;
440 service_path_map_[info->service_path] = container;
441 return needs_relayout;
442 }
443
444 bool NetworkListViewMd::PlaceViewAtIndex(views::View* view, int index) {
445 if (container_->child_at(index) == view)
446 return false;
447 container_->ReorderChildView(view, index);
448 return true;
449 }
450
451 bool NetworkListViewMd::UpdateInfoLabel(int message_id,
452 int index,
453 views::Label** label) {
454 CHECK(label);
455 bool needs_relayout = false;
456 if (message_id) {
457 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
458 base::string16 text = rb.GetLocalizedString(message_id);
459 if (!*label) {
460 *label = delegate_->CreateInfoLabel();
461 (*label)->SetText(text);
462 container_->AddChildViewAt(*label, index);
463 needs_relayout = true;
464 } else {
465 (*label)->SetText(text);
466 needs_relayout = PlaceViewAtIndex(*label, index);
467 }
468 } else if (*label) {
469 container_->RemoveChildView(*label);
470 delete *label;
471 *label = nullptr;
472 needs_relayout = true;
473 }
474 return needs_relayout;
475 }
476
477 bool NetworkListViewMd::UpdateWiFiHeaderRow(bool enabled,
478 int index,
479 WiFiHeaderRowView** view) {
480 CHECK(view);
481 bool needs_relayout = false;
482 if (!*view) {
483 *view = new WiFiHeaderRowView(this, enabled);
484 container_->AddChildViewAt(*view, index);
485 needs_relayout = true;
486 } else {
487 (*view)->SetEnabled(enabled);
488 needs_relayout = PlaceViewAtIndex(*view, index);
489 }
490 return needs_relayout;
491 }
492
493 void NetworkListViewMd::NetworkIconChanged() {
494 Update();
495 }
496
497 void NetworkListViewMd::ButtonPressed(views::Button* sender,
498 const ui::Event& event) {
499 if (sender == wifi_header_view_->toggle()) {
500 NetworkStateHandler* handler =
501 NetworkHandler::Get()->network_state_handler();
502 handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
503 wifi_header_view_->is_toggled(),
504 chromeos::network_handler::ErrorCallback());
505 return;
506 } else if (sender == wifi_header_view_->join()) {
507 delegate_->OnOtherWifiClicked();
508 return;
509 }
510 NOTREACHED();
511 }
512
513 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698