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.
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_service.h"
10 #include "chrome/browser/extensions/startup_helper.h"
11 #include "chrome/browser/extensions/webstore_installer_test.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/common/chrome_switches.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_registry.h"
27 #include "extensions/browser/extension_registry_observer.h"
28 #include "extensions/browser/extension_system.h"
29 #include "extensions/browser/install/extension_install_ui.h"
30 #include "extensions/common/extension_builder.h"
31 #include "extensions/common/value_builder.h"
32 #include "net/dns/mock_host_resolver.h"
35 using content::WebContents
;
36 using extensions::DictionaryBuilder
;
37 using extensions::Extension
;
38 using extensions::ExtensionBuilder
;
39 using extensions::ListBuilder
;
41 const char kWebstoreDomain
[] = "cws.com";
42 const char kAppDomain
[] = "app.com";
43 const char kNonAppDomain
[] = "nonapp.com";
44 const char kTestExtensionId
[] = "ecglahbcnmdpdciemllbhojghbkagdje";
45 const char kTestDataPath
[] = "extensions/api_test/webstore_inline_install";
46 const char kCrxFilename
[] = "extension.crx";
48 class WebstoreStartupInstallerTest
: public WebstoreInstallerTest
{
50 WebstoreStartupInstallerTest()
51 : WebstoreInstallerTest(
59 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, Install
) {
60 ExtensionInstallPrompt::g_auto_confirm_for_tests
=
61 ExtensionInstallPrompt::ACCEPT
;
63 ui_test_utils::NavigateToURL(
64 browser(), GenerateTestServerUrl(kAppDomain
, "install.html"));
68 extensions::ExtensionRegistry
* registry
=
69 extensions::ExtensionRegistry::Get(browser()->profile());
70 const extensions::Extension
* extension
=
71 registry
->enabled_extensions().GetByID(kTestExtensionId
);
72 EXPECT_TRUE(extension
);
75 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
,
76 InstallNotAllowedFromNonVerifiedDomains
) {
77 ExtensionInstallPrompt::g_auto_confirm_for_tests
=
78 ExtensionInstallPrompt::CANCEL
;
79 ui_test_utils::NavigateToURL(
81 GenerateTestServerUrl(kNonAppDomain
, "install_non_verified_domain.html"));
87 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, FindLink
) {
88 ui_test_utils::NavigateToURL(
89 browser(), GenerateTestServerUrl(kAppDomain
, "find_link.html"));
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
;
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(
108 GenerateTestServerUrl(kAppDomain
, "argument_validation.html"));
109 is_finished
= !RunIndexedTest("runTest", i
);
113 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, MultipleInstallCalls
) {
114 ExtensionInstallPrompt::g_auto_confirm_for_tests
=
115 ExtensionInstallPrompt::CANCEL
;
117 ui_test_utils::NavigateToURL(
119 GenerateTestServerUrl(kAppDomain
, "multiple_install_calls.html"));
123 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, InstallNotSupported
) {
124 ExtensionInstallPrompt::g_auto_confirm_for_tests
=
125 ExtensionInstallPrompt::CANCEL
;
126 ui_test_utils::NavigateToURL(
128 GenerateTestServerUrl(kAppDomain
, "install_not_supported.html"));
130 ui_test_utils::WindowedTabAddedNotificationObserver
observer(
131 content::NotificationService::AllSources());
135 // The inline install should fail, and a store-provided URL should be opened
137 WebContents
* web_contents
=
138 browser()->tab_strip_model()->GetActiveWebContents();
139 EXPECT_EQ(GURL("http://cws.com/show-me-the-money"), web_contents
->GetURL());
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
;
147 const GURL kInstallUrl
= GenerateTestServerUrl(kAppDomain
, "install.html");
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")
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))
161 ASSERT_TRUE(hosted_app
.get());
163 ExtensionService
* extension_service
=
164 extensions::ExtensionSystem::Get(browser()->profile())->
166 extensions::ExtensionRegistry
* registry
=
167 extensions::ExtensionRegistry::Get(browser()->profile());
169 extension_service
->AddExtension(hosted_app
.get());
170 EXPECT_TRUE(registry
->enabled_extensions().GetByID(hosted_app
->id()));
172 ui_test_utils::NavigateToURL(browser(), kInstallUrl
);
174 EXPECT_FALSE(registry
->enabled_extensions().GetByID(kTestExtensionId
));
176 EXPECT_TRUE(registry
->enabled_extensions().GetByID(kTestExtensionId
));
179 class WebstoreStartupInstallerSupervisedUsersTest
180 : public WebstoreStartupInstallerTest
{
182 // InProcessBrowserTest overrides:
183 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
184 WebstoreStartupInstallerTest::SetUpCommandLine(command_line
);
185 command_line
->AppendSwitchASCII(switches::kSupervisedUserId
, "asdf");
189 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerSupervisedUsersTest
,
191 #if defined(OS_WIN) && defined(USE_ASH)
192 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
193 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
194 switches::kAshBrowserTests
))
198 ExtensionInstallPrompt::g_auto_confirm_for_tests
=
199 ExtensionInstallPrompt::ACCEPT
;
201 ui_test_utils::NavigateToURL(
202 browser(), GenerateTestServerUrl(kAppDomain
, "install_prohibited.html"));
206 // No error infobar should show up.
207 WebContents
* contents
= browser()->tab_strip_model()->GetActiveWebContents();
208 InfoBarService
* infobar_service
= InfoBarService::FromWebContents(contents
);
209 EXPECT_EQ(0u, infobar_service
->infobar_count());
212 // The unpack failure test needs to use a different install .crx, which is
213 // specified via a command-line flag, so it needs its own test subclass.
214 class WebstoreStartupInstallUnpackFailureTest
215 : public WebstoreStartupInstallerTest
{
217 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
218 WebstoreStartupInstallerTest::SetUpCommandLine(command_line
);
220 GURL crx_url
= GenerateTestServerUrl(
221 kWebstoreDomain
, "malformed_extension.crx");
222 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
223 switches::kAppsGalleryUpdateURL
, crx_url
.spec());
226 void SetUpInProcessBrowserTestFixture() override
{
227 WebstoreStartupInstallerTest::SetUpInProcessBrowserTestFixture();
228 extensions::ExtensionInstallUI::set_disable_failure_ui_for_tests();
232 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallUnpackFailureTest
,
233 WebstoreStartupInstallUnpackFailureTest
) {
234 ExtensionInstallPrompt::g_auto_confirm_for_tests
=
235 ExtensionInstallPrompt::ACCEPT
;
237 ui_test_utils::NavigateToURL(browser(),
238 GenerateTestServerUrl(kAppDomain
, "install_unpack_failure.html"));
243 class CommandLineWebstoreInstall
244 : public WebstoreStartupInstallerTest
,
245 public content::NotificationObserver
,
246 public extensions::ExtensionRegistryObserver
{
248 CommandLineWebstoreInstall() : saw_install_(false), browser_open_count_(0) {}
249 ~CommandLineWebstoreInstall() override
{}
251 void SetUpOnMainThread() override
{
252 WebstoreStartupInstallerTest::SetUpOnMainThread();
253 extensions::ExtensionRegistry::Get(browser()->profile())->AddObserver(this);
254 registrar_
.Add(this, chrome::NOTIFICATION_BROWSER_OPENED
,
255 content::NotificationService::AllSources());
258 void TearDownOnMainThread() override
{
259 extensions::ExtensionRegistry::Get(browser()->profile())
260 ->RemoveObserver(this);
261 WebstoreStartupInstallerTest::TearDownOnMainThread();
264 bool saw_install() { return saw_install_
; }
266 int browser_open_count() { return browser_open_count_
; }
268 // NotificationObserver interface.
269 void Observe(int type
,
270 const content::NotificationSource
& source
,
271 const content::NotificationDetails
& details
) override
{
272 DCHECK_EQ(type
, chrome::NOTIFICATION_BROWSER_OPENED
);
273 ++browser_open_count_
;
276 void OnExtensionWillBeInstalled(content::BrowserContext
* browser_context
,
277 const extensions::Extension
* extension
,
280 const std::string
& old_name
) override
{
281 EXPECT_EQ(extension
->id(), kTestExtensionId
);
285 content::NotificationRegistrar registrar_
;
287 // Have we seen an installation notification for kTestExtensionId ?
290 // How many NOTIFICATION_BROWSER_OPENED notifications have we seen?
291 int browser_open_count_
;
294 IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall
, CannotInstallNonEphemeral
) {
295 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
296 command_line
->AppendSwitchASCII(
297 switches::kInstallEphemeralAppFromWebstore
, kTestExtensionId
);
298 ExtensionInstallPrompt::g_auto_confirm_for_tests
=
299 ExtensionInstallPrompt::ACCEPT
;
300 extensions::StartupHelper helper
;
301 EXPECT_FALSE(helper
.InstallEphemeralApp(*command_line
, browser()->profile()));
302 EXPECT_FALSE(saw_install());
303 EXPECT_EQ(0, browser_open_count());