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/command_line.h"
      6 #include "chrome/browser/chrome_notification_types.h"
      7 #include "chrome/browser/extensions/extension_install_ui.h"
      8 #include "chrome/browser/extensions/extension_service.h"
      9 #include "chrome/browser/extensions/startup_helper.h"
     10 #include "chrome/browser/extensions/webstore_installer_test.h"
     11 #include "chrome/browser/infobars/infobar_service.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/browser/ui/browser.h"
     14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     15 #include "chrome/common/chrome_switches.h"
     16 #include "chrome/common/pref_names.h"
     17 #include "chrome/test/base/in_process_browser_test.h"
     18 #include "chrome/test/base/test_switches.h"
     19 #include "chrome/test/base/ui_test_utils.h"
     20 #include "content/public/browser/notification_registrar.h"
     21 #include "content/public/browser/notification_service.h"
     22 #include "content/public/browser/notification_types.h"
     23 #include "content/public/browser/web_contents.h"
     24 #include "content/public/test/browser_test_utils.h"
     25 #include "extensions/browser/extension_host.h"
     26 #include "extensions/browser/extension_system.h"
     27 #include "extensions/common/extension_builder.h"
     28 #include "extensions/common/value_builder.h"
     29 #include "net/dns/mock_host_resolver.h"
     30 #include "url/gurl.h"
     31 
     32 using content::WebContents;
     33 using extensions::DictionaryBuilder;
     34 using extensions::Extension;
     35 using extensions::ExtensionBuilder;
     36 using extensions::ListBuilder;
     37 
     38 const char kWebstoreDomain[] = "cws.com";
     39 const char kAppDomain[] = "app.com";
     40 const char kNonAppDomain[] = "nonapp.com";
     41 const char kTestExtensionId[] = "ecglahbcnmdpdciemllbhojghbkagdje";
     42 const char kTestDataPath[] = "extensions/api_test/webstore_inline_install";
     43 const char kCrxFilename[] = "extension.crx";
     44 
     45 class WebstoreStartupInstallerTest : public WebstoreInstallerTest {
     46  public:
     47   WebstoreStartupInstallerTest()
     48       : WebstoreInstallerTest(
     49             kWebstoreDomain,
     50             kTestDataPath,
     51             kCrxFilename,
     52             kAppDomain,
     53             kNonAppDomain) {}
     54 };
     55 
     56 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, Install) {
     57   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     58       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
     59 
     60   ui_test_utils::NavigateToURL(
     61       browser(), GenerateTestServerUrl(kAppDomain, "install.html"));
     62 
     63   RunTest("runTest");
     64 
     65   const extensions::Extension* extension = browser()->profile()->
     66       GetExtensionService()->GetExtensionById(kTestExtensionId, false);
     67   EXPECT_TRUE(extension);
     68 }
     69 
     70 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest,
     71     InstallNotAllowedFromNonVerifiedDomains) {
     72   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     73       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
     74   ui_test_utils::NavigateToURL(
     75       browser(),
     76       GenerateTestServerUrl(kNonAppDomain, "install_non_verified_domain.html"));
     77 
     78   RunTest("runTest1");
     79   RunTest("runTest2");
     80 }
     81 
     82 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, FindLink) {
     83   ui_test_utils::NavigateToURL(
     84       browser(), GenerateTestServerUrl(kAppDomain, "find_link.html"));
     85 
     86   RunTest("runTest");
     87 }
     88 
     89 // Flakes on all platforms: http://crbug.com/95713, http://crbug.com/229947
     90 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest,
     91                        DISABLED_ArgumentValidation) {
     92   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     93       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
     94 
     95   // Each of these tests has to run separately, since one page/tab can
     96   // only have one in-progress install request. These tests don't all pass
     97   // callbacks to install, so they have no way to wait for the installation
     98   // to complete before starting the next test.
     99   bool is_finished = false;
    100   for (int i = 0; !is_finished; ++i) {
    101     ui_test_utils::NavigateToURL(
    102         browser(),
    103         GenerateTestServerUrl(kAppDomain, "argument_validation.html"));
    104     is_finished = !RunIndexedTest("runTest", i);
    105   }
    106 }
    107 
    108 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, MultipleInstallCalls) {
    109   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    110       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
    111 
    112   ui_test_utils::NavigateToURL(
    113       browser(),
    114       GenerateTestServerUrl(kAppDomain, "multiple_install_calls.html"));
    115   RunTest("runTest");
    116 }
    117 
    118 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, InstallNotSupported) {
    119   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    120       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
    121   ui_test_utils::NavigateToURL(
    122       browser(),
    123       GenerateTestServerUrl(kAppDomain, "install_not_supported.html"));
    124 
    125   ui_test_utils::WindowedTabAddedNotificationObserver observer(
    126       content::NotificationService::AllSources());
    127   RunTest("runTest");
    128   observer.Wait();
    129 
    130   // The inline install should fail, and a store-provided URL should be opened
    131   // in a new tab.
    132   WebContents* web_contents =
    133       browser()->tab_strip_model()->GetActiveWebContents();
    134   EXPECT_EQ(GURL("http://cws.com/show-me-the-money"), web_contents->GetURL());
    135 }
    136 
    137 // Regression test for http://crbug.com/144991.
    138 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, InstallFromHostedApp) {
    139   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    140       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
    141 
    142   const GURL kInstallUrl = GenerateTestServerUrl(kAppDomain, "install.html");
    143 
    144   // We're forced to construct a hosted app dynamically because we need the
    145   // app to run on a declared URL, but we don't know the port ahead of time.
    146   scoped_refptr<const Extension> hosted_app = ExtensionBuilder()
    147       .SetManifest(DictionaryBuilder()
    148           .Set("name", "hosted app")
    149           .Set("version", "1")
    150           .Set("app", DictionaryBuilder()
    151               .Set("urls", ListBuilder().Append(kInstallUrl.spec()))
    152               .Set("launch", DictionaryBuilder()
    153                   .Set("web_url", kInstallUrl.spec())))
    154           .Set("manifest_version", 2))
    155       .Build();
    156   ASSERT_TRUE(hosted_app.get());
    157 
    158   ExtensionService* extension_service =
    159       extensions::ExtensionSystem::Get(browser()->profile())->
    160           extension_service();
    161 
    162   extension_service->AddExtension(hosted_app.get());
    163   EXPECT_TRUE(extension_service->extensions()->Contains(hosted_app->id()));
    164 
    165   ui_test_utils::NavigateToURL(browser(), kInstallUrl);
    166 
    167   EXPECT_FALSE(extension_service->extensions()->Contains(kTestExtensionId));
    168   RunTest("runTest");
    169   EXPECT_TRUE(extension_service->extensions()->Contains(kTestExtensionId));
    170 }
    171 
    172 class WebstoreStartupInstallerManagedUsersTest
    173     : public WebstoreStartupInstallerTest {
    174  public:
    175   // InProcessBrowserTest overrides:
    176   virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
    177     WebstoreStartupInstallerTest::SetUpCommandLine(command_line);
    178     command_line->AppendSwitchASCII(switches::kSupervisedUserId, "asdf");
    179   }
    180 };
    181 
    182 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerManagedUsersTest,
    183                        InstallProhibited) {
    184 #if defined(OS_WIN) && defined(USE_ASH)
    185   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
    186   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
    187           switches::kAshBrowserTests))
    188     return;
    189 #endif
    190 
    191   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    192       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
    193 
    194   ui_test_utils::NavigateToURL(
    195       browser(), GenerateTestServerUrl(kAppDomain, "install_prohibited.html"));
    196 
    197   RunTest("runTest");
    198 
    199   // No error infobar should show up.
    200   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
    201   InfoBarService* infobar_service = InfoBarService::FromWebContents(contents);
    202   EXPECT_EQ(0u, infobar_service->infobar_count());
    203 }
    204 
    205 // The unpack failure test needs to use a different install .crx, which is
    206 // specified via a command-line flag, so it needs its own test subclass.
    207 class WebstoreStartupInstallUnpackFailureTest
    208     : public WebstoreStartupInstallerTest {
    209  public:
    210   virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
    211     WebstoreStartupInstallerTest::SetUpCommandLine(command_line);
    212 
    213     GURL crx_url = GenerateTestServerUrl(
    214         kWebstoreDomain, "malformed_extension.crx");
    215     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    216         switches::kAppsGalleryUpdateURL, crx_url.spec());
    217   }
    218 
    219   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
    220     WebstoreStartupInstallerTest::SetUpInProcessBrowserTestFixture();
    221     ExtensionInstallUI::set_disable_failure_ui_for_tests();
    222   }
    223 };
    224 
    225 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallUnpackFailureTest,
    226     WebstoreStartupInstallUnpackFailureTest) {
    227   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    228       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
    229 
    230   ui_test_utils::NavigateToURL(browser(),
    231       GenerateTestServerUrl(kAppDomain, "install_unpack_failure.html"));
    232 
    233   RunTest("runTest");
    234 }
    235 
    236 class CommandLineWebstoreInstall : public WebstoreStartupInstallerTest,
    237                                    public content::NotificationObserver {
    238  public:
    239   CommandLineWebstoreInstall() : saw_install_(false), browser_open_count_(0) {}
    240   virtual ~CommandLineWebstoreInstall() {}
    241 
    242   virtual void SetUpOnMainThread() OVERRIDE {
    243     WebstoreStartupInstallerTest::SetUpOnMainThread();
    244     registrar_.Add(this,
    245                    chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
    246                    content::NotificationService::AllSources());
    247     registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
    248                    content::NotificationService::AllSources());
    249   }
    250 
    251   bool saw_install() { return saw_install_; }
    252 
    253   int browser_open_count() { return browser_open_count_; }
    254 
    255   // NotificationObserver interface.
    256   virtual void Observe(int type,
    257                        const content::NotificationSource& source,
    258                        const content::NotificationDetails& details) OVERRIDE {
    259     if (type == chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED) {
    260       const Extension* extension =
    261           content::Details<const extensions::InstalledExtensionInfo>(details)->
    262               extension;
    263       ASSERT_TRUE(extension != NULL);
    264       EXPECT_EQ(extension->id(), kTestExtensionId);
    265       saw_install_ = true;
    266     } else if (type == chrome::NOTIFICATION_BROWSER_OPENED) {
    267       browser_open_count_++;
    268     } else {
    269       ASSERT_TRUE(false) << "Unexpected notification type : " << type;
    270     }
    271   }
    272 
    273   content::NotificationRegistrar registrar_;
    274 
    275   // Have we seen an installation notification for kTestExtensionId ?
    276   bool saw_install_;
    277 
    278   // How many NOTIFICATION_BROWSER_OPENED notifications have we seen?
    279   int browser_open_count_;
    280 };
    281 
    282 IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, Accept) {
    283   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    284   command_line->AppendSwitchASCII(
    285       switches::kInstallFromWebstore, kTestExtensionId);
    286   command_line->AppendSwitchASCII(
    287       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
    288   extensions::StartupHelper helper;
    289   EXPECT_TRUE(helper.InstallFromWebstore(*command_line, browser()->profile()));
    290   EXPECT_TRUE(saw_install());
    291   EXPECT_EQ(0, browser_open_count());
    292 }
    293 
    294 IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, Cancel) {
    295   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    296   command_line->AppendSwitchASCII(
    297       switches::kInstallFromWebstore, kTestExtensionId);
    298   command_line->AppendSwitchASCII(
    299       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
    300   extensions::StartupHelper helper;
    301   EXPECT_FALSE(helper.InstallFromWebstore(*command_line, browser()->profile()));
    302   EXPECT_FALSE(saw_install());
    303   EXPECT_EQ(0, browser_open_count());
    304 }
    305 
    306 IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, LimitedAccept) {
    307   extensions::StartupHelper helper;
    308 
    309   // Small test of "WebStoreIdFromLimitedInstallCmdLine" which made more
    310   // sense together with the rest of the test for "LimitedInstallFromWebstore".
    311   base::CommandLine command_line_test1(base::CommandLine::NO_PROGRAM);
    312   command_line_test1.AppendSwitchASCII(switches::kLimitedInstallFromWebstore,
    313       "1");
    314   EXPECT_EQ("nckgahadagoaajjgafhacjanaoiihapd",
    315       helper.WebStoreIdFromLimitedInstallCmdLine(command_line_test1));
    316 
    317   base::CommandLine command_line_test2(base::CommandLine::NO_PROGRAM);
    318   command_line_test1.AppendSwitchASCII(switches::kLimitedInstallFromWebstore,
    319       "2");
    320   EXPECT_EQ(kTestExtensionId,
    321       helper.WebStoreIdFromLimitedInstallCmdLine(command_line_test1));
    322 
    323   // Now, on to the real test for LimitedInstallFromWebstore.
    324   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    325   command_line->AppendSwitchASCII(
    326       switches::kLimitedInstallFromWebstore, "2");
    327   helper.LimitedInstallFromWebstore(*command_line, browser()->profile(),
    328       base::MessageLoop::QuitWhenIdleClosure());
    329   base::MessageLoop::current()->Run();
    330 
    331   EXPECT_TRUE(saw_install());
    332   EXPECT_EQ(0, browser_open_count());
    333 }
    334