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 "chrome/browser/extensions/crx_installer.h"
6
7#include "base/at_exit.h"
8#include "base/memory/ref_counted.h"
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/browser/download/download_crx_util.h"
11#include "chrome/browser/extensions/browser_action_test_util.h"
12#include "chrome/browser/extensions/extension_browsertest.h"
13#include "chrome/browser/extensions/extension_install_prompt.h"
14#include "chrome/browser/extensions/extension_service.h"
15#include "chrome/browser/extensions/extension_util.h"
16#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
17#include "chrome/browser/extensions/test_extension_dir.h"
18#include "chrome/browser/profiles/profile.h"
19#include "chrome/browser/ui/browser.h"
20#include "chrome/browser/ui/browser_window.h"
21#include "chrome/browser/ui/tabs/tab_strip_model.h"
22#include "chrome/grit/generated_resources.h"
23#include "chrome/test/base/ui_test_utils.h"
24#include "content/public/browser/browser_thread.h"
25#include "content/public/browser/download_manager.h"
26#include "content/public/browser/render_view_host.h"
27#include "content/public/test/browser_test_utils.h"
28#include "content/public/test/download_test_observer.h"
29#include "content/public/test/test_utils.h"
30#include "extensions/browser/extension_prefs.h"
31#include "extensions/browser/extension_registry.h"
32#include "extensions/browser/extension_system.h"
33#include "extensions/browser/management_policy.h"
34#include "extensions/browser/notification_types.h"
35#include "extensions/common/extension.h"
36#include "extensions/common/feature_switch.h"
37#include "extensions/common/file_util.h"
38#include "extensions/common/permissions/permission_set.h"
39#include "extensions/common/switches.h"
40#include "ui/base/l10n/l10n_util.h"
41
42#if defined(OS_CHROMEOS)
43#include "chrome/browser/chromeos/login/users/fake_user_manager.h"
44#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
45#include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
46#include "chromeos/chromeos_switches.h"
47#endif
48
49class SkBitmap;
50
51namespace extensions {
52
53namespace {
54
55class MockInstallPrompt;
56
57// This class holds information about things that happen with a
58// MockInstallPrompt. We create the MockInstallPrompt but need to pass
59// ownership of it to CrxInstaller, so it isn't safe to hang this data on
60// MockInstallPrompt itself becuase we can't guarantee it's lifetime.
61class MockPromptProxy : public base::RefCountedThreadSafe<MockPromptProxy> {
62 public:
63  explicit MockPromptProxy(content::WebContents* web_contents);
64
65  bool did_succeed() const { return !extension_id_.empty(); }
66  const std::string& extension_id() { return extension_id_; }
67  bool confirmation_requested() const { return confirmation_requested_; }
68  const base::string16& error() const { return error_; }
69
70  // To have any effect, this should be called before CreatePrompt.
71  void set_record_oauth2_grant(bool record_oauth2_grant) {
72    record_oauth2_grant_.reset(new bool(record_oauth2_grant));
73  }
74
75  void set_extension_id(const std::string& id) { extension_id_ = id; }
76  void set_confirmation_requested() { confirmation_requested_ = true; }
77  void set_error(const base::string16& error) { error_ = error; }
78
79  scoped_ptr<ExtensionInstallPrompt> CreatePrompt();
80
81 private:
82  friend class base::RefCountedThreadSafe<MockPromptProxy>;
83  virtual ~MockPromptProxy();
84
85  // Data used to create a prompt.
86  content::WebContents* web_contents_;
87  scoped_ptr<bool> record_oauth2_grant_;
88
89  // Data reported back to us by the prompt we created.
90  bool confirmation_requested_;
91  std::string extension_id_;
92  base::string16 error_;
93};
94
95class MockInstallPrompt : public ExtensionInstallPrompt {
96 public:
97  MockInstallPrompt(content::WebContents* web_contents,
98                    MockPromptProxy* proxy) :
99      ExtensionInstallPrompt(web_contents),
100      proxy_(proxy) {}
101
102  void set_record_oauth2_grant(bool record) { record_oauth2_grant_ = record; }
103
104  // Overriding some of the ExtensionInstallUI API.
105  virtual void ConfirmInstall(
106      Delegate* delegate,
107      const Extension* extension,
108      const ShowDialogCallback& show_dialog_callback) OVERRIDE {
109    proxy_->set_confirmation_requested();
110    delegate->InstallUIProceed();
111  }
112  virtual void OnInstallSuccess(const Extension* extension,
113                                SkBitmap* icon) OVERRIDE {
114    proxy_->set_extension_id(extension->id());
115    base::MessageLoopForUI::current()->Quit();
116  }
117  virtual void OnInstallFailure(const CrxInstallerError& error) OVERRIDE {
118    proxy_->set_error(error.message());
119    base::MessageLoopForUI::current()->Quit();
120  }
121
122 private:
123  scoped_refptr<MockPromptProxy> proxy_;
124};
125
126MockPromptProxy::MockPromptProxy(content::WebContents* web_contents)
127    : web_contents_(web_contents), confirmation_requested_(false) {
128}
129
130MockPromptProxy::~MockPromptProxy() {}
131
132scoped_ptr<ExtensionInstallPrompt> MockPromptProxy::CreatePrompt() {
133  scoped_ptr<MockInstallPrompt> prompt(
134      new MockInstallPrompt(web_contents_, this));
135  if (record_oauth2_grant_.get())
136    prompt->set_record_oauth2_grant(*record_oauth2_grant_.get());
137  return prompt.PassAs<ExtensionInstallPrompt>();
138}
139
140
141scoped_refptr<MockPromptProxy> CreateMockPromptProxyForBrowser(
142    Browser* browser) {
143  return new MockPromptProxy(
144      browser->tab_strip_model()->GetActiveWebContents());
145}
146
147class ManagementPolicyMock : public extensions::ManagementPolicy::Provider {
148 public:
149  ManagementPolicyMock() {}
150
151  virtual std::string GetDebugPolicyProviderName() const OVERRIDE {
152    return "ManagementPolicyMock";
153  }
154
155  virtual bool UserMayLoad(const Extension* extension,
156                           base::string16* error) const OVERRIDE {
157    *error = base::UTF8ToUTF16("Dummy error message");
158    return false;
159  }
160};
161
162}  // namespace
163
164class ExtensionCrxInstallerTest : public ExtensionBrowserTest {
165 public:
166  scoped_ptr<WebstoreInstaller::Approval> GetApproval(
167      const char* manifest_dir,
168      const std::string& id,
169      bool strict_manifest_checks) {
170    scoped_ptr<WebstoreInstaller::Approval> result;
171
172    base::FilePath ext_path = test_data_dir_.AppendASCII(manifest_dir);
173    std::string error;
174    scoped_ptr<base::DictionaryValue> parsed_manifest(
175        file_util::LoadManifest(ext_path, &error));
176    if (!parsed_manifest.get() || !error.empty())
177      return result.Pass();
178
179    return WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
180        browser()->profile(),
181        id,
182        parsed_manifest.Pass(),
183        strict_manifest_checks);
184  }
185
186  void RunCrxInstaller(const WebstoreInstaller::Approval* approval,
187                       scoped_ptr<ExtensionInstallPrompt> prompt,
188                       const base::FilePath& crx_path) {
189    ExtensionService* service = extensions::ExtensionSystem::Get(
190        browser()->profile())->extension_service();
191    scoped_refptr<CrxInstaller> installer(
192        CrxInstaller::Create(service, prompt.Pass(), approval));
193    installer->set_allow_silent_install(true);
194    installer->set_is_gallery_install(true);
195    installer->InstallCrx(crx_path);
196    content::RunMessageLoop();
197  }
198
199  // Installs a crx from |crx_relpath| (a path relative to the extension test
200  // data dir) with expected id |id|.
201  void InstallWithPrompt(const char* ext_relpath,
202                         const std::string& id,
203                         scoped_refptr<MockPromptProxy> mock_install_prompt) {
204    base::FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath);
205
206    scoped_ptr<WebstoreInstaller::Approval> approval;
207    if (!id.empty())
208      approval = GetApproval(ext_relpath, id, true);
209
210    base::FilePath crx_path = PackExtension(ext_path);
211    EXPECT_FALSE(crx_path.empty());
212    RunCrxInstaller(approval.get(), mock_install_prompt->CreatePrompt(),
213                    crx_path);
214
215    EXPECT_TRUE(mock_install_prompt->did_succeed());
216  }
217
218  // Installs an extension and checks that it has scopes granted IFF
219  // |record_oauth2_grant| is true.
220  void CheckHasEmptyScopesAfterInstall(const std::string& ext_relpath,
221                                       bool record_oauth2_grant) {
222    CommandLine::ForCurrentProcess()->AppendSwitch(
223        switches::kEnableExperimentalExtensionApis);
224
225    scoped_refptr<MockPromptProxy> mock_prompt =
226        CreateMockPromptProxyForBrowser(browser());
227
228    mock_prompt->set_record_oauth2_grant(record_oauth2_grant);
229    InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt);
230
231    scoped_refptr<PermissionSet> permissions =
232        ExtensionPrefs::Get(browser()->profile())
233            ->GetGrantedPermissions(mock_prompt->extension_id());
234    ASSERT_TRUE(permissions.get());
235  }
236};
237
238// This test is skipped on ChromeOS because it requires the NPAPI,
239// which is not available on that platform.
240#if !defined(OS_CHROMEOS)
241IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Whitelisting) {
242  std::string id = "hdgllgikmikobbofgnabhfimcfoopgnd";
243  ExtensionRegistry* registry = ExtensionRegistry::Get(
244      browser()->profile());
245
246  // Even whitelisted extensions with NPAPI should not prompt.
247  scoped_refptr<MockPromptProxy> mock_prompt =
248      CreateMockPromptProxyForBrowser(browser());
249  InstallWithPrompt("uitest/plugins", id, mock_prompt);
250  EXPECT_FALSE(mock_prompt->confirmation_requested());
251  EXPECT_TRUE(registry->enabled_extensions().GetByID(id));
252}
253#endif
254
255IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
256                       GalleryInstallGetsExperimental) {
257  // We must modify the command line temporarily in order to pack an extension
258  // that requests the experimental permission.
259  CommandLine* command_line = CommandLine::ForCurrentProcess();
260  CommandLine old_command_line = *command_line;
261  command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
262  base::FilePath crx_path = PackExtension(
263      test_data_dir_.AppendASCII("experimental"));
264  ASSERT_FALSE(crx_path.empty());
265
266  // Now reset the command line so that we are testing specifically whether
267  // installing from webstore enables experimental permissions.
268  *(CommandLine::ForCurrentProcess()) = old_command_line;
269
270  EXPECT_FALSE(InstallExtension(crx_path, 0));
271  EXPECT_TRUE(InstallExtensionFromWebstore(crx_path, 1));
272}
273
274IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, PlatformAppCrx) {
275  CommandLine::ForCurrentProcess()->AppendSwitch(
276      switches::kEnableExperimentalExtensionApis);
277  EXPECT_TRUE(InstallExtension(
278      test_data_dir_.AppendASCII("minimal_platform_app.crx"), 1));
279}
280
281IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, PackAndInstallExtension) {
282  if (!FeatureSwitch::easy_off_store_install()->IsEnabled())
283    return;
284
285  const int kNumDownloadsExpected = 1;
286
287  LOG(ERROR) << "PackAndInstallExtension: Packing extension";
288  base::FilePath crx_path = PackExtension(
289      test_data_dir_.AppendASCII("common/background_page"));
290  ASSERT_FALSE(crx_path.empty());
291  std::string crx_path_string(crx_path.value().begin(), crx_path.value().end());
292  GURL url = GURL(std::string("file:///").append(crx_path_string));
293
294  scoped_refptr<MockPromptProxy> mock_prompt =
295      CreateMockPromptProxyForBrowser(browser());
296  download_crx_util::SetMockInstallPromptForTesting(
297      mock_prompt->CreatePrompt());
298
299  LOG(ERROR) << "PackAndInstallExtension: Getting download manager";
300  content::DownloadManager* download_manager =
301      content::BrowserContext::GetDownloadManager(browser()->profile());
302
303  LOG(ERROR) << "PackAndInstallExtension: Setting observer";
304  scoped_ptr<content::DownloadTestObserver> observer(
305      new content::DownloadTestObserverTerminal(
306          download_manager, kNumDownloadsExpected,
307          content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));
308  LOG(ERROR) << "PackAndInstallExtension: Navigating to URL";
309  ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB,
310      ui_test_utils::BROWSER_TEST_NONE);
311
312  EXPECT_TRUE(WaitForCrxInstallerDone());
313  LOG(ERROR) << "PackAndInstallExtension: Extension install";
314  EXPECT_TRUE(mock_prompt->confirmation_requested());
315  LOG(ERROR) << "PackAndInstallExtension: Extension install confirmed";
316}
317
318// Tests that scopes are only granted if |record_oauth2_grant_| on the prompt is
319// true.
320#if defined(OS_WIN)
321#define MAYBE_GrantScopes DISABLED_GrantScopes
322#else
323#define MAYBE_GrantScopes GrantScopes
324#endif
325IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, MAYBE_GrantScopes) {
326  EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
327                                                          true));
328}
329
330IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, DoNotGrantScopes) {
331  EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
332                                                          false));
333}
334
335IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, AllowOffStore) {
336  ExtensionService* service = extensions::ExtensionSystem::Get(
337      browser()->profile())->extension_service();
338  const bool kTestData[] = {false, true};
339
340  for (size_t i = 0; i < arraysize(kTestData); ++i) {
341    scoped_refptr<MockPromptProxy> mock_prompt =
342        CreateMockPromptProxyForBrowser(browser());
343
344    scoped_refptr<CrxInstaller> crx_installer(
345        CrxInstaller::Create(service, mock_prompt->CreatePrompt()));
346    crx_installer->set_install_cause(
347        extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
348
349    if (kTestData[i]) {
350      crx_installer->set_off_store_install_allow_reason(
351          CrxInstaller::OffStoreInstallAllowedInTest);
352    }
353
354    crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx"));
355    // The |mock_prompt| will quit running the loop once the |crx_installer|
356    // is done.
357    content::RunMessageLoop();
358    EXPECT_EQ(kTestData[i], mock_prompt->did_succeed());
359    EXPECT_EQ(kTestData[i], mock_prompt->confirmation_requested()) <<
360        kTestData[i];
361    if (kTestData[i]) {
362      EXPECT_EQ(base::string16(), mock_prompt->error()) << kTestData[i];
363    } else {
364      EXPECT_EQ(l10n_util::GetStringUTF16(
365          IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE),
366          mock_prompt->error()) << kTestData[i];
367    }
368  }
369}
370
371IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, HiDpiThemeTest) {
372  base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx");
373  crx_path = crx_path.AppendASCII("theme_hidpi.crx");
374
375  ASSERT_TRUE(InstallExtension(crx_path, 1));
376
377  const std::string extension_id("gllekhaobjnhgeagipipnkpmmmpchacm");
378  ExtensionRegistry* registry = ExtensionRegistry::Get(
379      browser()->profile());
380  const extensions::Extension* extension =
381     registry->enabled_extensions().GetByID(extension_id);
382  ASSERT_TRUE(extension);
383  EXPECT_EQ(extension_id, extension->id());
384
385  UninstallExtension(extension_id);
386  EXPECT_FALSE(registry->enabled_extensions().GetByID(extension_id));
387}
388
389// See http://crbug.com/315299.
390#if defined(OS_WIN) || defined(OS_LINUX)
391#define MAYBE_InstallDelayedUntilNextUpdate \
392        DISABLED_InstallDelayedUntilNextUpdate
393#else
394#define MAYBE_InstallDelayedUntilNextUpdate InstallDelayedUntilNextUpdate
395#endif
396IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
397                       MAYBE_InstallDelayedUntilNextUpdate) {
398  const std::string extension_id("ldnnhddmnhbkjipkidpdiheffobcpfmf");
399  base::FilePath crx_path = test_data_dir_.AppendASCII("delayed_install");
400  ExtensionSystem* extension_system = extensions::ExtensionSystem::Get(
401      browser()->profile());
402  ExtensionService* service = extension_system->extension_service();
403  ASSERT_TRUE(service);
404  ExtensionRegistry* registry = ExtensionRegistry::Get(
405      browser()->profile());
406  ASSERT_TRUE(registry);
407
408  // Install version 1 of the test extension. This extension does not have
409  // a background page but does have a browser action.
410  ASSERT_TRUE(InstallExtension(crx_path.AppendASCII("v1.crx"), 1));
411  const extensions::Extension* extension =
412     registry->enabled_extensions().GetByID(extension_id);
413  ASSERT_TRUE(extension);
414  ASSERT_EQ(extension_id, extension->id());
415  ASSERT_EQ("1.0", extension->version()->GetString());
416
417  // Make test extension non-idle by opening the extension's browser action
418  // popup. This should cause the installation to be delayed.
419  content::WindowedNotificationObserver loading_observer(
420      extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
421      content::Source<Profile>(profile()));
422  BrowserActionTestUtil util(browser());
423  // There is only one extension, so just click the first browser action.
424  ASSERT_EQ(1, util.NumberOfBrowserActions());
425  util.Press(0);
426  loading_observer.Wait();
427  ExtensionHost* extension_host =
428      content::Details<ExtensionHost>(loading_observer.details()).ptr();
429
430  // Install version 2 of the extension and check that it is indeed delayed.
431  ASSERT_TRUE(UpdateExtensionWaitForIdle(
432      extension_id, crx_path.AppendASCII("v2.crx"), 0));
433
434  ASSERT_EQ(1u, service->delayed_installs()->size());
435  extension = registry->enabled_extensions().GetByID(extension_id);
436  ASSERT_EQ("1.0", extension->version()->GetString());
437
438  // Make the extension idle again by closing the popup. This should not trigger
439  // the delayed install.
440  content::RenderProcessHostWatcher terminated_observer(
441      extension_host->render_process_host(),
442      content::RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
443  extension_host->render_view_host()->ClosePage();
444  terminated_observer.Wait();
445  ASSERT_EQ(1u, service->delayed_installs()->size());
446
447  // Install version 3 of the extension. Because the extension is idle,
448  // this install should succeed.
449  ASSERT_TRUE(UpdateExtensionWaitForIdle(
450      extension_id, crx_path.AppendASCII("v3.crx"), 0));
451  extension = registry->enabled_extensions().GetByID(extension_id);
452  ASSERT_EQ("3.0", extension->version()->GetString());
453
454  // The version 2 delayed install should be cleaned up, and finishing
455  // delayed extension installation shouldn't break anything.
456  ASSERT_EQ(0u, service->delayed_installs()->size());
457  service->MaybeFinishDelayedInstallations();
458  extension = registry->enabled_extensions().GetByID(extension_id);
459  ASSERT_EQ("3.0", extension->version()->GetString());
460}
461
462#if defined(FULL_SAFE_BROWSING)
463IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Blacklist) {
464  scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
465      new FakeSafeBrowsingDatabaseManager(true));
466  Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
467
468  blacklist_db->SetUnsafe("gllekhaobjnhgeagipipnkpmmmpchacm");
469
470  base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx")
471                                          .AppendASCII("theme_hidpi.crx");
472  EXPECT_FALSE(InstallExtension(crx_path, 0));
473}
474#endif
475
476IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, NonStrictManifestCheck) {
477  scoped_refptr<MockPromptProxy> mock_prompt =
478      CreateMockPromptProxyForBrowser(browser());
479
480  // We want to simulate the case where the webstore sends a more recent
481  // version of the manifest, but the downloaded .crx file is old since
482  // the newly published version hasn't fully propagated to all the download
483  // servers yet. So load the v2 manifest, but then install the v1 crx file.
484  std::string id = "lhnaeclnpobnlbjbgogdanmhadigfnjp";
485  scoped_ptr<WebstoreInstaller::Approval> approval =
486      GetApproval("crx_installer/v2_no_permission_change/", id, false);
487
488  RunCrxInstaller(approval.get(), mock_prompt->CreatePrompt(),
489                  test_data_dir_.AppendASCII("crx_installer/v1.crx"));
490
491  EXPECT_TRUE(mock_prompt->did_succeed());
492}
493
494IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, KioskOnlyTest) {
495  base::FilePath crx_path =
496      test_data_dir_.AppendASCII("kiosk/kiosk_only.crx");
497  EXPECT_FALSE(InstallExtension(crx_path, 0));
498#if defined(OS_CHROMEOS)
499  // Simulate ChromeOS kiosk mode. |scoped_user_manager| will take over
500  // lifetime of |user_manager|.
501  chromeos::FakeUserManager* fake_user_manager =
502      new chromeos::FakeUserManager();
503  fake_user_manager->AddKioskAppUser("example@example.com");
504  fake_user_manager->LoginUser("example@example.com");
505  chromeos::ScopedUserManagerEnabler scoped_user_manager(fake_user_manager);
506  EXPECT_TRUE(InstallExtension(crx_path, 1));
507#endif
508}
509
510#if defined(OS_CHROMEOS)
511IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, InstallToSharedLocation) {
512  base::ShadowingAtExitManager at_exit_manager;
513  CommandLine::ForCurrentProcess()->AppendSwitch(
514      chromeos::switches::kEnableExtensionAssetsSharing);
515  base::ScopedTempDir cache_dir;
516  ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
517  ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(
518      cache_dir.path());
519
520  base::FilePath crx_path = test_data_dir_.AppendASCII("crx_installer/v1.crx");
521  const extensions::Extension* extension = InstallExtension(
522      crx_path, 1, extensions::Manifest::EXTERNAL_PREF);
523  base::FilePath extension_path = extension->path();
524  EXPECT_TRUE(cache_dir.path().IsParent(extension_path));
525  EXPECT_TRUE(base::PathExists(extension_path));
526
527  std::string extension_id = extension->id();
528  UninstallExtension(extension_id);
529  ExtensionRegistry* registry = ExtensionRegistry::Get(
530      browser()->profile());
531  EXPECT_FALSE(registry->enabled_extensions().GetByID(extension_id));
532
533  content::RunAllBlockingPoolTasksUntilIdle();
534
535  EXPECT_FALSE(base::PathExists(extension_path));
536}
537#endif
538
539IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, DoNotSync) {
540  ExtensionService* service = extensions::ExtensionSystem::Get(
541                                  browser()->profile())->extension_service();
542  scoped_refptr<CrxInstaller> crx_installer(
543      CrxInstaller::CreateSilent(service));
544  crx_installer->set_do_not_sync(true);
545  crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx"));
546  EXPECT_TRUE(WaitForCrxInstallerDone());
547  ASSERT_TRUE(crx_installer->extension());
548
549  const ExtensionPrefs* extension_prefs =
550      ExtensionPrefs::Get(browser()->profile());
551  EXPECT_TRUE(extension_prefs->DoNotSync(crx_installer->extension()->id()));
552  EXPECT_FALSE(extensions::util::ShouldSyncApp(crx_installer->extension(),
553                                               browser()->profile()));
554}
555
556IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, ManagementPolicy) {
557  ManagementPolicyMock policy;
558  extensions::ExtensionSystem::Get(profile())
559      ->management_policy()
560      ->RegisterProvider(&policy);
561
562  base::FilePath crx_path = test_data_dir_.AppendASCII("crx_installer/v1.crx");
563  EXPECT_FALSE(InstallExtension(crx_path, 0));
564}
565
566IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, WithheldElevationCheck) {
567  // Enable consent flag and install extension. The <all_hosts> permission will
568  // be withheld.
569  scoped_ptr<FeatureSwitch::ScopedOverride> enable_scripts_switch(
570      new FeatureSwitch::ScopedOverride(
571          FeatureSwitch::scripts_require_action(), true));
572
573  const char kManifest[] =
574      "{"
575      "  \"name\": \"Withheld test\","
576      "  \"version\": \"1.0\","
577      "  \"permissions\": ["
578      "    \"http://*/*\""
579      "  ],"
580      "  \"manifest_version\": 2"
581      "}";
582  TestExtensionDir dir;
583  dir.WriteManifest(kManifest);
584  base::FilePath crx_path = dir.Pack();
585  EXPECT_FALSE(crx_path.empty());
586  const Extension* extension = InstallExtension(crx_path, 1);
587  EXPECT_TRUE(base::PathExists(extension->path()));
588
589  std::string extension_id = extension->id();
590  ExtensionRegistry* registry = ExtensionRegistry::Get(
591      browser()->profile());
592  EXPECT_TRUE(registry->enabled_extensions().GetByID(extension_id));
593
594  // Disable consent flag and reinstall extension. It should now be disabled
595  // because previously withheld permissions are now being requested.
596  enable_scripts_switch.reset();
597  extension = InstallExtension(crx_path, -1);
598  EXPECT_FALSE(registry->enabled_extensions().GetByID(extension_id));
599  EXPECT_TRUE(registry->disabled_extensions().GetByID(extension_id));
600  EXPECT_TRUE(ExtensionPrefs::Get(browser()->profile())->GetDisableReasons(
601      extension_id) & Extension::DISABLE_PERMISSIONS_INCREASE);
602}
603
604}  // namespace extensions
605