1 // Copyright 2013 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/extensions/extension_install_prompt.h"
7 #include "chrome/browser/extensions/extension_service.h"
8 #include "chrome/browser/extensions/tab_helper.h"
9 #include "chrome/browser/extensions/webstore_inline_installer.h"
10 #include "chrome/browser/extensions/webstore_inline_installer_factory.h"
11 #include "chrome/browser/extensions/webstore_installer_test.h"
12 #include "chrome/browser/extensions/webstore_standalone_installer.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/ui_test_utils.h"
18 #include "content/public/browser/web_contents.h"
19 #include "extensions/browser/extension_system.h"
20 #include "url/gurl.h"
21
22 using content::WebContents;
23
24 namespace extensions {
25
26 namespace {
27
28 const char kWebstoreDomain[] = "cws.com";
29 const char kAppDomain[] = "app.com";
30 const char kNonAppDomain[] = "nonapp.com";
31 const char kTestExtensionId[] = "ecglahbcnmdpdciemllbhojghbkagdje";
32 const char kTestDataPath[] = "extensions/api_test/webstore_inline_install";
33 const char kCrxFilename[] = "extension.crx";
34
35 } // namespace
36
37 class WebstoreInlineInstallerTest : public WebstoreInstallerTest {
38 public:
WebstoreInlineInstallerTest()39 WebstoreInlineInstallerTest()
40 : WebstoreInstallerTest(
41 kWebstoreDomain,
42 kTestDataPath,
43 kCrxFilename,
44 kAppDomain,
45 kNonAppDomain) {}
46 };
47
48 class ProgrammableInstallPrompt : public ExtensionInstallPrompt {
49 public:
ProgrammableInstallPrompt(WebContents * contents)50 explicit ProgrammableInstallPrompt(WebContents* contents)
51 : ExtensionInstallPrompt(contents)
52 {}
53
~ProgrammableInstallPrompt()54 virtual ~ProgrammableInstallPrompt() {}
55
ConfirmStandaloneInstall(Delegate * delegate,const Extension * extension,SkBitmap * icon,scoped_refptr<ExtensionInstallPrompt::Prompt> prompt)56 virtual void ConfirmStandaloneInstall(
57 Delegate* delegate,
58 const Extension* extension,
59 SkBitmap* icon,
60 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt) OVERRIDE {
61 delegate_ = delegate;
62 }
63
Ready()64 static bool Ready() {
65 return delegate_ != NULL;
66 }
67
Accept()68 static void Accept() {
69 delegate_->InstallUIProceed();
70 }
71
Reject()72 static void Reject() {
73 delegate_->InstallUIAbort(true);
74 }
75
76 private:
77 static Delegate* delegate_;
78 };
79
80 ExtensionInstallPrompt::Delegate* ProgrammableInstallPrompt::delegate_;
81
82 // Fake inline installer which creates a programmable prompt in place of
83 // the normal dialog UI.
84 class WebstoreInlineInstallerForTest : public WebstoreInlineInstaller {
85 public:
WebstoreInlineInstallerForTest(WebContents * contents,const std::string & extension_id,const GURL & requestor_url,const Callback & callback)86 WebstoreInlineInstallerForTest(WebContents* contents,
87 const std::string& extension_id,
88 const GURL& requestor_url,
89 const Callback& callback)
90 : WebstoreInlineInstaller(
91 contents,
92 kTestExtensionId,
93 requestor_url,
94 base::Bind(DummyCallback)),
95 programmable_prompt_(NULL) {
96 }
97
CreateInstallUI()98 virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI() OVERRIDE {
99 programmable_prompt_ = new ProgrammableInstallPrompt(web_contents());
100 return make_scoped_ptr(programmable_prompt_).
101 PassAs<ExtensionInstallPrompt>();
102 }
103
104 private:
~WebstoreInlineInstallerForTest()105 virtual ~WebstoreInlineInstallerForTest() {}
106
107 friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
108
DummyCallback(bool,const std::string &)109 static void DummyCallback(bool /*success*/, const std::string& /*error*/) {
110 }
111
112 ProgrammableInstallPrompt* programmable_prompt_;
113 };
114
115 class WebstoreInlineInstallerForTestFactory :
116 public WebstoreInlineInstallerFactory {
~WebstoreInlineInstallerForTestFactory()117 virtual ~WebstoreInlineInstallerForTestFactory() {}
CreateInstaller(WebContents * contents,const std::string & webstore_item_id,const GURL & requestor_url,const WebstoreStandaloneInstaller::Callback & callback)118 virtual WebstoreInlineInstaller* CreateInstaller(
119 WebContents* contents,
120 const std::string& webstore_item_id,
121 const GURL& requestor_url,
122 const WebstoreStandaloneInstaller::Callback& callback) OVERRIDE {
123 return new WebstoreInlineInstallerForTest(
124 contents, webstore_item_id, requestor_url, callback);
125 }
126 };
127
IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest,CloseTabBeforeInstallConfirmation)128 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest,
129 CloseTabBeforeInstallConfirmation) {
130 GURL install_url = GenerateTestServerUrl(kAppDomain, "install.html");
131 ui_test_utils::NavigateToURL(browser(), install_url);
132 WebContents* web_contents =
133 browser()->tab_strip_model()->GetActiveWebContents();
134 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
135 tab_helper->SetWebstoreInlineInstallerFactoryForTests(
136 new WebstoreInlineInstallerForTestFactory());
137 RunTestAsync("runTest");
138 while (!ProgrammableInstallPrompt::Ready())
139 base::RunLoop().RunUntilIdle();
140 web_contents->Close();
141 ProgrammableInstallPrompt::Accept();
142 }
143
144 // Ensure that inline-installing a disabled extension simply re-enables it.
IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest,ReinstallDisabledExtension)145 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest,
146 ReinstallDisabledExtension) {
147 // Install an extension via inline install, and confirm it is successful.
148 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
149 switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
150 ui_test_utils::NavigateToURL(
151 browser(), GenerateTestServerUrl(kAppDomain, "install.html"));
152 RunTest("runTest");
153 ExtensionService* extension_service =
154 ExtensionSystem::Get(browser()->profile())->extension_service();
155 ASSERT_TRUE(extension_service->GetExtensionById(kTestExtensionId, false));
156
157 // Disable the extension.
158 extension_service->DisableExtension(kTestExtensionId,
159 Extension::DISABLE_USER_ACTION);
160 ASSERT_FALSE(extension_service->IsExtensionEnabled(kTestExtensionId));
161
162 // Revisit the inline install site and reinstall the extension. It should
163 // simply be re-enabled, rather than try to install again.
164 ui_test_utils::NavigateToURL(
165 browser(), GenerateTestServerUrl(kAppDomain, "install.html"));
166 RunTest("runTest");
167 ASSERT_TRUE(extension_service->IsExtensionEnabled(kTestExtensionId));
168 }
169
170 class WebstoreInlineInstallerListenerTest : public WebstoreInlineInstallerTest {
171 public:
WebstoreInlineInstallerListenerTest()172 WebstoreInlineInstallerListenerTest() {}
~WebstoreInlineInstallerListenerTest()173 virtual ~WebstoreInlineInstallerListenerTest() {}
174
175 protected:
RunTest(const std::string & file_name)176 void RunTest(const std::string& file_name) {
177 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
178 switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
179 ui_test_utils::NavigateToURL(browser(),
180 GenerateTestServerUrl(kAppDomain, file_name));
181 WebstoreInstallerTest::RunTest("runTest");
182 }
183 };
184
IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,InstallStageListenerTest)185 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,
186 InstallStageListenerTest) {
187 RunTest("install_stage_listener.html");
188 }
189
IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,DownloadProgressListenerTest)190 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,
191 DownloadProgressListenerTest) {
192 RunTest("download_progress_listener.html");
193 }
194
IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,BothListenersTest)195 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest, BothListenersTest) {
196 RunTest("both_listeners.html");
197 }
198
199 } // namespace extensions
200