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