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.
5 #include "ash/system/chromeos/network/network_state_notifier.h"
8 #include "ash/system/chromeos/network/network_connect.h"
9 #include "ash/system/system_notifier.h"
10 #include "ash/system/tray/system_tray_delegate.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chromeos/network/network_configuration_handler.h"
15 #include "chromeos/network/network_connection_handler.h"
16 #include "chromeos/network/network_event_log.h"
17 #include "chromeos/network/network_state.h"
18 #include "chromeos/network/network_state_handler.h"
19 #include "chromeos/network/shill_property_util.h"
20 #include "grit/ash_resources.h"
21 #include "grit/ash_strings.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/message_center/message_center.h"
26 #include "ui/message_center/notification.h"
28 using chromeos::NetworkConnectionHandler
;
29 using chromeos::NetworkHandler
;
30 using chromeos::NetworkState
;
31 using chromeos::NetworkStateHandler
;
32 using chromeos::NetworkTypePattern
;
36 const char kNetworkOutOfCreditsNotificationId
[] =
37 "chrome://settings/internet/out-of-credits";
39 const int kMinTimeBetweenOutOfCreditsNotifySeconds
= 10 * 60;
41 // Error messages based on |error_name|, not network_state->error().
42 base::string16
GetConnectErrorString(const std::string
& error_name
) {
43 if (error_name
== NetworkConnectionHandler::kErrorNotFound
)
44 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED
);
45 if (error_name
== NetworkConnectionHandler::kErrorConfigureFailed
)
46 return l10n_util::GetStringUTF16(
47 IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED
);
48 if (error_name
== ash::network_connect::kErrorActivateFailed
)
49 return l10n_util::GetStringUTF16(
50 IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED
);
51 return base::string16();
54 void ShowErrorNotification(const std::string
& notification_id
,
55 const std::string
& network_type
,
56 const base::string16
& title
,
57 const base::string16
& message
,
58 const base::Closure
& callback
) {
59 int icon_id
= (network_type
== shill::kTypeCellular
) ?
60 IDR_AURA_UBER_TRAY_CELLULAR_NETWORK_FAILED
:
61 IDR_AURA_UBER_TRAY_NETWORK_FAILED
;
62 const gfx::Image
& icon
=
63 ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id
);
64 message_center::MessageCenter::Get()->AddNotification(
65 message_center::Notification::CreateSystemNotification(
70 ash::system_notifier::kNotifierNetworkError
,
78 NetworkStateNotifier::NetworkStateNotifier()
79 : did_show_out_of_credits_(false),
80 weak_ptr_factory_(this) {
81 if (!NetworkHandler::IsInitialized())
83 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
84 handler
->AddObserver(this, FROM_HERE
);
85 UpdateDefaultNetwork(handler
->DefaultNetwork());
88 NetworkStateNotifier::~NetworkStateNotifier() {
89 if (!NetworkHandler::IsInitialized())
91 NetworkHandler::Get()->network_state_handler()->RemoveObserver(
95 void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState
* network
) {
96 if (!UpdateDefaultNetwork(network
))
98 // If the default network changes to another network, allow the out of
99 // credits notification to be shown again. A delay prevents the notification
100 // from being shown too frequently (see below).
102 did_show_out_of_credits_
= false;
105 void NetworkStateNotifier::NetworkPropertiesUpdated(
106 const NetworkState
* network
) {
107 if (network
->type() != shill::kTypeCellular
)
109 UpdateCellularOutOfCredits(network
);
110 UpdateCellularActivating(network
);
113 bool NetworkStateNotifier::UpdateDefaultNetwork(const NetworkState
* network
) {
114 std::string default_network_path
;
116 default_network_path
= network
->path();
117 if (default_network_path
!= last_default_network_
) {
118 last_default_network_
= default_network_path
;
124 void NetworkStateNotifier::UpdateCellularOutOfCredits(
125 const NetworkState
* cellular
) {
126 // Only display a notification if we are out of credits and have not already
127 // shown a notification (or have since connected to another network type).
128 if (!cellular
->cellular_out_of_credits() || did_show_out_of_credits_
)
131 // Only display a notification if not connected, connecting, or waiting to
132 // connect to another network.
133 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
134 const NetworkState
* default_network
= handler
->DefaultNetwork();
135 if (default_network
&& default_network
!= cellular
)
137 if (handler
->ConnectingNetworkByType(NetworkTypePattern::NonVirtual()) ||
138 NetworkHandler::Get()->network_connection_handler()
139 ->HasPendingConnectRequest())
142 did_show_out_of_credits_
= true;
143 base::TimeDelta dtime
= base::Time::Now() - out_of_credits_notify_time_
;
144 if (dtime
.InSeconds() > kMinTimeBetweenOutOfCreditsNotifySeconds
) {
145 out_of_credits_notify_time_
= base::Time::Now();
146 base::string16 error_msg
= l10n_util::GetStringFUTF16(
147 IDS_NETWORK_OUT_OF_CREDITS_BODY
,
148 UTF8ToUTF16(cellular
->name()));
149 ShowErrorNotification(
150 kNetworkOutOfCreditsNotificationId
,
152 l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_TITLE
),
154 base::Bind(&network_connect::ShowNetworkSettings
, cellular
->path()));
158 void NetworkStateNotifier::UpdateCellularActivating(
159 const NetworkState
* cellular
) {
160 // Keep track of any activating cellular network.
161 std::string activation_state
= cellular
->activation_state();
162 if (activation_state
== shill::kActivationStateActivating
) {
163 cellular_activating_
.insert(cellular
->path());
166 // Only display a notification if this network was activating and is now
168 if (!cellular_activating_
.count(cellular
->path()) ||
169 activation_state
!= shill::kActivationStateActivated
)
172 cellular_activating_
.erase(cellular
->path());
174 if (cellular
->network_technology() == shill::kNetworkTechnologyLte
)
175 icon_id
= IDR_AURA_UBER_TRAY_NOTIFICATION_LTE
;
177 icon_id
= IDR_AURA_UBER_TRAY_NOTIFICATION_3G
;
178 const gfx::Image
& icon
=
179 ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id
);
180 message_center::MessageCenter::Get()->AddNotification(
181 message_center::Notification::CreateSystemNotification(
182 ash::network_connect::kNetworkActivateNotificationId
,
183 l10n_util::GetStringUTF16(IDS_NETWORK_CELLULAR_ACTIVATED_TITLE
),
184 l10n_util::GetStringFUTF16(IDS_NETWORK_CELLULAR_ACTIVATED
,
185 UTF8ToUTF16((cellular
->name()))),
187 system_notifier::kNotifierNetwork
,
188 base::Bind(&ash::network_connect::ShowNetworkSettings
,
192 void NetworkStateNotifier::ShowNetworkConnectError(
193 const std::string
& error_name
,
194 const std::string
& shill_error
,
195 const std::string
& service_path
) {
196 if (service_path
.empty()) {
197 base::DictionaryValue shill_properties
;
198 ShowConnectErrorNotification(error_name
, shill_error
, service_path
,
202 // Get the up-to-date properties for the network and display the error.
203 NetworkHandler::Get()->network_configuration_handler()->GetProperties(
205 base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesSucceeded
,
206 weak_ptr_factory_
.GetWeakPtr(), error_name
, shill_error
),
207 base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesFailed
,
208 weak_ptr_factory_
.GetWeakPtr(), error_name
, shill_error
,
212 void NetworkStateNotifier::ConnectErrorPropertiesSucceeded(
213 const std::string
& error_name
,
214 const std::string
& shill_error
,
215 const std::string
& service_path
,
216 const base::DictionaryValue
& shill_properties
) {
217 ShowConnectErrorNotification(error_name
, shill_error
, service_path
,
221 void NetworkStateNotifier::ConnectErrorPropertiesFailed(
222 const std::string
& error_name
,
223 const std::string
& shill_error
,
224 const std::string
& service_path
,
225 const std::string
& shill_connect_error
,
226 scoped_ptr
<base::DictionaryValue
> shill_error_data
) {
227 base::DictionaryValue shill_properties
;
228 ShowConnectErrorNotification(error_name
, shill_error
, service_path
,
232 void NetworkStateNotifier::ShowConnectErrorNotification(
233 const std::string
& error_name
,
234 const std::string
& shill_error
,
235 const std::string
& service_path
,
236 const base::DictionaryValue
& shill_properties
) {
237 base::string16 error
= GetConnectErrorString(error_name
);
239 // Service.Error gets cleared shortly after State transitions to Failure,
240 // so rely on |shill_error| unless empty.
241 std::string network_error
= shill_error
;
242 if (network_error
.empty()) {
243 shill_properties
.GetStringWithoutPathExpansion(
244 shill::kErrorProperty
, &network_error
);
246 error
= network_connect::ErrorString(network_error
, service_path
);
248 error
= l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN
);
250 NET_LOG_ERROR("Connect error notification: " + UTF16ToUTF8(error
),
253 std::string network_name
=
254 chromeos::shill_property_util::GetNameFromProperties(service_path
,
256 std::string network_error_details
;
257 shill_properties
.GetStringWithoutPathExpansion(
258 shill::kErrorDetailsProperty
, &network_error_details
);
260 base::string16 error_msg
;
261 if (!network_error_details
.empty()) {
262 // network_name should't be empty if network_error_details is set.
263 error_msg
= l10n_util::GetStringFUTF16(
264 IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_SERVER_MESSAGE
,
265 UTF8ToUTF16(network_name
), error
,
266 UTF8ToUTF16(network_error_details
));
267 } else if (network_name
.empty()) {
268 error_msg
= l10n_util::GetStringFUTF16(
269 IDS_NETWORK_CONNECTION_ERROR_MESSAGE_NO_NAME
, error
);
271 error_msg
= l10n_util::GetStringFUTF16(
272 IDS_NETWORK_CONNECTION_ERROR_MESSAGE
,
273 UTF8ToUTF16(network_name
), error
);
276 std::string network_type
;
277 shill_properties
.GetStringWithoutPathExpansion(
278 shill::kTypeProperty
, &network_type
);
280 ShowErrorNotification(
281 network_connect::kNetworkConnectNotificationId
,
283 l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE
),
285 base::Bind(&network_connect::ShowNetworkSettings
, service_path
));