File: permissions_apitest.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (316 lines) | stat: -rw-r--r-- 13,077 bytes parent folder | download | duplicates (3)
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
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/files/file_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/extensions/api/permissions/permissions_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/browser/extensions/extension_with_management_policy_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "content/public/test/browser_test.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/switches.h"
#include "net/dns/mock_host_resolver.h"

namespace extensions {

namespace {

static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
  int schemes = URLPattern::SCHEME_ALL;
  extent->AddPattern(URLPattern(schemes, pattern));
}

}  // namespace

using ContextType = extensions::browser_test_util::ContextType;

class ExperimentalApiTest : public ExtensionApiTest {
 public:
  ExperimentalApiTest() = default;
  ~ExperimentalApiTest() override = default;
  ExperimentalApiTest(const ExperimentalApiTest&) = delete;
  ExperimentalApiTest& operator=(const ExperimentalApiTest&) = delete;

  void SetUpCommandLine(base::CommandLine* command_line) override {
    ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
  }
};

class PermissionsApiTest : public ExtensionApiTest {
 public:
 public:
  explicit PermissionsApiTest(ContextType context_type = ContextType::kNone)
      : ExtensionApiTest(context_type) {}
  ~PermissionsApiTest() override = default;
  PermissionsApiTest(const PermissionsApiTest&) = delete;
  PermissionsApiTest& operator=(const PermissionsApiTest&) = delete;

  void SetUpOnMainThread() override {
    ExtensionApiTest::SetUpOnMainThread();
    host_resolver()->AddRule("*", "127.0.0.1");
  }
};

class PermissionsApiTestWithContextType
    : public PermissionsApiTest,
      public testing::WithParamInterface<ContextType> {
 public:
  PermissionsApiTestWithContextType() : PermissionsApiTest(GetParam()) {}
  ~PermissionsApiTestWithContextType() override = default;
  PermissionsApiTestWithContextType(const PermissionsApiTestWithContextType&) =
      delete;
  PermissionsApiTestWithContextType& operator=(
      const PermissionsApiTestWithContextType&) = delete;
};

IN_PROC_BROWSER_TEST_P(PermissionsApiTestWithContextType, PermissionsFail) {
  ASSERT_TRUE(RunExtensionTest("permissions/disabled")) << message_;

  // Since the experimental APIs require a flag, this will fail even though
  // it's enabled.
  // TODO(erikkay) This test is currently broken because LoadExtension in
  // ExtensionBrowserTest doesn't actually fail, it just times out.  To fix this
  // I'll need to add an EXTENSION_LOAD_ERROR notification, which is probably
  // too much for the branch.  I'll enable this on trunk later.
  // ASSERT_FALSE(RunExtensionTest("permissions/enabled"))) << message_;
}

IN_PROC_BROWSER_TEST_F(ExperimentalApiTest, PermissionsSucceed) {
  ASSERT_TRUE(RunExtensionTest("permissions/enabled")) << message_;
}

IN_PROC_BROWSER_TEST_P(PermissionsApiTestWithContextType,
                       ExperimentalPermissionsFail) {
  // At the time this test is being created, there is no experimental
  // function that will not be graduating soon, and does not require a
  // tab id as an argument.  So, we need the tab permission to get
  // a tab id.
  ASSERT_TRUE(RunExtensionTest("permissions/experimental_disabled"))
      << message_;
}

// TODO(crbug.com/40124130): Flaky on ChromeOS, Linux, and Mac non-dbg builds.
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)) && \
    defined(NDEBUG)
#define MAYBE_FaviconPermission DISABLED_FaviconPermission
#else
#define MAYBE_FaviconPermission FaviconPermission
#endif
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, MAYBE_FaviconPermission) {
  ASSERT_TRUE(RunExtensionTest("permissions/favicon")) << message_;
}

// Test functions and APIs that are always allowed (even if you ask for no
// permissions).
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, AlwaysAllowed) {
  ASSERT_TRUE(RunExtensionTest("permissions/always_allowed")) << message_;
}

