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

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

Issue 2434683003: Move NetworkStateNotifier and NetworkConnect from src/ui (Closed)
Patch Set: Fix virtuals 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
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 "ui/chromeos/network/network_state_notifier.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chromeos/network/network_configuration_handler.h"
13 #include "chromeos/network/network_connection_handler.h"
14 #include "chromeos/network/network_state.h"
15 #include "chromeos/network/network_state_handler.h"
16 #include "chromeos/network/shill_property_util.h"
17 #include "components/device_event_log/device_event_log.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/base/resource/resource_bundle.h"
21 #include "ui/chromeos/network/network_connect.h"
22 #include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
23 #include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
24 #include "ui/message_center/message_center.h"
25 #include "ui/message_center/notification.h"
26
27 using chromeos::NetworkConnectionHandler;
28 using chromeos::NetworkHandler;
29 using chromeos::NetworkState;
30 using chromeos::NetworkStateHandler;
31 using chromeos::NetworkTypePattern;
32
33 namespace {
34
35 const int kMinTimeBetweenOutOfCreditsNotifySeconds = 10 * 60;
36
37 // Ignore in-progress error.
38 bool ShillErrorIsIgnored(const std::string& shill_error) {
39 if (shill_error == shill::kErrorResultInProgress)
40 return true;
41 return false;
42 }
43
44 // Error messages based on |error_name|, not network_state->error().
45 base::string16 GetConnectErrorString(const std::string& error_name) {
46 if (error_name == NetworkConnectionHandler::kErrorNotFound)
47 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
48 if (error_name == NetworkConnectionHandler::kErrorConfigureFailed) {
49 return l10n_util::GetStringUTF16(
50 IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED);
51 }
52 if (error_name == NetworkConnectionHandler::kErrorCertLoadTimeout) {
53 return l10n_util::GetStringUTF16(
54 IDS_CHROMEOS_NETWORK_ERROR_CERTIFICATES_NOT_LOADED);
55 }
56 if (error_name == ui::NetworkConnect::kErrorActivateFailed) {
57 return l10n_util::GetStringUTF16(
58 IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
59 }
60 return base::string16();
61 }
62
63 int GetErrorNotificationIconId(const std::string& network_type) {
64 if (network_type == shill::kTypeVPN)
65 return IDR_AURA_UBER_TRAY_NETWORK_VPN;
66 if (network_type == shill::kTypeCellular)
67 return IDR_AURA_UBER_TRAY_NETWORK_FAILED_CELLULAR;
68 return IDR_AURA_UBER_TRAY_NETWORK_FAILED;
69 }
70
71 void ShowErrorNotification(const std::string& service_path,
72 const std::string& notification_id,
73 const std::string& network_type,
74 const base::string16& title,
75 const base::string16& message,
76 const base::Closure& callback) {
77 NET_LOG(ERROR) << "ShowErrorNotification: " << service_path << ": "
78 << base::UTF16ToUTF8(title);
79 const gfx::Image& icon =
80 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
81 GetErrorNotificationIconId(network_type));
82 message_center::MessageCenter::Get()->AddNotification(
83 message_center::Notification::CreateSystemNotification(
84 notification_id, title, message, icon,
85 ui::NetworkStateNotifier::kNotifierNetworkError, callback));
86 }
87
88 } // namespace
89
90 namespace ui {
91
92 const char NetworkStateNotifier::kNotifierNetwork[] = "ui.chromeos.network";
93 const char NetworkStateNotifier::kNotifierNetworkError[] =
94 "ui.chromeos.network.error";
95
96 const char NetworkStateNotifier::kNetworkConnectNotificationId[] =
97 "chrome://settings/internet/connect";
98 const char NetworkStateNotifier::kNetworkActivateNotificationId[] =
99 "chrome://settings/internet/activate";
100 const char NetworkStateNotifier::kNetworkOutOfCreditsNotificationId[] =
101 "chrome://settings/internet/out-of-credits";
102
103 NetworkStateNotifier::NetworkStateNotifier(NetworkConnect* network_connect)
104 : network_connect_(network_connect),
105 did_show_out_of_credits_(false),
106 weak_ptr_factory_(this) {
107 if (!NetworkHandler::IsInitialized())
108 return;
109 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
110 handler->AddObserver(this, FROM_HERE);
111 UpdateDefaultNetwork(handler->DefaultNetwork());
112 NetworkHandler::Get()->network_connection_handler()->AddObserver(this);
113 }
114
115 NetworkStateNotifier::~NetworkStateNotifier() {
116 if (!NetworkHandler::IsInitialized())
117 return;
118 NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
119 FROM_HERE);
120 NetworkHandler::Get()->network_connection_handler()->RemoveObserver(this);
121 }
122
123 void NetworkStateNotifier::ConnectToNetworkRequested(
124 const std::string& service_path) {
125 const NetworkState* network =
126 NetworkHandler::Get()->network_state_handler()->GetNetworkState(
127 service_path);
128 if (network && network->type() == shill::kTypeVPN)
129 connected_vpn_.clear();
130
131 RemoveConnectNotification();
132 }
133
134 void NetworkStateNotifier::ConnectSucceeded(const std::string& service_path) {
135 RemoveConnectNotification();
136 }
137
138 void NetworkStateNotifier::ConnectFailed(const std::string& service_path,
139 const std::string& error_name) {
140 // Only show a notification for certain errors. Other failures are expected
141 // to be handled by the UI that initiated the connect request.
142 // Note: kErrorConnectFailed may also cause the configure dialog to be
143 // displayed, but we rely on the notification system to show additional
144 // details if available.
145 if (error_name != NetworkConnectionHandler::kErrorConnectFailed &&
146 error_name != NetworkConnectionHandler::kErrorNotFound &&
147 error_name != NetworkConnectionHandler::kErrorConfigureFailed &&
148 error_name != NetworkConnectionHandler::kErrorCertLoadTimeout) {
149 return;
150 }
151 ShowNetworkConnectError(error_name, service_path);
152 }
153
154 void NetworkStateNotifier::DisconnectRequested(
155 const std::string& service_path) {
156 const NetworkState* network =
157 NetworkHandler::Get()->network_state_handler()->GetNetworkState(
158 service_path);
159 if (network && network->type() == shill::kTypeVPN)
160 connected_vpn_.clear();
161 }
162
163 void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState* network) {
164 if (!UpdateDefaultNetwork(network))
165 return;
166 // If the default network changes to another network, allow the out of
167 // credits notification to be shown again. A delay prevents the notification
168 // from being shown too frequently (see below).
169 if (network)
170 did_show_out_of_credits_ = false;
171 }
172
173 void NetworkStateNotifier::NetworkConnectionStateChanged(
174 const NetworkState* network) {
175 if (network->type() == shill::kTypeVPN)
176 UpdateVpnConnectionState(network);
177 }
178
179 void NetworkStateNotifier::NetworkPropertiesUpdated(
180 const NetworkState* network) {
181 if (network->type() != shill::kTypeCellular)
182 return;
183 UpdateCellularOutOfCredits(network);
184 UpdateCellularActivating(network);
185 }
186
187 bool NetworkStateNotifier::UpdateDefaultNetwork(const NetworkState* network) {
188 std::string default_network_path;
189 if (network)
190 default_network_path = network->path();
191 if (default_network_path != last_default_network_) {
192 last_default_network_ = default_network_path;
193 return true;
194 }
195 return false;
196 }
197
198 void NetworkStateNotifier::UpdateVpnConnectionState(const NetworkState* vpn) {
199 if (vpn->path() == connected_vpn_) {
200 if (!vpn->IsConnectedState() && !vpn->IsConnectingState()) {
201 ShowVpnDisconnectedNotification(vpn);
202 connected_vpn_.clear();
203 }
204 } else if (vpn->IsConnectedState()) {
205 connected_vpn_ = vpn->path();
206 }
207 }
208
209 void NetworkStateNotifier::UpdateCellularOutOfCredits(
210 const NetworkState* cellular) {
211 // Only display a notification if we are out of credits and have not already
212 // shown a notification (or have since connected to another network type).
213 if (!cellular->cellular_out_of_credits() || did_show_out_of_credits_)
214 return;
215
216 // Only display a notification if not connected, connecting, or waiting to
217 // connect to another network.
218 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
219 const NetworkState* default_network = handler->DefaultNetwork();
220 if (default_network && default_network != cellular)
221 return;
222 if (handler->ConnectingNetworkByType(NetworkTypePattern::NonVirtual()) ||
223 NetworkHandler::Get()
224 ->network_connection_handler()
225 ->HasPendingConnectRequest())
226 return;
227
228 did_show_out_of_credits_ = true;
229 base::TimeDelta dtime = base::Time::Now() - out_of_credits_notify_time_;
230 if (dtime.InSeconds() > kMinTimeBetweenOutOfCreditsNotifySeconds) {
231 out_of_credits_notify_time_ = base::Time::Now();
232 base::string16 error_msg = l10n_util::GetStringFUTF16(
233 IDS_NETWORK_OUT_OF_CREDITS_BODY, base::UTF8ToUTF16(cellular->name()));
234 ShowErrorNotification(
235 cellular->path(), kNetworkOutOfCreditsNotificationId, cellular->type(),
236 l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_TITLE), error_msg,
237 base::Bind(&NetworkStateNotifier::ShowNetworkSettingsForPath,
238 weak_ptr_factory_.GetWeakPtr(), cellular->path()));
239 }
240 }
241
242 void NetworkStateNotifier::UpdateCellularActivating(
243 const NetworkState* cellular) {
244 // Keep track of any activating cellular network.
245 std::string activation_state = cellular->activation_state();
246 if (activation_state == shill::kActivationStateActivating) {
247 cellular_activating_.insert(cellular->path());
248 return;
249 }
250 // Only display a notification if this network was activating and is now
251 // activated.
252 if (!cellular_activating_.count(cellular->path()) ||
253 activation_state != shill::kActivationStateActivated)
254 return;
255
256 cellular_activating_.erase(cellular->path());
257 int icon_id;
258 if (cellular->network_technology() == shill::kNetworkTechnologyLte)
259 icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_LTE;
260 else
261 icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_3G;
262 const gfx::Image& icon =
263 ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id);
264 message_center::MessageCenter::Get()->AddNotification(
265 message_center::Notification::CreateSystemNotification(
266 kNetworkActivateNotificationId,
267 l10n_util::GetStringUTF16(IDS_NETWORK_CELLULAR_ACTIVATED_TITLE),
268 l10n_util::GetStringFUTF16(IDS_NETWORK_CELLULAR_ACTIVATED,
269 base::UTF8ToUTF16((cellular->name()))),
270 icon, kNotifierNetwork,
271 base::Bind(&NetworkStateNotifier::ShowNetworkSettingsForPath,
272 weak_ptr_factory_.GetWeakPtr(), cellular->path())));
273 }
274
275 void NetworkStateNotifier::ShowNetworkConnectError(
276 const std::string& error_name,
277 const std::string& service_path) {
278 if (service_path.empty()) {
279 base::DictionaryValue shill_properties;
280 ShowConnectErrorNotification(error_name, service_path, shill_properties);
281 return;
282 }
283 // Get the up-to-date properties for the network and display the error.
284 NetworkHandler::Get()->network_configuration_handler()->GetShillProperties(
285 service_path,
286 base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesSucceeded,
287 weak_ptr_factory_.GetWeakPtr(), error_name),
288 base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesFailed,
289 weak_ptr_factory_.GetWeakPtr(), error_name, service_path));
290 }
291
292 void NetworkStateNotifier::ShowMobileActivationError(
293 const std::string& service_path) {
294 const NetworkState* cellular =
295 NetworkHandler::Get()->network_state_handler()->GetNetworkState(
296 service_path);
297 if (!cellular || cellular->type() != shill::kTypeCellular) {
298 NET_LOG(ERROR) << "ShowMobileActivationError without Cellular network: "
299 << service_path;
300 return;
301 }
302 message_center::MessageCenter::Get()->AddNotification(
303 message_center::Notification::CreateSystemNotification(
304 kNetworkActivateNotificationId,
305 l10n_util::GetStringUTF16(IDS_NETWORK_ACTIVATION_ERROR_TITLE),
306 l10n_util::GetStringFUTF16(IDS_NETWORK_ACTIVATION_NEEDS_CONNECTION,
307 base::UTF8ToUTF16(cellular->name())),
308 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
309 IDR_AURA_UBER_TRAY_NETWORK_FAILED_CELLULAR),
310 kNotifierNetworkError,
311 base::Bind(&NetworkStateNotifier::ShowNetworkSettingsForPath,
312 weak_ptr_factory_.GetWeakPtr(), service_path)));
313 }
314
315 void NetworkStateNotifier::RemoveConnectNotification() {
316 message_center::MessageCenter* message_center =
317 message_center::MessageCenter::Get();
318 if (message_center) {
319 message_center->RemoveNotification(kNetworkConnectNotificationId,
320 false /* not by user */);
321 }
322 }
323
324 void NetworkStateNotifier::ConnectErrorPropertiesSucceeded(
325 const std::string& error_name,
326 const std::string& service_path,
327 const base::DictionaryValue& shill_properties) {
328 std::string state;
329 shill_properties.GetStringWithoutPathExpansion(shill::kStateProperty, &state);
330 if (chromeos::NetworkState::StateIsConnected(state) ||
331 chromeos::NetworkState::StateIsConnecting(state)) {
332 // Network is no longer in an error state. This can happen if an
333 // unexpected idle state transition occurs, see crbug.com/333955.
334 return;
335 }
336 ShowConnectErrorNotification(error_name, service_path, shill_properties);
337 }
338
339 void NetworkStateNotifier::ConnectErrorPropertiesFailed(
340 const std::string& error_name,
341 const std::string& service_path,
342 const std::string& shill_connect_error,
343 std::unique_ptr<base::DictionaryValue> shill_error_data) {
344 base::DictionaryValue shill_properties;
345 ShowConnectErrorNotification(error_name, service_path, shill_properties);
346 }
347
348 void NetworkStateNotifier::ShowConnectErrorNotification(
349 const std::string& error_name,
350 const std::string& service_path,
351 const base::DictionaryValue& shill_properties) {
352 base::string16 error = GetConnectErrorString(error_name);
353 NET_LOG(DEBUG) << "Notify: " << service_path
354 << ": Connect error: " << error_name << ": "
355 << base::UTF16ToUTF8(error);
356 if (error.empty()) {
357 std::string shill_error;
358 shill_properties.GetStringWithoutPathExpansion(shill::kErrorProperty,
359 &shill_error);
360 if (!chromeos::NetworkState::ErrorIsValid(shill_error)) {
361 shill_properties.GetStringWithoutPathExpansion(
362 shill::kPreviousErrorProperty, &shill_error);
363 NET_LOG(DEBUG) << "Notify: " << service_path
364 << ": Service.PreviousError: " << shill_error;
365 if (!chromeos::NetworkState::ErrorIsValid(shill_error))
366 shill_error.clear();
367 } else {
368 NET_LOG(DEBUG) << "Notify: " << service_path
369 << ": Service.Error: " << shill_error;
370 }
371
372 const NetworkState* network =
373 NetworkHandler::Get()->network_state_handler()->GetNetworkState(
374 service_path);
375 if (network) {
376 // Always log last_error, but only use it if shill_error is empty.
377 // TODO(stevenjb): This shouldn't ever be necessary, but is kept here as
378 // a failsafe since more information is better than less when debugging
379 // and we have encountered some strange edge cases before.
380 NET_LOG(DEBUG) << "Notify: " << service_path
381 << ": Network.last_error: " << network->last_error();
382 if (shill_error.empty())
383 shill_error = network->last_error();
384 }
385
386 if (ShillErrorIsIgnored(shill_error)) {
387 NET_LOG(DEBUG) << "Notify: " << service_path
388 << ": Ignoring error: " << error_name;
389 return;
390 }
391
392 error = network_connect_->GetShillErrorString(shill_error, service_path);
393 if (error.empty()) {
394 if (error_name == NetworkConnectionHandler::kErrorConnectFailed &&
395 network && !network->connectable()) {
396 // Connect failure on non connectable network with no additional
397 // information. We expect the UI to show configuration UI so do not
398 // show an additional (and unhelpful) notification.
399 return;
400 }
401 error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
402 }
403 }
404 NET_LOG(ERROR) << "Notify: " << service_path
405 << ": Connect error: " + base::UTF16ToUTF8(error);
406
407 std::string network_name =
408 chromeos::shill_property_util::GetNameFromProperties(service_path,
409 shill_properties);
410 std::string network_error_details;
411 shill_properties.GetStringWithoutPathExpansion(shill::kErrorDetailsProperty,
412 &network_error_details);
413
414 base::string16 error_msg;
415 if (!network_error_details.empty()) {
416 // network_name should't be empty if network_error_details is set.
417 error_msg = l10n_util::GetStringFUTF16(
418 IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_SERVER_MESSAGE,
419 base::UTF8ToUTF16(network_name), error,
420 base::UTF8ToUTF16(network_error_details));
421 } else if (network_name.empty()) {
422 error_msg = l10n_util::GetStringFUTF16(
423 IDS_NETWORK_CONNECTION_ERROR_MESSAGE_NO_NAME, error);
424 } else {
425 error_msg =
426 l10n_util::GetStringFUTF16(IDS_NETWORK_CONNECTION_ERROR_MESSAGE,
427 base::UTF8ToUTF16(network_name), error);
428 }
429
430 std::string network_type;
431 shill_properties.GetStringWithoutPathExpansion(shill::kTypeProperty,
432 &network_type);
433
434 ShowErrorNotification(
435 service_path, kNetworkConnectNotificationId, network_type,
436 l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE), error_msg,
437 base::Bind(&NetworkStateNotifier::ShowNetworkSettingsForPath,
438 weak_ptr_factory_.GetWeakPtr(), service_path));
439 }
440
441 void NetworkStateNotifier::ShowVpnDisconnectedNotification(
442 const NetworkState* vpn) {
443 base::string16 error_msg = l10n_util::GetStringFUTF16(
444 IDS_NETWORK_VPN_CONNECTION_LOST_BODY, base::UTF8ToUTF16(vpn->name()));
445 ShowErrorNotification(
446 vpn->path(), kNetworkConnectNotificationId, shill::kTypeVPN,
447 l10n_util::GetStringUTF16(IDS_NETWORK_VPN_CONNECTION_LOST_TITLE),
448 error_msg, base::Bind(&NetworkStateNotifier::ShowNetworkSettingsForPath,
449 weak_ptr_factory_.GetWeakPtr(), vpn->path()));
450 }
451
452 void NetworkStateNotifier::ShowNetworkSettingsForPath(
453 const std::string& service_path) {
454 network_connect_->ShowNetworkSettingsForPath(service_path);
455 }
456
457 } // namespace ui
OLDNEW
« no previous file with comments | « ui/chromeos/network/network_state_notifier.h ('k') | ui/chromeos/network/network_state_notifier_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698