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

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 (simpler) 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
« no previous file with comments | « ui/chromeos/network/network_list_md.h ('k') | ui/chromeos/network/network_list_view_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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/layout/fill_layout.h"
35 #include "ui/views/painter.h"
36 #include "ui/views/view.h"
37
38 using chromeos::LoginState;
39 using chromeos::NetworkHandler;
40 using chromeos::NetworkStateHandler;
41 using chromeos::ManagedNetworkConfigurationHandler;
42 using chromeos::NetworkTypePattern;
43
44 namespace ui {
45
46 namespace {
47
48 const int kWiFiButtonSize = 48;
49 const int kWifiRowVerticalInset = 4;
50 const int kWifiRowLeftInset = 18;
51 const int kWifiRowRightInset = 14;
52 const int kWifiRowSeparatorThickness = 1;
53 const int kWifiRowChildSpacing = 14;
54 ;
Evan Stade 2016/10/03 23:59:10 ^H
varkha 2016/10/04 01:51:26 Done.
55 const SkColor kWifiRowSeparatorColor = SkColorSetA(SK_ColorBLACK, 0x1F);
56 const SkColor kFocusBorderColor = SkColorSetRGB(64, 128, 250);
Evan Stade 2016/10/03 21:38:50 ick! could you at least use the color_palette con
varkha 2016/10/03 22:28:23 Done. Yes, we would likely need ink drop for those
Evan Stade 2016/10/03 23:59:10 if you want to use an ink drop (highlight), it sho
varkha 2016/10/04 01:51:26 Acknowledged.
57
58 bool IsProhibitedByPolicy(const chromeos::NetworkState* network) {
59 if (!NetworkTypePattern::WiFi().MatchesType(network->type()))
60 return false;
61 if (!LoginState::IsInitialized() || !LoginState::Get()->IsUserLoggedIn())
62 return false;
63 ManagedNetworkConfigurationHandler* managed_configuration_handler =
64 NetworkHandler::Get()->managed_network_configuration_handler();
65 const base::DictionaryValue* global_network_config =
66 managed_configuration_handler->GetGlobalConfigFromPolicy(
67 std::string() /* no username hash, device policy */);
68 bool policy_prohibites_unmanaged = false;
69 if (global_network_config) {
70 global_network_config->GetBooleanWithoutPathExpansion(
71 ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect,
72 &policy_prohibites_unmanaged);
73 }
74 if (!policy_prohibites_unmanaged)
75 return false;
76 return !managed_configuration_handler->FindPolicyByGuidAndProfile(
77 network->guid(), network->profile_path());
78 }
79
80 } // namespace
81
82 class NetworkListViewMd::WifiHeaderRowView : public views::View {
83 public:
84 WifiHeaderRowView(views::ButtonListener* listener, bool enabled)
85 : views::View(),
86 listener_(listener),
87 label_(nullptr),
88 toggle_(nullptr),
89 join_(nullptr) {
90 Init();
91 SetWifiEnabled(enabled);
92 }
93
94 ~WifiHeaderRowView() override {}
95
96 void SetWifiEnabled(bool enabled) {
97 join_->SetVisible(enabled);
98 toggle_->SetIsOn(enabled, true);
99 }
100
101 const views::Button* toggle() const { return toggle_; }
102 const views::Button* join() const { return join_; }
103 bool is_toggled() const { return toggle_->is_on(); }
104
105 protected:
106 // views::View:
107 gfx::Size GetPreferredSize() const override {
108 gfx::Size size = views::View::GetPreferredSize();
109 size.set_height(kWiFiButtonSize + kWifiRowVerticalInset * 2);
110 return size;
111 }
112
113 int GetHeightForWidth(int width) const override {
Evan Stade 2016/10/03 21:38:50 not sure you need this function since it parrots G
varkha 2016/10/03 22:28:23 Done.
114 return kWiFiButtonSize + kWifiRowVerticalInset * 2;
115 }
116
117 private:
118 void Init() {
119 // TODO(tdanderson): Need to unify this with the generic menu row class.
120 SetBorder(views::Border::CreateSolidSidedBorder(
121 kWifiRowSeparatorThickness, 0, 0, 0, kWifiRowSeparatorColor));
122 views::View* container = new views::View;
123 container->SetBorder(views::Border::CreateEmptyBorder(
124 0, kWifiRowLeftInset, 0, kWifiRowRightInset));
125 views::FillLayout* layout = new views::FillLayout;
126 SetLayoutManager(layout);
127 AddChildView(container);
128
129 views::BoxLayout* container_layout = new views::BoxLayout(
130 views::BoxLayout::kHorizontal, 0, 0, kWifiRowChildSpacing);
131 container_layout->set_cross_axis_alignment(
132 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
133 container->SetLayoutManager(container_layout);
134 SkColor color = GetNativeTheme()->GetSystemColor(
135 ui::NativeTheme::kColorId_ProminentButtonColor);
136 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
137 label_ = new views::Label(
138 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_WIFI),
139 rb.GetFontList(ui::ResourceBundle::MediumFont));
140 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
141 label_->SetEnabledColor(color);
142 container->AddChildView(label_);
143 container_layout->SetFlexForView(label_, 1);
144
145 // TODO(varkha): Make this a SystemMenuButton.
146 join_ = new views::ImageButton(listener_);
147 join_image_ = network_icon::GetImageForNewWifiNetwork(
148 SkColorSetA(color, 0xFF / 2), color);
149 join_->SetImage(views::CustomButton::STATE_NORMAL, &join_image_);
150
151 const int horizontal_padding = (kWiFiButtonSize - join_image_.width()) / 2;
152 const int vertical_padding = (kWiFiButtonSize - join_image_.height()) / 2;
153 join_->SetBorder(views::Border::CreateEmptyBorder(
154 gfx::Insets(vertical_padding, horizontal_padding)));
155 join_->SetFocusForPlatform();
156 join_->SetFocusPainter(views::Painter::CreateSolidFocusPainter(
157 kFocusBorderColor, gfx::Insets(1)));
158 container->AddChildView(join_);
159
160 toggle_ = new views::ToggleButton(listener_);
161 // TODO(varkha): Implement focus painter.
162 toggle_->SetFocusForPlatform();
163 container->AddChildView(toggle_);
164 }
165
166 // ButtonListener to notify when |toggle_| or |join_| are clicked.
167 views::ButtonListener* listener_;
168
169 // Text label for the row.
170 views::Label* label_;
171
172 // ToggleButton to toggle Wi-Fi on or off.
173 views::ToggleButton* toggle_;
174
175 // A button to invoke "Join Wi-Fi network" dialog.
176 views::ImageButton* join_;
177
178 // Image used for the |join_| button.
179 gfx::ImageSkia join_image_;
180
181 DISALLOW_COPY_AND_ASSIGN(WifiHeaderRowView);
182 };
183
184 // NetworkListViewMd:
185
186 NetworkListViewMd::NetworkListViewMd(NetworkListDelegate* delegate)
187 : needs_relayout_(false),
188 delegate_(delegate),
189 no_wifi_networks_view_(nullptr),
190 no_cellular_networks_view_(nullptr),
191 wifi_header_view_(nullptr) {
192 CHECK(delegate_);
193 }
194
195 NetworkListViewMd::~NetworkListViewMd() {
196 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
197 }
198
199 void NetworkListViewMd::Update() {
200 CHECK(container());
201 NetworkStateHandler::NetworkStateList network_list;
202 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
203 handler->GetVisibleNetworkList(&network_list);
204 UpdateNetworks(network_list);
205 OrderNetworks();
206 UpdateNetworkIcons();
207 UpdateNetworkListInternal();
208 }
209
210 bool NetworkListViewMd::IsNetworkEntry(views::View* view,
211 std::string* service_path) const {
212 std::map<views::View*, std::string>::const_iterator found =
213 network_map_.find(view);
214 if (found == network_map_.end())
215 return false;
216 *service_path = found->second;
217 return true;
218 }
219
220 void NetworkListViewMd::UpdateNetworks(
221 const NetworkStateHandler::NetworkStateList& networks) {
222 SCOPED_NET_LOG_IF_SLOW();
223 network_list_.clear();
224 const NetworkTypePattern pattern = delegate_->GetNetworkTypePattern();
225 for (const auto& network : networks) {
226 if (pattern.MatchesType(network->type()))
227 network_list_.push_back(base::MakeUnique<NetworkInfo>(network->path()));
228 }
229 }
230
231 void NetworkListViewMd::OrderNetworks() {
232 struct CompareNetwork {
233 explicit CompareNetwork(NetworkStateHandler* handler) : handler_(handler) {}
234
235 // Returns true if |network1| is less than (i.e. is ordered before)
236 // |network2|.
237 bool operator()(const std::unique_ptr<NetworkInfo>& network1,
238 const std::unique_ptr<NetworkInfo>& network2) {
239 const int order1 =
240 GetOrder(handler_->GetNetworkState(network1->service_path));
241 const int order2 =
242 GetOrder(handler_->GetNetworkState(network2->service_path));
243 if (order1 != order2)
244 return order1 < order2;
245 if (network1->highlight != network2->highlight)
246 return network1->highlight;
247 return network1->service_path.compare(network2->service_path) < 0;
248 }
249
250 private:
251 static int GetOrder(const chromeos::NetworkState* network) {
252 if (!network)
253 return 999;
254 if (network->Matches(NetworkTypePattern::Ethernet()))
255 return 0;
256 if (network->Matches(NetworkTypePattern::Cellular()))
257 return 1;
258 if (network->Matches(NetworkTypePattern::Mobile()))
259 return 2;
260 if (network->Matches(NetworkTypePattern::WiFi()))
261 return 3;
262 return 4;
263 }
264
265 NetworkStateHandler* handler_;
266 };
267 std::sort(network_list_.begin(), network_list_.end(),
268 CompareNetwork(NetworkHandler::Get()->network_state_handler()));
269 }
270
271 void NetworkListViewMd::UpdateNetworkIcons() {
272 SCOPED_NET_LOG_IF_SLOW();
273 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
274
275 // First, update state for all networks.
276 bool animating = false;
277
278 for (auto& info : network_list_) {
279 const chromeos::NetworkState* network =
280 handler->GetNetworkState(info->service_path);
281 if (!network)
282 continue;
283 bool prohibited_by_policy = IsProhibitedByPolicy(network);
284 info->label =
285 network_icon::GetLabelForNetwork(network, network_icon::ICON_TYPE_LIST);
286 info->image =
287 network_icon::GetImageForNetwork(network, network_icon::ICON_TYPE_LIST);
288 info->disable =
289 (network->activation_state() == shill::kActivationStateActivating) ||
290 prohibited_by_policy;
291 info->highlight =
292 network->IsConnectedState() || network->IsConnectingState();
293 info->is_wifi = network->Matches(NetworkTypePattern::WiFi());
294 if (prohibited_by_policy) {
295 info->tooltip =
296 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED);
297 }
298 if (!animating && network->IsConnectingState())
299 animating = true;
300 }
301 if (animating)
302 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
303 else
304 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
305 }
306
307 void NetworkListViewMd::UpdateNetworkListInternal() {
308 SCOPED_NET_LOG_IF_SLOW();
309 // Get the updated list entries.
310 needs_relayout_ = false;
311 network_map_.clear();
312 std::unique_ptr<std::set<std::string>> new_service_paths =
313 UpdateNetworkListEntries();
314
315 // Remove old children.
316 std::set<std::string> remove_service_paths;
317 for (const auto& iter : service_path_map_) {
318 if (new_service_paths->find(iter.first) == new_service_paths->end()) {
319 remove_service_paths.insert(iter.first);
320 network_map_.erase(iter.second);
321 delete iter.second;
322 needs_relayout_ = true;
323 }
324 }
325
326 for (const auto& remove_iter : remove_service_paths)
327 service_path_map_.erase(remove_iter);
328
329 if (!needs_relayout_)
330 return;
331
332 views::View* selected_view = nullptr;
333 for (const auto& iter : service_path_map_) {
334 if (delegate_->IsViewHovered(iter.second)) {
335 selected_view = iter.second;
336 break;
337 }
338 }
339 container()->SizeToPreferredSize();
340 delegate_->RelayoutScrollList();
341 if (selected_view)
342 container()->ScrollRectToVisible(selected_view->bounds());
343 }
344
345 std::unique_ptr<std::set<std::string>>
346 NetworkListViewMd::UpdateNetworkListEntries() {
347 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
348
349 // First add high-priority networks (not Wi-Fi).
350 std::unique_ptr<std::set<std::string>> new_service_paths =
351 UpdateNetworkChildren(false /* not Wi-Fi */, 0);
352
353 // Keep an index of the last inserted child.
354 int index = new_service_paths->size();
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 UpdateInfoLabel(message_id, index, &no_cellular_networks_view_);
366 if (message_id)
367 ++index;
368 }
369
370 if (pattern.MatchesPattern(NetworkTypePattern::WiFi())) {
371 UpdateWifiHeaderRow(
372 handler->IsTechnologyEnabled(NetworkTypePattern::WiFi()), index,
373 &wifi_header_view_);
374 ++index;
375
376 // "Wifi Enabled / Disabled".
377 int message_id = 0;
378 if (network_list_.empty()) {
379 message_id = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi())
380 ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
381 : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
382 }
383 UpdateInfoLabel(message_id, index, &no_wifi_networks_view_);
384 if (message_id)
385 ++index;
386
387 // Add Wi-Fi networks.
388 std::unique_ptr<std::set<std::string>> new_wifi_service_paths =
389 UpdateNetworkChildren(true /* Wi-Fi */, index);
390 index += new_wifi_service_paths->size();
391 new_service_paths->insert(new_wifi_service_paths->begin(),
392 new_wifi_service_paths->end());
393 }
394
395 // No networks or other messages (fallback).
396 if (index == 0) {
397 UpdateInfoLabel(IDS_ASH_STATUS_TRAY_NO_NETWORKS, index,
398 &no_wifi_networks_view_);
399 }
400
401 return new_service_paths;
402 }
403
404 std::unique_ptr<std::set<std::string>> NetworkListViewMd::UpdateNetworkChildren(
405 bool is_wifi,
406 int index) {
407 std::unique_ptr<std::set<std::string>> new_service_paths(
408 new std::set<std::string>);
409 for (const auto& info : network_list_) {
410 if (info->is_wifi != is_wifi)
411 continue;
412 UpdateNetworkChild(index++, info.get());
413 new_service_paths->insert(info->service_path);
414 }
415 return new_service_paths;
416 }
417
418 void NetworkListViewMd::UpdateNetworkChild(int index, const NetworkInfo* info) {
419 views::View* network_view = nullptr;
420 ServicePathMap::const_iterator found =
421 service_path_map_.find(info->service_path);
422 if (found == service_path_map_.end()) {
423 network_view = delegate_->CreateViewForNetwork(*info);
424 } else {
425 network_view = found->second;
426 network_view->RemoveAllChildViews(true);
427 delegate_->UpdateViewForNetwork(network_view, *info);
428 network_view->Layout();
429 network_view->SchedulePaint();
430 }
431 PlaceViewAtIndex(network_view, index);
432 if (info->disable)
433 network_view->SetEnabled(false);
434 network_map_[network_view] = info->service_path;
435 service_path_map_[info->service_path] = network_view;
436 }
437
438 void NetworkListViewMd::PlaceViewAtIndex(views::View* view, int index) {
439 if (view->parent() != container()) {
440 container()->AddChildViewAt(view, index);
441 } else {
442 if (container()->child_at(index) == view)
443 return;
444 container()->ReorderChildView(view, index);
445 }
446 needs_relayout_ = true;
447 }
448
449 void NetworkListViewMd::UpdateInfoLabel(int message_id,
450 int insertion_index,
451 views::Label** label_ptr) {
452 views::Label* label = *label_ptr;
453 if (!message_id) {
454 if (label) {
455 needs_relayout_ = true;
456 delete label;
457 *label_ptr = nullptr;
458 }
459 return;
460 }
461 base::string16 text =
462 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(message_id);
463 if (!label)
464 label = delegate_->CreateInfoLabel();
465 label->SetText(text);
466 PlaceViewAtIndex(label, insertion_index);
467 *label_ptr = label;
468 }
469
470 void NetworkListViewMd::UpdateWifiHeaderRow(bool enabled,
471 int child_index,
472 WifiHeaderRowView** view) {
473 if (!*view)
474 *view = new WifiHeaderRowView(this, enabled);
475 (*view)->SetWifiEnabled(enabled);
476 PlaceViewAtIndex(*view, child_index);
477 }
478
479 void NetworkListViewMd::NetworkIconChanged() {
480 Update();
481 }
482
483 void NetworkListViewMd::ButtonPressed(views::Button* sender,
484 const ui::Event& event) {
485 if (sender == wifi_header_view_->toggle()) {
486 NetworkStateHandler* handler =
487 NetworkHandler::Get()->network_state_handler();
488 handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
489 wifi_header_view_->is_toggled(),
490 chromeos::network_handler::ErrorCallback());
491 } else if (sender == wifi_header_view_->join()) {
492 delegate_->OnOtherWifiClicked();
493 } else {
494 NOTREACHED();
495 }
496 }
497
498 } // namespace ui
OLDNEW
« no previous file with comments | « ui/chromeos/network/network_list_md.h ('k') | ui/chromeos/network/network_list_view_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698