File: privacy_hub_geolocation_browsertest.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (341 lines) | stat: -rw-r--r-- 14,332 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <tuple>

#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/constants/geolocation_access_level.h"
#include "ash/shell.h"
#include "ash/system/privacy_hub/privacy_hub_controller.h"
#include "ash/webui/settings/public/constants/routes.mojom-forward.h"
#include "base/notreached.h"
#include "chrome/browser/ash/login/login_manager_test.h"
#include "chrome/browser/ash/login/test/device_state_mixin.h"
#include "chrome/browser/ash/login/test/login_manager_mixin.h"
#include "chrome/browser/ash/privacy_hub/privacy_hub_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/login/user_adding_screen.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/settings_window_manager_chromeos.h"
#include "chrome/browser/ui/webui/ash/settings/pages/privacy/privacy_hub_handler.h"
#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
#include "components/account_id/account_id.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"

namespace ash {

namespace {

bool IsLocationEnabledForBrowser(GeolocationAccessLevel access_level) {
  switch (access_level) {
    case GeolocationAccessLevel::kAllowed:
      return true;
    case GeolocationAccessLevel::kOnlyAllowedForSystem:
    case GeolocationAccessLevel::kDisallowed:
      return false;
    default:
      NOTREACHED() << "Invalid access level";
  }
}

}  // namespace
class PrivacyHubGeolocationBrowsertestBase : public LoginManagerTest {
 public:
  PrivacyHubGeolocationBrowsertestBase() {
    scoped_feature_list_.InitWithFeatures({ash::features::kCrosPrivacyHub}, {});
  }

  ~PrivacyHubGeolocationBrowsertestBase() override = default;

  // Set the `kUserGeolocationAccessLevel` pref for the active user.
  void SetGeolocationAccessLevelPref(GeolocationAccessLevel access_level) {
    g_browser_process->profile_manager()
        ->GetActiveUserProfile()
        ->GetPrefs()
        ->SetInteger(prefs::kUserGeolocationAccessLevel,
                     static_cast<int>(access_level));
  }

 protected:
  LoginManagerMixin login_manager_{&mixin_host_};
  DeviceStateMixin device_state_{
      &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CONSUMER_OWNED};
  base::test::ScopedFeatureList scoped_feature_list_;
};

class PrivacyHubGeolocationBrowsertestMultiUserSession
    : public PrivacyHubGeolocationBrowsertestBase,
      public testing::WithParamInterface<
          std::tuple<GeolocationAccessLevel, GeolocationAccessLevel>> {
 public:
  PrivacyHubGeolocationBrowsertestMultiUserSession() {
    login_manager_.AppendRegularUsers(3);
    regular_primary_user_ = login_manager_.users()[0].account_id;
    regular_secondary_user_1_ = login_manager_.users()[1].account_id;
    regular_secondary_user_2_ = login_manager_.users()[2].account_id;
  }
  ~PrivacyHubGeolocationBrowsertestMultiUserSession() = default;

 protected:
  AccountId regular_primary_user_;
  AccountId regular_secondary_user_1_;
  AccountId regular_secondary_user_2_;
};

IN_PROC_BROWSER_TEST_P(PrivacyHubGeolocationBrowsertestMultiUserSession,
                       SecondUserCanNotChangeGeolocationSetting) {
  SimpleGeolocationProvider* provider =
      SimpleGeolocationProvider::GetInstance();
  CHECK(provider);

  // Log in primary user.
  LoginUser(regular_primary_user_);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            GeolocationAccessLevel::kAllowed);

  const GeolocationAccessLevel primary_user_geolocation_choice =
      std::get<0>(GetParam());
  SetGeolocationAccessLevelPref(primary_user_geolocation_choice);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);

  // Add secondary user and log in.
  ash::UserAddingScreen::Get()->Start();
  AddUser(regular_secondary_user_1_);
  const GeolocationAccessLevel secondary_user_geolocation_choice =
      std::get<1>(GetParam());

  // Check that primary user's choice for Geolocation setting is
  // overriding secondary user's choice.
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);
  ASSERT_EQ(privacy_hub_util::ContentBlocked(
                privacy_hub_util::ContentType::GEOLOCATION),
            !IsLocationEnabledForBrowser(primary_user_geolocation_choice));

  // Modify the underlying preference for the secondary user. Check that the
  // effective geolocation setting is unaffected; still following the primary
  // user's choice.
  SetGeolocationAccessLevelPref(secondary_user_geolocation_choice);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);
  ASSERT_EQ(privacy_hub_util::ContentBlocked(
                privacy_hub_util::ContentType::GEOLOCATION),
            !IsLocationEnabledForBrowser(primary_user_geolocation_choice));
}

