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