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_host.h"
      8 #include "chrome/browser/extensions/extension_install_ui.h"
      9 #include "chrome/browser/extensions/extension_service.h"
     10 #include "chrome/browser/extensions/extension_system.h"
     11 #include "chrome/browser/extensions/startup_helper.h"
     12 #include "chrome/browser/extensions/webstore_installer_test.h"
     13 #include "chrome/browser/infobars/infobar_service.h"
     14 #include "chrome/browser/managed_mode/managed_user_service.h"
     15 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/ui/browser.h"
     18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     19 #include "chrome/common/chrome_switches.h"
     20 #include "chrome/common/pref_names.h"
     21 #include "chrome/test/base/in_process_browser_test.h"
     22 #include "chrome/test/base/test_switches.h"
     23 #include "chrome/test/base/ui_test_utils.h"
     24 #include "content/public/browser/notification_registrar.h"
     25 #include "content/public/browser/notification_service.h"
     26 #include "content/public/browser/notification_types.h"
     27 #include "content/public/browser/web_contents.h"
     28 #include "content/public/test/browser_test_utils.h"
     29 #include "extensions/common/extension_builder.h"
     30 #include "extensions/common/value_builder.h"
     31 #include "net/dns/mock_host_resolver.h"
     32 #include "url/gurl.h"
     33 
     34 using content::WebContents;
     35 using extensions::DictionaryBuilder;
     36 using extensions::Extension;
     37 using extensions::ExtensionBuilder;
     38 using extensions::ListBuilder;
     39 
     40 const char kWebstoreDomain[] = "cws.com";
     41 const char kAppDomain[] = "app.com";
     42 const char kNonAppDomain[] = "nonapp.com";
     43 const char kTestExtensionId[] = "ecglahbcnmdpdciemllbhojghbkagdje";
     44 const char kTestDataPath[] = "extensions/api_test/webstore_inline_install";
     45 const char kCrxFilename[] = "extension.crx";
     46 
     47 class WebstoreStartupInstallerTest : public WebstoreInstallerTest {
     48  public:
     49   WebstoreStartupInstallerTest()
     50       : WebstoreInstallerTest(
     51             kWebstoreDomain,
     52             kTestDataPath,
     53             kCrxFilename,
     54             kAppDomain,
     55             kNonAppDomain) {}
     56 };
     57 
     58 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, Install) {
     59   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     60       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
     61 
     62   ui_test_utils::NavigateToURL(
     63       browser(), GenerateTestServerUrl(kAppDomain, "install.html"));
     64 
     65   RunTest("runTest");
     66 
     67   const extensions::Extension* extension = browser()->profile()->
     68       GetExtensionService()->GetExtensionById(kTestExtensionId, false);
     69   EXPECT_TRUE(extension);
     70 }
     71 
     72 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest,
     73     InstallNotAllowedFromNonVerifiedDomains) {
     74   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     75       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
     76   ui_test_utils::NavigateToURL(
     77       browser(),
     78       GenerateTestServerUrl(kNonAppDomain, "install_non_verified_domain.html"));
     79 
     80   RunTest("runTest1");
     81   RunTest("runTest2");
     82 }
     83 
     84 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, FindLink) {
     85   ui_test_utils::NavigateToURL(
     86       browser(), GenerateTestServerUrl(kAppDomain, "find_link.html"));
     87 
     88   RunTest("runTest");
     89 }
     90 
     91 // Flakes on all platforms: http://crbug.com/95713, http://crbug.com/229947
     92 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest,
     93                        DISABLED_ArgumentValidation) {
     94   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     95       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
     96 
     97   // Each of these tests has to run separately, since one page/tab can
     98   // only have one in-progress install request. These tests don't all pass
     99   // callbacks to install, so they have no way to wait for the installation
    100   // to complete before starting the next test.
    101   bool is_finished = false;
    102   for (int i = 0; !is_finished; ++i) {
    103     ui_test_utils::NavigateToURL(
    104         browser(),
    105         GenerateTestServerUrl(kAppDomain, "argument_validation.html"));
    106     is_finished = !RunIndexedTest("runTest", i);
    107   }
    108 }
    109 
    110 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, MultipleInstallCalls) {
    111   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    112       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
    113 
    114   ui_test_utils::NavigateToURL(
    115       browser(),
    116       GenerateTestServerUrl(kAppDomain, "multiple_install_calls.html"));
    117   RunTest("runTest");
    118 }
    119 
    120 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, InstallNotSupported) {
    121   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    122       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
    123   ui_test_utils::NavigateToURL(
    124       browser(),
    125       GenerateTestServerUrl(kAppDomain, "install_not_supported.html"));
    126 
    127   ui_test_utils::WindowedTabAddedNotificationObserver observer(
    128       content::NotificationService::AllSources());
    129   RunTest("runTest");
    130   observer.Wait();
    131 
    132   // The inline install should fail, and a store-provided URL should be opened
    133   // in a new tab.
    134   WebContents* web_contents =
    135       browser()->tab_strip_model()->GetActiveWebContents();
    136   EXPECT_EQ(GURL("http://cws.com/show-me-the-money"), web_contents->GetURL());
    137 }
    138 
    139 // Regression test for http://crbug.com/144991.
    140 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest, InstallFromHostedApp) {
    141   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    142       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
    143 
    144   const GURL kInstallUrl = GenerateTestServerUrl(kAppDomain, "install.html");
    145 
    146   // We're forced to construct a hosted app dynamically because we need the
    147   // app to run on a declared URL, but we don't know the port ahead of time.
    148   scoped_refptr<const Extension> hosted_app = ExtensionBuilder()
    149       .SetManifest(DictionaryBuilder()
    150           .Set("name", "hosted app")
    151           .Set("version", "1")
    152           .Set("app", DictionaryBuilder()
    153               .Set("urls", ListBuilder().Append(kInstallUrl.spec()))
    154               .Set("launch", DictionaryBuilder()
    155                   .Set("web_url", kInstallUrl.spec())))
    156           .Set("manifest_version", 2))
    157       .Build();
    158   ASSERT_TRUE(hosted_app.get());
    159 
    160   ExtensionService* extension_service =
    161       extensions::ExtensionSystem::Get(browser()->profile())->
    162           extension_service();
    163 
    164   extension_service->AddExtension(hosted_app.get());
    165   EXPECT_TRUE(extension_service->extensions()->Contains(hosted_app->id()));
    166 
    167   ui_test_utils::NavigateToURL(browser(), kInstallUrl);
    168 
    169   EXPECT_FALSE(extension_service->extensions()->Contains(kTestExtensionId));
    170   RunTest("runTest");
    171   EXPECT_TRUE(extension_service->extensions()->Contains(kTestExtensionId));
    172 }
    173 
    174 class WebstoreStartupInstallerManagedUsersTest
    175     : public WebstoreStartupInstallerTest {
    176  public:
    177   // InProcessBrowserTest overrides:
    178   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    179     WebstoreStartupInstallerTest::SetUpCommandLine(command_line);
    180     command_line->AppendSwitchASCII(switches::kManagedUserId, "asdf");
    181   }
    182 };
    183 
    184 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerManagedUsersTest,
    185                        InstallProhibited) {
    186 #if defined(OS_WIN) && defined(USE_ASH)
    187   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
    188   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
    189     return;
    190 #endif
    191 
    192   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    193       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
    194 
    195   ui_test_utils::NavigateToURL(
    196       browser(), GenerateTestServerUrl(kAppDomain, "install_prohibited.html"));
    197 
    198   RunTest("runTest");
    199 
    200   // No error infobar should show up.
    201   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
    202   InfoBarService* info_bar_service = InfoBarService::FromWebContents(contents);
    203   EXPECT_EQ(info_bar_service->infobar_count(), 0u);
    204 }
    205 
    206 // The unpack failure test needs to use a different install .crx, which is
    207 // specified via a command-line flag, so it needs its own test subclass.
    208 class WebstoreStartupInstallUnpackFailureTest
    209     : public WebstoreStartupInstallerTest {
    210  public:
    211   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    212     WebstoreStartupInstallerTest::SetUpCommandLine(command_line);
    213 
    214     GURL crx_url = GenerateTestServerUrl(
    215         kWebstoreDomain, "malformed_extension.crx");
    216     CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    217         switches::kAppsGalleryUpdateURL, crx_url.spec());
    218   }
    219 
    220   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
    221     WebstoreStartupInstallerTest::SetUpInProcessBrowserTestFixture();
    222     ExtensionInstallUI::set_disable_failure_ui_for_tests();
    223   }
    224 };
    225 
    226 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallUnpackFailureTest,
    227     WebstoreStartupInstallUnpackFailureTest) {
    228   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    229       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
    230 
    231   ui_test_utils::NavigateToURL(browser(),
    232       GenerateTestServerUrl(kAppDomain, "install_unpack_failure.html"));
    233 
    234   RunTest("runTest");
    235 }
    236 
    237 class CommandLineWebstoreInstall : public WebstoreStartupInstallerTest,
    238                                    public content::NotificationObserver {
    239  public:
    240   CommandLineWebstoreInstall() : saw_install_(false), browser_open_count_(0) {}
    241   virtual ~CommandLineWebstoreInstall() {}
    242 
    243   virtual void SetUpOnMainThread() OVERRIDE {
    244     WebstoreStartupInstallerTest::SetUpOnMainThread();
    245     registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
    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) {
    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   CommandLine* command_line = 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   CommandLine* command_line = 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   CommandLine command_line_test1(CommandLine::NO_PROGRAM);
    312   command_line_test1.AppendSwitchASCII(switches::kLimitedInstallFromWebstore,
    313       "1");
    314   EXPECT_EQ("nckgahadagoaajjgafhacjanaoiihapd",
    315       helper.WebStoreIdFromLimitedInstallCmdLine(command_line_test1));
    316 
    317   CommandLine command_line_test2(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   CommandLine* command_line = 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