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

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

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