1 // Copyright (c) 2012 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
5 #include <memory>
6 #include <string>
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/compiler_specific.h"
12 #include "base/macros.h"
13 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/extensions/active_tab_permission_granter.h"
16 #include "chrome/browser/extensions/chrome_test_extension_loader.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_service_test_base.h"
19 #include "chrome/browser/extensions/extension_util.h"
20 #include "chrome/browser/extensions/tab_helper.h"
21 #include "chrome/browser/extensions/test_extension_system.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/common/webui_url_constants.h"
24 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "components/sessions/content/session_tab_helper.h"
27 #include "components/version_info/version_info.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/navigation_details.h"
30 #include "content/public/browser/navigation_entry.h"
31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/notification_types.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/test/navigation_simulator.h"
35 #include "content/public/test/web_contents_tester.h"
36 #include "extensions/browser/disable_reason.h"
37 #include "extensions/browser/extension_registry.h"
38 #include "extensions/browser/test_extension_registry_observer.h"
39 #include "extensions/common/constants.h"
40 #include "extensions/common/extension.h"
41 #include "extensions/common/extension_builder.h"
42 #include "extensions/common/extensions_client.h"
43 #include "extensions/common/features/feature.h"
44 #include "extensions/common/features/feature_channel.h"
45 #include "extensions/common/permissions/permissions_data.h"
46 #include "extensions/common/value_builder.h"
47 #include "extensions/test/test_extension_dir.h"
48
49 #if defined(OS_CHROMEOS)
50 #include "base/run_loop.h"
51 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
52 #include "chrome/browser/chromeos/extensions/active_tab_permission_granter_delegate_chromeos.h"
53 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
54 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
55 #include "chrome/browser/chromeos/profiles/profile_helper.h"
56 #include "chrome/browser/ui/ash/test_wallpaper_controller.h"
57 #include "chrome/browser/ui/ash/wallpaper_controller_client.h"
58 #include "chrome/test/base/scoped_testing_local_state.h"
59 #include "chrome/test/base/testing_browser_process.h"
60 #include "chromeos/constants/chromeos_switches.h"
61 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
62 #include "chromeos/login/login_state/scoped_test_public_session_login_state.h"
63 #include "components/account_id/account_id.h"
64 #include "components/sync/driver/sync_driver_switches.h"
65 #include "content/public/common/content_switches.h"
66 #include "extensions/browser/extension_dialog_auto_confirm.h"
67 #endif
68
69 using base::DictionaryValue;
70 using base::ListValue;
71 using content::BrowserThread;
72 using content::NavigationController;
73
74 namespace extensions {
75 namespace {
76
CreateTestExtension(const std::string & name,bool has_active_tab_permission,bool has_tab_capture_permission)77 scoped_refptr<const Extension> CreateTestExtension(
78 const std::string& name,
79 bool has_active_tab_permission,
80 bool has_tab_capture_permission) {
81 ExtensionBuilder builder(name);
82 if (has_active_tab_permission)
83 builder.AddPermission("activeTab");
84 if (has_tab_capture_permission)
85 builder.AddPermission("tabCapture");
86
87 return builder.Build();
88 }
89
90 enum PermittedFeature {
91 PERMITTED_NONE,
92 PERMITTED_SCRIPT_ONLY,
93 PERMITTED_CAPTURE_ONLY,
94 PERMITTED_BOTH
95 };
96
97 class ActiveTabPermissionGranterTestDelegate
98 : public ActiveTabPermissionGranter::Delegate {
99 public:
ActiveTabPermissionGranterTestDelegate()100 ActiveTabPermissionGranterTestDelegate() {}
~ActiveTabPermissionGranterTestDelegate()101 ~ActiveTabPermissionGranterTestDelegate() override {}
102
103 // ActiveTabPermissionGranterTestDelegate::Delegate
ShouldGrantActiveTabOrPrompt(const Extension * extension,content::WebContents * contents)104 bool ShouldGrantActiveTabOrPrompt(const Extension* extension,
105 content::WebContents* contents) override {
106 should_grant_call_count_++;
107 return should_grant_;
108 }
109
SetShouldGrant(bool should_grant)110 void SetShouldGrant(bool should_grant) {
111 should_grant_ = should_grant;
112 }
113
should_grant_call_count()114 int should_grant_call_count() { return should_grant_call_count_; }
115
116 private:
117 bool should_grant_ = false;
118 int should_grant_call_count_ = 0;
119
120 DISALLOW_COPY_AND_ASSIGN(ActiveTabPermissionGranterTestDelegate);
121 };
122
123 class ActiveTabTest : public ChromeRenderViewHostTestHarness {
124 protected:
ActiveTabTest()125 ActiveTabTest()
126 : current_channel(version_info::Channel::DEV),
127 extension(CreateTestExtension("deadbeef", true, false)),
128 another_extension(CreateTestExtension("feedbeef", true, false)),
129 extension_without_active_tab(CreateTestExtension("badbeef",
130 false,
131 false)),
132 extension_with_tab_capture(CreateTestExtension("cafebeef",
133 true,
134 true)) {}
135
SetUp()136 void SetUp() override {
137 ChromeRenderViewHostTestHarness::SetUp();
138 TabHelper::CreateForWebContents(web_contents());
139
140 // We need to add extensions to the ExtensionService; else trying to commit
141 // any of their URLs fails and redirects to about:blank.
142 ExtensionService* service =
143 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))
144 ->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
145 base::FilePath(), false);
146 service->AddExtension(extension.get());
147 service->AddExtension(another_extension.get());
148 service->AddExtension(extension_without_active_tab.get());
149 service->AddExtension(extension_with_tab_capture.get());
150 }
151
TearDown()152 void TearDown() override {
153 #if defined(OS_CHROMEOS)
154 chromeos::KioskAppManager::Shutdown();
155 #endif
156 ChromeRenderViewHostTestHarness::TearDown();
157 }
158
tab_id()159 int tab_id() {
160 return sessions::SessionTabHelper::IdForTab(web_contents()).id();
161 }
162
active_tab_permission_granter()163 ActiveTabPermissionGranter* active_tab_permission_granter() {
164 return extensions::TabHelper::FromWebContents(web_contents())->
165 active_tab_permission_granter();
166 }
167
IsAllowed(const scoped_refptr<const Extension> & extension,const GURL & url)168 bool IsAllowed(const scoped_refptr<const Extension>& extension,
169 const GURL& url) {
170 return IsAllowed(extension, url, PERMITTED_BOTH, tab_id());
171 }
172
IsAllowed(const scoped_refptr<const Extension> & extension,const GURL & url,PermittedFeature feature)173 bool IsAllowed(const scoped_refptr<const Extension>& extension,
174 const GURL& url,
175 PermittedFeature feature) {
176 return IsAllowed(extension, url, feature, tab_id());
177 }
178
IsAllowed(const scoped_refptr<const Extension> & extension,const GURL & url,PermittedFeature feature,int tab_id)179 bool IsAllowed(const scoped_refptr<const Extension>& extension,
180 const GURL& url,
181 PermittedFeature feature,
182 int tab_id) {
183 const PermissionsData* permissions_data = extension->permissions_data();
184 bool script =
185 permissions_data->CanAccessPage(url, tab_id, nullptr) &&
186 permissions_data->CanRunContentScriptOnPage(url, tab_id, nullptr);
187 bool capture = permissions_data->CanCaptureVisiblePage(
188 url, tab_id, NULL, extensions::CaptureRequirement::kActiveTabOrAllUrls);
189 switch (feature) {
190 case PERMITTED_SCRIPT_ONLY:
191 return script && !capture;
192 case PERMITTED_CAPTURE_ONLY:
193 return capture && !script;
194 case PERMITTED_BOTH:
195 return script && capture;
196 case PERMITTED_NONE:
197 return !script && !capture;
198 }
199 NOTREACHED();
200 return false;
201 }
202
IsBlocked(const scoped_refptr<const Extension> & extension,const GURL & url)203 bool IsBlocked(const scoped_refptr<const Extension>& extension,
204 const GURL& url) {
205 return IsBlocked(extension, url, tab_id());
206 }
207
IsBlocked(const scoped_refptr<const Extension> & extension,const GURL & url,int tab_id)208 bool IsBlocked(const scoped_refptr<const Extension>& extension,
209 const GURL& url,
210 int tab_id) {
211 return IsAllowed(extension, url, PERMITTED_NONE, tab_id);
212 }
213
HasTabsPermission(const scoped_refptr<const Extension> & extension)214 bool HasTabsPermission(const scoped_refptr<const Extension>& extension) {
215 return HasTabsPermission(extension, tab_id());
216 }
217
HasTabsPermission(const scoped_refptr<const Extension> & extension,int tab_id)218 bool HasTabsPermission(const scoped_refptr<const Extension>& extension,
219 int tab_id) {
220 return extension->permissions_data()->HasAPIPermissionForTab(
221 tab_id, APIPermission::kTab);
222 }
223
IsGrantedForTab(const Extension * extension,const content::WebContents * web_contents)224 bool IsGrantedForTab(const Extension* extension,
225 const content::WebContents* web_contents) {
226 return extension->permissions_data()->HasAPIPermissionForTab(
227 sessions::SessionTabHelper::IdForTab(web_contents).id(),
228 APIPermission::kTab);
229 }
230
231 // TODO(justinlin): Remove when tabCapture is moved to stable.
232 ScopedCurrentChannel current_channel;
233
234 // An extension with the activeTab permission.
235 scoped_refptr<const Extension> extension;
236
237 // Another extension with activeTab (for good measure).
238 scoped_refptr<const Extension> another_extension;
239
240 // An extension without the activeTab permission.
241 scoped_refptr<const Extension> extension_without_active_tab;
242
243 // An extension with both the activeTab and tabCapture permission.
244 scoped_refptr<const Extension> extension_with_tab_capture;
245 };
246
TEST_F(ActiveTabTest,GrantToSinglePage)247 TEST_F(ActiveTabTest, GrantToSinglePage) {
248 GURL google("http://www.google.com");
249 NavigateAndCommit(google);
250
251 // No access unless it's been granted.
252 EXPECT_TRUE(IsBlocked(extension, google));
253 EXPECT_TRUE(IsBlocked(another_extension, google));
254 EXPECT_TRUE(IsBlocked(extension_without_active_tab, google));
255
256 EXPECT_FALSE(HasTabsPermission(extension));
257 EXPECT_FALSE(HasTabsPermission(another_extension));
258 EXPECT_FALSE(HasTabsPermission(extension_without_active_tab));
259
260 active_tab_permission_granter()->GrantIfRequested(extension.get());
261 active_tab_permission_granter()->GrantIfRequested(
262 extension_without_active_tab.get());
263
264 // Granted to extension and extension_without_active_tab, but the latter
265 // doesn't have the activeTab permission so not granted.
266 EXPECT_TRUE(IsAllowed(extension, google));
267 EXPECT_TRUE(IsBlocked(another_extension, google));
268 EXPECT_TRUE(IsBlocked(extension_without_active_tab, google));
269
270 // Other subdomains shouldn't be given access.
271 GURL mail_google("http://mail.google.com");
272 EXPECT_TRUE(IsBlocked(extension, mail_google));
273 EXPECT_TRUE(IsBlocked(another_extension, mail_google));
274 EXPECT_TRUE(IsBlocked(extension_without_active_tab, mail_google));
275
276 // Reloading the page should not clear the active permissions, since the
277 // user remains on the same site.
278 content::NavigationSimulator::Reload(web_contents());
279
280 EXPECT_TRUE(IsAllowed(extension, google));
281 EXPECT_TRUE(IsBlocked(another_extension, google));
282 EXPECT_TRUE(IsBlocked(extension_without_active_tab, google));
283
284 EXPECT_TRUE(HasTabsPermission(extension));
285 EXPECT_FALSE(HasTabsPermission(another_extension));
286 EXPECT_FALSE(HasTabsPermission(extension_without_active_tab));
287
288 // And grant a few more times redundantly for good measure.
289 active_tab_permission_granter()->GrantIfRequested(extension.get());
290 active_tab_permission_granter()->GrantIfRequested(extension.get());
291 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
292 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
293 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
294 active_tab_permission_granter()->GrantIfRequested(extension.get());
295 active_tab_permission_granter()->GrantIfRequested(extension.get());
296 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
297 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
298
299 EXPECT_TRUE(IsAllowed(extension, google));
300 EXPECT_TRUE(IsAllowed(another_extension, google));
301 EXPECT_TRUE(IsBlocked(extension_without_active_tab, google));
302
303 // Navigating to a new URL should clear the active permissions.
304 GURL chromium("http://www.chromium.org");
305 NavigateAndCommit(chromium);
306
307 EXPECT_TRUE(IsBlocked(extension, google));
308 EXPECT_TRUE(IsBlocked(another_extension, google));
309 EXPECT_TRUE(IsBlocked(extension_without_active_tab, google));
310
311 EXPECT_TRUE(IsBlocked(extension, chromium));
312 EXPECT_TRUE(IsBlocked(another_extension, chromium));
313 EXPECT_TRUE(IsBlocked(extension_without_active_tab, chromium));
314
315 EXPECT_FALSE(HasTabsPermission(extension));
316 EXPECT_FALSE(HasTabsPermission(another_extension));
317 EXPECT_FALSE(HasTabsPermission(extension_without_active_tab));
318
319 // Should be able to grant to multiple extensions at the same time (if they
320 // have the activeTab permission, of course).
321 active_tab_permission_granter()->GrantIfRequested(extension.get());
322 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
323 active_tab_permission_granter()->GrantIfRequested(
324 extension_without_active_tab.get());
325
326 EXPECT_TRUE(IsBlocked(extension, google));
327 EXPECT_TRUE(IsBlocked(another_extension, google));
328 EXPECT_TRUE(IsBlocked(extension_without_active_tab, google));
329
330 EXPECT_TRUE(IsAllowed(extension, chromium));
331 EXPECT_TRUE(IsAllowed(another_extension, chromium));
332 EXPECT_TRUE(IsBlocked(extension_without_active_tab, chromium));
333
334 // Should be able to go back to URLs that were previously cleared.
335 NavigateAndCommit(google);
336
337 active_tab_permission_granter()->GrantIfRequested(extension.get());
338 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
339 active_tab_permission_granter()->GrantIfRequested(
340 extension_without_active_tab.get());
341
342 EXPECT_TRUE(IsAllowed(extension, google));
343 EXPECT_TRUE(IsAllowed(another_extension, google));
344 EXPECT_TRUE(IsBlocked(extension_without_active_tab, google));
345
346 EXPECT_TRUE(IsBlocked(extension, chromium));
347 EXPECT_TRUE(IsBlocked(another_extension, chromium));
348 EXPECT_TRUE(IsBlocked(extension_without_active_tab, chromium));
349 }
350
TEST_F(ActiveTabTest,CapturingPagesWithActiveTab)351 TEST_F(ActiveTabTest, CapturingPagesWithActiveTab) {
352 std::vector<GURL> test_urls = {
353 GURL("https://example.com"),
354 GURL(chrome::kChromeUIVersionURL),
355 GURL(chrome::kChromeUINewTabURL),
356 GURL("http://[2607:f8b0:4005:805::200e]"),
357 ExtensionsClient::Get()->GetWebstoreBaseURL(),
358 extension->GetResourceURL("test.html"),
359 another_extension->GetResourceURL("test.html"),
360 };
361
362 const GURL kAboutBlank("about:blank");
363
364 for (const GURL& url : test_urls) {
365 SCOPED_TRACE(url);
366 NavigateAndCommit(url);
367 EXPECT_EQ(url, web_contents()->GetLastCommittedURL());
368 // By default, there should be no access.
369 EXPECT_FALSE(extension->permissions_data()->CanCaptureVisiblePage(
370 url, tab_id(), nullptr /*error*/,
371 extensions::CaptureRequirement::kActiveTabOrAllUrls));
372 // Granting permission should allow page capture.
373 active_tab_permission_granter()->GrantIfRequested(extension.get());
374 EXPECT_TRUE(extension->permissions_data()->CanCaptureVisiblePage(
375 url, tab_id(), nullptr /*error*/,
376 extensions::CaptureRequirement::kActiveTabOrAllUrls));
377 // Navigating away should revoke access.
378 NavigateAndCommit(kAboutBlank);
379 EXPECT_FALSE(extension->permissions_data()->CanCaptureVisiblePage(
380 url, tab_id(), nullptr /*error*/,
381 extensions::CaptureRequirement::kActiveTabOrAllUrls));
382 }
383 }
384
TEST_F(ActiveTabTest,Unloading)385 TEST_F(ActiveTabTest, Unloading) {
386 // Some semi-arbitrary setup.
387 GURL google("http://www.google.com");
388 NavigateAndCommit(google);
389
390 active_tab_permission_granter()->GrantIfRequested(extension.get());
391
392 EXPECT_TRUE(IsGrantedForTab(extension.get(), web_contents()));
393 EXPECT_TRUE(IsAllowed(extension, google));
394
395 // Unloading the extension should clear its tab permissions.
396 ExtensionSystem::Get(web_contents()->GetBrowserContext())
397 ->extension_service()
398 ->DisableExtension(extension->id(), disable_reason::DISABLE_USER_ACTION);
399
400 // Note: can't EXPECT_FALSE(IsAllowed) here because uninstalled extensions
401 // are just that... considered to be uninstalled, and the manager might
402 // just ignore them from here on.
403
404 // Granting the extension again should give them back.
405 active_tab_permission_granter()->GrantIfRequested(extension.get());
406
407 EXPECT_TRUE(IsGrantedForTab(extension.get(), web_contents()));
408 EXPECT_TRUE(IsAllowed(extension, google));
409 }
410
TEST_F(ActiveTabTest,OnlyActiveTab)411 TEST_F(ActiveTabTest, OnlyActiveTab) {
412 GURL google("http://www.google.com");
413 NavigateAndCommit(google);
414
415 active_tab_permission_granter()->GrantIfRequested(extension.get());
416
417 EXPECT_TRUE(IsAllowed(extension, google, PERMITTED_BOTH, tab_id()));
418 EXPECT_TRUE(IsBlocked(extension, google, tab_id() + 1));
419 EXPECT_FALSE(HasTabsPermission(extension, tab_id() + 1));
420 }
421
TEST_F(ActiveTabTest,SameDocumentNavigations)422 TEST_F(ActiveTabTest, SameDocumentNavigations) {
423 GURL google("http://www.google.com");
424 NavigateAndCommit(google);
425
426 active_tab_permission_granter()->GrantIfRequested(extension.get());
427
428 // Perform a same-document navigation. The extension should not lose the
429 // temporary permission.
430 GURL google_h1("http://www.google.com#h1");
431 NavigateAndCommit(google_h1);
432
433 EXPECT_TRUE(IsAllowed(extension, google));
434 EXPECT_TRUE(IsAllowed(extension, google_h1));
435
436 GURL chromium("http://www.chromium.org");
437 NavigateAndCommit(chromium);
438
439 EXPECT_FALSE(IsAllowed(extension, google));
440 EXPECT_FALSE(IsAllowed(extension, google_h1));
441 EXPECT_FALSE(IsAllowed(extension, chromium));
442
443 active_tab_permission_granter()->GrantIfRequested(extension.get());
444
445 EXPECT_FALSE(IsAllowed(extension, google));
446 EXPECT_FALSE(IsAllowed(extension, google_h1));
447 EXPECT_TRUE(IsAllowed(extension, chromium));
448
449 GURL chromium_h1("http://www.chromium.org#h1");
450 NavigateAndCommit(chromium_h1);
451
452 EXPECT_FALSE(IsAllowed(extension, google));
453 EXPECT_FALSE(IsAllowed(extension, google_h1));
454 EXPECT_TRUE(IsAllowed(extension, chromium));
455 EXPECT_TRUE(IsAllowed(extension, chromium_h1));
456
457 content::NavigationSimulator::Reload(web_contents());
458
459 EXPECT_FALSE(IsAllowed(extension, google));
460 EXPECT_FALSE(IsAllowed(extension, google_h1));
461 EXPECT_TRUE(IsAllowed(extension, chromium));
462 EXPECT_TRUE(IsAllowed(extension, chromium_h1));
463 }
464
TEST_F(ActiveTabTest,ChromeUrlGrants)465 TEST_F(ActiveTabTest, ChromeUrlGrants) {
466 GURL internal(chrome::kChromeUIVersionURL);
467 NavigateAndCommit(internal);
468 active_tab_permission_granter()->GrantIfRequested(
469 extension_with_tab_capture.get());
470 // Do not grant tabs/hosts permissions for tab.
471 EXPECT_TRUE(IsAllowed(extension_with_tab_capture, internal,
472 PERMITTED_CAPTURE_ONLY));
473 const PermissionsData* permissions_data =
474 extension_with_tab_capture->permissions_data();
475 EXPECT_TRUE(permissions_data->HasAPIPermissionForTab(
476 tab_id(), APIPermission::kTabCaptureForTab));
477
478 EXPECT_TRUE(IsBlocked(extension_with_tab_capture, internal, tab_id() + 1));
479 EXPECT_FALSE(permissions_data->HasAPIPermissionForTab(
480 tab_id() + 1, APIPermission::kTabCaptureForTab));
481 }
482
483 class ActiveTabDelegateTest : public ActiveTabTest {
484 protected:
ActiveTabDelegateTest()485 ActiveTabDelegateTest() {
486 auto delegate = std::make_unique<ActiveTabPermissionGranterTestDelegate>();
487 test_delegate_ = delegate.get();
488 ActiveTabPermissionGranter::SetPlatformDelegate(std::move(delegate));
489 }
490
~ActiveTabDelegateTest()491 ~ActiveTabDelegateTest() override {
492 ActiveTabPermissionGranter::SetPlatformDelegate(nullptr);
493 }
494
495 ActiveTabPermissionGranterTestDelegate* test_delegate_;
496 };
497
498 // Test that the custom platform delegate works as expected.
TEST_F(ActiveTabDelegateTest,Delegate)499 TEST_F(ActiveTabDelegateTest, Delegate) {
500 GURL google("http://www.google.com");
501 NavigateAndCommit(google);
502
503 // Not granted because the delegate denies grant.
504 active_tab_permission_granter()->GrantIfRequested(extension.get());
505 EXPECT_TRUE(IsBlocked(extension, google));
506
507 // This time it's granted because the delegate allows it.
508 test_delegate_->SetShouldGrant(true);
509 active_tab_permission_granter()->GrantIfRequested(extension.get());
510 EXPECT_TRUE(IsAllowed(extension, google));
511 }
512
513 // Regression test for crbug.com/833188.
TEST_F(ActiveTabDelegateTest,DelegateUsedOnlyWhenNeeded)514 TEST_F(ActiveTabDelegateTest, DelegateUsedOnlyWhenNeeded) {
515 active_tab_permission_granter()->GrantIfRequested(
516 extension_without_active_tab.get());
517
518 EXPECT_EQ(0, test_delegate_->should_grant_call_count());
519 }
520
521 #if defined(OS_CHROMEOS)
522 class ActiveTabManagedSessionTest : public ActiveTabTest {
523 protected:
ActiveTabManagedSessionTest()524 ActiveTabManagedSessionTest() {}
525
SetUp()526 void SetUp() override {
527 ActiveTabTest::SetUp();
528
529 // Necessary to prevent instantiation of ProfileSyncService, which messes
530 // with our signin state below.
531 base::CommandLine::ForCurrentProcess()->AppendSwitch(
532 switches::kDisableSync);
533 // Necessary because no ProfileManager instance exists in this test.
534 base::CommandLine::ForCurrentProcess()->AppendSwitch(
535 chromeos::switches::kIgnoreUserProfileMappingForTests);
536 // Necessary to skip cryptohome/profile sanity check in
537 // ChromeUserManagerImpl for fake user login.
538 base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kTestType);
539
540 // Setup, login a public account user.
541 const std::string user_id = "public@account.user";
542 const std::string user_email = user_id;
543 const AccountId account_id =
544 AccountId::FromUserEmailGaiaId(user_email, user_id);
545 const std::string user_id_hash =
546 chromeos::ProfileHelper::Get()->GetUserIdHashByUserIdForTesting(
547 user_id);
548
549 local_state_ = std::make_unique<ScopedTestingLocalState>(
550 TestingBrowserProcess::GetGlobal());
551 wallpaper_controller_client_ =
552 std::make_unique<WallpaperControllerClient>();
553 wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_);
554 g_browser_process->local_state()->SetString(
555 "PublicAccountPendingDataRemoval", user_email);
556 user_manager::UserManager::Get()->UserLoggedIn(account_id, user_id_hash,
557 true /* browser_restart */,
558 false /* is_child */);
559 // Finish initialization - some things are run as separate tasks.
560 base::RunLoop().RunUntilIdle();
561
562 google_ = GURL("http://www.google.com");
563 NavigateAndCommit(google_);
564 }
565
TearDown()566 void TearDown() override {
567 // This one needs to be destructed here so it deregisters itself from
568 // CrosSettings before that is destructed down the line inside
569 // ChromeRenderViewHostTestHarness::TearDown.
570 wallpaper_controller_client_.reset();
571
572 chromeos::ChromeUserManagerImpl::ResetPublicAccountDelegatesForTesting();
573 chromeos::ChromeUserManager::Get()->Shutdown();
574
575 ActiveTabTest::TearDown();
576 }
577
578 std::unique_ptr<ScopedTestingLocalState> local_state_;
579 TestWallpaperController test_wallpaper_controller_;
580 std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_;
581 GURL google_;
582 };
583
584 // Test that there's no permission prompt in Managed Sessions (Public Sessions
585 // v2) for activeTab.
TEST_F(ActiveTabManagedSessionTest,NoPromptInManagedSession)586 TEST_F(ActiveTabManagedSessionTest, NoPromptInManagedSession) {
587 chromeos::ScopedTestPublicSessionLoginState login_state(
588 chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED);
589
590 active_tab_permission_granter()->GrantIfRequested(
591 extension_with_tab_capture.get());
592 EXPECT_TRUE(IsAllowed(extension_with_tab_capture, google_));
593 }
594
595 // Keep the unique_ptr around until callback has been run and don't forget to
596 // unset the ActiveTabPermissionGranterDelegateChromeOS.
597 std::unique_ptr<permission_helper::RequestResolvedCallback>
QuitRunLoopOnRequestResolved(base::RunLoop * run_loop)598 QuitRunLoopOnRequestResolved(base::RunLoop* run_loop) {
599 auto callback = std::make_unique<permission_helper::RequestResolvedCallback>(
600 base::BindRepeating([](base::RunLoop* run_loop, const PermissionIDSet&) {
601 run_loop->Quit();
602 }, run_loop));
603 ActiveTabPermissionGranterDelegateChromeOS::
604 SetRequestResolvedCallbackForTesting(callback.get());
605 return callback;
606 }
607
608 // Test that the platform delegate is being set and the activeTab permission is
609 // prompted for in Public Sessions.
TEST_F(ActiveTabManagedSessionTest,DelegateIsSetAndPromptIsShownInPublicSession)610 TEST_F(ActiveTabManagedSessionTest,
611 DelegateIsSetAndPromptIsShownInPublicSession) {
612 chromeos::ScopedTestPublicSessionLoginState login_state(
613 chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT);
614 // Grant and verify.
615 {
616 ScopedTestDialogAutoConfirm auto_confirm(
617 ScopedTestDialogAutoConfirm::ACCEPT);
618
619 // RunLoop needed to resolve the permission dialog.
620 base::RunLoop run_loop;
621 auto cb = QuitRunLoopOnRequestResolved(&run_loop);
622 active_tab_permission_granter()->GrantIfRequested(extension.get());
623 run_loop.Run();
624 EXPECT_TRUE(IsBlocked(extension, google_));
625
626 active_tab_permission_granter()->GrantIfRequested(extension.get());
627 EXPECT_TRUE(IsAllowed(extension, google_));
628 }
629
630 // Deny and verify. Use a different extension so it doesn't trigger the
631 // cache.
632 {
633 ScopedTestDialogAutoConfirm auto_confirm(
634 ScopedTestDialogAutoConfirm::CANCEL);
635
636 base::RunLoop run_loop;
637 auto cb = QuitRunLoopOnRequestResolved(&run_loop);
638 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
639 run_loop.Run();
640 EXPECT_TRUE(IsBlocked(another_extension, google_));
641
642 active_tab_permission_granter()->GrantIfRequested(another_extension.get());
643 EXPECT_TRUE(IsBlocked(another_extension, google_));
644 }
645
646 // Cleanup.
647 ActiveTabPermissionGranterDelegateChromeOS::
648 SetRequestResolvedCallbackForTesting(nullptr);
649 }
650 #endif // defined(OS_CHROMEOS)
651
652 // An active tab test that includes an ExtensionService.
653 class ActiveTabWithServiceTest : public ExtensionServiceTestBase {
654 public:
ActiveTabWithServiceTest()655 ActiveTabWithServiceTest() {}
656
657 void SetUp() override;
658
659 private:
660 DISALLOW_COPY_AND_ASSIGN(ActiveTabWithServiceTest);
661 };
662
SetUp()663 void ActiveTabWithServiceTest::SetUp() {
664 ExtensionServiceTestBase::SetUp();
665 }
666
667 // Tests that an extension can only capture file:// URLs with the active tab
668 // permission when it has file access granted.
669 // Regression test for https://crbug.com/810220.
TEST_F(ActiveTabWithServiceTest,FileURLs)670 TEST_F(ActiveTabWithServiceTest, FileURLs) {
671 InitializeEmptyExtensionService();
672
673 TestExtensionDir test_dir;
674 test_dir.WriteManifest(R"(
675 {
676 "name": "Active Tab Capture With File Urls",
677 "description": "Testing activeTab on file urls",
678 "version": "0.1",
679 "manifest_version": 2,
680 "permissions": ["activeTab"]
681 })");
682
683 ChromeTestExtensionLoader loader(profile());
684 loader.set_allow_file_access(false);
685 scoped_refptr<const Extension> extension =
686 loader.LoadExtension(test_dir.UnpackedPath());
687 ASSERT_TRUE(extension);
688 const std::string id = extension->id();
689 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
690
691 EXPECT_FALSE(util::AllowFileAccess(id, profile()));
692
693 std::unique_ptr<content::WebContents> web_contents(
694 content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
695 ASSERT_TRUE(web_contents);
696
697 const GURL file_url("file:///foo");
698 ASSERT_TRUE(content::WebContentsTester::For(web_contents.get()));
699 content::WebContentsTester::For(web_contents.get())
700 ->NavigateAndCommit(file_url);
701 EXPECT_EQ(file_url, web_contents->GetLastCommittedURL());
702
703 TabHelper::CreateForWebContents(web_contents.get());
704 ActiveTabPermissionGranter* permission_granter =
705 TabHelper::FromWebContents(web_contents.get())
706 ->active_tab_permission_granter();
707 ASSERT_TRUE(permission_granter);
708 const int tab_id =
709 sessions::SessionTabHelper::IdForTab(web_contents.get()).id();
710 EXPECT_NE(extension_misc::kUnknownTabId, tab_id);
711
712 EXPECT_FALSE(extension->permissions_data()->CanCaptureVisiblePage(
713 web_contents->GetLastCommittedURL(), tab_id, nullptr,
714 extensions::CaptureRequirement::kActiveTabOrAllUrls));
715
716 permission_granter->GrantIfRequested(extension.get());
717 EXPECT_FALSE(extension->permissions_data()->CanCaptureVisiblePage(
718 web_contents->GetLastCommittedURL(), tab_id, nullptr,
719 extensions::CaptureRequirement::kActiveTabOrAllUrls));
720
721 permission_granter->RevokeForTesting();
722 TestExtensionRegistryObserver observer(registry(), id);
723 // This will reload the extension, so we need to reset the extension pointer.
724 util::SetAllowFileAccess(id, profile(), true);
725 extension = observer.WaitForExtensionLoaded();
726 ASSERT_TRUE(extension);
727
728 EXPECT_FALSE(extension->permissions_data()->CanCaptureVisiblePage(
729 web_contents->GetLastCommittedURL(), tab_id, nullptr,
730 extensions::CaptureRequirement::kActiveTabOrAllUrls));
731 permission_granter->GrantIfRequested(extension.get());
732 EXPECT_TRUE(extension->permissions_data()->CanCaptureVisiblePage(
733 web_contents->GetLastCommittedURL(), tab_id, nullptr,
734 extensions::CaptureRequirement::kActiveTabOrAllUrls));
735 }
736
737 } // namespace
738 } // namespace extensions
739