// Tests that the optional permissions API works correctly.
IN_PROC_BROWSER_TEST_P(PermissionsApiTestWithContextType,
                       OptionalPermissionsGranted) {
  // Mark all the tested APIs as granted to bypass the confirmation UI.
  APIPermissionSet apis;
  apis.insert(extensions::mojom::APIPermissionID::kBookmark);
  URLPatternSet explicit_hosts;
  AddPattern(&explicit_hosts, "http://*.c.com/*");

  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
  prefs->AddRuntimeGrantedPermissions(
      "kjmkgkdkpedkejedfhmfcenooemhbpbo",
      PermissionSet(std::move(apis), ManifestPermissionSet(),
                    std::move(explicit_hosts), URLPatternSet()));

  PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
  ASSERT_TRUE(StartEmbeddedTestServer());
  EXPECT_TRUE(RunExtensionTest("permissions/optional")) << message_;
}

// Tests that the optional permissions API works correctly.
IN_PROC_BROWSER_TEST_P(PermissionsApiTestWithContextType,
                       OptionalPermissionsAutoConfirm) {
  // Rather than setting the granted permissions, set the UI autoconfirm flag
  // and run the same tests.
  auto dialog_action_reset =
      PermissionsRequestFunction::SetDialogActionForTests(
          PermissionsRequestFunction::DialogAction::kAutoConfirm);
  PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
  ASSERT_TRUE(StartEmbeddedTestServer());
  EXPECT_TRUE(RunExtensionTest("permissions/optional")) << message_;
}

// Test that denying the optional permissions confirmation dialog works.
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsDeny) {
  // Mark the management permission as already granted since we auto reject
  // user prompts.
  APIPermissionSet apis;
  apis.insert(mojom::APIPermissionID::kManagement);

  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
  prefs->AddRuntimeGrantedPermissions(
      "kjmkgkdkpedkejedfhmfcenooemhbpbo",
      PermissionSet(std::move(apis), ManifestPermissionSet(), URLPatternSet(),
                    URLPatternSet()));

  auto dialog_action_reset =
      PermissionsRequestFunction::SetDialogActionForTests(
          PermissionsRequestFunction::DialogAction::kAutoReject);
  PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
  ASSERT_TRUE(StartEmbeddedTestServer());
  EXPECT_TRUE(RunExtensionTest("permissions/optional_deny")) << message_;
}

// Tests that the permissions.request function must be called from within a
// user gesture.
IN_PROC_BROWSER_TEST_P(PermissionsApiTestWithContextType,
                       OptionalPermissionsGesture) {
  PermissionsRequestFunction::SetIgnoreUserGestureForTests(false);
  ASSERT_TRUE(StartEmbeddedTestServer());
  EXPECT_TRUE(RunExtensionTest("permissions/optional_gesture")) << message_;
}

// Tests that the user gesture is retained in the permissions.request function
// callback.
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsRetainGesture) {
  auto dialog_action_reset =
      PermissionsRequestFunction::SetDialogActionForTests(
          PermissionsRequestFunction::DialogAction::kAutoConfirm);
  PermissionsRequestFunction::SetIgnoreUserGestureForTests(false);
  ASSERT_TRUE(StartEmbeddedTestServer());
  EXPECT_TRUE(RunExtensionTest("permissions/optional_retain_gesture"))
      << message_;
}

// Test that optional permissions blocked by enterprise policy will be denied
// automatically.
IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy,
                       OptionalPermissionsPolicyBlocked) {
  // Set enterprise policy to block some API permissions.
  {
    ExtensionManagementPolicyUpdater pref(&policy_provider_);
    pref.AddBlockedPermission("*", "management");
  }
  // Set auto confirm UI flag.
  auto dialog_action_reset =
      PermissionsRequestFunction::SetDialogActionForTests(
          PermissionsRequestFunction::DialogAction::kAutoConfirm);
  PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
  EXPECT_TRUE(RunExtensionTest("permissions/optional_policy_blocked"))
      << message_;
}