IN_PROC_BROWSER_TEST_P(PrivacyHubGeolocationBrowsertestMultiUserSession,
                       SecondaryUsersCanNotChangeGeolocationSetting) {
  SimpleGeolocationProvider* provider =
      SimpleGeolocationProvider::GetInstance();
  CHECK(provider);

  // Log in primary user.
  LoginUser(regular_primary_user_);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            GeolocationAccessLevel::kAllowed);

  const GeolocationAccessLevel primary_user_geolocation_choice =
      std::get<0>(GetParam());
  SetGeolocationAccessLevelPref(primary_user_geolocation_choice);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);

  // Add secondary user and log in.
  ash::UserAddingScreen::Get()->Start();
  AddUser(regular_secondary_user_1_);
  const GeolocationAccessLevel secondary_user_geolocation_choice =
      std::get<1>(GetParam());
  // Check that primary user's choice for Geolocation setting is
  // overriding secondary user's choice.
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);
  ASSERT_EQ(privacy_hub_util::ContentBlocked(
                privacy_hub_util::ContentType::GEOLOCATION),
            !IsLocationEnabledForBrowser(primary_user_geolocation_choice));

  // Modify the underlying preference for the secondary user. Check that the
  // effective geolocation setting is unaffected; still following the primary
  // user's choice.
  SetGeolocationAccessLevelPref(secondary_user_geolocation_choice);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);
  ASSERT_EQ(privacy_hub_util::ContentBlocked(
                privacy_hub_util::ContentType::GEOLOCATION),
            !IsLocationEnabledForBrowser(primary_user_geolocation_choice));

  // Add another secondary user and conduct the same testing.
  ash::UserAddingScreen::Get()->Start();
  AddUser(regular_secondary_user_2_);

  // Check initial location access level follows the primary user choice.
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);
  ASSERT_EQ(privacy_hub_util::ContentBlocked(
                privacy_hub_util::ContentType::GEOLOCATION),
            !IsLocationEnabledForBrowser(primary_user_geolocation_choice));

  // Change the underlying preference for this user too. Check that the
  // effective geolocation setting is unaffected.
  SetGeolocationAccessLevelPref(secondary_user_geolocation_choice);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            primary_user_geolocation_choice);
  ASSERT_EQ(privacy_hub_util::ContentBlocked(
                privacy_hub_util::ContentType::GEOLOCATION),
            !IsLocationEnabledForBrowser(primary_user_geolocation_choice));
}

class MockPrivacyHubHandler : public settings::PrivacyHubHandler {
 public:
  MOCK_METHOD(void,
              SystemGeolocationAccessLevelChanged,
              (GeolocationAccessLevel),
              (override));
};

IN_PROC_BROWSER_TEST_P(PrivacyHubGeolocationBrowsertestMultiUserSession,
                       CheckCorrectSystemUICallbackIsCalled) {
  SimpleGeolocationProvider* provider =
      SimpleGeolocationProvider::GetInstance();
  CHECK(provider);

  // Log in primary user.
  LoginUser(regular_primary_user_);
  ASSERT_EQ(provider->GetGeolocationAccessLevel(),
            GeolocationAccessLevel::kAllowed);

  // Simulate opening the chrome://os-settings, by artificially setting the mock
  // frontend. Check that this will automatically notify the UI of the initial
  // geolocation value.
  ::testing::StrictMock<MockPrivacyHubHandler> primary_user_frontend;
  EXPECT_CALL(primary_user_frontend, SystemGeolocationAccessLevelChanged(
                                         GeolocationAccessLevel::kAllowed));
  Shell::Get()->privacy_hub_controller()->geolocation_controller()->SetFrontend(
      &primary_user_frontend);

  // Modify the primary user location preference and check that the UI is
  // notified.
  const GeolocationAccessLevel primary_user_geolocation_choice =
      std::get<0>(GetParam());
  EXPECT_CALL(primary_user_frontend, SystemGeolocationAccessLevelChanged(
                                         primary_user_geolocation_choice));
  SetGeolocationAccessLevelPref(primary_user_geolocation_choice);

  // Add secondary user and log in.
  ash::UserAddingScreen::Get()->Start();
  AddUser(regular_secondary_user_1_);

  // Simulate opening the chrome://os-settings, by artificially setting the mock
  // frontend. Check that this will automatically notify the UI of the initial
  // geolocation value, but the value should be of the primary user pref.
  ::testing::StrictMock<MockPrivacyHubHandler> secondary_user_frontend;
  EXPECT_CALL(secondary_user_frontend, SystemGeolocationAccessLevelChanged(
                                           primary_user_geolocation_choice));
  Shell::Get()->privacy_hub_controller()->geolocation_controller()->SetFrontend(
      &secondary_user_frontend);

  // Modify the underlying location preference for the secondary user and check
  // that it won't trigger the UI callback.
  const GeolocationAccessLevel secondary_user_geolocation_choice =
      std::get<1>(GetParam());
  EXPECT_CALL(secondary_user_frontend,
              SystemGeolocationAccessLevelChanged(testing::_))
      .Times(0);
  SetGeolocationAccessLevelPref(secondary_user_geolocation_choice);

  // Switch back to primary user and check its UI will re-fetch system
  // geolocation.
  EXPECT_CALL(primary_user_frontend, SystemGeolocationAccessLevelChanged(
                                         primary_user_geolocation_choice));
  user_manager::UserManager::Get()->SwitchActiveUser(regular_primary_user_);
}

