summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/cros/mock_network_library.h1
-rw-r--r--chrome/browser/chromeos/cros/network_library.cc268
-rw-r--r--chrome/browser/chromeos/cros/network_library.h52
-rw-r--r--chrome/browser/chromeos/cros/network_library_unittest.cc109
-rw-r--r--chrome/browser/chromeos/status/network_menu_icon.cc93
-rw-r--r--chrome/browser/chromeos/status/network_menu_icon.h20
-rw-r--r--chrome/browser/chromeos/status/network_menu_icon_unittest.cc333
-rw-r--r--chrome/chrome_tests.gypi2
8 files changed, 741 insertions, 137 deletions
diff --git a/chrome/browser/chromeos/cros/mock_network_library.h b/chrome/browser/chromeos/cros/mock_network_library.h
index fa880a2..731dfb3 100644
--- a/chrome/browser/chromeos/cros/mock_network_library.h
+++ b/chrome/browser/chromeos/cros/mock_network_library.h
@@ -149,6 +149,7 @@ class MockNetworkLibrary : public NetworkLibrary {
HardwareAddressFormat));
MOCK_METHOD1(SetIPConfig, void(const NetworkIPConfig&));
MOCK_METHOD0(SwitchToPreferredNetwork, void(void));
+ MOCK_METHOD2(SetActiveNetwork, bool(ConnectionType, const std::string&));
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index 880cd4a..a9ab183 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -1634,6 +1634,8 @@ class NetworkLibraryImplBase : public NetworkLibrary {
// virtual GetIPConfigs implemented in derived classes.
// virtual SetIPConfig implemented in derived classes.
virtual void SwitchToPreferredNetwork() OVERRIDE;
+ virtual bool SetActiveNetwork(ConnectionType type,
+ const std::string& service_path) OVERRIDE;
protected:
typedef ObserverList<NetworkObserver> NetworkObserverList;
@@ -1706,9 +1708,11 @@ class NetworkLibraryImplBase : public NetworkLibrary {
// Called from GetSignificantDataPlan.
const CellularDataPlan* GetSignificantDataPlanFromVector(
const CellularDataPlanVector* plans) const;
- CellularNetwork::DataLeft GetDataLeft(CellularDataPlanVector* data_plans);
+ CellularNetwork::DataLeft GetDataLeft(
+ CellularDataPlanVector* data_plan_vector);
+ // Takes ownership of |data_plan|.
void UpdateCellularDataPlan(const std::string& service_path,
- const CellularDataPlanList* data_plan_list);
+ CellularDataPlanVector* data_plan_vector);
// Network list management functions.
void UpdateActiveNetwork(Network* network);
@@ -2257,8 +2261,9 @@ GetSignificantDataPlanFromVector(const CellularDataPlanVector* plans) const {
}
CellularNetwork::DataLeft NetworkLibraryImplBase::GetDataLeft(
- CellularDataPlanVector* data_plans) {
- const CellularDataPlan* plan = GetSignificantDataPlanFromVector(data_plans);
+ CellularDataPlanVector* data_plan_vector) {
+ const CellularDataPlan* plan =
+ GetSignificantDataPlanFromVector(data_plan_vector);
if (!plan)
return CellularNetwork::DATA_UNKNOWN;
if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
@@ -2288,25 +2293,15 @@ CellularNetwork::DataLeft NetworkLibraryImplBase::GetDataLeft(
void NetworkLibraryImplBase::UpdateCellularDataPlan(
const std::string& service_path,
- const CellularDataPlanList* data_plan_list) {
+ CellularDataPlanVector* data_plan_vector) {
VLOG(1) << "Updating cellular data plans for: " << service_path;
- CellularDataPlanVector* data_plans = NULL;
// Find and delete any existing data plans associated with |service_path|.
CellularDataPlanMap::iterator found = data_plan_map_.find(service_path);
- if (found != data_plan_map_.end()) {
- data_plans = found->second;
- data_plans->reset(); // This will delete existing data plans.
- } else {
- data_plans = new CellularDataPlanVector;
- data_plan_map_[service_path] = data_plans;
- }
- for (size_t i = 0; i < data_plan_list->plans_size; ++i) {
- const CellularDataPlanInfo* info(data_plan_list->GetCellularDataPlan(i));
- CellularDataPlan* plan = new CellularDataPlan(*info);
- data_plans->push_back(plan);
- VLOG(2) << " Plan: " << plan->GetPlanDesciption()
- << " : " << plan->GetDataRemainingDesciption();
- }
+ if (found != data_plan_map_.end())
+ delete found->second; // This will delete existing data plans.
+ // Takes ownership of |data_plan_vector|.
+ data_plan_map_[service_path] = data_plan_vector;
+
// Now, update any matching cellular network's cached data
CellularNetwork* cellular = FindCellularNetworkByPath(service_path);
if (cellular) {
@@ -2315,7 +2310,7 @@ void NetworkLibraryImplBase::UpdateCellularDataPlan(
if (cellular->needs_new_plan())
data_left = CellularNetwork::DATA_NONE;
else
- data_left = GetDataLeft(data_plans);
+ data_left = GetDataLeft(data_plan_vector);
VLOG(2) << " Data left: " << data_left
<< " Need plan: " << cellular->needs_new_plan();
cellular->set_data_left(data_left);
@@ -2715,6 +2710,51 @@ void NetworkLibraryImplBase::SwitchToPreferredNetwork() {
}
}
+////////////////////////////////////////////////////////////////////////////
+// Testing functions.
+
+bool NetworkLibraryImplBase::SetActiveNetwork(
+ ConnectionType type, const std::string& service_path) {
+ Network* network = NULL;
+ if (!service_path.empty())
+ network = FindNetworkByPath(service_path);
+ if (network && network->type() != type) {
+ LOG(WARNING) << "SetActiveNetwork type mismatch for: " << network->name();
+ return false;
+ }
+
+ // Clear any existing active network matching |type|.
+ for (NetworkMap::iterator iter = network_map_.begin();
+ iter != network_map_.end(); ++iter) {
+ Network* other = iter->second;
+ if (other->type() == type)
+ other->set_is_active(false);
+ }
+ switch (type) {
+ case TYPE_ETHERNET:
+ ethernet_ = NULL;
+ break;
+ case TYPE_WIFI:
+ active_wifi_ = NULL;
+ break;
+ case TYPE_CELLULAR:
+ active_cellular_ = NULL;
+ break;
+ case TYPE_VPN:
+ active_virtual_ = NULL;
+ break;
+ default:
+ break;
+ }
+
+ if (!network)
+ return true;
+
+ // Set |network| to active.
+ network->set_is_active(true);
+ UpdateActiveNetwork(network);
+ return true;
+}
////////////////////////////////////////////////////////////////////////////
// Network list management functions.
@@ -2732,25 +2772,33 @@ void NetworkLibraryImplBase::UpdateActiveNetwork(Network* network) {
if (ethernet_enabled()) {
// Set ethernet_ to the first connected ethernet service, or the first
// disconnected ethernet service if none are connected.
- if (ethernet_ == NULL || !ethernet_->connected())
+ if (ethernet_ == NULL || !ethernet_->connected()) {
ethernet_ = static_cast<EthernetNetwork*>(network);
+ VLOG(2) << "Active ethernet -> " << ethernet_->name();
+ }
}
} else if (type == TYPE_WIFI) {
if (wifi_enabled()) {
// Set active_wifi_ to the first connected or connecting wifi service.
- if (active_wifi_ == NULL && network->connecting_or_connected())
+ if (active_wifi_ == NULL && network->connecting_or_connected()) {
active_wifi_ = static_cast<WifiNetwork*>(network);
+ VLOG(2) << "Active wifi -> " << active_wifi_->name();
+ }
}
} else if (type == TYPE_CELLULAR) {
if (cellular_enabled()) {
// Set active_cellular_ to first connected/connecting celluar service.
- if (active_cellular_ == NULL && network->connecting_or_connected())
+ if (active_cellular_ == NULL && network->connecting_or_connected()) {
active_cellular_ = static_cast<CellularNetwork*>(network);
+ VLOG(2) << "Active cellular -> " << active_cellular_->name();
+ }
}
} else if (type == TYPE_VPN) {
- // Set active_virtual_ to the first connected or connecting vpn service.
- if (active_virtual_ == NULL && network->connecting_or_connected())
+ // Set active_virtual_ to the first connected or connecting vpn service. {
+ if (active_virtual_ == NULL && network->connecting_or_connected()) {
active_virtual_ = static_cast<VirtualNetwork*>(network);
+ VLOG(2) << "Active virtual -> " << active_virtual_->name();
+ }
}
}
@@ -2781,8 +2829,8 @@ void NetworkLibraryImplBase::DeleteNetwork(Network* network) {
CellularDataPlanMap::iterator found =
data_plan_map_.find(network->service_path());
if (found != data_plan_map_.end()) {
- CellularDataPlanVector* data_plans = found->second;
- delete data_plans;
+ CellularDataPlanVector* data_plan_vector = found->second;
+ delete data_plan_vector;
data_plan_map_.erase(found);
}
}
@@ -2982,7 +3030,6 @@ std::string NetworkLibraryImplBase::GetProfilePath(NetworkProfileType type) {
// TODO(stevenjb): We should consider breaking this into multiple
// notifications, e.g. connection state, devices, services, etc.
void NetworkLibraryImplBase::NotifyNetworkManagerChanged(bool force_update) {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Cancel any pending signals.
if (notify_task_) {
notify_task_->Cancel();
@@ -3218,9 +3265,10 @@ class NetworkLibraryImplCros : public NetworkLibraryImplBase {
static void NetworkManagerUpdate(
void* object, const char* manager_path, GHashTable* ghash);
- static void DataPlanUpdateHandler(void* object,
- const char* modem_service_path,
- const CellularDataPlanList* dataplan);
+ static void DataPlanUpdateHandler(
+ void* object,
+ const char* modem_service_path,
+ const chromeos::CellularDataPlanList* data_plan_list);
static void NetworkServiceUpdate(
void* object, const char* service_path, GHashTable* ghash);
@@ -4044,14 +4092,24 @@ void NetworkLibraryImplCros::ParseNetworkManager(const DictionaryValue& dict) {
void NetworkLibraryImplCros::DataPlanUpdateHandler(
void* object,
const char* modem_service_path,
- const CellularDataPlanList* dataplan) {
+ const chromeos::CellularDataPlanList* data_plan_list) {
DCHECK(CrosLibrary::Get()->libcros_loaded());
NetworkLibraryImplCros* networklib =
static_cast<NetworkLibraryImplCros*>(object);
DCHECK(networklib);
- if (modem_service_path && dataplan) {
+ if (modem_service_path && data_plan_list) {
+ // Copy contents of |data_plan_list| from libcros to |data_plan_vector|.
+ CellularDataPlanVector* data_plan_vector = new CellularDataPlanVector;
+ for (size_t i = 0; i < data_plan_list->plans_size; ++i) {
+ const CellularDataPlanInfo* info(data_plan_list->GetCellularDataPlan(i));
+ CellularDataPlan* plan = new CellularDataPlan(*info);
+ data_plan_vector->push_back(plan);
+ VLOG(2) << " Plan: " << plan->GetPlanDesciption()
+ << " : " << plan->GetDataRemainingDesciption();
+ }
+ // |data_plan_vector| will become owned by networklib.
networklib->UpdateCellularDataPlan(std::string(modem_service_path),
- dataplan);
+ data_plan_vector);
}
}
@@ -4589,6 +4647,8 @@ class NetworkLibraryImplStub : public NetworkLibraryImplBase {
virtual void SetIPConfig(const NetworkIPConfig& ipconfig) OVERRIDE;
private:
+ void AddStubNetwork(Network* network);
+
std::string ip_address_;
std::string hardware_address_;
NetworkIPConfigVector ip_configs_;
@@ -4612,7 +4672,16 @@ NetworkLibraryImplStub::NetworkLibraryImplStub()
NetworkLibraryImplStub::~NetworkLibraryImplStub() {
}
+void NetworkLibraryImplStub::AddStubNetwork(Network* network) {
+ AddNetwork(network);
+ UpdateActiveNetwork(network);
+}
+
void NetworkLibraryImplStub::Init() {
+ // Delete any existing networks (in case we call this more than once, e.g.
+ // from tests).
+ DeleteNetworks();
+
is_locked_ = false;
// Devices
@@ -4630,68 +4699,64 @@ void NetworkLibraryImplStub::Init() {
// Networks
DeleteNetworks();
+ // If these change, the expectations in network_library_unittest and
+ // network_menu_icon_unittest need to be changed also.
ethernet_ = new EthernetNetwork("eth1");
+ ethernet_->set_name("Fake Ethernet");
ethernet_->set_connected(true);
- AddNetwork(ethernet_);
+ ethernet_->set_is_active(true);
+ AddStubNetwork(ethernet_);
- WifiNetwork* wifi1 = new WifiNetwork("fw1");
- wifi1->set_name("Fake WiFi Connected");
- wifi1->set_strength(90);
- wifi1->set_connected(false);
- wifi1->set_connecting(true);
+ WifiNetwork* wifi1 = new WifiNetwork("wifi1");
+ wifi1->set_name("Fake WiFi1 Connected");
+ wifi1->set_strength(100);
+ wifi1->set_connected(true);
wifi1->set_is_active(true);
wifi1->set_encryption(SECURITY_NONE);
wifi1->set_profile_type(PROFILE_SHARED);
- AddNetwork(wifi1);
+ AddStubNetwork(wifi1);
- WifiNetwork* wifi2 = new WifiNetwork("fw2");
- wifi2->set_name("Fake WiFi");
+ WifiNetwork* wifi2 = new WifiNetwork("wifi2");
+ wifi2->set_name("Fake WiFi2 Connecting");
wifi2->set_strength(70);
- wifi2->set_connected(false);
+ wifi2->set_connecting(true);
wifi2->set_encryption(SECURITY_NONE);
wifi2->set_profile_type(PROFILE_SHARED);
- AddNetwork(wifi2);
+ AddStubNetwork(wifi2);
- WifiNetwork* wifi3 = new WifiNetwork("fw3");
- wifi3->set_name("Fake WiFi Encrypted with a long name");
+ WifiNetwork* wifi3 = new WifiNetwork("wifi3");
+ wifi3->set_name("Fake WiFi3 Encrypted with a long name");
wifi3->set_strength(60);
- wifi3->set_connected(false);
wifi3->set_encryption(SECURITY_WEP);
wifi3->set_passphrase_required(true);
wifi3->set_profile_type(PROFILE_USER);
- AddNetwork(wifi3);
+ AddStubNetwork(wifi3);
- WifiNetwork* wifi4 = new WifiNetwork("fw4");
- wifi4->set_name("Fake WiFi 802.1x");
+ WifiNetwork* wifi4 = new WifiNetwork("wifi4");
+ wifi4->set_name("Fake WiFi4 802.1x");
wifi4->set_strength(50);
- wifi4->set_connected(false);
wifi4->set_connectable(false);
wifi4->set_encryption(SECURITY_8021X);
wifi4->SetEAPMethod(EAP_METHOD_PEAP);
wifi4->SetEAPIdentity("nobody@google.com");
wifi4->SetEAPPassphrase("password");
- AddNetwork(wifi4);
+ AddStubNetwork(wifi4);
- WifiNetwork* wifi5 = new WifiNetwork("fw5");
- wifi5->set_name("Fake WiFi UTF-8 SSID ");
- wifi5->SetSsid("Fake WiFi UTF-8 SSID \u3042\u3044\u3046");
+ WifiNetwork* wifi5 = new WifiNetwork("wifi5");
+ wifi5->set_name("Fake WiFi5 UTF-8 SSID ");
+ wifi5->SetSsid("Fake WiFi5 UTF-8 SSID \u3042\u3044\u3046");
wifi5->set_strength(25);
- wifi5->set_connected(false);
- AddNetwork(wifi5);
+ AddStubNetwork(wifi5);
- WifiNetwork* wifi6 = new WifiNetwork("fw6");
- wifi6->set_name("Fake WiFi latin-1 SSID ");
- wifi6->SetSsid("Fake WiFi latin-1 SSID \xc0\xcb\xcc\xd6\xfb");
+ WifiNetwork* wifi6 = new WifiNetwork("wifi6");
+ wifi6->set_name("Fake WiFi6 latin-1 SSID ");
+ wifi6->SetSsid("Fake WiFi6 latin-1 SSID \xc0\xcb\xcc\xd6\xfb");
wifi6->set_strength(20);
- wifi6->set_connected(false);
- AddNetwork(wifi6);
-
- active_wifi_ = wifi1;
+ AddStubNetwork(wifi6);
- CellularNetwork* cellular1 = new CellularNetwork("fc1");
- cellular1->set_name("Fake Cellular");
+ CellularNetwork* cellular1 = new CellularNetwork("cellular1");
+ cellular1->set_name("Fake Cellular1 Connecting");
cellular1->set_strength(70);
- cellular1->set_connected(false);
cellular1->set_connecting(true);
cellular1->set_is_active(true);
cellular1->set_activation_state(ACTIVATION_STATE_ACTIVATED);
@@ -4699,71 +4764,67 @@ void NetworkLibraryImplStub::Init() {
cellular1->set_usage_url(std::string("http://www.google.com"));
cellular1->set_network_technology(NETWORK_TECHNOLOGY_EVDO);
cellular1->set_roaming_state(ROAMING_STATE_ROAMING);
+ AddStubNetwork(cellular1);
+
+ CellularNetwork* cellular2 = new CellularNetwork("cellular2");
+ cellular2->set_name("Fake Cellular2");
+ cellular2->set_strength(50);
+ cellular2->set_connected(false);
+ cellular2->set_activation_state(ACTIVATION_STATE_ACTIVATED);
+ cellular2->set_network_technology(NETWORK_TECHNOLOGY_UMTS);
+ AddStubNetwork(cellular2);
CellularDataPlan* base_plan = new CellularDataPlan();
base_plan->plan_name = "Base plan";
base_plan->plan_type = CELLULAR_DATA_PLAN_METERED_BASE;
base_plan->plan_data_bytes = 100ll * 1024 * 1024;
- base_plan->data_bytes_used = 75ll * 1024 * 1024;
- CellularDataPlanVector* data_plans = new CellularDataPlanVector();
- data_plan_map_[cellular1->service_path()] = data_plans;
- data_plans->push_back(base_plan);
+ base_plan->data_bytes_used = base_plan->plan_data_bytes / 4;
CellularDataPlan* paid_plan = new CellularDataPlan();
paid_plan->plan_name = "Paid plan";
paid_plan->plan_type = CELLULAR_DATA_PLAN_METERED_PAID;
paid_plan->plan_data_bytes = 5ll * 1024 * 1024 * 1024;
- paid_plan->data_bytes_used = 3ll * 1024 * 1024 * 1024;
- data_plans->push_back(paid_plan);
+ paid_plan->data_bytes_used = paid_plan->plan_data_bytes / 2;
- AddNetwork(cellular1);
- active_cellular_ = cellular1;
-
- CellularNetwork* cellular2 = new CellularNetwork("fc2");
- cellular2->set_name("Fake Cellular 2");
- cellular2->set_strength(70);
- cellular2->set_connected(true);
- cellular2->set_activation_state(ACTIVATION_STATE_ACTIVATED);
- cellular2->set_network_technology(NETWORK_TECHNOLOGY_UMTS);
- AddNetwork(cellular2);
+ CellularDataPlanVector* data_plan_vector = new CellularDataPlanVector;
+ data_plan_vector->push_back(base_plan);
+ data_plan_vector->push_back(paid_plan);
+ UpdateCellularDataPlan(cellular1->service_path(), data_plan_vector);
// VPNs
- VirtualNetwork* vpn1 = new VirtualNetwork("fv1");
- vpn1->set_name("Fake VPN Provider 1");
+ VirtualNetwork* vpn1 = new VirtualNetwork("vpn1");
+ vpn1->set_name("Fake VPN1");
vpn1->set_server_hostname("vpn1server.fake.com");
vpn1->set_provider_type(PROVIDER_TYPE_L2TP_IPSEC_PSK);
vpn1->set_username("VPN User 1");
- vpn1->set_connected(false);
- AddNetwork(vpn1);
+ AddStubNetwork(vpn1);
- VirtualNetwork* vpn2 = new VirtualNetwork("fv2");
- vpn2->set_name("Fake VPN Provider 2");
+ VirtualNetwork* vpn2 = new VirtualNetwork("vpn2");
+ vpn2->set_name("Fake VPN2");
vpn2->set_server_hostname("vpn2server.fake.com");
vpn2->set_provider_type(PROVIDER_TYPE_L2TP_IPSEC_USER_CERT);
vpn2->set_username("VPN User 2");
vpn2->set_connected(true);
- AddNetwork(vpn2);
+ vpn2->set_is_active(true);
+ AddStubNetwork(vpn2);
- VirtualNetwork* vpn3 = new VirtualNetwork("fv3");
- vpn3->set_name("Fake VPN Provider 3");
+ VirtualNetwork* vpn3 = new VirtualNetwork("vpn3");
+ vpn3->set_name("Fake VPN3");
vpn3->set_server_hostname("vpn3server.fake.com");
vpn3->set_provider_type(PROVIDER_TYPE_OPEN_VPN);
- vpn3->set_connected(false);
- AddNetwork(vpn3);
-
- active_virtual_ = vpn2;
+ AddStubNetwork(vpn3);
// Remembered Networks
DeleteRememberedNetworks();
NetworkProfile profile("default", PROFILE_SHARED);
- profile.services.insert("fw2");
- profile.services.insert("fv2");
+ profile.services.insert("wifi2");
+ profile.services.insert("vpn2");
profile_list_.push_back(profile);
- WifiNetwork* remembered_wifi2 = new WifiNetwork("fw2");
+ WifiNetwork* remembered_wifi2 = new WifiNetwork("wifi2");
remembered_wifi2->set_name("Fake WiFi 2");
remembered_wifi2->set_encryption(SECURITY_WEP);
AddRememberedNetwork(remembered_wifi2);
- VirtualNetwork* remembered_vpn2 = new VirtualNetwork("fv2");
+ VirtualNetwork* remembered_vpn2 = new VirtualNetwork("vpn2");
remembered_vpn2->set_name("Fake VPN Provider 2");
remembered_vpn2->set_server_hostname("vpn2server.fake.com");
remembered_vpn2->set_provider_type(
@@ -4779,6 +4840,7 @@ void NetworkLibraryImplStub::Init() {
// NetworkLibraryImplBase implementation.
void NetworkLibraryImplStub::CallConnectToNetwork(Network* network) {
+ network->set_connected(true);
NetworkConnectCompleted(network, CONNECT_SUCCESS);
}
@@ -4880,7 +4942,7 @@ NetworkLibrary* NetworkLibrary::GetImpl(bool stub) {
NetworkLibrary* impl;
// If CrosLibrary failed to load, use the stub implementation, since the
// cros implementation would crash on any libcros call.
- if (!CrosLibrary::Get()->libcros_loaded()) {
+ if (!stub && !CrosLibrary::Get()->libcros_loaded()) {
LOG(WARNING) << "NetworkLibrary: falling back to stub impl.";
stub = true;
}
diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h
index 04e7d67..87fe89b 100644
--- a/chrome/browser/chromeos/cros/network_library.h
+++ b/chrome/browser/chromeos/cros/network_library.h
@@ -551,6 +551,16 @@ class Network {
public:
virtual ~Network();
+ // Test API for accessing setters in tests.
+ class TestApi {
+ public:
+ explicit TestApi(Network* network) : network_(network) {}
+ void SetConnected(bool connected) { network_->set_connected(connected); }
+ private:
+ Network* network_;
+ };
+ friend class TestApi;
+
const std::string& service_path() const { return service_path_; }
const std::string& name() const { return name_; }
const std::string& device_path() const { return device_path_; }
@@ -880,6 +890,16 @@ typedef std::vector<VirtualNetwork*> VirtualNetworkVector;
// Base class for networks of TYPE_WIFI or TYPE_CELLULAR.
class WirelessNetwork : public Network {
public:
+ // Test API for accessing setters in tests.
+ class TestApi {
+ public:
+ explicit TestApi(WirelessNetwork* network) : network_(network) {}
+ void SetStrength(int strength) { network_->set_strength(strength); }
+ private:
+ WirelessNetwork* network_;
+ };
+ friend class TestApi;
+
int strength() const { return strength_; }
protected:
@@ -918,6 +938,18 @@ class CellularNetwork : public WirelessNetwork {
DATA_NONE
};
+ // Test API for accessing setters in tests.
+ class TestApi {
+ public:
+ explicit TestApi(CellularNetwork* network) : network_(network) {}
+ void SetRoamingState(NetworkRoamingState roaming_state) {
+ network_->set_roaming_state(roaming_state);
+ }
+ private:
+ CellularNetwork* network_;
+ };
+ friend class TestApi;
+
explicit CellularNetwork(const std::string& service_path);
virtual ~CellularNetwork();
@@ -1036,6 +1068,18 @@ typedef std::vector<CellularNetwork*> CellularNetworkVector;
// Class for networks of TYPE_WIFI.
class WifiNetwork : public WirelessNetwork {
public:
+ // Test API for accessing setters in tests.
+ class TestApi {
+ public:
+ explicit TestApi(WifiNetwork* network) : network_(network) {}
+ void SetEncryption(ConnectionSecurity encryption) {
+ network_->set_encryption(encryption);
+ }
+ private:
+ WifiNetwork* network_;
+ };
+ friend class TestApi;
+
explicit WifiNetwork(const std::string& service_path);
virtual ~WifiNetwork();
@@ -1642,6 +1686,14 @@ class NetworkLibrary {
// changes.
virtual void SwitchToPreferredNetwork() = 0;
+ // This sets the active network for the network type. Note: priority order
+ // is unchanged (i.e. if a wifi network is set to active, but an ethernet
+ // network is still active, active_network() will still return the ethernet
+ // network). Other networks of the same type will become inactive.
+ // Used for testing.
+ virtual bool SetActiveNetwork(ConnectionType type,
+ const std::string& service_path) = 0;
+
// Factory function, creates a new instance and returns ownership.
// For normal usage, access the singleton via CrosLibrary::Get().
static NetworkLibrary* GetImpl(bool stub);
diff --git a/chrome/browser/chromeos/cros/network_library_unittest.cc b/chrome/browser/chromeos/cros/network_library_unittest.cc
index 211b924..adc6315 100644
--- a/chrome/browser/chromeos/cros/network_library_unittest.cc
+++ b/chrome/browser/chromeos/cros/network_library_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
+#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -118,4 +119,112 @@ TEST(NetworkLibraryTest, DecodeNonAsciiSSID) {
}
}
+// Create a stub libcros for testing NetworkLibrary functionality through
+// NetworkLibraryStubImpl.
+// NOTE: It would be of little value to test stub functions that simply return
+// predefined values, e.g. ethernet_available(). However, many other functions
+// such as connected_network() return values which are set indirectly and thus
+// we can test the logic of those setters.
+
+class NetworkLibraryStubTest : public testing::Test {
+ public:
+ NetworkLibraryStubTest() : cros_(NULL) {}
+
+ protected:
+ virtual void SetUp() {
+ cros_ = CrosLibrary::Get()->GetNetworkLibrary();
+ ASSERT_TRUE(cros_) << "GetNetworkLibrary() Failed!";
+ }
+ virtual void TearDown() {
+ cros_ = NULL;
+ }
+
+ ScopedStubCrosEnabler cros_stub_;
+ NetworkLibrary* cros_;
+};
+
+// Default stub state:
+// eth1: connected
+// wifi1: connected
+// wifi2: connecting
+// wifi3: disconnected, WEP
+// wifi4: disconnected, 8021x
+// wifi5: disconnected
+// wifi6: disconnected
+// cellular1: connecting, activated, roaming
+// cellular2: disconnected, activated, not roaming
+// vpn1: disconnected, L2TP/IPsec + PSK
+// vpn2: connected, L2TP/IPsec + user cert
+// vpn3: disconnected, OpenVpn
+
+TEST_F(NetworkLibraryStubTest, NetworkLibraryAccessors) {
+ // Ethernet
+ ASSERT_NE(static_cast<const EthernetNetwork*>(NULL),
+ cros_->ethernet_network());
+ EXPECT_EQ("eth1", cros_->ethernet_network()->service_path());
+ EXPECT_NE(static_cast<const Network*>(NULL),
+ cros_->FindNetworkByPath("eth1"));
+ EXPECT_TRUE(cros_->ethernet_connected());
+ EXPECT_FALSE(cros_->ethernet_connecting());
+
+ // Wifi
+ ASSERT_NE(static_cast<const WifiNetwork*>(NULL), cros_->wifi_network());
+ EXPECT_EQ("wifi1", cros_->wifi_network()->service_path());
+ EXPECT_NE(static_cast<const WifiNetwork*>(NULL),
+ cros_->FindWifiNetworkByPath("wifi1"));
+ EXPECT_TRUE(cros_->wifi_connected());
+ EXPECT_FALSE(cros_->wifi_connecting()); // Only true for active wifi.
+ EXPECT_EQ(6U, cros_->wifi_networks().size());
+
+ // Cellular
+ ASSERT_NE(static_cast<const CellularNetwork*>(NULL),
+ cros_->cellular_network());
+ EXPECT_EQ("cellular1", cros_->cellular_network()->service_path());
+ EXPECT_NE(static_cast<const CellularNetwork*>(NULL),
+ cros_->FindCellularNetworkByPath("cellular1"));
+ EXPECT_FALSE(cros_->cellular_connected());
+ EXPECT_TRUE(cros_->cellular_connecting());
+ EXPECT_EQ(2U, cros_->cellular_networks().size());
+
+ // VPN
+ ASSERT_NE(static_cast<const VirtualNetwork*>(NULL), cros_->virtual_network());
+ EXPECT_EQ("vpn2", cros_->virtual_network()->service_path());
+ EXPECT_NE(static_cast<const VirtualNetwork*>(NULL),
+ cros_->FindVirtualNetworkByPath("vpn1"));
+ EXPECT_TRUE(cros_->virtual_network_connected());
+ EXPECT_FALSE(cros_->virtual_network_connecting());
+ EXPECT_EQ(3U, cros_->virtual_networks().size());
+
+ // Active network and global state
+ EXPECT_TRUE(cros_->Connected());
+ EXPECT_TRUE(cros_->Connecting());
+ EXPECT_EQ("eth1", cros_->active_network()->service_path());
+ EXPECT_EQ("eth1", cros_->connected_network()->service_path());
+ // The "wifi1" is connected, so we do not return "wifi2" for the connecting
+ // network. There is no conencted cellular network, so "cellular1" is
+ // returned by connecting_network().
+ EXPECT_EQ("cellular1", cros_->connecting_network()->service_path());
+}
+
+TEST_F(NetworkLibraryStubTest, NetworkConnect) {
+ WifiNetwork* wifi1 = cros_->FindWifiNetworkByPath("wifi1");
+ ASSERT_NE(static_cast<const WifiNetwork*>(NULL), wifi1);
+ EXPECT_TRUE(wifi1->connected());
+ cros_->DisconnectFromNetwork(wifi1);
+ EXPECT_FALSE(wifi1->connected());
+ EXPECT_TRUE(cros_->CanConnectToNetwork(wifi1));
+ cros_->ConnectToWifiNetwork(wifi1);
+ EXPECT_TRUE(wifi1->connected());
+}
+
+// TODO(stevenjb): Test remembered networks.
+
+// TODO(stevenjb): Test network profiles.
+
+// TODO(stevenjb): Test network devices.
+
+// TODO(stevenjb): Test data plans.
+
+// TODO(stevenjb): Test monitor network / device.
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/status/network_menu_icon.cc b/chrome/browser/chromeos/status/network_menu_icon.cc
index 967754c..546229a 100644
--- a/chrome/browser/chromeos/status/network_menu_icon.cc
+++ b/chrome/browser/chromeos/status/network_menu_icon.cc
@@ -221,8 +221,10 @@ class NetworkIcon {
if (!network) {
// If not a visible network, check for a remembered network.
network = cros->FindRememberedNetworkByPath(service_path_);
- if (!network)
+ if (!network) {
+ LOG(WARNING) << "Unable to find network:" << service_path_;
return;
+ }
}
bool dirty = bitmap_.empty();
if (state_ != network->state()) {
@@ -365,28 +367,13 @@ class NetworkIcon {
void GenerateBitmap() {
if (!icon_)
return;
-
- gfx::CanvasSkia canvas(icon_->width(), icon_->height(), false);
- canvas.DrawBitmapInt(*icon_, 0, 0);
-
- if (top_left_badge_) {
- canvas.DrawBitmapInt(
- *top_left_badge_, kBadgeLeftX, kBadgeTopY);
- }
- if (top_right_badge_) {
- canvas.DrawBitmapInt(
- *top_right_badge_, kBadgeRightX, kBadgeTopY);
- }
- if (bottom_left_badge_) {
- canvas.DrawBitmapInt(
- *bottom_left_badge_, kBadgeLeftX, kBadgeBottomY);
- }
- if (bottom_right_badge_) {
- canvas.DrawBitmapInt(
- *bottom_right_badge_, kBadgeRightX, kBadgeBottomY);
- }
-
- bitmap_ = canvas.ExtractBitmap();
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ icon_,
+ top_left_badge_,
+ top_right_badge_,
+ bottom_left_badge_,
+ bottom_right_badge_,
+ &bitmap_);
}
const SkBitmap* GetBitmap() const { return &bitmap_; }
@@ -431,11 +418,6 @@ NetworkMenuIcon::NetworkMenuIcon(Delegate* delegate, Mode mode)
last_network_type_(TYPE_WIFI) {
// Generate empty images for blending.
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- const SkBitmap* source_badge = rb.GetBitmapNamed(kArcsImages[0]);
- empty_badge_.setConfig(SkBitmap::kARGB_8888_Config,
- source_badge->width(), source_badge->height(), 0);
- empty_badge_.allocPixels();
- empty_badge_.eraseARGB(0, 0, 0, 0);
const SkBitmap* vpn_badge = rb.GetBitmapNamed(kVpnBadgeId);
empty_vpn_badge_.setConfig(SkBitmap::kARGB_8888_Config,
vpn_badge->width(), vpn_badge->height(), 0);
@@ -521,8 +503,7 @@ void NetworkMenuIcon::SetConnectingIcon(const Network* network,
if (images[index].empty()) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
SkBitmap* source = rb.GetBitmapNamed(source_image_ids[1 + index]);
- images[index] = SkBitmapOperations::CreateBlendedBitmap(
- empty_badge_, *source, kConnectingImageAlpha);
+ NetworkMenuIcon::GenerateConnectingBitmap(source, &images[index]);
}
icon_->set_icon(&images[index]);
}
@@ -651,9 +632,59 @@ void NetworkMenuIcon::SetIconAndText(string16* text) {
}
}
+////////////////////////////////////////////////////////////////////////////////
// Static functions for generating network icon bitmaps:
-// Generatings an icon bitmap for a network's current state.
+// This defines how we assemble a network icon.
+void NetworkMenuIcon::GenerateBitmapFromComponents(
+ const SkBitmap* icon,
+ const SkBitmap* top_left_badge,
+ const SkBitmap* top_right_badge,
+ const SkBitmap* bottom_left_badge,
+ const SkBitmap* bottom_right_badge,
+ SkBitmap* result) {
+ DCHECK(icon);
+ DCHECK(result);
+ gfx::CanvasSkia canvas(icon->width(), icon->height(), false);
+ canvas.DrawBitmapInt(*icon, 0, 0);
+
+ if (top_left_badge) {
+ canvas.DrawBitmapInt(
+ *top_left_badge, kBadgeLeftX, kBadgeTopY);
+ }
+ if (top_right_badge) {
+ canvas.DrawBitmapInt(
+ *top_right_badge, kBadgeRightX, kBadgeTopY);
+ }
+ if (bottom_left_badge) {
+ canvas.DrawBitmapInt(
+ *bottom_left_badge, kBadgeLeftX, kBadgeBottomY);
+ }
+ if (bottom_right_badge) {
+ canvas.DrawBitmapInt(
+ *bottom_right_badge, kBadgeRightX, kBadgeBottomY);
+ }
+
+ *result = canvas.ExtractBitmap();
+}
+
+// We blend connecting icons with a black image to generate a faded icon.
+void NetworkMenuIcon::GenerateConnectingBitmap(
+ const SkBitmap* source, SkBitmap* image) {
+ static SkBitmap empty_badge;
+ if (empty_badge.empty()) {
+ empty_badge.setConfig(SkBitmap::kARGB_8888_Config,
+ source->width(), source->height(), 0);
+ empty_badge.allocPixels();
+ empty_badge.eraseARGB(0, 0, 0, 0);
+ }
+ DCHECK(empty_badge.width() == source->width());
+ DCHECK(empty_badge.height() == source->height());
+ *image = SkBitmapOperations::CreateBlendedBitmap(
+ empty_badge, *source, kConnectingImageAlpha);
+}
+
+// Generates and caches an icon bitmap for a network's current state.
const SkBitmap* NetworkMenuIcon::GetBitmap(const Network* network) {
DCHECK(network);
// Maintain a static (global) icon map. Note: Icons are never destroyed;
diff --git a/chrome/browser/chromeos/status/network_menu_icon.h b/chrome/browser/chromeos/status/network_menu_icon.h
index 7171e09..35b2685 100644
--- a/chrome/browser/chromeos/status/network_menu_icon.h
+++ b/chrome/browser/chromeos/status/network_menu_icon.h
@@ -43,25 +43,39 @@ class NetworkMenuIcon : public ui::AnimationDelegate {
const SkBitmap* GetIconAndText(string16* text);
// ui::AnimationDelegate implementation.
- virtual void AnimationProgressed(const ui::Animation* animation);
+ virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
// Static functions for generating network icon bitmaps:
+ // Composites the bitmaps to generate a network icon.
+ static void GenerateBitmapFromComponents(
+ const SkBitmap* icon,
+ const SkBitmap* top_left_badge,
+ const SkBitmap* top_right_badge,
+ const SkBitmap* bottom_left_badge,
+ const SkBitmap* bottom_right_badge,
+ SkBitmap* result);
+
+ // Sets a blended bitmap for connecting images.
+ static void GenerateConnectingBitmap(const SkBitmap* source, SkBitmap* image);
+
// Returns a bitmap associated with |network|, reflecting its current state.
static const SkBitmap* GetBitmap(const Network* network);
// Returns a bitmap representing an unconnected VPN.
static const SkBitmap* GetVpnBitmap();
+ protected:
+ // Virtual for testing.
+ virtual double GetAnimation();
+
private:
- double GetAnimation();
const Network* GetConnectingNetwork();
void SetConnectingIcon(const Network* network, double animation);
void SetIconAndText(string16* text);
Mode mode_;
Delegate* delegate_;
- SkBitmap empty_badge_;
SkBitmap empty_vpn_badge_;
SkBitmap vpn_connecting_badge_;
ui::ThrobAnimation animation_connecting_;
diff --git a/chrome/browser/chromeos/status/network_menu_icon_unittest.cc b/chrome/browser/chromeos/status/network_menu_icon_unittest.cc
new file mode 100644
index 0000000..f53d029
--- /dev/null
+++ b/chrome/browser/chromeos/status/network_menu_icon_unittest.cc
@@ -0,0 +1,333 @@
+// Copyright (c) 2011 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 "chrome/browser/chromeos/status/network_menu_icon.h"
+
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "grit/theme_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+bool CompareBitmaps(const SkBitmap* a, const SkBitmap* b) {
+ CHECK(a);
+ CHECK(b);
+ if (a->getSize() != b->getSize()) {
+ LOG(WARNING) << "Mistmatched size: "
+ << a->getSize() << " != " << b->getSize();
+ return false;
+ }
+ size_t bytes = a->getSize();
+ SkAutoLockPixels locka(*a);
+ SkAutoLockPixels lockb(*b);
+ const char* pixa = static_cast<const char*>(a->getPixels());
+ const char* pixb = static_cast<const char*>(b->getPixels());
+ if (!pixa || !pixb) {
+ if (!pixa)
+ LOG(WARNING) << "getPixels() returned NULL for LHS";
+ if (!pixb)
+ LOG(WARNING) << "getPixels() returned NULL for RHS";
+ return false;
+ }
+ size_t width = a->width();
+ size_t height = a->height();
+ size_t bpp = a->bytesPerPixel();
+ if (width * height * bpp != bytes) {
+ LOG(WARNING) << "Width: " << width << " x Height: " << height
+ << " x bpp: " << bpp << " != Size: " << bytes;
+ return false;
+ }
+ for (int y=0; y<a->height(); ++y) {
+ for (int x=0; x<a->width(); ++x) {
+ for (size_t i = 0; i<bpp; ++i) {
+ if (*pixa++ != *pixb++) {
+ LOG(WARNING) << "Icon: " << width << " x " << height << " x " << bpp
+ << ", Mismatch at: " << x << "," << y << ":" << i;
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+namespace chromeos {
+
+class NetworkMenuIconTest : public testing::Test {
+ protected:
+ NetworkMenuIconTest() : rb_(ResourceBundle::GetSharedInstance()) {}
+
+ // testing::Test implementation.
+ virtual void SetUp() OVERRIDE {
+ cros_ = CrosLibrary::Get()->GetNetworkLibrary();
+ // Ethernet connected = WIRED icon, no badges.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_WIRED),
+ NULL, NULL, NULL, NULL,
+ &ethernet_connected_bitmap_);
+ // Ethernet disonnected = WIRED icon + DISCONNECTED badge.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_WIRED),
+ NULL, NULL, NULL,
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED),
+ &ethernet_disconnected_bitmap_);
+ // Wifi connected, strength = 100% = ARCS7 icon, no badges.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_ARCS7),
+ NULL, NULL, NULL, NULL,
+ &wifi_connected_100_bitmap_);
+ // Wifi connected, strength = 50%, encrypted = ARCS4 icon + SECURE badge.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_ARCS4),
+ NULL, NULL, NULL, rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE),
+ &wifi_encrypted_50_bitmap_);
+ // Wifi disconnected (strength = 0%) = ARCS0 icon.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_ARCS0),
+ NULL, NULL, NULL, NULL,
+ &wifi_disconnected_bitmap_);
+ // Wifi connecting = IDR_STATUSBAR_NETWORK_ARCS1 (faded).
+ NetworkMenuIcon::GenerateConnectingBitmap(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_ARCS1),
+ &wifi_connecting_bitmap_);
+ // 3G connected, strength = 100% = BARS4 icon + 3G badge.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS4),
+ NULL, NULL, NULL, rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G),
+ &cellular_connected_100_bitmap_);
+ // 3G connected, strength = 50%, roaming = BARS2 icon + roaming & 3G badges.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS3),
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_ROAMING), NULL,
+ NULL, rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G),
+ &cellular_roaming_50_bitmap_);
+ // 3G disconnected (strength = 0%) = BARS0 icon + 3G badge.
+ NetworkMenuIcon::GenerateBitmapFromComponents(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0),
+ NULL, NULL, NULL, rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G),
+ &cellular_disconnected_bitmap_);
+ // 3G connecting = IDR_STATUSBAR_NETWORK_BARS1 (faded).
+ NetworkMenuIcon::GenerateConnectingBitmap(
+ rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS1),
+ &cellular_connecting_bitmap_);
+ }
+ virtual void TearDown() OVERRIDE {
+ }
+
+ void SetConnected(Network* network, bool connected) {
+ Network::TestApi test_network(network);
+ test_network.SetConnected(connected);
+ }
+ void SetActive(Network* network, bool active) {
+ if (active) {
+ cros_->SetActiveNetwork(network->type(), network->service_path());
+ } else {
+ cros_->SetActiveNetwork(network->type(), "");
+ }
+ }
+ void SetStrength(WirelessNetwork* network, int strength) {
+ WirelessNetwork::TestApi test_network(network);
+ test_network.SetStrength(strength);
+ }
+ void SetEncryption(WifiNetwork* network, ConnectionSecurity encryption) {
+ WifiNetwork::TestApi test_network(network);
+ test_network.SetEncryption(encryption);
+ }
+ void SetRoamingState(CellularNetwork* network, NetworkRoamingState roaming) {
+ CellularNetwork::TestApi test_network(network);
+ test_network.SetRoamingState(roaming);
+ }
+
+ ScopedStubCrosEnabler cros_stub_;
+ NetworkLibrary* cros_;
+ ResourceBundle& rb_;
+ SkBitmap ethernet_connected_bitmap_;
+ SkBitmap ethernet_disconnected_bitmap_;
+ SkBitmap wifi_connected_100_bitmap_;
+ SkBitmap wifi_encrypted_50_bitmap_;
+ SkBitmap wifi_disconnected_bitmap_;
+ SkBitmap wifi_connecting_bitmap_;
+ SkBitmap cellular_connected_100_bitmap_;
+ SkBitmap cellular_roaming_50_bitmap_;
+ SkBitmap cellular_disconnected_bitmap_;
+ SkBitmap cellular_connecting_bitmap_;
+};
+
+// Test icon cache consistency.
+TEST_F(NetworkMenuIconTest, NetworkIconCache) {
+ Network* network1 = cros_->FindNetworkByPath("wifi1"); // connected
+ Network* network2 = cros_->FindNetworkByPath("wifi2"); // connecting
+ ASSERT_NE(static_cast<const Network*>(NULL), network1);
+ ASSERT_NE(static_cast<const Network*>(NULL), network2);
+ // Different network paths should return different icons.
+ const SkBitmap* icon1 = NetworkMenuIcon::GetBitmap(network1);
+ const SkBitmap* icon2 = NetworkMenuIcon::GetBitmap(network2);
+ EXPECT_NE(icon1, icon2);
+ // Same network paths should return the same icon.
+ const SkBitmap* icon1b = NetworkMenuIcon::GetBitmap(network1);
+ EXPECT_EQ(icon1, icon1b);
+ // Changing properties of a network should update the icon, but not change
+ // the returned pointer.
+ SetConnected(network2, false);
+ const SkBitmap* icon2b = NetworkMenuIcon::GetBitmap(network2);
+ EXPECT_EQ(icon2, icon2b);
+}
+
+// Compare icon cache results against expected results fron SetUp().
+TEST_F(NetworkMenuIconTest, EthernetIcon) {
+ Network* network = cros_->FindNetworkByPath("eth1");
+ ASSERT_NE(static_cast<const Network*>(NULL), network);
+ SetConnected(network, true);
+ const SkBitmap* icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &ethernet_connected_bitmap_));
+
+ SetConnected(network, false);
+ icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &ethernet_disconnected_bitmap_));
+}
+
+TEST_F(NetworkMenuIconTest, WifiIcon) {
+ WifiNetwork* network = cros_->FindWifiNetworkByPath("wifi1");
+ ASSERT_NE(static_cast<const Network*>(NULL), network);
+ const SkBitmap* icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &wifi_connected_100_bitmap_));
+
+ SetStrength(network, 50);
+ SetEncryption(network, SECURITY_RSN);
+ icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &wifi_encrypted_50_bitmap_));
+
+ SetConnected(network, false);
+ SetStrength(network, 0);
+ SetEncryption(network, SECURITY_NONE);
+ icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &wifi_disconnected_bitmap_));
+}
+
+TEST_F(NetworkMenuIconTest, CellularIcon) {
+ CellularNetwork* network = cros_->FindCellularNetworkByPath("cellular1");
+ ASSERT_NE(static_cast<const Network*>(NULL), network);
+ SetConnected(network, true);
+ SetStrength(network, 100);
+ SetRoamingState(network, ROAMING_STATE_HOME);
+ const SkBitmap* icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &cellular_connected_100_bitmap_));
+
+ SetStrength(network, 50);
+ SetRoamingState(network, ROAMING_STATE_ROAMING);
+ icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &cellular_roaming_50_bitmap_));
+
+ SetConnected(network, false);
+ SetStrength(network, 0);
+ SetRoamingState(network, ROAMING_STATE_HOME);
+ icon = NetworkMenuIcon::GetBitmap(network);
+ EXPECT_TRUE(CompareBitmaps(icon, &cellular_disconnected_bitmap_));
+}
+
+namespace {
+
+class TestNetworkMenuIcon : public NetworkMenuIcon {
+ public:
+ explicit TestNetworkMenuIcon(Mode mode)
+ : NetworkMenuIcon(&delegate_, mode),
+ animation_(0.0) {
+ }
+ virtual ~TestNetworkMenuIcon() {}
+
+ // NetworkMenuIcon override.
+ virtual double GetAnimation() OVERRIDE { return animation_; }
+
+ void set_animation(double animation) { animation_ = animation; }
+
+ private:
+ class Delegate : public NetworkMenuIcon::Delegate {
+ public:
+ Delegate() : changed_(0) {}
+ virtual void NetworkMenuIconChanged() OVERRIDE {
+ ++changed_;
+ }
+ int changed() const { return changed_; }
+ private:
+ int changed_;
+ };
+ Delegate delegate_;
+ double animation_;
+};
+
+
+} // namespace
+
+// Test Network Menu status icon logic.
+
+// Default relevent stub state:
+// eth1: connected (active ethernet)
+// wifi1: connected, strength 100 (active wifi)
+// wifi2: connecting
+// wifi3: disconnected, WEP
+// cellular1: connecting, activated, roaming (active cellular)
+// See network_library_unit_test.cc for more info.
+
+TEST_F(NetworkMenuIconTest, StatusIconMenuMode) {
+ TestNetworkMenuIcon menu_icon(NetworkMenuIcon::MENU_MODE);
+ const SkBitmap* icon;
+
+ // Set up the initial network state.
+ CellularNetwork* cellular1 = cros_->FindCellularNetworkByPath("cellular1");
+ ASSERT_NE(static_cast<const Network*>(NULL), cellular1);
+ SetRoamingState(cellular1, ROAMING_STATE_HOME); // Clear romaing state
+
+ // For MENU_MODE, we always display the connecting icon (cellular1).
+ icon = menu_icon.GetIconAndText(NULL);
+ EXPECT_TRUE(CompareBitmaps(icon, &cellular_connecting_bitmap_));
+
+ // Set cellular1 to connected; ethernet icon should be shown.
+ SetConnected(cellular1, true);
+ icon = menu_icon.GetIconAndText(NULL);
+ EXPECT_TRUE(CompareBitmaps(icon, &ethernet_connected_bitmap_));
+
+ // Set ethernet to inactive/disconnected; wifi icon should be shown.
+ Network* eth1 = cros_->FindNetworkByPath("eth1");
+ ASSERT_NE(static_cast<const Network*>(NULL), eth1);
+ SetActive(eth1, false);
+ SetConnected(eth1, false);
+ icon = menu_icon.GetIconAndText(NULL);
+ EXPECT_TRUE(CompareBitmaps(icon, &wifi_connected_100_bitmap_));
+}
+
+TEST_F(NetworkMenuIconTest, StatusIconDropdownMode) {
+ TestNetworkMenuIcon menu_icon(NetworkMenuIcon::DROPDOWN_MODE);
+ const SkBitmap* icon;
+
+ // Start with the default stub network state.
+
+ // For DROPDOWN_MODE, we prioritize the connected network (ethernet).
+ icon = menu_icon.GetIconAndText(NULL);
+ EXPECT_TRUE(CompareBitmaps(icon, &ethernet_connected_bitmap_));
+
+ // Set ethernet to disconnected+inactive; wifi icon should be shown.
+ Network* ethernet = cros_->FindNetworkByPath("eth1");
+ ASSERT_NE(static_cast<const Network*>(NULL), ethernet);
+ SetActive(ethernet, false);
+ SetConnected(ethernet, false);
+
+ icon = menu_icon.GetIconAndText(NULL);
+ EXPECT_TRUE(CompareBitmaps(icon, &wifi_connected_100_bitmap_));
+
+ // Set wifi2 to active; wifi connecting icon should be shown.
+ WifiNetwork* wifi1 = cros_->FindWifiNetworkByPath("wifi1");
+ WifiNetwork* wifi2 = cros_->FindWifiNetworkByPath("wifi2");
+ ASSERT_NE(static_cast<const Network*>(NULL), wifi2);
+ SetConnected(wifi1, false);
+ SetActive(wifi2, true);
+
+ icon = menu_icon.GetIconAndText(NULL);
+ EXPECT_TRUE(CompareBitmaps(icon, &wifi_connecting_bitmap_));
+}
+
+} // namespace chromeos
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index c0d8a8d..a9e19a4 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1187,6 +1187,8 @@
'browser/chromeos/login/user_controller_unittest.cc',
'browser/chromeos/login/wizard_accessibility_handler_unittest.cc',
'browser/chromeos/mobile_config_unittest.cc',
+ 'browser/chromeos/status/network_menu_icon.cc',
+ 'browser/chromeos/status/network_menu_icon_unittest.cc',
'browser/chromeos/system/name_value_pairs_parser_unittest.cc',
'browser/chromeos/network_message_observer_unittest.cc',
'browser/chromeos/notifications/desktop_notifications_unittest.cc',