active_network_icon_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. // Copyright 2019 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. #include "ash/system/network/active_network_icon.h"
  5. #include <memory>
  6. #include <string>
  7. #include "ash/public/cpp/network_config_service.h"
  8. #include "ash/strings/grit/ash_strings.h"
  9. #include "ash/system/network/network_icon.h"
  10. #include "ash/system/network/tray_network_state_model.h"
  11. #include "ash/test/ash_test_base.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/strings/utf_string_conversions.h"
  14. #include "chromeos/ash/components/network/network_state_handler.h"
  15. #include "chromeos/ash/components/network/network_state_test_helper.h"
  16. #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
  17. #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
  18. #include "ui/base/l10n/l10n_util.h"
  19. #include "ui/gfx/image/image_unittest_util.h"
  20. using chromeos::network_config::mojom::ConnectionStateType;
  21. using chromeos::network_config::mojom::NetworkType;
  22. namespace ash {
  23. namespace {
  24. const char kShillManagerClientStubCellularDevice[] =
  25. "/device/stub_cellular_device";
  26. const char kCellularNetworkGuid[] = "cellular_guid";
  27. const char16_t kCellularNetworkGuid16[] = u"cellular_guid";
  28. } // namespace
  29. class ActiveNetworkIconTest : public AshTestBase {
  30. public:
  31. ActiveNetworkIconTest() = default;
  32. ActiveNetworkIconTest(const ActiveNetworkIconTest&) = delete;
  33. ActiveNetworkIconTest& operator=(const ActiveNetworkIconTest&) = delete;
  34. ~ActiveNetworkIconTest() override = default;
  35. void SetUp() override {
  36. AshTestBase::SetUp();
  37. network_state_model_ = std::make_unique<TrayNetworkStateModel>();
  38. active_network_icon_ =
  39. std::make_unique<ActiveNetworkIcon>(network_state_model_.get());
  40. }
  41. void TearDown() override {
  42. active_network_icon_.reset();
  43. AshTestBase::TearDown();
  44. }
  45. void SetupEthernet() {
  46. if (eth_path_.empty()) {
  47. network_state_helper().device_test()->AddDevice(
  48. "/device/stub_eth_device", shill::kTypeEthernet, "stub_eth_device");
  49. eth_path_ = ConfigureService(
  50. R"({"GUID": "eth_guid", "Type": "ethernet", "State": "online"})");
  51. }
  52. base::RunLoop().RunUntilIdle();
  53. }
  54. void SetupWiFi(const char* state) {
  55. if (wifi_path_.empty()) {
  56. // WiFi device already exists.
  57. wifi_path_ = ConfigureService(
  58. R"({"GUID": "wifi_guid", "Type": "wifi", "State": "idle"})");
  59. }
  60. SetServiceProperty(wifi_path_, shill::kStateProperty, base::Value(state));
  61. SetServiceProperty(wifi_path_, shill::kSignalStrengthProperty,
  62. base::Value(100));
  63. base::RunLoop().RunUntilIdle();
  64. }
  65. void SetupCellular(const char* state) {
  66. if (cellular_path_.empty()) {
  67. network_state_helper().manager_test()->AddTechnology(shill::kTypeCellular,
  68. true /* enabled */);
  69. network_state_helper().AddDevice(kShillManagerClientStubCellularDevice,
  70. shill::kTypeCellular,
  71. "stub_cellular_device");
  72. cellular_path_ = ConfigureService(base::StringPrintf(
  73. R"({"GUID": "%s", "Type": "cellular", "Technology": "LTE",
  74. "State": "idle"})",
  75. kCellularNetworkGuid));
  76. SetServiceProperty(cellular_path_, shill::kDeviceProperty,
  77. base::Value(kShillManagerClientStubCellularDevice));
  78. }
  79. SetServiceProperty(cellular_path_, shill::kStateProperty,
  80. base::Value(state));
  81. SetServiceProperty(cellular_path_, shill::kSignalStrengthProperty,
  82. base::Value(100));
  83. base::RunLoop().RunUntilIdle();
  84. }
  85. void SetCellularUninitialized(bool scanning) {
  86. const bool enabled = scanning;
  87. network_state_helper().manager_test()->RemoveTechnology(
  88. shill::kTypeCellular);
  89. network_state_helper().manager_test()->AddTechnology(shill::kTypeCellular,
  90. enabled);
  91. network_state_helper().device_test()->AddDevice(
  92. kShillManagerClientStubCellularDevice, shill::kTypeCellular,
  93. "stub_cellular_device");
  94. if (scanning) {
  95. network_state_helper().device_test()->SetDeviceProperty(
  96. kShillManagerClientStubCellularDevice, shill::kScanningProperty,
  97. base::Value(true), true /* notify_changed */);
  98. } else {
  99. network_state_helper().manager_test()->SetTechnologyInitializing(
  100. shill::kTypeCellular, true);
  101. }
  102. base::RunLoop().RunUntilIdle();
  103. }
  104. gfx::ImageSkia ImageForNetwork(
  105. chromeos::network_config::mojom::NetworkType type,
  106. chromeos::network_config::mojom::ConnectionStateType connection_state,
  107. int signal_strength = 100) {
  108. std::string id = base::StringPrintf("reference_%d", reference_count_++);
  109. chromeos::network_config::mojom::NetworkStatePropertiesPtr
  110. reference_properties =
  111. network_config_helper_.CreateStandaloneNetworkProperties(
  112. id, type, connection_state, signal_strength);
  113. return network_icon::GetImageForNonVirtualNetwork(
  114. reference_properties.get(), icon_type_, false /* show_vpn_badge */);
  115. }
  116. bool AreImagesEqual(const gfx::ImageSkia& image,
  117. const gfx::ImageSkia& reference) {
  118. return gfx::test::AreBitmapsEqual(*image.bitmap(), *reference.bitmap());
  119. }
  120. std::string ConfigureService(const std::string& shill_json_string) {
  121. return network_state_helper().ConfigureService(shill_json_string);
  122. }
  123. void SetServiceProperty(const std::string& service_path,
  124. const std::string& key,
  125. const base::Value& value) {
  126. network_state_helper().SetServiceProperty(service_path, key, value);
  127. }
  128. NetworkStateTestHelper& network_state_helper() {
  129. return network_config_helper_.network_state_helper();
  130. }
  131. NetworkStateHandler* network_state_handler() {
  132. return network_state_helper().network_state_handler();
  133. }
  134. ActiveNetworkIcon* active_network_icon() {
  135. return active_network_icon_.get();
  136. }
  137. TrayNetworkStateModel* network_state_model() {
  138. return network_state_model_.get();
  139. }
  140. const std::string& eth_path() const { return eth_path_; }
  141. const std::string& wifi_path() const { return wifi_path_; }
  142. const std::string& cellular_path() const { return cellular_path_; }
  143. network_icon::IconType icon_type() { return icon_type_; }
  144. private:
  145. chromeos::network_config::CrosNetworkConfigTestHelper network_config_helper_;
  146. std::unique_ptr<TrayNetworkStateModel> network_state_model_;
  147. std::unique_ptr<ActiveNetworkIcon> active_network_icon_;
  148. std::string eth_path_;
  149. std::string wifi_path_;
  150. std::string cellular_path_;
  151. network_icon::IconType icon_type_ = network_icon::ICON_TYPE_TRAY_REGULAR;
  152. // Counter to provide unique ids for reference networks.
  153. int reference_count_ = 0;
  154. };
  155. TEST_F(ActiveNetworkIconTest, GetConnectionStatusStrings) {
  156. // TODO(902409): Test multi icon and improve coverage.
  157. SetupCellular(shill::kStateOnline);
  158. std::u16string name, desc, tooltip;
  159. active_network_icon()->GetConnectionStatusStrings(
  160. ActiveNetworkIcon::Type::kSingle, &name, &desc, &tooltip);
  161. // Note: The guid is used for the name in ConfigureService.
  162. EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED,
  163. kCellularNetworkGuid16),
  164. name);
  165. EXPECT_EQ(
  166. l10n_util::GetStringFUTF16(
  167. IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED_TOOLTIP, kCellularNetworkGuid16,
  168. l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_STRONG)),
  169. tooltip);
  170. }
  171. TEST_F(ActiveNetworkIconTest, GetSingleImage) {
  172. // Cellular only = Cellular icon
  173. SetupCellular(shill::kStateOnline);
  174. bool animating;
  175. gfx::ImageSkia image = active_network_icon()->GetImage(
  176. ActiveNetworkIcon::Type::kSingle, icon_type(), &animating);
  177. EXPECT_TRUE(AreImagesEqual(
  178. image,
  179. ImageForNetwork(NetworkType::kCellular, ConnectionStateType::kOnline)));
  180. EXPECT_FALSE(animating);
  181. // Cellular + WiFi connected = WiFi connected icon
  182. SetupWiFi(shill::kStateOnline);
  183. image = active_network_icon()->GetImage(ActiveNetworkIcon::Type::kSingle,
  184. icon_type(), &animating);
  185. EXPECT_TRUE(AreImagesEqual(
  186. image,
  187. ImageForNetwork(NetworkType::kWiFi, ConnectionStateType::kOnline)));
  188. EXPECT_FALSE(animating);
  189. // Cellular + WiFi connecting = WiFi connecting icon
  190. SetupWiFi(shill::kStateAssociation);
  191. network_state_handler()->SetNetworkConnectRequested(wifi_path(), true);
  192. SetServiceProperty(wifi_path(), shill::kSignalStrengthProperty,
  193. base::Value(50));
  194. base::RunLoop().RunUntilIdle();
  195. image = active_network_icon()->GetImage(ActiveNetworkIcon::Type::kSingle,
  196. icon_type(), &animating);
  197. EXPECT_TRUE(AreImagesEqual(
  198. image, ImageForNetwork(NetworkType::kWiFi,
  199. ConnectionStateType::kConnecting, 50)));
  200. EXPECT_TRUE(animating);
  201. // Cellular + WiFi connecting + Ethernet = WiFi connecting icon
  202. SetupEthernet();
  203. image = active_network_icon()->GetImage(ActiveNetworkIcon::Type::kSingle,
  204. icon_type(), &animating);
  205. EXPECT_TRUE(AreImagesEqual(
  206. image, ImageForNetwork(NetworkType::kWiFi,
  207. ConnectionStateType::kConnecting, 50)));
  208. EXPECT_TRUE(animating);
  209. // Cellular + WiFi connected + Ethernet = No icon
  210. SetupWiFi(shill::kStateOnline);
  211. network_state_handler()->SetNetworkConnectRequested(wifi_path(), false);
  212. image = active_network_icon()->GetImage(ActiveNetworkIcon::Type::kSingle,
  213. icon_type(), &animating);
  214. EXPECT_TRUE(image.isNull());
  215. EXPECT_FALSE(animating);
  216. }
  217. TEST_F(ActiveNetworkIconTest, CellularUninitialized) {
  218. SetCellularUninitialized(false /* scanning */);
  219. bool animating;
  220. gfx::ImageSkia image = active_network_icon()->GetImage(
  221. ActiveNetworkIcon::Type::kSingle, icon_type(), &animating);
  222. EXPECT_TRUE(
  223. AreImagesEqual(image, ImageForNetwork(NetworkType::kCellular,
  224. ConnectionStateType::kConnecting)));
  225. EXPECT_TRUE(animating);
  226. }
  227. TEST_F(ActiveNetworkIconTest, CellularScanning) {
  228. SetCellularUninitialized(true /* scanning */);
  229. ASSERT_TRUE(network_state_handler()->GetScanningByType(
  230. NetworkTypePattern::Cellular()));
  231. bool animating;
  232. gfx::ImageSkia image = active_network_icon()->GetImage(
  233. ActiveNetworkIcon::Type::kSingle, icon_type(), &animating);
  234. EXPECT_TRUE(
  235. AreImagesEqual(image, ImageForNetwork(NetworkType::kCellular,
  236. ConnectionStateType::kConnecting)));
  237. EXPECT_TRUE(animating);
  238. // Set scanning property to false, expect no network connections icon.
  239. network_state_helper().device_test()->SetDeviceProperty(
  240. kShillManagerClientStubCellularDevice, shill::kScanningProperty,
  241. base::Value(false), true /* notify_changed */);
  242. base::RunLoop().RunUntilIdle();
  243. image = active_network_icon()->GetImage(ActiveNetworkIcon::Type::kSingle,
  244. icon_type(), &animating);
  245. EXPECT_TRUE(AreImagesEqual(
  246. image, network_icon::GetImageForWiFiNoConnections(icon_type())));
  247. EXPECT_FALSE(animating);
  248. }
  249. TEST_F(ActiveNetworkIconTest, CellularDisable) {
  250. SetupCellular(shill::kStateOnline);
  251. bool animating;
  252. gfx::ImageSkia image = active_network_icon()->GetImage(
  253. ActiveNetworkIcon::Type::kSingle, icon_type(), &animating);
  254. EXPECT_TRUE(AreImagesEqual(
  255. image,
  256. ImageForNetwork(NetworkType::kCellular, ConnectionStateType::kOnline)));
  257. EXPECT_FALSE(animating);
  258. // The cellular device's scanning property may be true while it's being
  259. // disabled, mock this.
  260. network_state_helper().device_test()->SetDeviceProperty(
  261. kShillManagerClientStubCellularDevice, shill::kScanningProperty,
  262. base::Value(true), true /* notify_changed */);
  263. // Disable the device.
  264. network_state_model()->SetNetworkTypeEnabledState(NetworkType::kCellular,
  265. false);
  266. // Disabling the device doesn't actually remove the services in the fakes,
  267. // remove them explicitly.
  268. network_state_helper().ClearServices();
  269. base::RunLoop().RunUntilIdle();
  270. image = active_network_icon()->GetImage(ActiveNetworkIcon::Type::kSingle,
  271. icon_type(), &animating);
  272. EXPECT_TRUE(AreImagesEqual(
  273. image, network_icon::GetImageForWiFiNoConnections(icon_type())));
  274. EXPECT_FALSE(animating);
  275. }
  276. // TODO(stevenjb): Test GetDualImagePrimary, GetDualImageCellular.
  277. } // namespace ash