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