- add sources.
[platform/framework/web/crosswalk.git] / src / ash / system / chromeos / network / network_state_notifier.cc
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 "ash/system/chromeos/network/network_state_notifier.h"
6
7 #include "ash/shell.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"
27
28 using chromeos::NetworkConnectionHandler;
29 using chromeos::NetworkHandler;
30 using chromeos::NetworkState;
31 using chromeos::NetworkStateHandler;
32 using chromeos::NetworkTypePattern;
33
34 namespace {
35
36 const char kNetworkOutOfCreditsNotificationId[] =
37     "chrome://settings/internet/out-of-credits";
38
39 const int kMinTimeBetweenOutOfCreditsNotifySeconds = 10 * 60;
40
41 // Error messages based on |error_name|, not network_state->error().
42 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 string16();
52 }
53
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(
66           notification_id,
67           title,
68           message,
69           icon,
70           ash::system_notifier::NOTIFIER_NETWORK_ERROR,
71           callback));
72 }
73
74 }  // namespace
75
76 namespace ash {
77
78 NetworkStateNotifier::NetworkStateNotifier()
79     : did_show_out_of_credits_(false),
80       weak_ptr_factory_(this) {
81   if (!NetworkHandler::IsInitialized())
82     return;
83   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
84   handler->AddObserver(this, FROM_HERE);
85   UpdateDefaultNetwork(handler->DefaultNetwork());
86 }
87
88 NetworkStateNotifier::~NetworkStateNotifier() {
89   if (!NetworkHandler::IsInitialized())
90     return;
91   NetworkHandler::Get()->network_state_handler()->RemoveObserver(
92       this, FROM_HERE);
93 }
94
95 void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState* network) {
96   if (!UpdateDefaultNetwork(network))
97     return;
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).
101   if (network)
102     did_show_out_of_credits_ = false;
103 }
104
105 void NetworkStateNotifier::NetworkPropertiesUpdated(
106     const NetworkState* network) {
107   if (network->type() != shill::kTypeCellular)
108     return;
109   UpdateCellularOutOfCredits(network);
110   UpdateCellularActivating(network);
111 }
112
113 bool NetworkStateNotifier::UpdateDefaultNetwork(const NetworkState* network) {
114   std::string default_network_path;
115   if (network)
116     default_network_path = network->path();
117   if (default_network_path != last_default_network_) {
118     last_default_network_ = default_network_path;
119     return true;
120   }
121   return false;
122 }
123
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_)
129     return;
130
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)
136     return;
137   if (handler->ConnectingNetworkByType(NetworkTypePattern::NonVirtual()) ||
138       NetworkHandler::Get()->network_connection_handler()
139           ->HasPendingConnectRequest())
140     return;
141
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     string16 error_msg = l10n_util::GetStringFUTF16(
147         IDS_NETWORK_OUT_OF_CREDITS_BODY,
148         UTF8ToUTF16(cellular->name()));
149     ShowErrorNotification(
150         kNetworkOutOfCreditsNotificationId,
151         cellular->type(),
152         l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_TITLE),
153         error_msg,
154         base::Bind(&network_connect::ShowNetworkSettings, cellular->path()));
155   }
156 }
157
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());
164     return;
165   }
166   // Only display a notification if this network was activating and is now
167   // activated.
168   if (!cellular_activating_.count(cellular->path()) ||
169       activation_state != shill::kActivationStateActivated)
170     return;
171
172   cellular_activating_.erase(cellular->path());
173   int icon_id;
174   if (cellular->network_technology() == shill::kNetworkTechnologyLte)
175     icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_LTE;
176   else
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()))),
186           icon,
187           system_notifier::NOTIFIER_NETWORK,
188           base::Bind(&ash::network_connect::ShowNetworkSettings,
189                      cellular->path())));
190 }
191
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,
199                                  shill_properties);
200     return;
201   }
202   // Get the up-to-date properties for the network and display the error.
203   NetworkHandler::Get()->network_configuration_handler()->GetProperties(
204       service_path,
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,
209                  service_path));
210 }
211
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,
218                                shill_properties);
219 }
220
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,
229                                shill_properties);
230 }
231
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   string16 error = GetConnectErrorString(error_name);
238   if (error.empty()) {
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);
245     }
246     error = network_connect::ErrorString(network_error, service_path);
247     if (error.empty())
248       error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
249   }
250   NET_LOG_ERROR("Connect error notification: " + UTF16ToUTF8(error),
251                 service_path);
252
253   std::string network_name =
254       chromeos::shill_property_util::GetNameFromProperties(service_path,
255                                                            shill_properties);
256   std::string network_error_details;
257   shill_properties.GetStringWithoutPathExpansion(
258         shill::kErrorDetailsProperty, &network_error_details);
259
260   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);
270   } else {
271     error_msg = l10n_util::GetStringFUTF16(
272         IDS_NETWORK_CONNECTION_ERROR_MESSAGE,
273         UTF8ToUTF16(network_name), error);
274   }
275
276   std::string network_type;
277   shill_properties.GetStringWithoutPathExpansion(
278       shill::kTypeProperty, &network_type);
279
280   ShowErrorNotification(
281       network_connect::kNetworkConnectNotificationId,
282       network_type,
283       l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE),
284       error_msg,
285       base::Bind(&network_connect::ShowNetworkSettings, service_path));
286 }
287
288 }  // namespace ash