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