[email protected] | 098fa7a | 2013-03-08 22:11:17 | [diff] [blame] | 1 | // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 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 "chrome/browser/extensions/unpacked_installer.h" |
| 6 | |
| 7 | #include "base/bind.h" |
| 8 | #include "base/callback.h" |
thestig | 18dfb7a5 | 2014-08-26 10:44:04 | [diff] [blame] | 9 | #include "base/files/file_util.h" |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 10 | #include "base/memory/ptr_util.h" |
michaelpg | a8ea037 | 2017-04-06 20:41:35 | [diff] [blame] | 11 | #include "base/strings/string16.h" |
[email protected] | 46acbf1 | 2013-06-10 18:43:42 | [diff] [blame] | 12 | #include "base/strings/string_util.h" |
michaelpg | a8ea037 | 2017-04-06 20:41:35 | [diff] [blame] | 13 | #include "base/strings/utf_string_conversions.h" |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame^] | 14 | #include "base/task_scheduler/post_task.h" |
[email protected] | bebe1d0 | 2012-08-02 20:17:09 | [diff] [blame] | 15 | #include "base/threading/thread_restrictions.h" |
[email protected] | 1f072244 | 2014-05-01 17:26:02 | [diff] [blame] | 16 | #include "chrome/browser/extensions/extension_error_reporter.h" |
[email protected] | c82da8c4 | 2012-06-08 19:49:11 | [diff] [blame] | 17 | #include "chrome/browser/extensions/extension_install_prompt.h" |
binjin | 1569c9b | 2014-09-05 13:33:18 | [diff] [blame] | 18 | #include "chrome/browser/extensions/extension_management.h" |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 19 | #include "chrome/browser/extensions/extension_service.h" |
[email protected] | 0d90431 | 2012-01-25 23:00:16 | [diff] [blame] | 20 | #include "chrome/browser/extensions/permissions_updater.h" |
[email protected] | 284ffac | 2014-02-12 01:08:58 | [diff] [blame] | 21 | #include "chrome/browser/profiles/profile.h" |
pkotwicz | a57a1f32 | 2014-10-21 00:24:30 | [diff] [blame] | 22 | #include "chrome/browser/ui/extensions/extension_install_ui_factory.h" |
[email protected] | fdd2837 | 2014-08-21 02:27:26 | [diff] [blame] | 23 | #include "components/crx_file/id_util.h" |
skym | 7160384 | 2016-10-10 18:17:31 | [diff] [blame] | 24 | #include "components/sync/model/string_ordinal.h" |
[email protected] | 79a6064 | 2012-10-20 21:03:18 | [diff] [blame] | 25 | #include "content/public/browser/browser_thread.h" |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame^] | 26 | #include "extensions/browser/extension_file_task_runner.h" |
[email protected] | 489db084 | 2014-01-22 18:20:03 | [diff] [blame] | 27 | #include "extensions/browser/extension_prefs.h" |
[email protected] | 284ffac | 2014-02-12 01:08:58 | [diff] [blame] | 28 | #include "extensions/browser/extension_registry.h" |
pkotwicz | a57a1f32 | 2014-10-21 00:24:30 | [diff] [blame] | 29 | #include "extensions/browser/install/extension_install_ui.h" |
[email protected] | 4a1d9c0d | 2014-06-13 12:50:11 | [diff] [blame] | 30 | #include "extensions/browser/install_flag.h" |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 31 | #include "extensions/browser/policy_check.h" |
| 32 | #include "extensions/browser/preload_check_group.h" |
| 33 | #include "extensions/browser/requirements_checker.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 34 | #include "extensions/common/extension.h" |
[email protected] | 6668e5d | 2014-04-08 23:32:52 | [diff] [blame] | 35 | #include "extensions/common/extension_l10n_util.h" |
[email protected] | 85df9d1 | 2014-04-15 17:02:14 | [diff] [blame] | 36 | #include "extensions/common/file_util.h" |
[email protected] | d42c1115 | 2013-08-22 19:36:32 | [diff] [blame] | 37 | #include "extensions/common/manifest.h" |
michaelpg | a8ea037 | 2017-04-06 20:41:35 | [diff] [blame] | 38 | #include "extensions/common/manifest_handlers/plugins_handler.h" |
elijahtaylor | e343b54 | 2014-10-03 19:48:19 | [diff] [blame] | 39 | #include "extensions/common/manifest_handlers/shared_module_info.h" |
rdevlin.cronin | e2d0fd0 | 2015-09-24 22:35:49 | [diff] [blame] | 40 | #include "extensions/common/permissions/permissions_data.h" |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 41 | |
[email protected] | 545ab7a | 2011-11-03 14:54:21 | [diff] [blame] | 42 | using content::BrowserThread; |
[email protected] | 1c321ee | 2012-05-21 03:02:34 | [diff] [blame] | 43 | using extensions::Extension; |
elijahtaylor | e343b54 | 2014-10-03 19:48:19 | [diff] [blame] | 44 | using extensions::SharedModuleInfo; |
[email protected] | 545ab7a | 2011-11-03 14:54:21 | [diff] [blame] | 45 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 46 | namespace { |
| 47 | |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 48 | const char kUnpackedExtensionsBlacklistedError[] = |
| 49 | "Loading of unpacked extensions is disabled by the administrator."; |
| 50 | |
elijahtaylor | c93f7547 | 2014-10-15 18:42:25 | [diff] [blame] | 51 | const char kImportMinVersionNewer[] = |
| 52 | "'import' version requested is newer than what is installed."; |
| 53 | const char kImportMissing[] = "'import' extension is not installed."; |
| 54 | const char kImportNotSharedModule[] = "'import' is not a shared module."; |
| 55 | |
[email protected] | c82da8c4 | 2012-06-08 19:49:11 | [diff] [blame] | 56 | // Manages an ExtensionInstallPrompt for a particular extension. |
rdevlin.cronin | 4159305 | 2016-01-08 01:40:12 | [diff] [blame] | 57 | class SimpleExtensionLoadPrompt { |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 58 | public: |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 59 | SimpleExtensionLoadPrompt(const Extension* extension, |
| 60 | Profile* profile, |
| 61 | const base::Closure& callback); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 62 | |
| 63 | void ShowPrompt(); |
| 64 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 65 | private: |
rdevlin.cronin | 4159305 | 2016-01-08 01:40:12 | [diff] [blame] | 66 | ~SimpleExtensionLoadPrompt(); // Manages its own lifetime. |
| 67 | |
| 68 | void OnInstallPromptDone(ExtensionInstallPrompt::Result result); |
| 69 | |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 70 | std::unique_ptr<ExtensionInstallPrompt> install_ui_; |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 71 | scoped_refptr<const Extension> extension_; |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 72 | base::Closure callback_; |
rdevlin.cronin | 4159305 | 2016-01-08 01:40:12 | [diff] [blame] | 73 | |
| 74 | DISALLOW_COPY_AND_ASSIGN(SimpleExtensionLoadPrompt); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 75 | }; |
| 76 | |
| 77 | SimpleExtensionLoadPrompt::SimpleExtensionLoadPrompt( |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 78 | const Extension* extension, |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 79 | Profile* profile, |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 80 | const base::Closure& callback) |
pkotwicz | a57a1f32 | 2014-10-21 00:24:30 | [diff] [blame] | 81 | : extension_(extension), callback_(callback) { |
dcheng | c963c714 | 2016-04-08 03:55:22 | [diff] [blame] | 82 | std::unique_ptr<extensions::ExtensionInstallUI> ui( |
pkotwicz | a57a1f32 | 2014-10-21 00:24:30 | [diff] [blame] | 83 | extensions::CreateExtensionInstallUI(profile)); |
| 84 | install_ui_.reset(new ExtensionInstallPrompt( |
pkotwicz | 2175c62 | 2014-10-22 19:56:28 | [diff] [blame] | 85 | profile, ui->GetDefaultInstallDialogParent())); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | SimpleExtensionLoadPrompt::~SimpleExtensionLoadPrompt() { |
| 89 | } |
| 90 | |
| 91 | void SimpleExtensionLoadPrompt::ShowPrompt() { |
rdevlin.cronin | be6e8cf | 2016-02-08 19:28:06 | [diff] [blame] | 92 | // Unretained() is safe because this object manages its own lifetime. |
| 93 | install_ui_->ShowDialog( |
| 94 | base::Bind(&SimpleExtensionLoadPrompt::OnInstallPromptDone, |
| 95 | base::Unretained(this)), |
| 96 | extension_.get(), nullptr, |
| 97 | ExtensionInstallPrompt::GetDefaultShowDialogCallback()); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 98 | } |
| 99 | |
rdevlin.cronin | 4159305 | 2016-01-08 01:40:12 | [diff] [blame] | 100 | void SimpleExtensionLoadPrompt::OnInstallPromptDone( |
| 101 | ExtensionInstallPrompt::Result result) { |
| 102 | if (result == ExtensionInstallPrompt::Result::ACCEPTED) |
| 103 | callback_.Run(); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 104 | delete this; |
| 105 | } |
| 106 | |
| 107 | } // namespace |
| 108 | |
| 109 | namespace extensions { |
| 110 | |
| 111 | // static |
| 112 | scoped_refptr<UnpackedInstaller> UnpackedInstaller::Create( |
| 113 | ExtensionService* extension_service) { |
[email protected] | 3a7fbc24 | 2013-12-19 17:43:37 | [diff] [blame] | 114 | DCHECK(extension_service); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 115 | return scoped_refptr<UnpackedInstaller>( |
| 116 | new UnpackedInstaller(extension_service)); |
| 117 | } |
| 118 | |
| 119 | UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service) |
| 120 | : service_weak_(extension_service->AsWeakPtr()), |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 121 | profile_(extension_service->profile()), |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 122 | prompt_for_plugins_(true), |
[email protected] | 9d02fa1 | 2013-02-19 05:12:57 | [diff] [blame] | 123 | require_modern_manifest_version_(true), |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 124 | be_noisy_on_failure_(true) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 125 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | UnpackedInstaller::~UnpackedInstaller() { |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 129 | } |
| 130 | |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 131 | void UnpackedInstaller::Load(const base::FilePath& path_in) { |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 132 | DCHECK(extension_path_.empty()); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 133 | extension_path_ = path_in; |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame^] | 134 | GetExtensionFileTaskRunner()->PostTask( |
| 135 | FROM_HERE, base::BindOnce(&UnpackedInstaller::GetAbsolutePath, this)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 136 | } |
| 137 | |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 138 | bool UnpackedInstaller::LoadFromCommandLine(const base::FilePath& path_in, |
proberge | 80a37f3 | 2016-08-04 19:44:55 | [diff] [blame] | 139 | std::string* extension_id, |
| 140 | bool only_allow_apps) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 141 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 142 | DCHECK(extension_path_.empty()); |
| 143 | |
[email protected] | e8dad9b | 2013-06-04 04:43:45 | [diff] [blame] | 144 | if (!service_weak_.get()) |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 145 | return false; |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 146 | // Load extensions from the command line synchronously to avoid a race |
| 147 | // between extension loading and loading an URL from the command line. |
| 148 | base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 149 | |
[email protected] | 1547693 | 2013-04-12 05:17:15 | [diff] [blame] | 150 | extension_path_ = base::MakeAbsoluteFilePath(path_in); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 151 | |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 152 | if (!IsLoadingUnpackedAllowed()) { |
| 153 | ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError); |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 154 | return false; |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 155 | } |
| 156 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 157 | std::string error; |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 158 | extension_ = file_util::LoadExtension(extension_path_, Manifest::COMMAND_LINE, |
| 159 | GetFlags(), &error); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 160 | |
proberge | ac2a4b6 | 2016-08-29 16:16:09 | [diff] [blame] | 161 | if (!extension() || |
| 162 | !extension_l10n_util::ValidateExtensionLocales( |
| 163 | extension_path_, extension()->manifest()->value(), &error)) { |
| 164 | ReportExtensionLoadError(error); |
| 165 | return false; |
| 166 | } |
| 167 | |
proberge | 80a37f3 | 2016-08-04 19:44:55 | [diff] [blame] | 168 | if (only_allow_apps && !extension()->is_platform_app()) { |
| 169 | #if defined(GOOGLE_CHROME_BUILD) |
| 170 | // Avoid crashing for users with hijacked shortcuts. |
| 171 | return true; |
| 172 | #else |
| 173 | // Defined here to avoid unused variable errors in official builds. |
| 174 | const char extension_instead_of_app_error[] = |
| 175 | "App loading flags cannot be used to load extensions. Please use " |
| 176 | "--load-extension instead."; |
| 177 | ReportExtensionLoadError(extension_instead_of_app_error); |
| 178 | return false; |
| 179 | #endif |
| 180 | } |
| 181 | |
rdevlin.cronin | e2d0fd0 | 2015-09-24 22:35:49 | [diff] [blame] | 182 | extension()->permissions_data()->BindToCurrentThread(); |
rdevlin.cronin | f173cbc4 | 2014-09-24 18:03:32 | [diff] [blame] | 183 | PermissionsUpdater( |
| 184 | service_weak_->profile(), PermissionsUpdater::INIT_FLAG_TRANSIENT) |
| 185 | .InitializePermissions(extension()); |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 186 | ShowInstallPrompt(); |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 187 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 188 | *extension_id = extension()->id(); |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 189 | return true; |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 190 | } |
| 191 | |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 192 | void UnpackedInstaller::ShowInstallPrompt() { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 193 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | e8dad9b | 2013-06-04 04:43:45 | [diff] [blame] | 194 | if (!service_weak_.get()) |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 195 | return; |
| 196 | |
[email protected] | 284ffac | 2014-02-12 01:08:58 | [diff] [blame] | 197 | const ExtensionSet& disabled_extensions = |
| 198 | ExtensionRegistry::Get(service_weak_->profile())->disabled_extensions(); |
rdevlin.cronin | 726ab49 | 2017-01-30 21:36:07 | [diff] [blame] | 199 | if (prompt_for_plugins_ && |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 200 | PluginInfo::HasPlugins(extension()) && |
| 201 | !disabled_extensions.Contains(extension()->id())) { |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 202 | SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt( |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 203 | extension(), profile_, |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 204 | base::Bind(&UnpackedInstaller::StartInstallChecks, this)); |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 205 | prompt->ShowPrompt(); |
| 206 | return; |
| 207 | } |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 208 | StartInstallChecks(); |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 209 | } |
| 210 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 211 | void UnpackedInstaller::StartInstallChecks() { |
elijahtaylor | c93f7547 | 2014-10-15 18:42:25 | [diff] [blame] | 212 | // TODO(crbug.com/421128): Enable these checks all the time. The reason |
| 213 | // they are disabled for extensions loaded from the command-line is that |
| 214 | // installing unpacked extensions is asynchronous, but there can be |
| 215 | // dependencies between the extensions loaded by the command line. |
| 216 | if (extension()->manifest()->location() != Manifest::COMMAND_LINE) { |
| 217 | ExtensionService* service = service_weak_.get(); |
| 218 | if (!service || service->browser_terminating()) |
| 219 | return; |
| 220 | |
| 221 | // TODO(crbug.com/420147): Move this code to a utility class to avoid |
| 222 | // duplication of SharedModuleService::CheckImports code. |
| 223 | if (SharedModuleInfo::ImportsModules(extension())) { |
| 224 | const std::vector<SharedModuleInfo::ImportInfo>& imports = |
| 225 | SharedModuleInfo::GetImports(extension()); |
| 226 | std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; |
| 227 | for (i = imports.begin(); i != imports.end(); ++i) { |
pwnall | cbd7319 | 2016-08-22 18:59:17 | [diff] [blame] | 228 | base::Version version_required(i->minimum_version); |
elijahtaylor | c93f7547 | 2014-10-15 18:42:25 | [diff] [blame] | 229 | const Extension* imported_module = |
| 230 | service->GetExtensionById(i->extension_id, true); |
| 231 | if (!imported_module) { |
| 232 | ReportExtensionLoadError(kImportMissing); |
| 233 | return; |
| 234 | } else if (imported_module && |
| 235 | !SharedModuleInfo::IsSharedModule(imported_module)) { |
| 236 | ReportExtensionLoadError(kImportNotSharedModule); |
| 237 | return; |
| 238 | } else if (imported_module && (version_required.IsValid() && |
| 239 | imported_module->version()->CompareTo( |
| 240 | version_required) < 0)) { |
| 241 | ReportExtensionLoadError(kImportMinVersionNewer); |
| 242 | return; |
| 243 | } |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 248 | policy_check_ = base::MakeUnique<PolicyCheck>(profile_, extension_); |
| 249 | requirements_check_ = base::MakeUnique<RequirementsChecker>(extension_); |
| 250 | |
| 251 | check_group_ = base::MakeUnique<PreloadCheckGroup>(); |
| 252 | check_group_->set_stop_on_first_error(true); |
| 253 | |
| 254 | check_group_->AddCheck(policy_check_.get()); |
| 255 | check_group_->AddCheck(requirements_check_.get()); |
| 256 | check_group_->Start( |
| 257 | base::BindOnce(&UnpackedInstaller::OnInstallChecksComplete, this)); |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 258 | } |
| 259 | |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 260 | void UnpackedInstaller::OnInstallChecksComplete(PreloadCheck::Errors errors) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 261 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 262 | |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 263 | if (errors.empty()) { |
| 264 | InstallExtension(); |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 265 | return; |
| 266 | } |
| 267 | |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 268 | base::string16 error_message; |
| 269 | if (errors.count(PreloadCheck::DISALLOWED_BY_POLICY)) |
| 270 | error_message = policy_check_->GetErrorMessage(); |
| 271 | else |
| 272 | error_message = requirements_check_->GetErrorMessage(); |
| 273 | |
| 274 | DCHECK(!error_message.empty()); |
| 275 | ReportExtensionLoadError(base::UTF16ToUTF8(error_message)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 276 | } |
| 277 | |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 278 | int UnpackedInstaller::GetFlags() { |
[email protected] | fdd2837 | 2014-08-21 02:27:26 | [diff] [blame] | 279 | std::string id = crx_file::id_util::GenerateIdForPath(extension_path_); |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 280 | bool allow_file_access = |
[email protected] | 12075d1 | 2013-02-27 05:38:05 | [diff] [blame] | 281 | Manifest::ShouldAlwaysAllowFileAccess(Manifest::UNPACKED); |
[email protected] | 7c82539c | 2014-02-19 06:09:17 | [diff] [blame] | 282 | ExtensionPrefs* prefs = ExtensionPrefs::Get(service_weak_->profile()); |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 283 | if (prefs->HasAllowFileAccessSetting(id)) |
| 284 | allow_file_access = prefs->AllowFileAccess(id); |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 285 | |
| 286 | int result = Extension::FOLLOW_SYMLINKS_ANYWHERE; |
| 287 | if (allow_file_access) |
| 288 | result |= Extension::ALLOW_FILE_ACCESS; |
| 289 | if (require_modern_manifest_version_) |
| 290 | result |= Extension::REQUIRE_MODERN_MANIFEST_VERSION; |
| 291 | |
| 292 | return result; |
| 293 | } |
| 294 | |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 295 | bool UnpackedInstaller::IsLoadingUnpackedAllowed() const { |
[email protected] | e8dad9b | 2013-06-04 04:43:45 | [diff] [blame] | 296 | if (!service_weak_.get()) |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 297 | return true; |
| 298 | // If there is a "*" in the extension blacklist, then no extensions should be |
| 299 | // allowed at all (except explicitly whitelisted extensions). |
binjin | 1569c9b | 2014-09-05 13:33:18 | [diff] [blame] | 300 | return !ExtensionManagementFactory::GetForBrowserContext( |
| 301 | service_weak_->profile())->BlacklistedByDefault(); |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 302 | } |
| 303 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 304 | void UnpackedInstaller::GetAbsolutePath() { |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame^] | 305 | base::ThreadRestrictions::AssertIOAllowed(); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 306 | |
[email protected] | 1547693 | 2013-04-12 05:17:15 | [diff] [blame] | 307 | extension_path_ = base::MakeAbsoluteFilePath(extension_path_); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 308 | |
[email protected] | 5ccca8ad | 2013-08-19 22:35:34 | [diff] [blame] | 309 | std::string error; |
[email protected] | 85df9d1 | 2014-04-15 17:02:14 | [diff] [blame] | 310 | if (!file_util::CheckForIllegalFilenames(extension_path_, &error)) { |
[email protected] | 5ccca8ad | 2013-08-19 22:35:34 | [diff] [blame] | 311 | BrowserThread::PostTask( |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 312 | BrowserThread::UI, FROM_HERE, |
| 313 | base::BindOnce(&UnpackedInstaller::ReportExtensionLoadError, this, |
| 314 | error)); |
[email protected] | 5ccca8ad | 2013-08-19 22:35:34 | [diff] [blame] | 315 | return; |
| 316 | } |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 317 | BrowserThread::PostTask( |
| 318 | BrowserThread::UI, FROM_HERE, |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 319 | base::BindOnce(&UnpackedInstaller::CheckExtensionFileAccess, this)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | void UnpackedInstaller::CheckExtensionFileAccess() { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 323 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | e8dad9b | 2013-06-04 04:43:45 | [diff] [blame] | 324 | if (!service_weak_.get()) |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 325 | return; |
| 326 | |
| 327 | if (!IsLoadingUnpackedAllowed()) { |
| 328 | ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError); |
| 329 | return; |
| 330 | } |
| 331 | |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame^] | 332 | GetExtensionFileTaskRunner()->PostTask( |
| 333 | FROM_HERE, |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 334 | base::BindOnce(&UnpackedInstaller::LoadWithFileAccess, this, GetFlags())); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 335 | } |
| 336 | |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 337 | void UnpackedInstaller::LoadWithFileAccess(int flags) { |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame^] | 338 | base::ThreadRestrictions::AssertIOAllowed(); |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 339 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 340 | std::string error; |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 341 | extension_ = file_util::LoadExtension(extension_path_, Manifest::UNPACKED, |
| 342 | flags, &error); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 343 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 344 | if (!extension() || |
[email protected] | 557c7bd | 2013-09-18 21:51:25 | [diff] [blame] | 345 | !extension_l10n_util::ValidateExtensionLocales( |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 346 | extension_path_, extension()->manifest()->value(), &error)) { |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 347 | BrowserThread::PostTask( |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 348 | BrowserThread::UI, FROM_HERE, |
| 349 | base::BindOnce(&UnpackedInstaller::ReportExtensionLoadError, this, |
| 350 | error)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 351 | return; |
| 352 | } |
| 353 | |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 354 | BrowserThread::PostTask( |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 355 | BrowserThread::UI, FROM_HERE, |
| 356 | base::BindOnce(&UnpackedInstaller::ShowInstallPrompt, this)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 357 | } |
| 358 | |
| 359 | void UnpackedInstaller::ReportExtensionLoadError(const std::string &error) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 360 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 500c7bb | 2014-04-26 22:44:33 | [diff] [blame] | 361 | |
[email protected] | 1f072244 | 2014-05-01 17:26:02 | [diff] [blame] | 362 | if (service_weak_.get()) { |
| 363 | ExtensionErrorReporter::GetInstance()->ReportLoadError( |
| 364 | extension_path_, |
| 365 | error, |
| 366 | service_weak_->profile(), |
| 367 | be_noisy_on_failure_); |
| 368 | } |
rdevlin.cronin | f6ea63a | 2015-03-04 17:51:04 | [diff] [blame] | 369 | |
| 370 | if (!callback_.is_null()) { |
| 371 | callback_.Run(nullptr, extension_path_, error); |
| 372 | callback_.Reset(); |
| 373 | } |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 374 | } |
| 375 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 376 | void UnpackedInstaller::InstallExtension() { |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 377 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 0d90431 | 2012-01-25 23:00:16 | [diff] [blame] | 378 | |
asargent | 1e46c51 | 2016-09-16 00:46:09 | [diff] [blame] | 379 | if (!service_weak_.get()) { |
| 380 | callback_.Reset(); |
| 381 | return; |
| 382 | } |
| 383 | |
[email protected] | 0d90431 | 2012-01-25 23:00:16 | [diff] [blame] | 384 | PermissionsUpdater perms_updater(service_weak_->profile()); |
gpdavis.chromium | 48f08c4 | 2014-09-18 22:09:34 | [diff] [blame] | 385 | perms_updater.InitializePermissions(extension()); |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 386 | perms_updater.GrantActivePermissions(extension()); |
[email protected] | 9d02fa1 | 2013-02-19 05:12:57 | [diff] [blame] | 387 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 388 | service_weak_->OnExtensionInstalled( |
| 389 | extension(), syncer::StringOrdinal(), kInstallFlagInstallImmediately); |
rdevlin.cronin | f6ea63a | 2015-03-04 17:51:04 | [diff] [blame] | 390 | |
| 391 | if (!callback_.is_null()) { |
| 392 | callback_.Run(extension(), extension_path_, std::string()); |
| 393 | callback_.Reset(); |
| 394 | } |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 395 | } |
| 396 | |
| 397 | } // namespace extensions |