diff options
-rw-r--r-- | chrome/browser/chromeos/cros/mock_network_library.h | 1 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/network_library.cc | 268 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/network_library.h | 52 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/network_library_unittest.cc | 109 | ||||
-rw-r--r-- | chrome/browser/chromeos/status/network_menu_icon.cc | 93 | ||||
-rw-r--r-- | chrome/browser/chromeos/status/network_menu_icon.h | 20 | ||||
-rw-r--r-- | chrome/browser/chromeos/status/network_menu_icon_unittest.cc | 333 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 |
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, + ðernet_connected_bitmap_); + // Ethernet disonnected = WIRED icon + DISCONNECTED badge. + NetworkMenuIcon::GenerateBitmapFromComponents( + rb_.GetBitmapNamed(IDR_STATUSBAR_WIRED), + NULL, NULL, NULL, + rb_.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED), + ðernet_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, ðernet_connected_bitmap_)); + + SetConnected(network, false); + icon = NetworkMenuIcon::GetBitmap(network); + EXPECT_TRUE(CompareBitmaps(icon, ðernet_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, ðernet_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, ðernet_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', |