blob: 3026f2347bd4cd2cd266331a1fa3bfbe4948059e [file] [log] [blame]
[email protected]35385332012-03-28 02:32:031// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]a01e00632010-11-05 16:58:142// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]bf2fcd52012-04-16 22:59:395#include "chrome/browser/download/download_crx_util.h"
6#include "chrome/browser/download/download_service.h"
7#include "chrome/browser/download/download_service_factory.h"
8#include "chrome/browser/download/download_test_observer.h"
[email protected]a01e00632010-11-05 16:58:149#include "chrome/browser/extensions/crx_installer.h"
10#include "chrome/browser/extensions/extension_browsertest.h"
[email protected]c82da8c42012-06-08 19:49:1111#include "chrome/browser/extensions/extension_install_prompt.h"
[email protected]eaa7dd182010-12-14 11:09:0012#include "chrome/browser/extensions/extension_service.h"
[email protected]8ecad5e2010-12-02 21:18:3313#include "chrome/browser/profiles/profile.h"
[email protected]2ad4a902010-11-17 06:05:1314#include "chrome/browser/ui/browser.h"
[email protected]619f86182012-07-03 21:30:1815#include "chrome/browser/ui/browser_window.h"
[email protected]240cc92a2011-12-01 01:22:2416#include "chrome/common/chrome_switches.h"
[email protected]b70a2d92012-06-28 19:51:2117#include "chrome/common/extensions/extension.h"
[email protected]35385332012-03-28 02:32:0318#include "chrome/common/extensions/extension_file_util.h"
[email protected]89019d62012-05-17 18:47:0919#include "chrome/common/extensions/extension_switch_utils.h"
[email protected]b70a2d92012-06-28 19:51:2120#include "chrome/common/extensions/permissions/permission_set.h"
[email protected]af44e7fb2011-07-29 18:32:3221#include "chrome/test/base/ui_test_utils.h"
[email protected]a9736892012-05-30 15:58:0522#include "grit/generated_resources.h"
23#include "ui/base/l10n/l10n_util.h"
[email protected]a01e00632010-11-05 16:58:1424
[email protected]7a5452f2010-12-13 23:03:1925class SkBitmap;
26
[email protected]bf3d9df2012-07-24 23:20:2727namespace extensions {
[email protected]b70a2d92012-06-28 19:51:2128
[email protected]a01e00632010-11-05 16:58:1429namespace {
30
[email protected]bf2fcd52012-04-16 22:59:3931// Observer waits for exactly one download to finish.
32
[email protected]c82da8c42012-06-08 19:49:1133class MockInstallPrompt : public ExtensionInstallPrompt {
[email protected]a01e00632010-11-05 16:58:1434 public:
[email protected]619f86182012-07-03 21:30:1835 explicit MockInstallPrompt(gfx::NativeWindow parent,
36 content::PageNavigator* navigator,
37 Profile* profile) :
38 ExtensionInstallPrompt(parent, navigator, profile),
[email protected]b70a2d92012-06-28 19:51:2139 confirmation_requested_(false),
40 extension_(NULL) {}
[email protected]a01e00632010-11-05 16:58:1441
[email protected]b70a2d92012-06-28 19:51:2142 bool did_succeed() const { return !!extension_; }
43 const Extension* extension() const { return extension_; }
[email protected]a9736892012-05-30 15:58:0544 bool confirmation_requested() const { return confirmation_requested_; }
45 const string16& error() const { return error_; }
[email protected]b70a2d92012-06-28 19:51:2146 void set_record_oauth2_grant(bool record) { record_oauth2_grant_ = record; }
[email protected]a01e00632010-11-05 16:58:1447
48 // Overriding some of the ExtensionInstallUI API.
[email protected]1c321ee2012-05-21 03:02:3449 void ConfirmInstall(Delegate* delegate,
[email protected]b70a2d92012-06-28 19:51:2150 const Extension* extension) {
[email protected]a01e00632010-11-05 16:58:1451 confirmation_requested_ = true;
52 delegate->InstallUIProceed();
53 }
[email protected]b70a2d92012-06-28 19:51:2154 void OnInstallSuccess(const Extension* extension,
[email protected]1c321ee2012-05-21 03:02:3455 SkBitmap* icon) {
[email protected]b70a2d92012-06-28 19:51:2156 extension_ = extension;
[email protected]a01e00632010-11-05 16:58:1457 MessageLoopForUI::current()->Quit();
58 }
[email protected]4eaf0b32012-06-19 06:33:2859 void OnInstallFailure(const CrxInstallerError& error) {
60 error_ = error.message();
[email protected]a01e00632010-11-05 16:58:1461 MessageLoopForUI::current()->Quit();
62 }
63
64 private:
[email protected]a01e00632010-11-05 16:58:1465 bool confirmation_requested_;
[email protected]a9736892012-05-30 15:58:0566 string16 error_;
[email protected]b70a2d92012-06-28 19:51:2167 const Extension* extension_;
[email protected]a01e00632010-11-05 16:58:1468};
69
[email protected]619f86182012-07-03 21:30:1870MockInstallPrompt* CreateMockInstallPromptForBrowser(Browser* browser) {
71 gfx::NativeWindow parent =
72 browser->window() ? browser->window()->GetNativeWindow() : NULL;
73 return new MockInstallPrompt(parent, browser, browser->profile());
74}
75
[email protected]a01e00632010-11-05 16:58:1476} // namespace
77
78class ExtensionCrxInstallerTest : public ExtensionBrowserTest {
79 public:
80 // Installs a crx from |crx_relpath| (a path relative to the extension test
[email protected]b70a2d92012-06-28 19:51:2181 // data dir) with expected id |id|. Returns the installer.
82 scoped_refptr<CrxInstaller> InstallWithPrompt(
83 const std::string& ext_relpath,
84 const std::string& id,
85 MockInstallPrompt* mock_install_prompt) {
[email protected]eaa7dd182010-12-14 11:09:0086 ExtensionService* service = browser()->profile()->GetExtensionService();
[email protected]35385332012-03-28 02:32:0387 FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath);
88
89 std::string error;
90 base::DictionaryValue* parsed_manifest =
91 extension_file_util::LoadManifest(ext_path, &error);
92 if (!parsed_manifest)
[email protected]b70a2d92012-06-28 19:51:2193 return scoped_refptr<CrxInstaller>();
[email protected]35385332012-03-28 02:32:0394
[email protected]bf3d9df2012-07-24 23:20:2795 scoped_ptr<WebstoreInstaller::Approval> approval;
[email protected]b70a2d92012-06-28 19:51:2196 if (!id.empty()) {
[email protected]bf3d9df2012-07-24 23:20:2797 approval = WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
98 browser()->profile(),
99 id,
100 scoped_ptr<base::DictionaryValue>(parsed_manifest));
[email protected]b70a2d92012-06-28 19:51:21101 }
[email protected]a01e00632010-11-05 16:58:14102
103 scoped_refptr<CrxInstaller> installer(
[email protected]d8c8f25f2011-11-02 18:18:01104 CrxInstaller::Create(service,
[email protected]c82da8c42012-06-08 19:49:11105 mock_install_prompt, /* ownership transferred */
106 approval.get() /* keep ownership */));
[email protected]a01e00632010-11-05 16:58:14107 installer->set_allow_silent_install(true);
[email protected]b1f04cc2010-11-10 22:59:30108 installer->set_is_gallery_install(true);
[email protected]35385332012-03-28 02:32:03109 installer->InstallCrx(PackExtension(ext_path));
[email protected]a01e00632010-11-05 16:58:14110 ui_test_utils::RunMessageLoop();
111
[email protected]c82da8c42012-06-08 19:49:11112 EXPECT_TRUE(mock_install_prompt->did_succeed());
[email protected]b70a2d92012-06-28 19:51:21113 return installer;
114 }
115
116 // Installs an extension and checks that it has scopes granted IFF
117 // |record_oauth2_grant| is true.
118 void CheckHasEmptyScopesAfterInstall(const std::string& ext_relpath,
119 bool record_oauth2_grant) {
120 CommandLine::ForCurrentProcess()->AppendSwitch(
121 switches::kEnableExperimentalExtensionApis);
122
123 ExtensionService* service = browser()->profile()->GetExtensionService();
124
[email protected]619f86182012-07-03 21:30:18125 MockInstallPrompt* mock_prompt =
126 CreateMockInstallPromptForBrowser(browser());
[email protected]b70a2d92012-06-28 19:51:21127 mock_prompt->set_record_oauth2_grant(record_oauth2_grant);
128 scoped_refptr<CrxInstaller> installer =
129 InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt);
130
[email protected]bf3d9df2012-07-24 23:20:27131 scoped_refptr<PermissionSet> permissions =
[email protected]b70a2d92012-06-28 19:51:21132 service->extension_prefs()->GetGrantedPermissions(
133 mock_prompt->extension()->id());
134 ASSERT_TRUE(permissions.get());
[email protected]d4a37f1c2012-07-09 21:36:13135 EXPECT_EQ(record_oauth2_grant, installer->record_oauth2_grant_);
[email protected]a01e00632010-11-05 16:58:14136 }
137};
138
[email protected]45dd1b4802012-06-05 23:07:59139#if defined(OS_CHROMEOS)
140#define MAYBE_Whitelisting DISABLED_Whitelisting
141#else
142#define MAYBE_Whitelisting Whitelisting
143#endif
144IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, MAYBE_Whitelisting) {
[email protected]21a5ad62012-04-03 04:48:45145 std::string id = "hdgllgikmikobbofgnabhfimcfoopgnd";
146 ExtensionService* service = browser()->profile()->GetExtensionService();
147
148 // Even whitelisted extensions with NPAPI should not prompt.
[email protected]619f86182012-07-03 21:30:18149 MockInstallPrompt* mock_prompt =
150 CreateMockInstallPromptForBrowser(browser());
[email protected]b70a2d92012-06-28 19:51:21151 scoped_refptr<CrxInstaller> installer =
152 InstallWithPrompt("uitest/plugins", id, mock_prompt);
153 EXPECT_FALSE(mock_prompt->confirmation_requested());
[email protected]21a5ad62012-04-03 04:48:45154 EXPECT_TRUE(service->GetExtensionById(id, false));
[email protected]a01e00632010-11-05 16:58:14155}
[email protected]fc38935a2011-10-31 23:53:28156
157IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
[email protected]240cc92a2011-12-01 01:22:24158 GalleryInstallGetsExperimental) {
159 // We must modify the command line temporarily in order to pack an extension
160 // that requests the experimental permission.
161 CommandLine* command_line = CommandLine::ForCurrentProcess();
162 CommandLine old_command_line = *command_line;
163 command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
164 FilePath crx_path = PackExtension(
165 test_data_dir_.AppendASCII("experimental"));
166 ASSERT_FALSE(crx_path.empty());
167
168 // Now reset the command line so that we are testing specifically whether
169 // installing from webstore enables experimental permissions.
170 *(CommandLine::ForCurrentProcess()) = old_command_line;
171
172 EXPECT_FALSE(InstallExtension(crx_path, 0));
173 EXPECT_TRUE(InstallExtensionFromWebstore(crx_path, 1));
[email protected]fc38935a2011-10-31 23:53:28174}
[email protected]ee14cad2012-03-29 01:59:37175
176IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, PlatformAppCrx) {
[email protected]b70a2d92012-06-28 19:51:21177 CommandLine::ForCurrentProcess()->AppendSwitch(
178 switches::kEnableExperimentalExtensionApis);
[email protected]ee14cad2012-03-29 01:59:37179 EXPECT_TRUE(InstallExtension(
[email protected]dc37b002012-04-23 23:02:26180 test_data_dir_.AppendASCII("minimal_platform_app.crx"), 1));
[email protected]ee14cad2012-03-29 01:59:37181}
[email protected]bf2fcd52012-04-16 22:59:39182
[email protected]3f3365c62012-07-09 19:13:21183// http://crbug.com/136397
184#if defined(OS_CHROMEOS)
185#define MAYBE_PackAndInstallExtension DISABLED_PackAndInstallExtension
186#else
187#define MAYBE_PackAndInstallExtension PackAndInstallExtension
188#endif
189IN_PROC_BROWSER_TEST_F(
190 ExtensionCrxInstallerTest, MAYBE_PackAndInstallExtension) {
[email protected]bf3d9df2012-07-24 23:20:27191 if (!switch_utils::IsEasyOffStoreInstallEnabled())
[email protected]89019d62012-05-17 18:47:09192 return;
193
[email protected]bf2fcd52012-04-16 22:59:39194 const int kNumDownloadsExpected = 1;
195 const bool kExpectFileSelectDialog = false;
196
197 LOG(ERROR) << "PackAndInstallExtension: Packing extension";
198 FilePath crx_path = PackExtension(
199 test_data_dir_.AppendASCII("common/background_page"));
200 ASSERT_FALSE(crx_path.empty());
201 std::string crx_path_string(crx_path.value().begin(), crx_path.value().end());
202 GURL url = GURL(std::string("file:///").append(crx_path_string));
203
[email protected]619f86182012-07-03 21:30:18204 MockInstallPrompt* mock_prompt =
205 CreateMockInstallPromptForBrowser(browser());
[email protected]c82da8c42012-06-08 19:49:11206 download_crx_util::SetMockInstallPromptForTesting(mock_prompt);
[email protected]bf2fcd52012-04-16 22:59:39207
208 LOG(ERROR) << "PackAndInstallExtension: Getting download manager";
209 content::DownloadManager* download_manager =
[email protected]b441a8492012-06-06 14:55:57210 content::BrowserContext::GetDownloadManager(browser()->profile());
[email protected]bf2fcd52012-04-16 22:59:39211
212 LOG(ERROR) << "PackAndInstallExtension: Setting observer";
213 scoped_ptr<DownloadTestObserver> observer(
214 new DownloadTestObserverTerminal(
215 download_manager, kNumDownloadsExpected, kExpectFileSelectDialog,
216 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));
217 LOG(ERROR) << "PackAndInstallExtension: Navigating to URL";
218 ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB,
219 ui_test_utils::BROWSER_TEST_NONE);
220
[email protected]8c6af5b2012-06-15 20:10:26221 EXPECT_TRUE(WaitForCrxInstallerDone());
[email protected]bf2fcd52012-04-16 22:59:39222 LOG(ERROR) << "PackAndInstallExtension: Extension install";
[email protected]c82da8c42012-06-08 19:49:11223 EXPECT_TRUE(mock_prompt->confirmation_requested());
[email protected]bf2fcd52012-04-16 22:59:39224 LOG(ERROR) << "PackAndInstallExtension: Extension install confirmed";
225}
[email protected]a9736892012-05-30 15:58:05226
[email protected]b70a2d92012-06-28 19:51:21227// Tests that scopes are only granted if |record_oauth2_grant_| on the prompt is
228// true.
229IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, GrantScopes) {
230 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
231 true));
232}
233
234IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, DoNotGrantScopes) {
235 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
236 false));
237}
238
[email protected]45dd1b4802012-06-05 23:07:59239// Off-store install cannot yet be disabled on Aura.
[email protected]a9736892012-05-30 15:58:05240#if defined(USE_AURA)
[email protected]45dd1b4802012-06-05 23:07:59241#define MAYBE_AllowOffStore DISABLED_AllowOffStore
[email protected]a9736892012-05-30 15:58:05242#else
[email protected]45dd1b4802012-06-05 23:07:59243#define MAYBE_AllowOffStore AllowOffStore
244#endif
245IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, MAYBE_AllowOffStore) {
[email protected]a9736892012-05-30 15:58:05246 ExtensionService* service = browser()->profile()->GetExtensionService();
247 const bool kTestData[] = {false, true};
248
249 for (size_t i = 0; i < arraysize(kTestData); ++i) {
[email protected]619f86182012-07-03 21:30:18250 MockInstallPrompt* mock_prompt =
251 CreateMockInstallPromptForBrowser(browser());
[email protected]a9736892012-05-30 15:58:05252 scoped_refptr<CrxInstaller> crx_installer(
[email protected]c82da8c42012-06-08 19:49:11253 CrxInstaller::Create(service, mock_prompt));
[email protected]7224dbd2012-06-05 15:21:50254 crx_installer->set_install_cause(
255 extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
[email protected]d9039812012-06-09 06:05:48256
257 if (kTestData[i]) {
258 crx_installer->set_off_store_install_allow_reason(
259 CrxInstaller::OffStoreInstallAllowedInTest);
260 }
[email protected]a9736892012-05-30 15:58:05261
262 crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx"));
263 EXPECT_EQ(kTestData[i], WaitForExtensionInstall()) << kTestData[i];
[email protected]c82da8c42012-06-08 19:49:11264 EXPECT_EQ(kTestData[i], mock_prompt->did_succeed());
265 EXPECT_EQ(kTestData[i], mock_prompt->confirmation_requested()) <<
266 kTestData[i];
[email protected]a9736892012-05-30 15:58:05267 if (kTestData[i]) {
[email protected]c82da8c42012-06-08 19:49:11268 EXPECT_EQ(string16(), mock_prompt->error()) << kTestData[i];
[email protected]a9736892012-05-30 15:58:05269 } else {
270 EXPECT_EQ(l10n_util::GetStringUTF16(
271 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE),
[email protected]c82da8c42012-06-08 19:49:11272 mock_prompt->error()) << kTestData[i];
[email protected]a9736892012-05-30 15:58:05273 }
274 }
[email protected]a9736892012-05-30 15:58:05275}
[email protected]bf3d9df2012-07-24 23:20:27276
277} // namespace extensions