14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/extension_install_prompt.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h"
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/webstore_inline_installer.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/webstore_inline_installer_factory.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/webstore_installer_test.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/extensions/webstore_standalone_installer.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/web_contents.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "url/gurl.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using content::WebContents;
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace extensions {
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kWebstoreDomain[] = "cws.com";
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kAppDomain[] = "app.com";
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kNonAppDomain[] = "nonapp.com";
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kTestExtensionId[] = "ecglahbcnmdpdciemllbhojghbkagdje";
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kTestDataPath[] = "extensions/api_test/webstore_inline_install";
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kCrxFilename[] = "extension.crx";
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class WebstoreInlineInstallerTest : public WebstoreInstallerTest {
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebstoreInlineInstallerTest()
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : WebstoreInstallerTest(
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            kWebstoreDomain,
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            kTestDataPath,
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            kCrxFilename,
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            kAppDomain,
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            kNonAppDomain) {}
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class ProgrammableInstallPrompt : public ExtensionInstallPrompt {
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  explicit ProgrammableInstallPrompt(WebContents* contents)
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : ExtensionInstallPrompt(contents)
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {}
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual ~ProgrammableInstallPrompt() {}
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void ConfirmStandaloneInstall(
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Delegate* delegate,
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const Extension* extension,
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SkBitmap* icon,
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_refptr<ExtensionInstallPrompt::Prompt> prompt) OVERRIDE {
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    delegate_ = delegate;
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static bool Ready() {
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return delegate_ != NULL;
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static void Accept() {
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    delegate_->InstallUIProceed();
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static void Reject() {
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    delegate_->InstallUIAbort(true);
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static Delegate* delegate_;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ExtensionInstallPrompt::Delegate* ProgrammableInstallPrompt::delegate_;
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Fake inline installer which creates a programmable prompt in place of
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// the normal dialog UI.
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class WebstoreInlineInstallerForTest : public WebstoreInlineInstaller {
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebstoreInlineInstallerForTest(WebContents* contents,
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                 const std::string& extension_id,
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                 const GURL& requestor_url,
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                 const Callback& callback)
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : WebstoreInlineInstaller(
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            contents,
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            kTestExtensionId,
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            requestor_url,
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            base::Bind(DummyCallback)),
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        programmable_prompt_(NULL) {
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI() OVERRIDE {
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    programmable_prompt_ = new ProgrammableInstallPrompt(web_contents());
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return make_scoped_ptr(programmable_prompt_).
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        PassAs<ExtensionInstallPrompt>();
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual ~WebstoreInlineInstallerForTest() {}
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static void DummyCallback(bool success,
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            const std::string& error,
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            webstore_install::Result result) {
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ProgrammableInstallPrompt* programmable_prompt_;
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class WebstoreInlineInstallerForTestFactory :
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    public WebstoreInlineInstallerFactory {
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual ~WebstoreInlineInstallerForTestFactory() {}
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual WebstoreInlineInstaller* CreateInstaller(
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      WebContents* contents,
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const std::string& webstore_item_id,
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const GURL& requestor_url,
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const WebstoreStandaloneInstaller::Callback& callback) OVERRIDE {
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return new WebstoreInlineInstallerForTest(
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        contents, webstore_item_id, requestor_url, callback);
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest,
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CloseTabBeforeInstallConfirmation) {
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  GURL install_url = GenerateTestServerUrl(kAppDomain, "install.html");
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), install_url);
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebContents* web_contents =
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      browser()->tab_strip_model()->GetActiveWebContents();
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  tab_helper->SetWebstoreInlineInstallerFactoryForTests(
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      new WebstoreInlineInstallerForTestFactory());
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  RunTestAsync("runTest");
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  while (!ProgrammableInstallPrompt::Ready())
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  web_contents->Close();
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ProgrammableInstallPrompt::Accept();
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Ensure that inline-installing a disabled extension simply re-enables it.
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       ReinstallDisabledExtension) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Install an extension via inline install, and confirm it is successful.
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ExtensionInstallPrompt::g_auto_confirm_for_tests =
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ExtensionInstallPrompt::ACCEPT;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui_test_utils::NavigateToURL(
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      browser(), GenerateTestServerUrl(kAppDomain, "install.html"));
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunTest("runTest");
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionService* extension_service =
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionSystem::Get(browser()->profile())->extension_service();
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(extension_service->GetExtensionById(kTestExtensionId, false));
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Disable the extension.
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extension_service->DisableExtension(kTestExtensionId,
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      Extension::DISABLE_USER_ACTION);
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(extension_service->IsExtensionEnabled(kTestExtensionId));
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Revisit the inline install site and reinstall the extension. It should
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // simply be re-enabled, rather than try to install again.
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui_test_utils::NavigateToURL(
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      browser(), GenerateTestServerUrl(kAppDomain, "install.html"));
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunTest("runTest");
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(extension_service->IsExtensionEnabled(kTestExtensionId));
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass WebstoreInlineInstallerListenerTest : public WebstoreInlineInstallerTest {
171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public:
172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  WebstoreInlineInstallerListenerTest() {}
173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual ~WebstoreInlineInstallerListenerTest() {}
174effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch protected:
176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void RunTest(const std::string& file_name) {
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionInstallPrompt::g_auto_confirm_for_tests =
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ExtensionInstallPrompt::ACCEPT;
179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ui_test_utils::NavigateToURL(browser(),
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                 GenerateTestServerUrl(kAppDomain, file_name));
181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    WebstoreInstallerTest::RunTest("runTest");
182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch};
184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
185effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochIN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,
186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       InstallStageListenerTest) {
187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  RunTest("install_stage_listener.html");
188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
190effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochIN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,
191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       DownloadProgressListenerTest) {
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  RunTest("download_progress_listener.html");
193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
195effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochIN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest, BothListenersTest) {
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  RunTest("both_listeners.html");
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace extensions
200