network_feature_pod_controller_unittest.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. // Copyright 2021 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/network_feature_pod_controller.h"
  5. #include <memory>
  6. #include <string>
  7. #include "ash/constants/ash_features.h"
  8. #include "ash/session/test_session_controller_client.h"
  9. #include "ash/shell.h"
  10. #include "ash/strings/grit/ash_strings.h"
  11. #include "ash/system/model/system_tray_model.h"
  12. #include "ash/system/network/active_network_icon.h"
  13. #include "ash/system/network/network_icon.h"
  14. #include "ash/system/unified/unified_system_tray.h"
  15. #include "ash/system/unified/unified_system_tray_bubble.h"
  16. #include "ash/system/unified/unified_system_tray_controller.h"
  17. #include "ash/system/unified/unified_system_tray_model.h"
  18. #include "ash/system/unified/unified_system_tray_view.h"
  19. #include "ash/test/ash_test_base.h"
  20. #include "base/strings/stringprintf.h"
  21. #include "base/test/scoped_feature_list.h"
  22. #include "chromeos/ash/components/network/network_handler_callbacks.h"
  23. #include "chromeos/ash/components/network/network_state_handler.h"
  24. #include "chromeos/ash/components/network/network_state_test_helper.h"
  25. #include "chromeos/ash/components/network/network_type_pattern.h"
  26. #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
  27. #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
  28. #include "ui/base/l10n/l10n_util.h"
  29. #include "ui/gfx/image/image.h"
  30. #include "ui/gfx/image/image_skia.h"
  31. #include "ui/gfx/image/image_unittest_util.h"
  32. #include "ui/views/controls/button/button.h"
  33. #include "ui/views/controls/button/image_button.h"
  34. namespace ash {
  35. namespace {
  36. const char* kStubCellularDevice = "/device/stub_cellular_device";
  37. // The GUIDs used for the different network types.
  38. const char* kNetworkGuidCellular = "cellular_guid";
  39. const char* kNetworkGuidTether = "tether_guid";
  40. const char* kNetworkGuidWifi = "wifi_guid";
  41. constexpr char kNetworkGuidEthernet[] = "ethernet_guid";
  42. constexpr char kNetworkGuidTetherWiFi[] = "tether_wifi_guid";
  43. // The templates used to configure services for different network types.
  44. constexpr char kServicePatternCellular[] = R"({
  45. "GUID": "%s", "Type": "cellular", "State": "online", "Strength": 100,
  46. "Device": "%s", "Cellular.NetworkTechnology": "LTE"})";
  47. constexpr char kServicePatternEthernet[] = R"({
  48. "GUID": "%s", "Type": "ethernet", "State": "online"})";
  49. constexpr char kServicePatternWiFi[] = R"({
  50. "GUID": "%s", "Type": "wifi", "State": "online", "Strength": 100})";
  51. constexpr char kServicePatternTetherWiFi[] = R"({
  52. "GUID": "%s", "Type": "wifi", "State": "idle"})";
  53. // Compute the next signal strength that is larger than |signal_strength| that
  54. // would be placed into a different bucket (e.g. NONE to WEAK).
  55. int ComputeNextSignalStrength(int signal_strength) {
  56. EXPECT_LE(0, signal_strength);
  57. const network_icon::SignalStrength previous =
  58. network_icon::GetSignalStrength(signal_strength);
  59. do {
  60. // Don't bother incrementing past |100|.
  61. if (signal_strength >= 90) {
  62. return 100;
  63. }
  64. // Small signal strength changes don't cause the network to be "changed".
  65. signal_strength += 10;
  66. } while (network_icon::GetSignalStrength(signal_strength) == previous);
  67. return signal_strength;
  68. }
  69. } // namespace
  70. class NetworkFeaturePodControllerTest : public AshTestBase {
  71. public:
  72. void SetUp() override {
  73. AshTestBase::SetUp();
  74. feature_list_.InitAndEnableFeature(features::kQuickSettingsNetworkRevamp);
  75. GetPrimaryUnifiedSystemTray()->ShowBubble();
  76. network_feature_pod_controller_ =
  77. std::make_unique<NetworkFeaturePodController>(tray_controller());
  78. feature_pod_button_.reset(network_feature_pod_controller_->CreateButton());
  79. // Add the non-default cellular and ethernet devices to Shill.
  80. network_state_helper()->manager_test()->AddTechnology(shill::kTypeCellular,
  81. /*enabled=*/true);
  82. network_state_helper()->AddDevice(kStubCellularDevice, shill::kTypeCellular,
  83. "stub_cellular_device");
  84. network_state_helper()->AddDevice("/device/stub_eth_device",
  85. shill::kTypeEthernet, "stub_eth_device");
  86. network_state_handler()->SetTetherTechnologyState(
  87. NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED);
  88. base::RunLoop().RunUntilIdle();
  89. }
  90. void TearDown() override {
  91. network_feature_pod_controller_.reset();
  92. feature_pod_button_.reset();
  93. AshTestBase::TearDown();
  94. }
  95. protected:
  96. // Disabling a network technology does not remove corresponding networks from
  97. // the testing fakes. This function is used to clear the existing networks.
  98. void ClearNetworks() {
  99. network_state_handler()->RemoveTetherNetworkState(kNetworkGuidTether);
  100. network_state_helper()->ClearServices();
  101. base::RunLoop().RunUntilIdle();
  102. }
  103. void LockScreen() {
  104. GetSessionControllerClient()->LockScreen();
  105. // Perform an action to cause the button to be updated since we do not
  106. // actually observe session state changes.
  107. PressLabel();
  108. }
  109. void PressIcon() {
  110. network_feature_pod_controller_->OnIconPressed();
  111. base::RunLoop().RunUntilIdle();
  112. }
  113. void PressLabel() {
  114. network_feature_pod_controller_->OnLabelPressed();
  115. base::RunLoop().RunUntilIdle();
  116. }
  117. void SetupCellular() {
  118. ASSERT_TRUE(cellular_path_.empty());
  119. cellular_path_ = ConfigureService(base::StringPrintf(
  120. kServicePatternCellular, kNetworkGuidCellular, kStubCellularDevice));
  121. base::RunLoop().RunUntilIdle();
  122. }
  123. void SetupEthernet() {
  124. ASSERT_TRUE(ethernet_path_.empty());
  125. ethernet_path_ = ConfigureService(
  126. base::StringPrintf(kServicePatternEthernet, kNetworkGuidEthernet));
  127. base::RunLoop().RunUntilIdle();
  128. }
  129. void SetupTether() {
  130. ASSERT_TRUE(tether_path_.empty());
  131. ASSERT_TRUE(tether_wifi_path_.empty());
  132. tether_wifi_path_ = ConfigureService(
  133. base::StringPrintf(kServicePatternTetherWiFi, kNetworkGuidTetherWiFi));
  134. base::RunLoop().RunUntilIdle();
  135. network_state_handler()->AddTetherNetworkState(
  136. kNetworkGuidTether, /*name=*/kNetworkGuidTether,
  137. /*carrier=*/"carrier_stub",
  138. /*battery_percentage=*/0, /*signal_strength=*/0,
  139. /*has_connected_to_host=*/false);
  140. network_state_handler()->SetTetherNetworkStateConnecting(
  141. /*guid=*/kNetworkGuidTether);
  142. ASSERT_TRUE(
  143. network_state_handler()->AssociateTetherNetworkStateWithWifiNetwork(
  144. /*tether_network_guid=*/kNetworkGuidTether,
  145. /*wifi_network_guid=*/kNetworkGuidTetherWiFi));
  146. network_state_handler()->SetTetherNetworkStateConnected(
  147. /*guid=*/kNetworkGuidTether);
  148. SetServiceProperty(/*service_path=*/tether_wifi_path_,
  149. /*key=*/shill::kStateProperty,
  150. /*value=*/base::Value(shill::kStateOnline));
  151. base::RunLoop().RunUntilIdle();
  152. network_state_handler()->SetTetherNetworkStateConnected(
  153. /*guid=*/kNetworkGuidTether);
  154. }
  155. void SetupWiFi() {
  156. ASSERT_TRUE(wifi_path_.empty());
  157. wifi_path_ = ConfigureService(
  158. base::StringPrintf(kServicePatternWiFi, kNetworkGuidWifi));
  159. base::RunLoop().RunUntilIdle();
  160. }
  161. void SetServiceProperty(const std::string& service_path,
  162. const std::string& key,
  163. const base::Value& value) {
  164. network_state_helper()->SetServiceProperty(service_path, key, value);
  165. base::RunLoop().RunUntilIdle();
  166. }
  167. void CheckNetworkDetailedViewFocused() {
  168. EXPECT_TRUE(tray_view()->detailed_view());
  169. const views::View::Views& children =
  170. tray_view()->detailed_view()->children();
  171. EXPECT_EQ(1u, children.size());
  172. EXPECT_STREQ("NetworkDetailedNetworkViewImpl",
  173. children.at(0)->GetClassName());
  174. }
  175. void CheckSignalStrengthSubLabel(
  176. base::RepeatingCallback<void(int)> set_signal_strength) {
  177. int signal_strength = 0;
  178. set_signal_strength.Run(signal_strength);
  179. EXPECT_EQ(
  180. l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED),
  181. feature_pod_label_button()->GetSubLabelText());
  182. signal_strength = ComputeNextSignalStrength(signal_strength);
  183. set_signal_strength.Run(signal_strength);
  184. EXPECT_EQ(l10n_util::GetStringUTF16(
  185. IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_WEAK_SUBLABEL),
  186. feature_pod_label_button()->GetSubLabelText());
  187. signal_strength = ComputeNextSignalStrength(signal_strength);
  188. set_signal_strength.Run(signal_strength);
  189. EXPECT_EQ(l10n_util::GetStringUTF16(
  190. IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_MEDIUM_SUBLABEL),
  191. feature_pod_label_button()->GetSubLabelText());
  192. signal_strength = ComputeNextSignalStrength(signal_strength);
  193. set_signal_strength.Run(signal_strength);
  194. EXPECT_EQ(l10n_util::GetStringUTF16(
  195. IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_STRONG_SUBLABEL),
  196. feature_pod_label_button()->GetSubLabelText());
  197. }
  198. NetworkStateTestHelper* network_state_helper() {
  199. return &network_config_helper_.network_state_helper();
  200. }
  201. NetworkStateHandler* network_state_handler() {
  202. return network_state_helper()->network_state_handler();
  203. }
  204. FeaturePodButton* feature_pod_button() { return feature_pod_button_.get(); }
  205. FeaturePodIconButton* feature_pod_icon_button() {
  206. return feature_pod_button_->icon_button_;
  207. }
  208. FeaturePodLabelButton* feature_pod_label_button() {
  209. return feature_pod_button_->label_button_;
  210. }
  211. UnifiedSystemTrayController* tray_controller() {
  212. return GetPrimaryUnifiedSystemTray()
  213. ->bubble()
  214. ->unified_system_tray_controller();
  215. }
  216. UnifiedSystemTrayView* tray_view() {
  217. return GetPrimaryUnifiedSystemTray()->bubble()->unified_view();
  218. }
  219. const std::string& cellular_path() const { return cellular_path_; }
  220. const std::string& ethernet_path() const { return ethernet_path_; }
  221. const std::string& tether_wifi_path() const { return tether_wifi_path_; }
  222. const std::string& wifi_path() const { return wifi_path_; }
  223. private:
  224. std::string ConfigureService(const std::string& shill_json_string) {
  225. return network_state_helper()->ConfigureService(shill_json_string);
  226. }
  227. chromeos::network_config::CrosNetworkConfigTestHelper network_config_helper_;
  228. base::test::ScopedFeatureList feature_list_;
  229. std::string cellular_path_;
  230. std::string ethernet_path_;
  231. std::string wifi_path_;
  232. std::string tether_path_;
  233. std::string tether_wifi_path_;
  234. std::unique_ptr<FeaturePodButton> feature_pod_button_;
  235. std::unique_ptr<NetworkFeaturePodController> network_feature_pod_controller_;
  236. };
  237. TEST_F(NetworkFeaturePodControllerTest, PressingLabelShowsNetworkDetailedView) {
  238. ASSERT_TRUE(tray_view()->detailed_view()->children().empty());
  239. PressLabel();
  240. CheckNetworkDetailedViewFocused();
  241. }
  242. // This test validates that pressing the icon will show the detailed Network
  243. // view when the Quick Settings is collapsed and the technology of the active
  244. // network cannot be toggled, e.g. ethernet.
  245. TEST_F(NetworkFeaturePodControllerTest,
  246. PressingIconConditionallyShowsDetailedView) {
  247. EXPECT_TRUE(tray_view()->detailed_view()->children().empty());
  248. tray_controller()->CollapseWithoutAnimating();
  249. base::RunLoop().RunUntilIdle();
  250. // Disable WiFi.
  251. PressIcon();
  252. EXPECT_TRUE(tray_view()->detailed_view()->children().empty());
  253. // Disable Cellular.
  254. PressIcon();
  255. EXPECT_TRUE(tray_view()->detailed_view()->children().empty());
  256. SetupEthernet();
  257. PressIcon();
  258. CheckNetworkDetailedViewFocused();
  259. }
  260. TEST_F(NetworkFeaturePodControllerTest,
  261. EnablingNetworkTechnologyShowsNetworkDetailedView) {
  262. // Disable WiFi.
  263. PressIcon();
  264. // We do not navigate to the detailed view when a network technology becomes
  265. // disabled.
  266. EXPECT_TRUE(tray_view()->detailed_view()->children().empty());
  267. PressIcon();
  268. CheckNetworkDetailedViewFocused();
  269. }
  270. TEST_F(NetworkFeaturePodControllerTest,
  271. HasCorrectButtonStateWhenNetworkStateChanges) {
  272. EXPECT_TRUE(feature_pod_button()->GetEnabled());
  273. EXPECT_TRUE(feature_pod_button()->GetVisible());
  274. // When WiFi is available the button will always be toggled, even when there
  275. // are no connected networks.
  276. EXPECT_TRUE(feature_pod_button()->IsToggled());
  277. SetupWiFi();
  278. EXPECT_TRUE(feature_pod_button()->IsToggled());
  279. ClearNetworks();
  280. SetupTether();
  281. EXPECT_TRUE(feature_pod_button()->IsToggled());
  282. ClearNetworks();
  283. network_state_handler()->SetTechnologyEnabled(
  284. NetworkTypePattern::WiFi(), /*enabled=*/false,
  285. network_handler::ErrorCallback());
  286. base::RunLoop().RunUntilIdle();
  287. // Any connected network should cause the button to be toggled.
  288. EXPECT_FALSE(feature_pod_button()->IsToggled());
  289. SetupCellular();
  290. EXPECT_TRUE(feature_pod_button()->IsToggled());
  291. ClearNetworks();
  292. EXPECT_FALSE(feature_pod_button()->IsToggled());
  293. SetupEthernet();
  294. EXPECT_TRUE(feature_pod_button()->IsToggled());
  295. ClearNetworks();
  296. }
  297. TEST_F(NetworkFeaturePodControllerTest, CannotBeModifiedWhenScreenIsLocked) {
  298. EXPECT_TRUE(feature_pod_button()->GetEnabled());
  299. LockScreen();
  300. EXPECT_FALSE(feature_pod_button()->GetEnabled());
  301. }
  302. TEST_F(NetworkFeaturePodControllerTest,
  303. PressingIconOrLabelIsHandledCorrectly_Cellular) {
  304. ASSERT_TRUE(network_state_handler()->IsTechnologyEnabled(
  305. NetworkTypePattern::Cellular()));
  306. SetupCellular();
  307. // Make sure that Cellular cannot be toggled on when the icon or label is
  308. // pressed, only toggled off.
  309. for (int i = 0; i < 2; ++i) {
  310. PressIcon();
  311. EXPECT_FALSE(network_state_handler()->IsTechnologyEnabled(
  312. NetworkTypePattern::Cellular()));
  313. ClearNetworks();
  314. }
  315. PressLabel();
  316. EXPECT_FALSE(network_state_handler()->IsTechnologyEnabled(
  317. NetworkTypePattern::Cellular()));
  318. }
  319. TEST_F(NetworkFeaturePodControllerTest,
  320. PressingIconOrLabelIsHandledCorrectly_Ethernet) {
  321. ASSERT_TRUE(network_state_handler()->IsTechnologyEnabled(
  322. NetworkTypePattern::Ethernet()));
  323. SetupEthernet();
  324. // Make sure that Ethernet cannot be toggled when the icon is pressed.
  325. PressIcon();
  326. EXPECT_TRUE(network_state_handler()->IsTechnologyEnabled(
  327. NetworkTypePattern::Ethernet()));
  328. // Make sure that Ethernet cannot be toggled when the label is pressed.
  329. PressLabel();
  330. EXPECT_TRUE(network_state_handler()->IsTechnologyEnabled(
  331. NetworkTypePattern::Ethernet()));
  332. }
  333. TEST_F(NetworkFeaturePodControllerTest,
  334. PressingIconOrLabelIsHandledCorrectly_Tether) {
  335. ASSERT_TRUE(network_state_handler()->IsTechnologyEnabled(
  336. NetworkTypePattern::Tether()));
  337. SetupTether();
  338. // Make sure that Tether can only be toggled off when the icon is pressed.
  339. for (int i = 0; i < 2; ++i) {
  340. PressIcon();
  341. EXPECT_FALSE(network_state_handler()->IsTechnologyEnabled(
  342. NetworkTypePattern::Tether()));
  343. ClearNetworks();
  344. }
  345. // Make sure that Tether cannot be toggled on when the label is pressed.
  346. PressLabel();
  347. EXPECT_FALSE(network_state_handler()->IsTechnologyEnabled(
  348. NetworkTypePattern::Tether()));
  349. }
  350. TEST_F(NetworkFeaturePodControllerTest,
  351. PressingIconOrLabelIsHandledCorrectly_WiFi) {
  352. ASSERT_TRUE(
  353. network_state_handler()->IsTechnologyEnabled(NetworkTypePattern::WiFi()));
  354. // Make sure that WiFi can be toggled on and off when the icon is pressed.
  355. PressIcon();
  356. EXPECT_FALSE(
  357. network_state_handler()->IsTechnologyEnabled(NetworkTypePattern::WiFi()));
  358. PressIcon();
  359. EXPECT_TRUE(
  360. network_state_handler()->IsTechnologyEnabled(NetworkTypePattern::WiFi()));
  361. PressIcon();
  362. EXPECT_FALSE(
  363. network_state_handler()->IsTechnologyEnabled(NetworkTypePattern::WiFi()));
  364. // Make sure that WiFi is toggled on, and only on, when the label is pressed.
  365. for (int i = 0; i < 2; ++i) {
  366. PressLabel();
  367. EXPECT_TRUE(network_state_handler()->IsTechnologyEnabled(
  368. NetworkTypePattern::WiFi()));
  369. }
  370. }
  371. TEST_F(NetworkFeaturePodControllerTest, HasCorrectLabel) {
  372. EXPECT_EQ(
  373. l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_LABEL),
  374. feature_pod_label_button()->GetLabelText());
  375. // For Ethernet we use a generic label.
  376. SetupEthernet();
  377. EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET),
  378. feature_pod_label_button()->GetLabelText());
  379. ClearNetworks();
  380. // For all other networks we use the name.
  381. SetupCellular();
  382. EXPECT_EQ(base::ASCIIToUTF16(kNetworkGuidCellular),
  383. feature_pod_label_button()->GetLabelText());
  384. ClearNetworks();
  385. SetupTether();
  386. EXPECT_EQ(base::ASCIIToUTF16(kNetworkGuidTether),
  387. feature_pod_label_button()->GetLabelText());
  388. ClearNetworks();
  389. SetupWiFi();
  390. EXPECT_EQ(base::ASCIIToUTF16(kNetworkGuidWifi),
  391. feature_pod_label_button()->GetLabelText());
  392. }
  393. TEST_F(NetworkFeaturePodControllerTest, HasCorrectSubLabel_Cellular) {
  394. EXPECT_EQ(l10n_util::GetStringUTF16(
  395. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  396. feature_pod_label_button()->GetSubLabelText());
  397. SetupCellular();
  398. // A network exists but we are not connected to it.
  399. SetServiceProperty(cellular_path(), shill::kStateProperty,
  400. base::Value(shill::kStateIdle));
  401. EXPECT_EQ(l10n_util::GetStringUTF16(
  402. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  403. feature_pod_label_button()->GetSubLabelText());
  404. // Mark the network as currently connecting.
  405. SetServiceProperty(cellular_path(), shill::kStateProperty,
  406. base::Value(shill::kStateAssociation));
  407. EXPECT_EQ(l10n_util::GetStringUTF16(
  408. IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING_SUBLABEL),
  409. feature_pod_label_button()->GetSubLabelText());
  410. // Cellular networks in the process of activating have a specific sub-label,
  411. // even if the network is in the connecting state.
  412. SetServiceProperty(cellular_path(), shill::kActivationStateProperty,
  413. base::Value(shill::kActivationStateActivating));
  414. EXPECT_EQ(l10n_util::GetStringUTF16(
  415. IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING_SUBLABEL),
  416. feature_pod_label_button()->GetSubLabelText());
  417. // Cellular networks that are activated and online have a specific sub-label
  418. // depending on the network technology (e.g. LTE).
  419. SetServiceProperty(cellular_path(), shill::kActivationStateProperty,
  420. base::Value(shill::kActivationStateActivated));
  421. SetServiceProperty(cellular_path(), shill::kStateProperty,
  422. base::Value(shill::kStateOnline));
  423. const base::flat_map<const char*, int> network_technology_to_text_id{{
  424. {shill::kNetworkTechnology1Xrtt,
  425. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_ONE_X},
  426. {shill::kNetworkTechnologyGsm,
  427. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_GSM},
  428. {shill::kNetworkTechnologyGprs,
  429. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_GPRS},
  430. {shill::kNetworkTechnologyEdge,
  431. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_EDGE},
  432. {shill::kNetworkTechnologyEvdo,
  433. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_THREE_G},
  434. {shill::kNetworkTechnologyUmts,
  435. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_THREE_G},
  436. {shill::kNetworkTechnologyHspa,
  437. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_HSPA},
  438. {shill::kNetworkTechnologyHspaPlus,
  439. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_HSPA_PLUS},
  440. {shill::kNetworkTechnologyLte,
  441. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_LTE},
  442. {shill::kNetworkTechnologyLteAdvanced,
  443. IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_LTE_PLUS},
  444. }};
  445. for (const auto& it : network_technology_to_text_id) {
  446. SetServiceProperty(cellular_path(), shill::kNetworkTechnologyProperty,
  447. base::Value(it.first));
  448. EXPECT_EQ(l10n_util::GetStringUTF16(it.second),
  449. feature_pod_label_button()->GetSubLabelText());
  450. }
  451. }
  452. TEST_F(NetworkFeaturePodControllerTest, HasCorrectSubLabel_Ethernet) {
  453. EXPECT_EQ(l10n_util::GetStringUTF16(
  454. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  455. feature_pod_label_button()->GetSubLabelText());
  456. SetupEthernet();
  457. // A network exists but we are not connected to it.
  458. SetServiceProperty(ethernet_path(), shill::kStateProperty,
  459. base::Value(shill::kStateIdle));
  460. EXPECT_EQ(l10n_util::GetStringUTF16(
  461. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  462. feature_pod_label_button()->GetSubLabelText());
  463. // Ethernet is not eligible to be the default network until it is connected.
  464. // Mark the network as currently connecting and ensure this is true.
  465. SetServiceProperty(ethernet_path(), shill::kStateProperty,
  466. base::Value(shill::kStateAssociation));
  467. network_state_handler()->SetNetworkConnectRequested(ethernet_path(), true);
  468. base::RunLoop().RunUntilIdle();
  469. EXPECT_EQ(l10n_util::GetStringUTF16(
  470. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  471. feature_pod_label_button()->GetSubLabelText());
  472. SetServiceProperty(ethernet_path(), shill::kStateProperty,
  473. base::Value(shill::kStateOnline));
  474. EXPECT_EQ(
  475. l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED),
  476. feature_pod_label_button()->GetSubLabelText());
  477. }
  478. TEST_F(NetworkFeaturePodControllerTest, HasCorrectSubLabel_Tether) {
  479. EXPECT_EQ(l10n_util::GetStringUTF16(
  480. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  481. feature_pod_label_button()->GetSubLabelText());
  482. SetupTether();
  483. // A network exists but we are not connected to it.
  484. network_state_handler()->SetTetherNetworkStateDisconnected(
  485. /*guid=*/kNetworkGuidTether);
  486. base::RunLoop().RunUntilIdle();
  487. EXPECT_EQ(l10n_util::GetStringUTF16(
  488. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  489. feature_pod_label_button()->GetSubLabelText());
  490. // Mark the network as currently connecting.
  491. network_state_handler()->SetTetherNetworkStateConnecting(
  492. /*guid=*/kNetworkGuidTether);
  493. base::RunLoop().RunUntilIdle();
  494. EXPECT_EQ(l10n_util::GetStringUTF16(
  495. IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING_SUBLABEL),
  496. feature_pod_label_button()->GetSubLabelText());
  497. // Mark the network as connected.
  498. network_state_handler()->SetTetherNetworkStateConnected(
  499. /*guid=*/kNetworkGuidTether);
  500. base::RunLoop().RunUntilIdle();
  501. CheckSignalStrengthSubLabel(base::BindRepeating(
  502. [](NetworkStateHandler* handler, int signal_strength) {
  503. EXPECT_TRUE(handler->UpdateTetherNetworkProperties(
  504. kNetworkGuidTether, /*carrier=*/"carrier_stub",
  505. /*battery_percentage=*/0, signal_strength));
  506. base::RunLoop().RunUntilIdle();
  507. },
  508. network_state_handler()));
  509. }
  510. TEST_F(NetworkFeaturePodControllerTest, HasCorrectSubLabel_WiFi) {
  511. EXPECT_EQ(l10n_util::GetStringUTF16(
  512. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  513. feature_pod_label_button()->GetSubLabelText());
  514. SetupWiFi();
  515. // A network exists but we are not connected to it.
  516. SetServiceProperty(wifi_path(), shill::kStateProperty,
  517. base::Value(shill::kStateIdle));
  518. EXPECT_EQ(l10n_util::GetStringUTF16(
  519. IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL),
  520. feature_pod_label_button()->GetSubLabelText());
  521. // Mark the network as currently connecting.
  522. SetServiceProperty(wifi_path(), shill::kStateProperty,
  523. base::Value(shill::kStateAssociation));
  524. network_state_handler()->SetNetworkConnectRequested(wifi_path(), true);
  525. base::RunLoop().RunUntilIdle();
  526. EXPECT_EQ(l10n_util::GetStringUTF16(
  527. IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING_SUBLABEL),
  528. feature_pod_label_button()->GetSubLabelText());
  529. SetServiceProperty(wifi_path(), shill::kStateProperty,
  530. base::Value(shill::kStateOnline));
  531. CheckSignalStrengthSubLabel(base::BindRepeating(
  532. [](NetworkStateTestHelper* helper, const std::string& service_path,
  533. int signal_strength) {
  534. helper->SetServiceProperty(service_path, shill::kSignalStrengthProperty,
  535. base::Value(signal_strength));
  536. },
  537. network_state_helper(), wifi_path()));
  538. }
  539. TEST_F(NetworkFeaturePodControllerTest, HasCorrectTooltips) {
  540. std::u16string tooltip;
  541. ActiveNetworkIcon* active_network_icon =
  542. Shell::Get()->system_tray_model()->active_network_icon();
  543. SetupEthernet();
  544. active_network_icon->GetConnectionStatusStrings(
  545. ActiveNetworkIcon::Type::kSingle,
  546. /*a11y_name=*/nullptr,
  547. /*a11y_desc=*/nullptr, &tooltip);
  548. // When the network type cannot actually be toggled the tooltip should be the
  549. // same for the icon as it is for the label.
  550. EXPECT_EQ(l10n_util::GetStringFUTF16(
  551. IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP, tooltip),
  552. feature_pod_icon_button()->GetTooltipText());
  553. EXPECT_EQ(l10n_util::GetStringFUTF16(
  554. IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP, tooltip),
  555. feature_pod_label_button()->GetTooltipText());
  556. ClearNetworks();
  557. active_network_icon->GetConnectionStatusStrings(
  558. ActiveNetworkIcon::Type::kSingle,
  559. /*a11y_name=*/nullptr,
  560. /*a11y_desc=*/nullptr, &tooltip);
  561. EXPECT_EQ(l10n_util::GetStringFUTF16(
  562. IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP, tooltip),
  563. feature_pod_icon_button()->GetTooltipText());
  564. EXPECT_EQ(l10n_util::GetStringFUTF16(
  565. IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP, tooltip),
  566. feature_pod_label_button()->GetTooltipText());
  567. PressIcon();
  568. EXPECT_EQ(l10n_util::GetStringFUTF16(
  569. IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP, tooltip),
  570. feature_pod_icon_button()->GetTooltipText());
  571. // Pressing the label when the network type is disabled but can be enabled
  572. // will enable that network type.
  573. EXPECT_EQ(l10n_util::GetStringFUTF16(
  574. IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP, tooltip),
  575. feature_pod_label_button()->GetTooltipText());
  576. LockScreen();
  577. active_network_icon->GetConnectionStatusStrings(
  578. ActiveNetworkIcon::Type::kSingle,
  579. /*a11y_name=*/nullptr,
  580. /*a11y_desc=*/nullptr, &tooltip);
  581. EXPECT_EQ(tooltip, feature_pod_icon_button()->GetTooltipText());
  582. EXPECT_EQ(tooltip, feature_pod_label_button()->GetTooltipText());
  583. }
  584. // This test does not check whether the icons are correct, and is only intended
  585. // to cover whether the icons supplied by the ActiveNetworkIcon class are used.
  586. TEST_F(NetworkFeaturePodControllerTest, HasCorrectIcons) {
  587. ActiveNetworkIcon* active_network_icon =
  588. Shell::Get()->system_tray_model()->active_network_icon();
  589. EXPECT_TRUE(gfx::test::AreImagesEqual(
  590. gfx::Image(active_network_icon->GetImage(
  591. ActiveNetworkIcon::Type::kSingle,
  592. network_icon::ICON_TYPE_FEATURE_POD_TOGGLED, /*animating=*/nullptr)),
  593. gfx::Image(
  594. feature_pod_icon_button()->GetImage(views::Button::STATE_NORMAL))));
  595. feature_pod_button()->SetEnabled(false);
  596. EXPECT_TRUE(gfx::test::AreImagesEqual(
  597. gfx::Image(active_network_icon->GetImage(
  598. ActiveNetworkIcon::Type::kSingle,
  599. network_icon::ICON_TYPE_FEATURE_POD_DISABLED, /*animating=*/nullptr)),
  600. gfx::Image(
  601. feature_pod_icon_button()->GetImage(views::Button::STATE_DISABLED))));
  602. // Disable WiFi which will update the feature pod button state to be enabled
  603. // but not toggled.
  604. network_state_handler()->SetTechnologyEnabled(
  605. NetworkTypePattern::WiFi(), /*enabled=*/false,
  606. network_handler::ErrorCallback());
  607. base::RunLoop().RunUntilIdle();
  608. EXPECT_TRUE(gfx::test::AreImagesEqual(
  609. gfx::Image(active_network_icon->GetImage(
  610. ActiveNetworkIcon::Type::kSingle, network_icon::ICON_TYPE_FEATURE_POD,
  611. /*animating=*/nullptr)),
  612. gfx::Image(
  613. feature_pod_icon_button()->GetImage(views::Button::STATE_NORMAL))));
  614. }
  615. } // namespace ash