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 "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/managed_mode/managed_user_service.h"
13 #include "chrome/browser/managed_mode/managed_user_service_factory.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_system.h"
29 #include "extensions/common/extension_builder.h"
30 #include "extensions/common/value_builder.h"
31 #include "net/dns/mock_host_resolver.h"
34 using content::WebContents
;
35 using extensions::DictionaryBuilder
;
36 using extensions::Extension
;
37 using extensions::ExtensionBuilder
;
38 using extensions::ListBuilder
;
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";
47 class WebstoreStartupInstallerTest
: public WebstoreInstallerTest
{
49 WebstoreStartupInstallerTest()
50 : WebstoreInstallerTest(
58 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, Install
) {
59 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
60 switches::kAppsGalleryInstallAutoConfirmForTests
, "accept");
62 ui_test_utils::NavigateToURL(
63 browser(), GenerateTestServerUrl(kAppDomain
, "install.html"));
67 const extensions::Extension
* extension
= browser()->profile()->
68 GetExtensionService()->GetExtensionById(kTestExtensionId
, false);
69 EXPECT_TRUE(extension
);
72 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
,
73 InstallNotAllowedFromNonVerifiedDomains
) {
74 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
75 switches::kAppsGalleryInstallAutoConfirmForTests
, "cancel");
76 ui_test_utils::NavigateToURL(
78 GenerateTestServerUrl(kNonAppDomain
, "install_non_verified_domain.html"));
84 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, FindLink
) {
85 ui_test_utils::NavigateToURL(
86 browser(), GenerateTestServerUrl(kAppDomain
, "find_link.html"));
91 // Flakes on all platforms: http://crbug.com/95713, http://crbug.com/229947
92 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
,
93 DISABLED_ArgumentValidation
) {
94 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
95 switches::kAppsGalleryInstallAutoConfirmForTests
, "cancel");
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(
105 GenerateTestServerUrl(kAppDomain
, "argument_validation.html"));
106 is_finished
= !RunIndexedTest("runTest", i
);
110 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, MultipleInstallCalls
) {
111 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
112 switches::kAppsGalleryInstallAutoConfirmForTests
, "cancel");
114 ui_test_utils::NavigateToURL(
116 GenerateTestServerUrl(kAppDomain
, "multiple_install_calls.html"));
120 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, InstallNotSupported
) {
121 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
122 switches::kAppsGalleryInstallAutoConfirmForTests
, "cancel");
123 ui_test_utils::NavigateToURL(
125 GenerateTestServerUrl(kAppDomain
, "install_not_supported.html"));
127 ui_test_utils::WindowedTabAddedNotificationObserver
observer(
128 content::NotificationService::AllSources());
132 // The inline install should fail, and a store-provided URL should be opened
134 WebContents
* web_contents
=
135 browser()->tab_strip_model()->GetActiveWebContents();
136 EXPECT_EQ(GURL("http://cws.com/show-me-the-money"), web_contents
->GetURL());
139 // Regression test for http://crbug.com/144991.
140 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest
, InstallFromHostedApp
) {
141 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
142 switches::kAppsGalleryInstallAutoConfirmForTests
, "accept");
144 const GURL kInstallUrl
= GenerateTestServerUrl(kAppDomain
, "install.html");
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")
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))
158 ASSERT_TRUE(hosted_app
.get());
160 ExtensionService
* extension_service
=
161 extensions::ExtensionSystem::Get(browser()->profile())->
164 extension_service
->AddExtension(hosted_app
.get());
165 EXPECT_TRUE(extension_service
->extensions()->Contains(hosted_app
->id()));
167 ui_test_utils::NavigateToURL(browser(), kInstallUrl
);
169 EXPECT_FALSE(extension_service
->extensions()->Contains(kTestExtensionId
));
171 EXPECT_TRUE(extension_service
->extensions()->Contains(kTestExtensionId
));
174 class WebstoreStartupInstallerManagedUsersTest
175 : public WebstoreStartupInstallerTest
{
177 // InProcessBrowserTest overrides:
178 virtual void SetUpCommandLine(base::CommandLine
* command_line
) OVERRIDE
{
179 WebstoreStartupInstallerTest::SetUpCommandLine(command_line
);
180 command_line
->AppendSwitchASCII(switches::kManagedUserId
, "asdf");
184 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerManagedUsersTest
,
186 #if defined(OS_WIN) && defined(USE_ASH)
187 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
188 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
189 switches::kAshBrowserTests
))
193 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
194 switches::kAppsGalleryInstallAutoConfirmForTests
, "accept");
196 ui_test_utils::NavigateToURL(
197 browser(), GenerateTestServerUrl(kAppDomain
, "install_prohibited.html"));
201 // No error infobar should show up.
202 WebContents
* contents
= browser()->tab_strip_model()->GetActiveWebContents();
203 InfoBarService
* infobar_service
= InfoBarService::FromWebContents(contents
);
204 EXPECT_EQ(0u, infobar_service
->infobar_count());
207 // The unpack failure test needs to use a different install .crx, which is
208 // specified via a command-line flag, so it needs its own test subclass.
209 class WebstoreStartupInstallUnpackFailureTest
210 : public WebstoreStartupInstallerTest
{
212 virtual void SetUpCommandLine(base::CommandLine
* command_line
) OVERRIDE
{
213 WebstoreStartupInstallerTest::SetUpCommandLine(command_line
);
215 GURL crx_url
= GenerateTestServerUrl(
216 kWebstoreDomain
, "malformed_extension.crx");
217 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
218 switches::kAppsGalleryUpdateURL
, crx_url
.spec());
221 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
222 WebstoreStartupInstallerTest::SetUpInProcessBrowserTestFixture();
223 ExtensionInstallUI::set_disable_failure_ui_for_tests();
227 IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallUnpackFailureTest
,
228 WebstoreStartupInstallUnpackFailureTest
) {
229 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
230 switches::kAppsGalleryInstallAutoConfirmForTests
, "accept");
232 ui_test_utils::NavigateToURL(browser(),
233 GenerateTestServerUrl(kAppDomain
, "install_unpack_failure.html"));
238 class CommandLineWebstoreInstall
: public WebstoreStartupInstallerTest
,
239 public content::NotificationObserver
{
241 CommandLineWebstoreInstall() : saw_install_(false), browser_open_count_(0) {}
242 virtual ~CommandLineWebstoreInstall() {}
244 virtual void SetUpOnMainThread() OVERRIDE
{
245 WebstoreStartupInstallerTest::SetUpOnMainThread();
246 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED
,
247 content::NotificationService::AllSources());
248 registrar_
.Add(this, chrome::NOTIFICATION_BROWSER_OPENED
,
249 content::NotificationService::AllSources());
252 bool saw_install() { return saw_install_
; }
254 int browser_open_count() { return browser_open_count_
; }
256 // NotificationObserver interface.
257 virtual void Observe(int type
,
258 const content::NotificationSource
& source
,
259 const content::NotificationDetails
& details
) OVERRIDE
{
260 if (type
== chrome::NOTIFICATION_EXTENSION_INSTALLED
) {
261 const Extension
* extension
=
262 content::Details
<const extensions::InstalledExtensionInfo
>(details
)->
264 ASSERT_TRUE(extension
!= NULL
);
265 EXPECT_EQ(extension
->id(), kTestExtensionId
);
267 } else if (type
== chrome::NOTIFICATION_BROWSER_OPENED
) {
268 browser_open_count_
++;
270 ASSERT_TRUE(false) << "Unexpected notification type : " << type
;
274 content::NotificationRegistrar registrar_
;
276 // Have we seen an installation notification for kTestExtensionId ?
279 // How many NOTIFICATION_BROWSER_OPENED notifications have we seen?
280 int browser_open_count_
;
283 IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall
, Accept
) {
284 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
285 command_line
->AppendSwitchASCII(
286 switches::kInstallFromWebstore
, kTestExtensionId
);
287 command_line
->AppendSwitchASCII(
288 switches::kAppsGalleryInstallAutoConfirmForTests
, "accept");
289 extensions::StartupHelper helper
;
290 EXPECT_TRUE(helper
.InstallFromWebstore(*command_line
, browser()->profile()));
291 EXPECT_TRUE(saw_install());
292 EXPECT_EQ(0, browser_open_count());
295 IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall
, Cancel
) {
296 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
297 command_line
->AppendSwitchASCII(
298 switches::kInstallFromWebstore
, kTestExtensionId
);
299 command_line
->AppendSwitchASCII(
300 switches::kAppsGalleryInstallAutoConfirmForTests
, "cancel");
301 extensions::StartupHelper helper
;
302 EXPECT_FALSE(helper
.InstallFromWebstore(*command_line
, browser()->profile()));
303 EXPECT_FALSE(saw_install());
304 EXPECT_EQ(0, browser_open_count());
307 IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall
, LimitedAccept
) {
308 extensions::StartupHelper helper
;
310 // Small test of "WebStoreIdFromLimitedInstallCmdLine" which made more
311 // sense together with the rest of the test for "LimitedInstallFromWebstore".
312 base::CommandLine
command_line_test1(base::CommandLine::NO_PROGRAM
);
313 command_line_test1
.AppendSwitchASCII(switches::kLimitedInstallFromWebstore
,
315 EXPECT_EQ("nckgahadagoaajjgafhacjanaoiihapd",
316 helper
.WebStoreIdFromLimitedInstallCmdLine(command_line_test1
));
318 base::CommandLine
command_line_test2(base::CommandLine::NO_PROGRAM
);
319 command_line_test1
.AppendSwitchASCII(switches::kLimitedInstallFromWebstore
,
321 EXPECT_EQ(kTestExtensionId
,
322 helper
.WebStoreIdFromLimitedInstallCmdLine(command_line_test1
));
324 // Now, on to the real test for LimitedInstallFromWebstore.
325 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
326 command_line
->AppendSwitchASCII(
327 switches::kLimitedInstallFromWebstore
, "2");
328 helper
.LimitedInstallFromWebstore(*command_line
, browser()->profile(),
329 base::MessageLoop::QuitWhenIdleClosure());
330 base::MessageLoop::current()->Run();
332 EXPECT_TRUE(saw_install());
333 EXPECT_EQ(0, browser_open_count());