summaryrefslogtreecommitdiff
path: root/chromium/ash/system/chromeos/network/network_state_notifier.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/system/chromeos/network/network_state_notifier.cc')
-rw-r--r--chromium/ash/system/chromeos/network/network_state_notifier.cc288
1 files changed, 288 insertions, 0 deletions
diff --git a/chromium/ash/system/chromeos/network/network_state_notifier.cc b/chromium/ash/system/chromeos/network/network_state_notifier.cc
new file mode 100644
index 00000000000..ac69a8ab559
--- /dev/null
+++ b/chromium/ash/system/chromeos/network/network_state_notifier.cc
@@ -0,0 +1,288 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/system/chromeos/network/network_state_notifier.h"
+
+#include "ash/shell.h"
+#include "ash/system/chromeos/network/network_connect.h"
+#include "ash/system/system_notifier.h"
+#include "ash/system/tray/system_tray_delegate.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_connection_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/shill_property_util.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+
+using chromeos::NetworkConnectionHandler;
+using chromeos::NetworkHandler;
+using chromeos::NetworkState;
+using chromeos::NetworkStateHandler;
+using chromeos::NetworkTypePattern;
+
+namespace {
+
+const char kNetworkOutOfCreditsNotificationId[] =
+ "chrome://settings/internet/out-of-credits";
+
+const int kMinTimeBetweenOutOfCreditsNotifySeconds = 10 * 60;
+
+// Error messages based on |error_name|, not network_state->error().
+string16 GetConnectErrorString(const std::string& error_name) {
+ if (error_name == NetworkConnectionHandler::kErrorNotFound)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
+ if (error_name == NetworkConnectionHandler::kErrorConfigureFailed)
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED);
+ if (error_name == ash::network_connect::kErrorActivateFailed)
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
+ return string16();
+}
+
+void ShowErrorNotification(const std::string& notification_id,
+ const std::string& network_type,
+ const base::string16& title,
+ const base::string16& message,
+ const base::Closure& callback) {
+ int icon_id = (network_type == shill::kTypeCellular) ?
+ IDR_AURA_UBER_TRAY_CELLULAR_NETWORK_FAILED :
+ IDR_AURA_UBER_TRAY_NETWORK_FAILED;
+ const gfx::Image& icon =
+ ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id);
+ message_center::MessageCenter::Get()->AddNotification(
+ message_center::Notification::CreateSystemNotification(
+ notification_id,
+ title,
+ message,
+ icon,
+ ash::system_notifier::kNotifierNetworkError,
+ callback));
+}
+
+} // namespace
+
+namespace ash {
+
+NetworkStateNotifier::NetworkStateNotifier()
+ : did_show_out_of_credits_(false),
+ weak_ptr_factory_(this) {
+ if (!NetworkHandler::IsInitialized())
+ return;
+ NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
+ handler->AddObserver(this, FROM_HERE);
+ UpdateDefaultNetwork(handler->DefaultNetwork());
+}
+
+NetworkStateNotifier::~NetworkStateNotifier() {
+ if (!NetworkHandler::IsInitialized())
+ return;
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+ this, FROM_HERE);
+}
+
+void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState* network) {
+ if (!UpdateDefaultNetwork(network))
+ return;
+ // If the default network changes to another network, allow the out of
+ // credits notification to be shown again. A delay prevents the notification
+ // from being shown too frequently (see below).
+ if (network)
+ did_show_out_of_credits_ = false;
+}
+
+void NetworkStateNotifier::NetworkPropertiesUpdated(
+ const NetworkState* network) {
+ if (network->type() != shill::kTypeCellular)
+ return;
+ UpdateCellularOutOfCredits(network);
+ UpdateCellularActivating(network);
+}
+
+bool NetworkStateNotifier::UpdateDefaultNetwork(const NetworkState* network) {
+ std::string default_network_path;
+ if (network)
+ default_network_path = network->path();
+ if (default_network_path != last_default_network_) {
+ last_default_network_ = default_network_path;
+ return true;
+ }
+ return false;
+}
+
+void NetworkStateNotifier::UpdateCellularOutOfCredits(
+ const NetworkState* cellular) {
+ // Only display a notification if we are out of credits and have not already
+ // shown a notification (or have since connected to another network type).
+ if (!cellular->cellular_out_of_credits() || did_show_out_of_credits_)
+ return;
+
+ // Only display a notification if not connected, connecting, or waiting to
+ // connect to another network.
+ NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
+ const NetworkState* default_network = handler->DefaultNetwork();
+ if (default_network && default_network != cellular)
+ return;
+ if (handler->ConnectingNetworkByType(NetworkTypePattern::NonVirtual()) ||
+ NetworkHandler::Get()->network_connection_handler()
+ ->HasPendingConnectRequest())
+ return;
+
+ did_show_out_of_credits_ = true;
+ base::TimeDelta dtime = base::Time::Now() - out_of_credits_notify_time_;
+ if (dtime.InSeconds() > kMinTimeBetweenOutOfCreditsNotifySeconds) {
+ out_of_credits_notify_time_ = base::Time::Now();
+ string16 error_msg = l10n_util::GetStringFUTF16(
+ IDS_NETWORK_OUT_OF_CREDITS_BODY,
+ UTF8ToUTF16(cellular->name()));
+ ShowErrorNotification(
+ kNetworkOutOfCreditsNotificationId,
+ cellular->type(),
+ l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_TITLE),
+ error_msg,
+ base::Bind(&network_connect::ShowNetworkSettings, cellular->path()));
+ }
+}
+
+void NetworkStateNotifier::UpdateCellularActivating(
+ const NetworkState* cellular) {
+ // Keep track of any activating cellular network.
+ std::string activation_state = cellular->activation_state();
+ if (activation_state == shill::kActivationStateActivating) {
+ cellular_activating_.insert(cellular->path());
+ return;
+ }
+ // Only display a notification if this network was activating and is now
+ // activated.
+ if (!cellular_activating_.count(cellular->path()) ||
+ activation_state != shill::kActivationStateActivated)
+ return;
+
+ cellular_activating_.erase(cellular->path());
+ int icon_id;
+ if (cellular->network_technology() == shill::kNetworkTechnologyLte)
+ icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_LTE;
+ else
+ icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_3G;
+ const gfx::Image& icon =
+ ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id);
+ message_center::MessageCenter::Get()->AddNotification(
+ message_center::Notification::CreateSystemNotification(
+ ash::network_connect::kNetworkActivateNotificationId,
+ l10n_util::GetStringUTF16(IDS_NETWORK_CELLULAR_ACTIVATED_TITLE),
+ l10n_util::GetStringFUTF16(IDS_NETWORK_CELLULAR_ACTIVATED,
+ UTF8ToUTF16((cellular->name()))),
+ icon,
+ system_notifier::kNotifierNetwork,
+ base::Bind(&ash::network_connect::ShowNetworkSettings,
+ cellular->path())));
+}
+
+void NetworkStateNotifier::ShowNetworkConnectError(
+ const std::string& error_name,
+ const std::string& shill_error,
+ const std::string& service_path) {
+ if (service_path.empty()) {
+ base::DictionaryValue shill_properties;
+ ShowConnectErrorNotification(error_name, shill_error, service_path,
+ shill_properties);
+ return;
+ }
+ // Get the up-to-date properties for the network and display the error.
+ NetworkHandler::Get()->network_configuration_handler()->GetProperties(
+ service_path,
+ base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesSucceeded,
+ weak_ptr_factory_.GetWeakPtr(), error_name, shill_error),
+ base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesFailed,
+ weak_ptr_factory_.GetWeakPtr(), error_name, shill_error,
+ service_path));
+}
+
+void NetworkStateNotifier::ConnectErrorPropertiesSucceeded(
+ const std::string& error_name,
+ const std::string& shill_error,
+ const std::string& service_path,
+ const base::DictionaryValue& shill_properties) {
+ ShowConnectErrorNotification(error_name, shill_error, service_path,
+ shill_properties);
+}
+
+void NetworkStateNotifier::ConnectErrorPropertiesFailed(
+ const std::string& error_name,
+ const std::string& shill_error,
+ const std::string& service_path,
+ const std::string& shill_connect_error,
+ scoped_ptr<base::DictionaryValue> shill_error_data) {
+ base::DictionaryValue shill_properties;
+ ShowConnectErrorNotification(error_name, shill_error, service_path,
+ shill_properties);
+}
+
+void NetworkStateNotifier::ShowConnectErrorNotification(
+ const std::string& error_name,
+ const std::string& shill_error,
+ const std::string& service_path,
+ const base::DictionaryValue& shill_properties) {
+ string16 error = GetConnectErrorString(error_name);
+ if (error.empty()) {
+ // Service.Error gets cleared shortly after State transitions to Failure,
+ // so rely on |shill_error| unless empty.
+ std::string network_error = shill_error;
+ if (network_error.empty()) {
+ shill_properties.GetStringWithoutPathExpansion(
+ shill::kErrorProperty, &network_error);
+ }
+ error = network_connect::ErrorString(network_error, service_path);
+ if (error.empty())
+ error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
+ }
+ NET_LOG_ERROR("Connect error notification: " + UTF16ToUTF8(error),
+ service_path);
+
+ std::string network_name =
+ chromeos::shill_property_util::GetNameFromProperties(service_path,
+ shill_properties);
+ std::string network_error_details;
+ shill_properties.GetStringWithoutPathExpansion(
+ shill::kErrorDetailsProperty, &network_error_details);
+
+ string16 error_msg;
+ if (!network_error_details.empty()) {
+ // network_name should't be empty if network_error_details is set.
+ error_msg = l10n_util::GetStringFUTF16(
+ IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_SERVER_MESSAGE,
+ UTF8ToUTF16(network_name), error,
+ UTF8ToUTF16(network_error_details));
+ } else if (network_name.empty()) {
+ error_msg = l10n_util::GetStringFUTF16(
+ IDS_NETWORK_CONNECTION_ERROR_MESSAGE_NO_NAME, error);
+ } else {
+ error_msg = l10n_util::GetStringFUTF16(
+ IDS_NETWORK_CONNECTION_ERROR_MESSAGE,
+ UTF8ToUTF16(network_name), error);
+ }
+
+ std::string network_type;
+ shill_properties.GetStringWithoutPathExpansion(
+ shill::kTypeProperty, &network_type);
+
+ ShowErrorNotification(
+ network_connect::kNetworkConnectNotificationId,
+ network_type,
+ l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE),
+ error_msg,
+ base::Bind(&network_connect::ShowNetworkSettings, service_path));
+}
+
+} // namespace ash