blob: bec23e437bc20e84ec0f67907af0cc4b9f8541cd [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
mtomaszf7d99a5c2014-09-15 16:23:465#include "chrome/browser/extensions/crx_installer.h"
6
avia2f4804a2015-12-24 23:11:137#include <stddef.h>
8
[email protected]5a145e82014-05-29 22:19:079#include "base/at_exit.h"
kalmanae342c92014-12-12 22:04:2310#include "base/files/file_path.h"
avia2f4804a2015-12-24 23:11:1311#include "base/macros.h"
[email protected]f8636f92013-08-09 21:02:3712#include "base/memory/ref_counted.h"
[email protected]253fc2bb2014-07-10 04:21:1813#include "base/strings/utf_string_conversions.h"
avia2f4804a2015-12-24 23:11:1314#include "build/build_config.h"
[email protected]bf2fcd52012-04-16 22:59:3915#include "chrome/browser/download/download_crx_util.h"
[email protected]52b76592013-11-02 17:59:0316#include "chrome/browser/extensions/browser_action_test_util.h"
[email protected]a01e00632010-11-05 16:58:1417#include "chrome/browser/extensions/extension_browsertest.h"
[email protected]c82da8c42012-06-08 19:49:1118#include "chrome/browser/extensions/extension_install_prompt.h"
pkotwicz2f181782014-10-29 17:33:4519#include "chrome/browser/extensions/extension_install_prompt_show_params.h"
[email protected]eaa7dd182010-12-14 11:09:0020#include "chrome/browser/extensions/extension_service.h"
mekc95f9d062015-01-10 00:52:0421#include "chrome/browser/extensions/extension_tab_util.h"
[email protected]658eae52014-06-14 20:28:0522#include "chrome/browser/extensions/extension_util.h"
[email protected]3f2a2fa2013-09-24 02:55:2523#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
gpdavis.chromium48f08c42014-09-18 22:09:3424#include "chrome/browser/extensions/test_extension_dir.h"
[email protected]8ecad5e2010-12-02 21:18:3325#include "chrome/browser/profiles/profile.h"
[email protected]2ad4a902010-11-17 06:05:1326#include "chrome/browser/ui/browser.h"
[email protected]619f86182012-07-03 21:30:1827#include "chrome/browser/ui/browser_window.h"
[email protected]91e51d612012-10-21 23:03:0528#include "chrome/browser/ui/tabs/tab_strip_model.h"
dominickn675536f2015-11-06 03:25:3829#include "chrome/common/web_application_info.h"
[email protected]af39f002014-08-22 10:18:1830#include "chrome/grit/generated_resources.h"
[email protected]af44e7fb2011-07-29 18:32:3231#include "chrome/test/base/ui_test_utils.h"
[email protected]5a145e82014-05-29 22:19:0732#include "content/public/browser/browser_thread.h"
[email protected]f34efa22013-03-05 19:14:2333#include "content/public/browser/download_manager.h"
[email protected]52b76592013-11-02 17:59:0334#include "content/public/browser/render_view_host.h"
[email protected]8ffad4e2014-01-02 23:18:2635#include "content/public/test/browser_test_utils.h"
[email protected]49b264f2012-08-14 17:12:2636#include "content/public/test/download_test_observer.h"
mtomaszf7d99a5c2014-09-15 16:23:4637#include "content/public/test/test_utils.h"
rdevlin.croninca5bf2da2015-12-17 21:21:0838#include "extensions/browser/extension_dialog_auto_confirm.h"
[email protected]dccba4f82014-05-29 00:52:5639#include "extensions/browser/extension_prefs.h"
gpdavis.chromium48f08c42014-09-18 22:09:3440#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2441#include "extensions/browser/extension_system.h"
ginkage47e603e2015-02-27 08:42:4142#include "extensions/browser/install/crx_install_error.h"
[email protected]253fc2bb2014-07-10 04:21:1843#include "extensions/browser/management_policy.h"
[email protected]adf5a102014-07-31 12:44:0644#include "extensions/browser/notification_types.h"
[email protected]e4452d32013-11-15 23:07:4145#include "extensions/common/extension.h"
[email protected]5ef835a2013-11-08 20:42:5746#include "extensions/common/feature_switch.h"
[email protected]85df9d12014-04-15 17:02:1447#include "extensions/common/file_util.h"
kalmanae342c92014-12-12 22:04:2348#include "extensions/common/permissions/api_permission.h"
[email protected]5a55f3f2013-10-29 01:08:2949#include "extensions/common/permissions/permission_set.h"
kalmanae342c92014-12-12 22:04:2350#include "extensions/common/permissions/permissions_data.h"
[email protected]c8d02992013-07-31 22:16:5151#include "extensions/common/switches.h"
dominickn675536f2015-11-06 03:25:3852#include "third_party/skia/include/core/SkBitmap.h"
[email protected]a9736892012-05-30 15:58:0553#include "ui/base/l10n/l10n_util.h"
[email protected]a01e00632010-11-05 16:58:1454
[email protected]14a18bf2013-09-26 08:42:3055#if defined(OS_CHROMEOS)
merkulova793f3022015-02-04 10:18:3056#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
[email protected]4d390782014-08-15 09:22:5857#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
[email protected]5a145e82014-05-29 22:19:0758#include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
59#include "chromeos/chromeos_switches.h"
[email protected]14a18bf2013-09-26 08:42:3060#endif
61
[email protected]7a5452f2010-12-13 23:03:1962class SkBitmap;
63
dominickn675536f2015-11-06 03:25:3864namespace {
65
66const char kAppUrl[] = "http://www.google.com";
67const char kAppTitle[] = "Test title";
68const char kAppDescription[] = "Test description";
69
70} // anonymous namespace
71
[email protected]bf3d9df2012-07-24 23:20:2772namespace extensions {
[email protected]b70a2d92012-06-28 19:51:2173
[email protected]a01e00632010-11-05 16:58:1474namespace {
75
[email protected]f8636f92013-08-09 21:02:3776class MockInstallPrompt;
77
78// This class holds information about things that happen with a
79// MockInstallPrompt. We create the MockInstallPrompt but need to pass
80// ownership of it to CrxInstaller, so it isn't safe to hang this data on
81// MockInstallPrompt itself becuase we can't guarantee it's lifetime.
rdevlin.croninca5bf2da2015-12-17 21:21:0882class MockPromptProxy {
[email protected]f8636f92013-08-09 21:02:3783 public:
84 explicit MockPromptProxy(content::WebContents* web_contents);
rdevlin.croninca5bf2da2015-12-17 21:21:0885 ~MockPromptProxy();
[email protected]f8636f92013-08-09 21:02:3786
87 bool did_succeed() const { return !extension_id_.empty(); }
88 const std::string& extension_id() { return extension_id_; }
89 bool confirmation_requested() const { return confirmation_requested_; }
[email protected]439f1e32013-12-09 20:09:0990 const base::string16& error() const { return error_; }
[email protected]f8636f92013-08-09 21:02:3791
[email protected]f8636f92013-08-09 21:02:3792 void set_extension_id(const std::string& id) { extension_id_ = id; }
rdevlin.croninca5bf2da2015-12-17 21:21:0893 void set_confirmation_requested(bool requested) {
94 confirmation_requested_ = requested;
95 }
[email protected]439f1e32013-12-09 20:09:0996 void set_error(const base::string16& error) { error_ = error; }
[email protected]f8636f92013-08-09 21:02:3797
98 scoped_ptr<ExtensionInstallPrompt> CreatePrompt();
99
100 private:
[email protected]f8636f92013-08-09 21:02:37101
102 // Data used to create a prompt.
103 content::WebContents* web_contents_;
[email protected]f8636f92013-08-09 21:02:37104
105 // Data reported back to us by the prompt we created.
106 bool confirmation_requested_;
107 std::string extension_id_;
[email protected]439f1e32013-12-09 20:09:09108 base::string16 error_;
rdevlin.croninca5bf2da2015-12-17 21:21:08109
110 scoped_ptr<ScopedTestDialogAutoConfirm> auto_confirm;
111
112 DISALLOW_COPY_AND_ASSIGN(MockPromptProxy);
[email protected]f8636f92013-08-09 21:02:37113};
[email protected]bf2fcd52012-04-16 22:59:39114
dominickn675536f2015-11-06 03:25:38115SkBitmap CreateSquareBitmap(int size) {
116 SkBitmap bitmap;
117 bitmap.allocN32Pixels(size, size);
118 bitmap.eraseColor(SK_ColorRED);
119 return bitmap;
120}
121
122WebApplicationInfo::IconInfo CreateIconInfoWithBitmap(int size) {
123 WebApplicationInfo::IconInfo icon_info;
124 icon_info.width = size;
125 icon_info.height = size;
126 icon_info.data = CreateSquareBitmap(size);
127 return icon_info;
128}
129
130WebApplicationInfo CreateWebAppInfo(const char* title,
131 const char* description,
132 const char* app_url,
133 int size) {
134 WebApplicationInfo web_app_info;
135 web_app_info.title = base::UTF8ToUTF16(title);
136 web_app_info.description = base::UTF8ToUTF16(description);
137 web_app_info.app_url = GURL(app_url);
138
139 web_app_info.icons.push_back(CreateIconInfoWithBitmap(size));
140
141 return web_app_info;
142}
143
[email protected]c82da8c42012-06-08 19:49:11144class MockInstallPrompt : public ExtensionInstallPrompt {
[email protected]a01e00632010-11-05 16:58:14145 public:
[email protected]f8636f92013-08-09 21:02:37146 MockInstallPrompt(content::WebContents* web_contents,
147 MockPromptProxy* proxy) :
[email protected]91e51d612012-10-21 23:03:05148 ExtensionInstallPrompt(web_contents),
[email protected]f8636f92013-08-09 21:02:37149 proxy_(proxy) {}
[email protected]a01e00632010-11-05 16:58:14150
[email protected]a01e00632010-11-05 16:58:14151 // Overriding some of the ExtensionInstallUI API.
dchengae36a4a2014-10-21 12:36:36152 void OnInstallSuccess(const Extension* extension, SkBitmap* icon) override {
[email protected]f8636f92013-08-09 21:02:37153 proxy_->set_extension_id(extension->id());
rdevlin.croninca5bf2da2015-12-17 21:21:08154 proxy_->set_confirmation_requested(did_call_show_dialog());
ki.stfuc4f8e242015-10-09 20:40:20155 base::MessageLoopForUI::current()->QuitWhenIdle();
[email protected]a01e00632010-11-05 16:58:14156 }
ginkage47e603e2015-02-27 08:42:41157 void OnInstallFailure(const CrxInstallError& error) override {
[email protected]f8636f92013-08-09 21:02:37158 proxy_->set_error(error.message());
rdevlin.croninca5bf2da2015-12-17 21:21:08159 proxy_->set_confirmation_requested(did_call_show_dialog());
ki.stfuc4f8e242015-10-09 20:40:20160 base::MessageLoopForUI::current()->QuitWhenIdle();
[email protected]a01e00632010-11-05 16:58:14161 }
162
163 private:
rdevlin.croninca5bf2da2015-12-17 21:21:08164 MockPromptProxy* proxy_;
165
166 DISALLOW_COPY_AND_ASSIGN(MockInstallPrompt);
[email protected]a01e00632010-11-05 16:58:14167};
168
[email protected]658eae52014-06-14 20:28:05169MockPromptProxy::MockPromptProxy(content::WebContents* web_contents)
rdevlin.croninca5bf2da2015-12-17 21:21:08170 : web_contents_(web_contents),
171 confirmation_requested_(false),
172 auto_confirm(new ScopedTestDialogAutoConfirm(
173 ScopedTestDialogAutoConfirm::ACCEPT)) {
[email protected]f8636f92013-08-09 21:02:37174}
175
176MockPromptProxy::~MockPromptProxy() {}
177
178scoped_ptr<ExtensionInstallPrompt> MockPromptProxy::CreatePrompt() {
rdevlin.croninf84cab72015-12-12 03:45:23179 return scoped_ptr<MockInstallPrompt>(
[email protected]f8636f92013-08-09 21:02:37180 new MockInstallPrompt(web_contents_, this));
[email protected]f8636f92013-08-09 21:02:37181}
182
183
rdevlin.croninca5bf2da2015-12-17 21:21:08184scoped_ptr<MockPromptProxy> CreateMockPromptProxyForBrowser(
[email protected]f8636f92013-08-09 21:02:37185 Browser* browser) {
rdevlin.croninca5bf2da2015-12-17 21:21:08186 return make_scoped_ptr(new MockPromptProxy(
187 browser->tab_strip_model()->GetActiveWebContents()));
[email protected]619f86182012-07-03 21:30:18188}
189
[email protected]253fc2bb2014-07-10 04:21:18190class ManagementPolicyMock : public extensions::ManagementPolicy::Provider {
191 public:
192 ManagementPolicyMock() {}
193
dchengae36a4a2014-10-21 12:36:36194 std::string GetDebugPolicyProviderName() const override {
[email protected]253fc2bb2014-07-10 04:21:18195 return "ManagementPolicyMock";
196 }
197
dchengae36a4a2014-10-21 12:36:36198 bool UserMayLoad(const Extension* extension,
199 base::string16* error) const override {
[email protected]253fc2bb2014-07-10 04:21:18200 *error = base::UTF8ToUTF16("Dummy error message");
201 return false;
202 }
203};
204
kalmanae342c92014-12-12 22:04:23205// Appends "enable-experimental-extension-apis" to the command line for the
206// lifetime of this class.
207class ScopedExperimentalCommandLine {
208 public:
avi3ef9ec9e2014-12-22 22:50:17209 ScopedExperimentalCommandLine()
210 : saved_(*base::CommandLine::ForCurrentProcess()) {
211 base::CommandLine::ForCurrentProcess()->AppendSwitch(
kalmanae342c92014-12-12 22:04:23212 switches::kEnableExperimentalExtensionApis);
213 }
214
215 ~ScopedExperimentalCommandLine() {
avi3ef9ec9e2014-12-22 22:50:17216 *base::CommandLine::ForCurrentProcess() = saved_;
kalmanae342c92014-12-12 22:04:23217 }
218
219 private:
avi3ef9ec9e2014-12-22 22:50:17220 base::CommandLine saved_;
kalmanae342c92014-12-12 22:04:23221};
222
[email protected]a01e00632010-11-05 16:58:14223} // namespace
224
225class ExtensionCrxInstallerTest : public ExtensionBrowserTest {
kalmanae342c92014-12-12 22:04:23226 protected:
[email protected]85290822013-08-23 20:27:38227 scoped_ptr<WebstoreInstaller::Approval> GetApproval(
228 const char* manifest_dir,
[email protected]b70a2d92012-06-28 19:51:21229 const std::string& id,
[email protected]85290822013-08-23 20:27:38230 bool strict_manifest_checks) {
231 scoped_ptr<WebstoreInstaller::Approval> result;
232
233 base::FilePath ext_path = test_data_dir_.AppendASCII(manifest_dir);
234 std::string error;
235 scoped_ptr<base::DictionaryValue> parsed_manifest(
[email protected]85df9d12014-04-15 17:02:14236 file_util::LoadManifest(ext_path, &error));
[email protected]85290822013-08-23 20:27:38237 if (!parsed_manifest.get() || !error.empty())
238 return result.Pass();
239
240 return WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
241 browser()->profile(),
242 id,
243 parsed_manifest.Pass(),
244 strict_manifest_checks);
245 }
246
247 void RunCrxInstaller(const WebstoreInstaller::Approval* approval,
248 scoped_ptr<ExtensionInstallPrompt> prompt,
249 const base::FilePath& crx_path) {
[email protected]06bdd2b2012-11-30 18:47:13250 ExtensionService* service = extensions::ExtensionSystem::Get(
251 browser()->profile())->extension_service();
[email protected]a01e00632010-11-05 16:58:14252 scoped_refptr<CrxInstaller> installer(
[email protected]85290822013-08-23 20:27:38253 CrxInstaller::Create(service, prompt.Pass(), approval));
[email protected]a01e00632010-11-05 16:58:14254 installer->set_allow_silent_install(true);
[email protected]b1f04cc2010-11-10 22:59:30255 installer->set_is_gallery_install(true);
[email protected]85290822013-08-23 20:27:38256 installer->InstallCrx(crx_path);
[email protected]729eb632012-07-26 04:45:26257 content::RunMessageLoop();
[email protected]85290822013-08-23 20:27:38258 }
259
260 // Installs a crx from |crx_relpath| (a path relative to the extension test
261 // data dir) with expected id |id|.
262 void InstallWithPrompt(const char* ext_relpath,
263 const std::string& id,
rdevlin.croninca5bf2da2015-12-17 21:21:08264 MockPromptProxy* mock_install_prompt) {
[email protected]85290822013-08-23 20:27:38265 base::FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath);
266
267 scoped_ptr<WebstoreInstaller::Approval> approval;
268 if (!id.empty())
269 approval = GetApproval(ext_relpath, id, true);
270
271 base::FilePath crx_path = PackExtension(ext_path);
272 EXPECT_FALSE(crx_path.empty());
273 RunCrxInstaller(approval.get(), mock_install_prompt->CreatePrompt(),
274 crx_path);
[email protected]a01e00632010-11-05 16:58:14275
[email protected]c82da8c42012-06-08 19:49:11276 EXPECT_TRUE(mock_install_prompt->did_succeed());
[email protected]b70a2d92012-06-28 19:51:21277 }
278
279 // Installs an extension and checks that it has scopes granted IFF
280 // |record_oauth2_grant| is true.
281 void CheckHasEmptyScopesAfterInstall(const std::string& ext_relpath,
282 bool record_oauth2_grant) {
kalmanae342c92014-12-12 22:04:23283 ScopedExperimentalCommandLine scope;
[email protected]b70a2d92012-06-28 19:51:21284
rdevlin.croninca5bf2da2015-12-17 21:21:08285 scoped_ptr<MockPromptProxy> mock_prompt =
[email protected]f8636f92013-08-09 21:02:37286 CreateMockPromptProxyForBrowser(browser());
287
rdevlin.croninca5bf2da2015-12-17 21:21:08288 InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt.get());
[email protected]b70a2d92012-06-28 19:51:21289
rdevlin.cronine2d0fd02015-09-24 22:35:49290 scoped_ptr<const PermissionSet> permissions =
[email protected]7c82539c2014-02-19 06:09:17291 ExtensionPrefs::Get(browser()->profile())
292 ->GetGrantedPermissions(mock_prompt->extension_id());
[email protected]b70a2d92012-06-28 19:51:21293 ASSERT_TRUE(permissions.get());
[email protected]a01e00632010-11-05 16:58:14294 }
kalmanae342c92014-12-12 22:04:23295
296 // Returns a FilePath to an unpacked "experimental" extension (a test
297 // Extension which requests the "experimental" permission).
298 base::FilePath PackExperimentalExtension() {
299 // We must modify the command line temporarily in order to pack an
300 // extension that requests the experimental permission.
301 ScopedExperimentalCommandLine scope;
302 base::FilePath test_path = test_data_dir_.AppendASCII("experimental");
303 base::FilePath crx_path = PackExtension(test_path);
304 CHECK(!crx_path.empty()) << "Extension not found at " << test_path.value();
305 return crx_path;
306 }
dominickn675536f2015-11-06 03:25:38307
308 void InstallWebAppAndVerifyNoErrors() {
309 ExtensionService* service =
310 extensions::ExtensionSystem::Get(browser()->profile())
311 ->extension_service();
312 scoped_refptr<CrxInstaller> crx_installer(
313 CrxInstaller::CreateSilent(service));
314 crx_installer->set_error_on_unsupported_requirements(true);
315 crx_installer->InstallWebApp(
316 CreateWebAppInfo(kAppTitle, kAppDescription, kAppUrl, 64));
317 EXPECT_TRUE(WaitForCrxInstallerDone());
318 ASSERT_TRUE(crx_installer->extension());
319 ASSERT_FALSE(HasRequirementErrors(crx_installer.get()));
320 ASSERT_FALSE(HasPolicyErrors(crx_installer.get()));
321 }
322
323 bool HasRequirementErrors(CrxInstaller* crx_installer) {
324 return !crx_installer->install_checker_.requirement_errors().empty();
325 }
326
327 bool HasPolicyErrors(CrxInstaller* crx_installer) {
328 return !crx_installer->install_checker_.policy_error().empty();
329 }
[email protected]a01e00632010-11-05 16:58:14330};
331
[email protected]d4b4d7af2014-08-20 10:45:15332// This test is skipped on ChromeOS because it requires the NPAPI,
333// which is not available on that platform.
334#if !defined(OS_CHROMEOS)
335IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Whitelisting) {
[email protected]21a5ad62012-04-03 04:48:45336 std::string id = "hdgllgikmikobbofgnabhfimcfoopgnd";
gpdavis.chromium48f08c42014-09-18 22:09:34337 ExtensionRegistry* registry = ExtensionRegistry::Get(
338 browser()->profile());
[email protected]21a5ad62012-04-03 04:48:45339
340 // Even whitelisted extensions with NPAPI should not prompt.
rdevlin.croninca5bf2da2015-12-17 21:21:08341 scoped_ptr<MockPromptProxy> mock_prompt =
[email protected]f8636f92013-08-09 21:02:37342 CreateMockPromptProxyForBrowser(browser());
rdevlin.croninca5bf2da2015-12-17 21:21:08343 InstallWithPrompt("uitest/plugins", id, mock_prompt.get());
[email protected]b70a2d92012-06-28 19:51:21344 EXPECT_FALSE(mock_prompt->confirmation_requested());
gpdavis.chromium48f08c42014-09-18 22:09:34345 EXPECT_TRUE(registry->enabled_extensions().GetByID(id));
[email protected]a01e00632010-11-05 16:58:14346}
[email protected]d4b4d7af2014-08-20 10:45:15347#endif
[email protected]fc38935a2011-10-31 23:53:28348
349IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
kalmanae342c92014-12-12 22:04:23350 ExperimentalExtensionFromGallery) {
351 // Gallery-installed extensions should have their experimental permission
352 // preserved, since we allow the Webstore to make that decision.
353 base::FilePath crx_path = PackExperimentalExtension();
354 const Extension* extension = InstallExtensionFromWebstore(crx_path, 1);
355 ASSERT_TRUE(extension);
356 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
357 APIPermission::kExperimental));
358}
[email protected]240cc92a2011-12-01 01:22:24359
kalmanae342c92014-12-12 22:04:23360IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
361 ExperimentalExtensionFromOutsideGallery) {
362 // Non-gallery-installed extensions should lose their experimental
363 // permission if the flag isn't enabled.
364 base::FilePath crx_path = PackExperimentalExtension();
365 const Extension* extension = InstallExtension(crx_path, 1);
366 ASSERT_TRUE(extension);
367 EXPECT_FALSE(extension->permissions_data()->HasAPIPermission(
368 APIPermission::kExperimental));
369}
[email protected]240cc92a2011-12-01 01:22:24370
kalmanae342c92014-12-12 22:04:23371IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
372 ExperimentalExtensionFromOutsideGalleryWithFlag) {
373 // Non-gallery-installed extensions should maintain their experimental
374 // permission if the flag is enabled.
375 base::FilePath crx_path = PackExperimentalExtension();
376 ScopedExperimentalCommandLine scope;
377 const Extension* extension = InstallExtension(crx_path, 1);
378 ASSERT_TRUE(extension);
379 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
380 APIPermission::kExperimental));
[email protected]fc38935a2011-10-31 23:53:28381}
[email protected]ee14cad2012-03-29 01:59:37382
383IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, PlatformAppCrx) {
kalmanae342c92014-12-12 22:04:23384 ScopedExperimentalCommandLine scope;
[email protected]ee14cad2012-03-29 01:59:37385 EXPECT_TRUE(InstallExtension(
[email protected]dc37b002012-04-23 23:02:26386 test_data_dir_.AppendASCII("minimal_platform_app.crx"), 1));
[email protected]ee14cad2012-03-29 01:59:37387}
[email protected]bf2fcd52012-04-16 22:59:39388
[email protected]d4b4d7af2014-08-20 10:45:15389IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, PackAndInstallExtension) {
[email protected]544471a2012-10-13 05:27:09390 if (!FeatureSwitch::easy_off_store_install()->IsEnabled())
[email protected]89019d62012-05-17 18:47:09391 return;
392
[email protected]bf2fcd52012-04-16 22:59:39393 const int kNumDownloadsExpected = 1;
[email protected]bf2fcd52012-04-16 22:59:39394
395 LOG(ERROR) << "PackAndInstallExtension: Packing extension";
[email protected]650b2d52013-02-10 03:41:45396 base::FilePath crx_path = PackExtension(
[email protected]bf2fcd52012-04-16 22:59:39397 test_data_dir_.AppendASCII("common/background_page"));
398 ASSERT_FALSE(crx_path.empty());
399 std::string crx_path_string(crx_path.value().begin(), crx_path.value().end());
400 GURL url = GURL(std::string("file:///").append(crx_path_string));
401
rdevlin.croninca5bf2da2015-12-17 21:21:08402 scoped_ptr<MockPromptProxy> mock_prompt =
[email protected]f8636f92013-08-09 21:02:37403 CreateMockPromptProxyForBrowser(browser());
404 download_crx_util::SetMockInstallPromptForTesting(
405 mock_prompt->CreatePrompt());
[email protected]bf2fcd52012-04-16 22:59:39406
407 LOG(ERROR) << "PackAndInstallExtension: Getting download manager";
408 content::DownloadManager* download_manager =
[email protected]b441a8492012-06-06 14:55:57409 content::BrowserContext::GetDownloadManager(browser()->profile());
[email protected]bf2fcd52012-04-16 22:59:39410
411 LOG(ERROR) << "PackAndInstallExtension: Setting observer";
[email protected]49b264f2012-08-14 17:12:26412 scoped_ptr<content::DownloadTestObserver> observer(
413 new content::DownloadTestObserverTerminal(
[email protected]47665442012-07-27 02:31:22414 download_manager, kNumDownloadsExpected,
[email protected]49b264f2012-08-14 17:12:26415 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));
[email protected]bf2fcd52012-04-16 22:59:39416 LOG(ERROR) << "PackAndInstallExtension: Navigating to URL";
417 ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB,
418 ui_test_utils::BROWSER_TEST_NONE);
419
[email protected]8c6af5b2012-06-15 20:10:26420 EXPECT_TRUE(WaitForCrxInstallerDone());
[email protected]bf2fcd52012-04-16 22:59:39421 LOG(ERROR) << "PackAndInstallExtension: Extension install";
[email protected]c82da8c42012-06-08 19:49:11422 EXPECT_TRUE(mock_prompt->confirmation_requested());
[email protected]bf2fcd52012-04-16 22:59:39423 LOG(ERROR) << "PackAndInstallExtension: Extension install confirmed";
424}
[email protected]a9736892012-05-30 15:58:05425
[email protected]b70a2d92012-06-28 19:51:21426// Tests that scopes are only granted if |record_oauth2_grant_| on the prompt is
427// true.
[email protected]7a561912012-08-21 21:06:05428#if defined(OS_WIN)
[email protected]1e09ec82012-12-21 22:48:09429#define MAYBE_GrantScopes DISABLED_GrantScopes
[email protected]7a561912012-08-21 21:06:05430#else
431#define MAYBE_GrantScopes GrantScopes
432#endif
433IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, MAYBE_GrantScopes) {
[email protected]b70a2d92012-06-28 19:51:21434 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
435 true));
436}
437
438IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, DoNotGrantScopes) {
439 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
440 false));
441}
442
[email protected]d4b4d7af2014-08-20 10:45:15443IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, AllowOffStore) {
[email protected]06bdd2b2012-11-30 18:47:13444 ExtensionService* service = extensions::ExtensionSystem::Get(
445 browser()->profile())->extension_service();
[email protected]a9736892012-05-30 15:58:05446 const bool kTestData[] = {false, true};
447
448 for (size_t i = 0; i < arraysize(kTestData); ++i) {
rdevlin.croninca5bf2da2015-12-17 21:21:08449 scoped_ptr<MockPromptProxy> mock_prompt =
[email protected]f8636f92013-08-09 21:02:37450 CreateMockPromptProxyForBrowser(browser());
451
[email protected]a9736892012-05-30 15:58:05452 scoped_refptr<CrxInstaller> crx_installer(
[email protected]f8636f92013-08-09 21:02:37453 CrxInstaller::Create(service, mock_prompt->CreatePrompt()));
[email protected]7224dbd2012-06-05 15:21:50454 crx_installer->set_install_cause(
455 extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
[email protected]d9039812012-06-09 06:05:48456
457 if (kTestData[i]) {
458 crx_installer->set_off_store_install_allow_reason(
459 CrxInstaller::OffStoreInstallAllowedInTest);
460 }
[email protected]a9736892012-05-30 15:58:05461
462 crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx"));
[email protected]d4b4d7af2014-08-20 10:45:15463 // The |mock_prompt| will quit running the loop once the |crx_installer|
464 // is done.
465 content::RunMessageLoop();
[email protected]c82da8c42012-06-08 19:49:11466 EXPECT_EQ(kTestData[i], mock_prompt->did_succeed());
467 EXPECT_EQ(kTestData[i], mock_prompt->confirmation_requested()) <<
468 kTestData[i];
[email protected]a9736892012-05-30 15:58:05469 if (kTestData[i]) {
[email protected]b959d7d42013-12-13 17:26:37470 EXPECT_EQ(base::string16(), mock_prompt->error()) << kTestData[i];
[email protected]a9736892012-05-30 15:58:05471 } else {
472 EXPECT_EQ(l10n_util::GetStringUTF16(
473 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE),
[email protected]c82da8c42012-06-08 19:49:11474 mock_prompt->error()) << kTestData[i];
[email protected]a9736892012-05-30 15:58:05475 }
476 }
[email protected]a9736892012-05-30 15:58:05477}
[email protected]bf3d9df2012-07-24 23:20:27478
[email protected]90d3c042013-06-06 10:10:39479IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, HiDpiThemeTest) {
480 base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx");
481 crx_path = crx_path.AppendASCII("theme_hidpi.crx");
482
[email protected]658eae52014-06-14 20:28:05483 ASSERT_TRUE(InstallExtension(crx_path, 1));
[email protected]90d3c042013-06-06 10:10:39484
485 const std::string extension_id("gllekhaobjnhgeagipipnkpmmmpchacm");
gpdavis.chromium48f08c42014-09-18 22:09:34486 ExtensionRegistry* registry = ExtensionRegistry::Get(
487 browser()->profile());
[email protected]90d3c042013-06-06 10:10:39488 const extensions::Extension* extension =
gpdavis.chromium48f08c42014-09-18 22:09:34489 registry->enabled_extensions().GetByID(extension_id);
[email protected]90d3c042013-06-06 10:10:39490 ASSERT_TRUE(extension);
491 EXPECT_EQ(extension_id, extension->id());
492
493 UninstallExtension(extension_id);
gpdavis.chromium48f08c42014-09-18 22:09:34494 EXPECT_FALSE(registry->enabled_extensions().GetByID(extension_id));
[email protected]90d3c042013-06-06 10:10:39495}
496
[email protected]9e9c1d12013-07-31 01:58:12497IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
mekc95f9d062015-01-10 00:52:04498 InstallDelayedUntilNextUpdate) {
[email protected]9e9c1d12013-07-31 01:58:12499 const std::string extension_id("ldnnhddmnhbkjipkidpdiheffobcpfmf");
mekc95f9d062015-01-10 00:52:04500 base::FilePath base_path = test_data_dir_.AppendASCII("delayed_install");
501
[email protected]9e9c1d12013-07-31 01:58:12502 ExtensionSystem* extension_system = extensions::ExtensionSystem::Get(
503 browser()->profile());
504 ExtensionService* service = extension_system->extension_service();
505 ASSERT_TRUE(service);
gpdavis.chromium48f08c42014-09-18 22:09:34506 ExtensionRegistry* registry = ExtensionRegistry::Get(
507 browser()->profile());
508 ASSERT_TRUE(registry);
[email protected]9e9c1d12013-07-31 01:58:12509
510 // Install version 1 of the test extension. This extension does not have
511 // a background page but does have a browser action.
mekc95f9d062015-01-10 00:52:04512 base::FilePath v1_path = PackExtension(base_path.AppendASCII("v1"));
513 ASSERT_FALSE(v1_path.empty());
514 ASSERT_TRUE(InstallExtension(v1_path, 1));
[email protected]9e9c1d12013-07-31 01:58:12515 const extensions::Extension* extension =
gpdavis.chromium48f08c42014-09-18 22:09:34516 registry->enabled_extensions().GetByID(extension_id);
[email protected]9e9c1d12013-07-31 01:58:12517 ASSERT_TRUE(extension);
518 ASSERT_EQ(extension_id, extension->id());
519 ASSERT_EQ("1.0", extension->version()->GetString());
520
mekc95f9d062015-01-10 00:52:04521 // Make test extension non-idle by opening the extension's options page.
522 ExtensionTabUtil::OpenOptionsPage(extension, browser());
523 WaitForExtensionNotIdle(extension_id);
[email protected]9e9c1d12013-07-31 01:58:12524
525 // Install version 2 of the extension and check that it is indeed delayed.
mekc95f9d062015-01-10 00:52:04526 base::FilePath v2_path = PackExtension(base_path.AppendASCII("v2"));
527 ASSERT_FALSE(v2_path.empty());
528 ASSERT_TRUE(UpdateExtensionWaitForIdle(extension_id, v2_path, 0));
[email protected]9e9c1d12013-07-31 01:58:12529
530 ASSERT_EQ(1u, service->delayed_installs()->size());
gpdavis.chromium48f08c42014-09-18 22:09:34531 extension = registry->enabled_extensions().GetByID(extension_id);
[email protected]9e9c1d12013-07-31 01:58:12532 ASSERT_EQ("1.0", extension->version()->GetString());
533
mekc95f9d062015-01-10 00:52:04534 // Make the extension idle again by navigating away from the options page.
535 // This should not trigger the delayed install.
536 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
537 WaitForExtensionIdle(extension_id);
[email protected]9e9c1d12013-07-31 01:58:12538 ASSERT_EQ(1u, service->delayed_installs()->size());
mekc95f9d062015-01-10 00:52:04539 extension = registry->enabled_extensions().GetByID(extension_id);
540 ASSERT_EQ("1.0", extension->version()->GetString());
[email protected]9e9c1d12013-07-31 01:58:12541
542 // Install version 3 of the extension. Because the extension is idle,
543 // this install should succeed.
mekc95f9d062015-01-10 00:52:04544 base::FilePath v3_path = PackExtension(base_path.AppendASCII("v3"));
545 ASSERT_FALSE(v3_path.empty());
546 ASSERT_TRUE(UpdateExtensionWaitForIdle(extension_id, v3_path, 0));
gpdavis.chromium48f08c42014-09-18 22:09:34547 extension = registry->enabled_extensions().GetByID(extension_id);
[email protected]9e9c1d12013-07-31 01:58:12548 ASSERT_EQ("3.0", extension->version()->GetString());
549
550 // The version 2 delayed install should be cleaned up, and finishing
551 // delayed extension installation shouldn't break anything.
552 ASSERT_EQ(0u, service->delayed_installs()->size());
553 service->MaybeFinishDelayedInstallations();
gpdavis.chromium48f08c42014-09-18 22:09:34554 extension = registry->enabled_extensions().GetByID(extension_id);
[email protected]9e9c1d12013-07-31 01:58:12555 ASSERT_EQ("3.0", extension->version()->GetString());
556}
557
[email protected]e3767aa2013-11-08 23:49:07558#if defined(FULL_SAFE_BROWSING)
[email protected]9f3c8532013-07-31 19:52:07559IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Blacklist) {
[email protected]3f2a2fa2013-09-24 02:55:25560 scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
561 new FakeSafeBrowsingDatabaseManager(true));
562 Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
[email protected]9f3c8532013-07-31 19:52:07563
[email protected]3f2a2fa2013-09-24 02:55:25564 blacklist_db->SetUnsafe("gllekhaobjnhgeagipipnkpmmmpchacm");
[email protected]9f3c8532013-07-31 19:52:07565
566 base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx")
567 .AppendASCII("theme_hidpi.crx");
568 EXPECT_FALSE(InstallExtension(crx_path, 0));
569}
[email protected]e3767aa2013-11-08 23:49:07570#endif
[email protected]9f3c8532013-07-31 19:52:07571
[email protected]85290822013-08-23 20:27:38572IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, NonStrictManifestCheck) {
rdevlin.croninca5bf2da2015-12-17 21:21:08573 scoped_ptr<MockPromptProxy> mock_prompt =
[email protected]85290822013-08-23 20:27:38574 CreateMockPromptProxyForBrowser(browser());
575
576 // We want to simulate the case where the webstore sends a more recent
577 // version of the manifest, but the downloaded .crx file is old since
578 // the newly published version hasn't fully propagated to all the download
579 // servers yet. So load the v2 manifest, but then install the v1 crx file.
580 std::string id = "lhnaeclnpobnlbjbgogdanmhadigfnjp";
581 scoped_ptr<WebstoreInstaller::Approval> approval =
582 GetApproval("crx_installer/v2_no_permission_change/", id, false);
583
584 RunCrxInstaller(approval.get(), mock_prompt->CreatePrompt(),
585 test_data_dir_.AppendASCII("crx_installer/v1.crx"));
586
587 EXPECT_TRUE(mock_prompt->did_succeed());
588}
589
limasdfebff7fd02015-12-25 14:45:31590#if defined(OS_CHROMEOS)
[email protected]14a18bf2013-09-26 08:42:30591IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, KioskOnlyTest) {
limasdfebff7fd02015-12-25 14:45:31592 // kiosk_only is whitelisted from non-chromeos.
[email protected]14a18bf2013-09-26 08:42:30593 base::FilePath crx_path =
594 test_data_dir_.AppendASCII("kiosk/kiosk_only.crx");
595 EXPECT_FALSE(InstallExtension(crx_path, 0));
[email protected]14a18bf2013-09-26 08:42:30596 // Simulate ChromeOS kiosk mode. |scoped_user_manager| will take over
597 // lifetime of |user_manager|.
merkulova793f3022015-02-04 10:18:30598 chromeos::FakeChromeUserManager* fake_user_manager =
599 new chromeos::FakeChromeUserManager();
alemate3ffbde6f2015-11-03 02:02:55600 const AccountId account_id(AccountId::FromUserEmail("[email protected]"));
601 fake_user_manager->AddKioskAppUser(account_id);
602 fake_user_manager->LoginUser(account_id);
[email protected]14a18bf2013-09-26 08:42:30603 chromeos::ScopedUserManagerEnabler scoped_user_manager(fake_user_manager);
604 EXPECT_TRUE(InstallExtension(crx_path, 1));
[email protected]14a18bf2013-09-26 08:42:30605}
606
dpolukhincbd48d192015-06-04 14:09:37607IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, InstallToSharedLocation) {
avi3ef9ec9e2014-12-22 22:50:17608 base::CommandLine::ForCurrentProcess()->AppendSwitch(
[email protected]5a145e82014-05-29 22:19:07609 chromeos::switches::kEnableExtensionAssetsSharing);
610 base::ScopedTempDir cache_dir;
611 ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
612 ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(
613 cache_dir.path());
614
615 base::FilePath crx_path = test_data_dir_.AppendASCII("crx_installer/v1.crx");
616 const extensions::Extension* extension = InstallExtension(
617 crx_path, 1, extensions::Manifest::EXTERNAL_PREF);
618 base::FilePath extension_path = extension->path();
619 EXPECT_TRUE(cache_dir.path().IsParent(extension_path));
620 EXPECT_TRUE(base::PathExists(extension_path));
621
622 std::string extension_id = extension->id();
623 UninstallExtension(extension_id);
gpdavis.chromium48f08c42014-09-18 22:09:34624 ExtensionRegistry* registry = ExtensionRegistry::Get(
625 browser()->profile());
626 EXPECT_FALSE(registry->enabled_extensions().GetByID(extension_id));
[email protected]5a145e82014-05-29 22:19:07627
mtomaszf7d99a5c2014-09-15 16:23:46628 content::RunAllBlockingPoolTasksUntilIdle();
[email protected]5a145e82014-05-29 22:19:07629
630 EXPECT_FALSE(base::PathExists(extension_path));
631}
632#endif
633
[email protected]658eae52014-06-14 20:28:05634IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, DoNotSync) {
635 ExtensionService* service = extensions::ExtensionSystem::Get(
636 browser()->profile())->extension_service();
637 scoped_refptr<CrxInstaller> crx_installer(
638 CrxInstaller::CreateSilent(service));
[email protected]c30bda262014-06-19 04:10:13639 crx_installer->set_do_not_sync(true);
[email protected]658eae52014-06-14 20:28:05640 crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx"));
641 EXPECT_TRUE(WaitForCrxInstallerDone());
642 ASSERT_TRUE(crx_installer->extension());
643
644 const ExtensionPrefs* extension_prefs =
645 ExtensionPrefs::Get(browser()->profile());
646 EXPECT_TRUE(extension_prefs->DoNotSync(crx_installer->extension()->id()));
treibc644a1c2015-07-13 08:37:04647 EXPECT_FALSE(extensions::util::ShouldSync(crx_installer->extension(),
648 browser()->profile()));
[email protected]658eae52014-06-14 20:28:05649}
650
[email protected]253fc2bb2014-07-10 04:21:18651IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, ManagementPolicy) {
652 ManagementPolicyMock policy;
653 extensions::ExtensionSystem::Get(profile())
654 ->management_policy()
655 ->RegisterProvider(&policy);
656
657 base::FilePath crx_path = test_data_dir_.AppendASCII("crx_installer/v1.crx");
658 EXPECT_FALSE(InstallExtension(crx_path, 0));
659}
660
dominickn675536f2015-11-06 03:25:38661IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, InstallWebApp) {
662 InstallWebAppAndVerifyNoErrors();
663}
664
665IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
666 InstallWebAppSucceedsWithBlockPolicy) {
667 // Verify that the install still works when a management policy blocking
668 // extension installation is in force. Bookmark apps are special-cased to skip
669 // these checks (see https://crbug.com/545541).
670 ManagementPolicyMock policy;
671 extensions::ExtensionSystem::Get(profile())
672 ->management_policy()
673 ->RegisterProvider(&policy);
674
675 InstallWebAppAndVerifyNoErrors();
676}
677
[email protected]bf3d9df2012-07-24 23:20:27678} // namespace extensions