// Tests that an extension can't gain access to file: URLs without the checkbox
// entry in prefs. There shouldn't be a warning either.
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsFileAccess) {
  // There shouldn't be a warning, so we shouldn't need to autoconfirm.
  auto dialog_action_reset =
      PermissionsRequestFunction::SetDialogActionForTests(
          PermissionsRequestFunction::DialogAction::kAutoReject);
  PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);

  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());

  EXPECT_TRUE(RunExtensionTest("permissions/file_access_no")) << message_;
  EXPECT_FALSE(prefs->AllowFileAccess(last_loaded_extension_id()));
  EXPECT_TRUE(RunExtensionTest("permissions/file_access_yes", {},
                               {.allow_file_access = true}))
      << message_;
  EXPECT_TRUE(prefs->AllowFileAccess(last_loaded_extension_id()));
}

// Tests loading of files or directory listings when an extension has file
// access.
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, FileLoad) {
  base::ScopedTempDir temp_dir;
  {
    base::ScopedAllowBlockingForTesting allow_blocking;
    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    base::FilePath empty_file = temp_dir.GetPath().AppendASCII("empty.html");
    base::FilePath original_empty_file = ui_test_utils::GetTestFilePath(
        base::FilePath(), base::FilePath().AppendASCII("empty.html"));

    EXPECT_TRUE(base::PathExists(original_empty_file));
    EXPECT_TRUE(base::CopyFile(original_empty_file, empty_file));
  }
  EXPECT_TRUE(RunExtensionTest(
      "permissions/file_load",
      {.custom_arg = temp_dir.GetPath().MaybeAsASCII().c_str()},
      {.allow_file_access = true}))
      << message_;
  {
    base::ScopedAllowBlockingForTesting allow_blocking;
    ASSERT_TRUE(temp_dir.Delete());
  }
}

// Test requesting, querying, and removing host permissions for host
// permissions that are a subset of the optional permissions.
IN_PROC_BROWSER_TEST_P(PermissionsApiTestWithContextType, HostSubsets) {
  auto dialog_action_reset =
      PermissionsRequestFunction::SetDialogActionForTests(
          PermissionsRequestFunction::DialogAction::kAutoConfirm);
  PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
  EXPECT_TRUE(RunExtensionTest("permissions/host_subsets")) << message_;
}

// Tests that requesting an optional permission from a background page, with
// another window open, grants the permission and updates the bindings
// (chrome.whatever, in this case chrome.alarms). Regression test for
// crbug.com/435141, see details there for trickiness.
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsUpdatesBindings) {
  ASSERT_TRUE(RunExtensionTest("permissions/optional_updates_bindings"))
      << message_;
}

INSTANTIATE_TEST_SUITE_P(PersistentBackground,
                         PermissionsApiTestWithContextType,
                         testing::Values(ContextType::kPersistentBackground));
INSTANTIATE_TEST_SUITE_P(ServiceWorker,
                         PermissionsApiTestWithContextType,
                         testing::Values(ContextType::kServiceWorker));

class PermissionsApiHostAccessRequestsTest : public PermissionsApiTest {
 public:
  PermissionsApiHostAccessRequestsTest() {
    scoped_feature_list_.InitAndEnableFeature(
        extensions_features::kApiPermissionsHostAccessRequests);
  }
  ~PermissionsApiHostAccessRequestsTest() override = default;
  PermissionsApiHostAccessRequestsTest(
      const PermissionsApiHostAccessRequestsTest&) = delete;
  PermissionsApiHostAccessRequestsTest& operator=(
      const PermissionsApiHostAccessRequestsTest&) = delete;

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
};

IN_PROC_BROWSER_TEST_F(PermissionsApiHostAccessRequestsTest,
                       InvalidAddHostAccessRequests) {
  ASSERT_TRUE(StartEmbeddedTestServer());

  ASSERT_TRUE(RunExtensionTest("permissions/add_host_access_request"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(PermissionsApiHostAccessRequestsTest,
                       InvalidRemoveHostAccessRequests) {
  ASSERT_TRUE(StartEmbeddedTestServer());

  ASSERT_TRUE(RunExtensionTest("permissions/remove_host_access_request"))
      << message_;
}

}  // namespace extensions