Home | History | Annotate | Download | only in network
      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/chromeos/network/network_observer.h"
     10 #include "ash/system/tray/system_tray_notifier.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_connection_handler.h"
     15 #include "chromeos/network/network_event_log.h"
     16 #include "chromeos/network/network_state.h"
     17 #include "chromeos/network/network_state_handler.h"
     18 #include "grit/ash_strings.h"
     19 #include "third_party/cros_system_api/dbus/service_constants.h"
     20 #include "ui/base/l10n/l10n_util.h"
     21 
     22 using chromeos::NetworkConnectionHandler;
     23 using chromeos::NetworkHandler;
     24 using chromeos::NetworkState;
     25 using chromeos::NetworkStateHandler;
     26 
     27 namespace {
     28 
     29 const int kMinTimeBetweenOutOfCreditsNotifySeconds = 10 * 60;
     30 
     31 // Error messages based on |error_name|, not network_state->error().
     32 string16 GetConnectErrorString(const std::string& error_name) {
     33   if (error_name == NetworkConnectionHandler::kErrorNotFound)
     34     return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
     35   if (error_name == NetworkConnectionHandler::kErrorConfigureFailed)
     36     return l10n_util::GetStringUTF16(
     37         IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED);
     38   if (error_name == ash::network_connect::kErrorActivateFailed)
     39     return l10n_util::GetStringUTF16(
     40         IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
     41   return string16();
     42 }
     43 
     44 }  // namespace
     45 
     46 namespace ash {
     47 
     48 NetworkStateNotifier::NetworkStateNotifier()
     49     : cellular_out_of_credits_(false) {
     50   if (!NetworkHandler::IsInitialized())
     51     return;
     52   NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
     53 
     54   // Initialize |last_active_network_|.
     55   const NetworkState* default_network =
     56       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
     57   if (default_network && default_network->IsConnectedState())
     58     last_active_network_ = default_network->path();
     59 }
     60 
     61 NetworkStateNotifier::~NetworkStateNotifier() {
     62   if (!NetworkHandler::IsInitialized())
     63     return;
     64   NetworkHandler::Get()->network_state_handler()->RemoveObserver(
     65       this, FROM_HERE);
     66 }
     67 
     68 void NetworkStateNotifier::NetworkListChanged() {
     69   // Trigger any pending connect failed error if the network list changes
     70   // (which indicates all NetworkState entries are up to date). This is in
     71   // case a connect attempt fails because a network is no longer visible.
     72   if (!connect_failed_network_.empty()) {
     73     ShowNetworkConnectError(
     74         flimflam::kErrorConnectFailed, connect_failed_network_);
     75   }
     76 }
     77 
     78 void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState* network) {
     79   if (!network || !network->IsConnectedState())
     80     return;
     81   if (network->path() != last_active_network_) {
     82     last_active_network_ = network->path();
     83     // Reset state for new connected network
     84     cellular_out_of_credits_ = false;
     85   }
     86 }
     87 
     88 void NetworkStateNotifier::NetworkPropertiesUpdated(
     89     const NetworkState* network) {
     90   DCHECK(network);
     91   // Trigger a pending connect failed error for |network| when the Error
     92   // property has been set.
     93   if (network->path() == connect_failed_network_ && !network->error().empty()) {
     94     ShowNetworkConnectError(
     95         flimflam::kErrorConnectFailed, connect_failed_network_);
     96   }
     97   // Trigger "Out of credits" notification if the cellular network is the most
     98   // recent default network (i.e. we have not switched to another network).
     99   if (network->type() == flimflam::kTypeCellular &&
    100       network->path() == last_active_network_) {
    101     cellular_network_ = network->path();
    102     if (network->cellular_out_of_credits() &&
    103         !cellular_out_of_credits_) {
    104       cellular_out_of_credits_ = true;
    105       base::TimeDelta dtime = base::Time::Now() - out_of_credits_notify_time_;
    106       if (dtime.InSeconds() > kMinTimeBetweenOutOfCreditsNotifySeconds) {
    107         out_of_credits_notify_time_ = base::Time::Now();
    108         std::vector<string16> links;
    109         links.push_back(
    110             l10n_util::GetStringFUTF16(IDS_NETWORK_OUT_OF_CREDITS_LINK,
    111                                        UTF8ToUTF16(network->name())));
    112         ash::Shell::GetInstance()->system_tray_notifier()->
    113             NotifySetNetworkMessage(
    114                 this,
    115                 NetworkObserver::ERROR_OUT_OF_CREDITS,
    116                 NetworkObserver::GetNetworkTypeForNetworkState(network),
    117                 l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_TITLE),
    118                 l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_BODY),
    119                 links);
    120       }
    121     }
    122   }
    123 }
    124 
    125 void NetworkStateNotifier::NotificationLinkClicked(
    126     NetworkObserver::MessageType message_type,
    127     size_t link_index) {
    128   if (message_type == NetworkObserver::ERROR_OUT_OF_CREDITS) {
    129     if (!cellular_network_.empty()) {
    130       // This will trigger the activation / portal code.
    131       Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
    132           cellular_network_);
    133     }
    134     ash::Shell::GetInstance()->system_tray_notifier()->
    135         NotifyClearNetworkMessage(message_type);
    136   }
    137 }
    138 
    139 void NetworkStateNotifier::ShowNetworkConnectError(
    140     const std::string& error_name,
    141     const std::string& service_path) {
    142   const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
    143       GetNetworkState(service_path);
    144   if (error_name == flimflam::kErrorConnectFailed &&
    145       service_path != connect_failed_network_) {
    146     // Shill may not have set the Error property yet. First request an update
    147     // and wait for either the update to complete or the network list to be
    148     // updated before displaying the error.
    149     connect_failed_network_ = service_path;
    150     return;
    151   }
    152   connect_failed_network_.clear();
    153 
    154   string16 error = GetConnectErrorString(error_name);
    155   if (error.empty() && network)
    156     error = network_connect::ErrorString(network->error());
    157   if (error.empty())
    158     error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
    159   NET_LOG_ERROR("Connect error notification: " + UTF16ToUTF8(error),
    160                 service_path);
    161 
    162   std::string name = network ? network->name() : "";
    163   string16 error_msg;
    164   if (network && !network->error_details().empty()) {
    165     error_msg = l10n_util::GetStringFUTF16(
    166         IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_SERVER_MESSAGE,
    167         UTF8ToUTF16(name), error, UTF8ToUTF16(network->error_details()));
    168   } else {
    169     error_msg = l10n_util::GetStringFUTF16(
    170         IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_DETAILS,
    171         UTF8ToUTF16(name), error);
    172   }
    173 
    174   std::vector<string16> no_links;
    175   ash::Shell::GetInstance()->system_tray_notifier()->NotifySetNetworkMessage(
    176       this,
    177       NetworkObserver::ERROR_CONNECT_FAILED,
    178       NetworkObserver::GetNetworkTypeForNetworkState(network),
    179       l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE),
    180       error_msg,
    181       no_links);
    182 }
    183 
    184 }  // namespace ash
    185