// std::get<0>(GetParam()) - Location preference of the primary user.
// std::get<1>(GetParam()) - Location preference of the secondary user[s].
// Values of these pairs are meant to be different to test that secondary
// users' preference won't affect the effective geolocation state.
INSTANTIATE_TEST_SUITE_P(
    All,
    PrivacyHubGeolocationBrowsertestMultiUserSession,
    testing::Values(
        std::make_tuple(GeolocationAccessLevel::kDisallowed,
                        GeolocationAccessLevel::kAllowed),
        std::make_tuple(GeolocationAccessLevel::kAllowed,
                        GeolocationAccessLevel::kDisallowed),
        std::make_tuple(GeolocationAccessLevel::kOnlyAllowedForSystem,
                        GeolocationAccessLevel::kDisallowed)));

class MockSettingsWindowManager : public chrome::SettingsWindowManager {
 public:
  MOCK_METHOD(void,
              ShowChromePageForProfile,
              (Profile * profile,
               const GURL& gurl,
               int64_t display_id,
               apps::LaunchCallback callback),
              (override));
};

class PrivacyHubGeolocationBrowsertestCheckSystemSettingsLink
    : public PrivacyHubGeolocationBrowsertestBase {
 public:
  PrivacyHubGeolocationBrowsertestCheckSystemSettingsLink() {
    login_manager_.AppendRegularUsers(2);
    primary_user_ = login_manager_.users()[0].account_id;
    secondary_user_ = login_manager_.users()[1].account_id;
  }
  ~PrivacyHubGeolocationBrowsertestCheckSystemSettingsLink() override = default;

 protected:
  AccountId primary_user_;
  AccountId secondary_user_;
};

IN_PROC_BROWSER_TEST_F(PrivacyHubGeolocationBrowsertestCheckSystemSettingsLink,
                       AlwaysOpenActiveUserSettingsPage) {
  MockSettingsWindowManager mock_settings_window_manager;
  chrome::SettingsWindowManager::SetInstanceForTesting(
      &mock_settings_window_manager);

  // Sign in with the first/primary user.
  LoginUser(primary_user_);
  Profile* primary_profile = ProfileManager::GetActiveUserProfile();
  // When primary user clicks the redirection link from the Browser, the opened
  // OS settings page has to be tied to the primary user's profile.
  EXPECT_CALL(
      mock_settings_window_manager,
      ShowChromePageForProfile(
          primary_profile,
          chrome::GetOSSettingsUrl(
              chromeos::settings::mojom::kPrivacyHubGeolocationSubpagePath),
          testing::_, testing::_));
  // Directly call the underlying method to simulate the link click.
  privacy_hub_util::OpenSystemSettings(
      privacy_hub_util::ContentType::GEOLOCATION);

  // Add another/secondary user to the session and log in.
  ash::UserAddingScreen::Get()->Start();
  AddUser(secondary_user_);
  // Check that a different profile is being loaded.
  Profile* secondary_profile = ProfileManager::GetActiveUserProfile();
  ASSERT_NE(primary_profile, secondary_profile);
  // When secondary user clicks the redirection link from the Browser, the
  // opened OS settings page has to be tied to the secondary user's profile.
  EXPECT_CALL(
      mock_settings_window_manager,
      ShowChromePageForProfile(
          secondary_profile,
          chrome::GetOSSettingsUrl(
              chromeos::settings::mojom::kPrivacyHubGeolocationSubpagePath),
          testing::_, testing::_));
  // Directly call the underlying method to simulate the link click.
  privacy_hub_util::OpenSystemSettings(
      privacy_hub_util::ContentType::GEOLOCATION);
}

}  // namespace ash