[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" |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 10 | #include "base/json/json_file_value_serializer.h" |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 11 | #include "base/memory/ptr_util.h" |
michaelpg | a8ea037 | 2017-04-06 20:41:35 | [diff] [blame] | 12 | #include "base/strings/string16.h" |
[email protected] | 46acbf1 | 2013-06-10 18:43:42 | [diff] [blame] | 13 | #include "base/strings/string_util.h" |
michaelpg | a8ea037 | 2017-04-06 20:41:35 | [diff] [blame] | 14 | #include "base/strings/utf_string_conversions.h" |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame] | 15 | #include "base/task_scheduler/post_task.h" |
[email protected] | bebe1d0 | 2012-08-02 20:17:09 | [diff] [blame] | 16 | #include "base/threading/thread_restrictions.h" |
binjin | 1569c9b | 2014-09-05 13:33:18 | [diff] [blame] | 17 | #include "chrome/browser/extensions/extension_management.h" |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 18 | #include "chrome/browser/extensions/extension_service.h" |
Devlin Cronin | 9722a72 | 2017-12-16 03:35:10 | [diff] [blame] | 19 | #include "chrome/browser/extensions/load_error_reporter.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" |
[email protected] | fdd2837 | 2014-08-21 02:27:26 | [diff] [blame] | 22 | #include "components/crx_file/id_util.h" |
skym | 7160384 | 2016-10-10 18:17:31 | [diff] [blame] | 23 | #include "components/sync/model/string_ordinal.h" |
[email protected] | 79a6064 | 2012-10-20 21:03:18 | [diff] [blame] | 24 | #include "content/public/browser/browser_thread.h" |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 25 | #include "extensions/browser/api/declarative_net_request/utils.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] | 4a1d9c0d | 2014-06-13 12:50:11 | [diff] [blame] | 28 | #include "extensions/browser/install_flag.h" |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 29 | #include "extensions/browser/policy_check.h" |
| 30 | #include "extensions/browser/preload_check_group.h" |
| 31 | #include "extensions/browser/requirements_checker.h" |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 32 | #include "extensions/common/api/declarative_net_request/dnr_manifest_data.h" |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 33 | #include "extensions/common/constants.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" |
Karan Bhatia | 71f6a62 | 2017-10-02 19:39:10 | [diff] [blame] | 38 | #include "extensions/common/manifest_constants.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 | |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 46 | namespace extensions { |
| 47 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 48 | namespace { |
| 49 | |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 50 | const char kUnpackedExtensionsBlacklistedError[] = |
| 51 | "Loading of unpacked extensions is disabled by the administrator."; |
| 52 | |
elijahtaylor | c93f7547 | 2014-10-15 18:42:25 | [diff] [blame] | 53 | const char kImportMinVersionNewer[] = |
| 54 | "'import' version requested is newer than what is installed."; |
| 55 | const char kImportMissing[] = "'import' extension is not installed."; |
| 56 | const char kImportNotSharedModule[] = "'import' is not a shared module."; |
| 57 | |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 58 | // Deletes files reserved for use by the Extension system in the kMetadataFolder |
| 59 | // and the kMetadataFolder itself if it is empty. |
| 60 | void MaybeCleanupMetadataFolder(const base::FilePath& extension_path) { |
| 61 | const std::vector<base::FilePath> reserved_filepaths = |
| 62 | file_util::GetReservedMetadataFilePaths(extension_path); |
| 63 | for (const auto& file : reserved_filepaths) |
| 64 | base::DeleteFile(file, false /*recursive*/); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 65 | |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 66 | const base::FilePath& metadata_dir = extension_path.Append(kMetadataFolder); |
| 67 | if (base::IsDirectoryEmpty(metadata_dir)) |
| 68 | base::DeleteFile(metadata_dir, true /*recursive*/); |
| 69 | } |
| 70 | |
| 71 | } // namespace |
Alexander Alekseev | 63c0214 | 2017-09-14 19:19:19 | [diff] [blame] | 72 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 73 | // static |
| 74 | scoped_refptr<UnpackedInstaller> UnpackedInstaller::Create( |
| 75 | ExtensionService* extension_service) { |
[email protected] | 3a7fbc24 | 2013-12-19 17:43:37 | [diff] [blame] | 76 | DCHECK(extension_service); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 77 | return scoped_refptr<UnpackedInstaller>( |
| 78 | new UnpackedInstaller(extension_service)); |
| 79 | } |
| 80 | |
| 81 | UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service) |
| 82 | : service_weak_(extension_service->AsWeakPtr()), |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 83 | profile_(extension_service->profile()), |
[email protected] | 9d02fa1 | 2013-02-19 05:12:57 | [diff] [blame] | 84 | require_modern_manifest_version_(true), |
dgozman | d741d25d | 2017-03-23 00:35:34 | [diff] [blame] | 85 | be_noisy_on_failure_(true) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 86 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | UnpackedInstaller::~UnpackedInstaller() { |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 90 | } |
| 91 | |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 92 | void UnpackedInstaller::Load(const base::FilePath& path_in) { |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 93 | DCHECK(extension_path_.empty()); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 94 | extension_path_ = path_in; |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame] | 95 | GetExtensionFileTaskRunner()->PostTask( |
| 96 | FROM_HERE, base::BindOnce(&UnpackedInstaller::GetAbsolutePath, this)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 97 | } |
| 98 | |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 99 | bool UnpackedInstaller::LoadFromCommandLine(const base::FilePath& path_in, |
proberge | 80a37f3 | 2016-08-04 19:44:55 | [diff] [blame] | 100 | std::string* extension_id, |
| 101 | bool only_allow_apps) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 102 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 103 | DCHECK(extension_path_.empty()); |
| 104 | |
[email protected] | e8dad9b | 2013-06-04 04:43:45 | [diff] [blame] | 105 | if (!service_weak_.get()) |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 106 | return false; |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 107 | // Load extensions from the command line synchronously to avoid a race |
| 108 | // between extension loading and loading an URL from the command line. |
| 109 | base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 110 | |
[email protected] | 1547693 | 2013-04-12 05:17:15 | [diff] [blame] | 111 | extension_path_ = base::MakeAbsoluteFilePath(path_in); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 112 | |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 113 | if (!IsLoadingUnpackedAllowed()) { |
| 114 | ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError); |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 115 | return false; |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 116 | } |
| 117 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 118 | std::string error; |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 119 | if (!LoadExtension(Manifest::COMMAND_LINE, GetFlags(), &error)) { |
proberge | ac2a4b6 | 2016-08-29 16:16:09 | [diff] [blame] | 120 | ReportExtensionLoadError(error); |
| 121 | return false; |
| 122 | } |
| 123 | |
proberge | 80a37f3 | 2016-08-04 19:44:55 | [diff] [blame] | 124 | if (only_allow_apps && !extension()->is_platform_app()) { |
| 125 | #if defined(GOOGLE_CHROME_BUILD) |
| 126 | // Avoid crashing for users with hijacked shortcuts. |
| 127 | return true; |
| 128 | #else |
| 129 | // Defined here to avoid unused variable errors in official builds. |
| 130 | const char extension_instead_of_app_error[] = |
| 131 | "App loading flags cannot be used to load extensions. Please use " |
| 132 | "--load-extension instead."; |
| 133 | ReportExtensionLoadError(extension_instead_of_app_error); |
| 134 | return false; |
| 135 | #endif |
| 136 | } |
| 137 | |
rdevlin.cronin | e2d0fd0 | 2015-09-24 22:35:49 | [diff] [blame] | 138 | extension()->permissions_data()->BindToCurrentThread(); |
rdevlin.cronin | f173cbc4 | 2014-09-24 18:03:32 | [diff] [blame] | 139 | PermissionsUpdater( |
| 140 | service_weak_->profile(), PermissionsUpdater::INIT_FLAG_TRANSIENT) |
| 141 | .InitializePermissions(extension()); |
Karan Bhatia | f70d840b | 2017-11-22 19:21:09 | [diff] [blame] | 142 | StartInstallChecks(); |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 143 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 144 | *extension_id = extension()->id(); |
[email protected] | 2a69b94 | 2013-05-31 09:37:53 | [diff] [blame] | 145 | return true; |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 146 | } |
| 147 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 148 | void UnpackedInstaller::StartInstallChecks() { |
Karan Bhatia | f70d840b | 2017-11-22 19:21:09 | [diff] [blame] | 149 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 150 | ExtensionService* service = service_weak_.get(); |
| 151 | if (!service) |
| 152 | return; |
| 153 | |
elijahtaylor | c93f7547 | 2014-10-15 18:42:25 | [diff] [blame] | 154 | // TODO(crbug.com/421128): Enable these checks all the time. The reason |
| 155 | // they are disabled for extensions loaded from the command-line is that |
| 156 | // installing unpacked extensions is asynchronous, but there can be |
| 157 | // dependencies between the extensions loaded by the command line. |
| 158 | if (extension()->manifest()->location() != Manifest::COMMAND_LINE) { |
Karan Bhatia | f70d840b | 2017-11-22 19:21:09 | [diff] [blame] | 159 | if (service->browser_terminating()) |
elijahtaylor | c93f7547 | 2014-10-15 18:42:25 | [diff] [blame] | 160 | return; |
| 161 | |
| 162 | // TODO(crbug.com/420147): Move this code to a utility class to avoid |
| 163 | // duplication of SharedModuleService::CheckImports code. |
| 164 | if (SharedModuleInfo::ImportsModules(extension())) { |
| 165 | const std::vector<SharedModuleInfo::ImportInfo>& imports = |
| 166 | SharedModuleInfo::GetImports(extension()); |
| 167 | std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; |
| 168 | for (i = imports.begin(); i != imports.end(); ++i) { |
pwnall | cbd7319 | 2016-08-22 18:59:17 | [diff] [blame] | 169 | base::Version version_required(i->minimum_version); |
elijahtaylor | c93f7547 | 2014-10-15 18:42:25 | [diff] [blame] | 170 | const Extension* imported_module = |
| 171 | service->GetExtensionById(i->extension_id, true); |
| 172 | if (!imported_module) { |
| 173 | ReportExtensionLoadError(kImportMissing); |
| 174 | return; |
| 175 | } else if (imported_module && |
| 176 | !SharedModuleInfo::IsSharedModule(imported_module)) { |
| 177 | ReportExtensionLoadError(kImportNotSharedModule); |
| 178 | return; |
| 179 | } else if (imported_module && (version_required.IsValid() && |
| 180 | imported_module->version()->CompareTo( |
| 181 | version_required) < 0)) { |
| 182 | ReportExtensionLoadError(kImportMinVersionNewer); |
| 183 | return; |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | } |
| 188 | |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 189 | policy_check_ = base::MakeUnique<PolicyCheck>(profile_, extension_); |
| 190 | requirements_check_ = base::MakeUnique<RequirementsChecker>(extension_); |
| 191 | |
| 192 | check_group_ = base::MakeUnique<PreloadCheckGroup>(); |
| 193 | check_group_->set_stop_on_first_error(true); |
| 194 | |
| 195 | check_group_->AddCheck(policy_check_.get()); |
| 196 | check_group_->AddCheck(requirements_check_.get()); |
| 197 | check_group_->Start( |
| 198 | base::BindOnce(&UnpackedInstaller::OnInstallChecksComplete, this)); |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 199 | } |
| 200 | |
Istiaque Ahmed | 400c83a | 2017-10-11 02:39:35 | [diff] [blame] | 201 | void UnpackedInstaller::OnInstallChecksComplete( |
| 202 | const PreloadCheck::Errors& errors) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 203 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 9827043 | 2012-09-11 20:51:24 | [diff] [blame] | 204 | |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 205 | if (errors.empty()) { |
| 206 | InstallExtension(); |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 207 | return; |
| 208 | } |
| 209 | |
michaelpg | 6a4874f | 2017-04-13 20:41:33 | [diff] [blame] | 210 | base::string16 error_message; |
| 211 | if (errors.count(PreloadCheck::DISALLOWED_BY_POLICY)) |
| 212 | error_message = policy_check_->GetErrorMessage(); |
| 213 | else |
| 214 | error_message = requirements_check_->GetErrorMessage(); |
| 215 | |
| 216 | DCHECK(!error_message.empty()); |
| 217 | ReportExtensionLoadError(base::UTF16ToUTF8(error_message)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 218 | } |
| 219 | |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 220 | int UnpackedInstaller::GetFlags() { |
[email protected] | fdd2837 | 2014-08-21 02:27:26 | [diff] [blame] | 221 | std::string id = crx_file::id_util::GenerateIdForPath(extension_path_); |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 222 | bool allow_file_access = |
[email protected] | 12075d1 | 2013-02-27 05:38:05 | [diff] [blame] | 223 | Manifest::ShouldAlwaysAllowFileAccess(Manifest::UNPACKED); |
[email protected] | 7c82539c | 2014-02-19 06:09:17 | [diff] [blame] | 224 | ExtensionPrefs* prefs = ExtensionPrefs::Get(service_weak_->profile()); |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 225 | if (prefs->HasAllowFileAccessSetting(id)) |
| 226 | allow_file_access = prefs->AllowFileAccess(id); |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 227 | |
| 228 | int result = Extension::FOLLOW_SYMLINKS_ANYWHERE; |
| 229 | if (allow_file_access) |
| 230 | result |= Extension::ALLOW_FILE_ACCESS; |
| 231 | if (require_modern_manifest_version_) |
| 232 | result |= Extension::REQUIRE_MODERN_MANIFEST_VERSION; |
| 233 | |
| 234 | return result; |
| 235 | } |
| 236 | |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 237 | bool UnpackedInstaller::LoadExtension(Manifest::Location location, |
| 238 | int flags, |
| 239 | std::string* error) { |
Francois Doray | 66bdfd8 | 2017-10-20 13:50:37 | [diff] [blame] | 240 | base::AssertBlockingAllowed(); |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 241 | |
| 242 | // Clean up the kMetadataFolder if necessary. This prevents spurious |
| 243 | // warnings/errors and ensures we don't treat a user provided file as one by |
| 244 | // the Extension system. |
| 245 | MaybeCleanupMetadataFolder(extension_path_); |
| 246 | |
| 247 | // Treat presence of illegal filenames as a hard error for unpacked |
| 248 | // extensions. Don't do so for command line extensions since this breaks |
| 249 | // Chrome OS autotests (crbug.com/764787). |
| 250 | if (location == Manifest::UNPACKED && |
| 251 | !file_util::CheckForIllegalFilenames(extension_path_, error)) { |
| 252 | return false; |
| 253 | } |
| 254 | |
| 255 | extension_ = |
| 256 | file_util::LoadExtension(extension_path_, location, flags, error); |
| 257 | |
| 258 | return extension() && |
| 259 | extension_l10n_util::ValidateExtensionLocales( |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 260 | extension_path_, extension()->manifest()->value(), error) && |
| 261 | IndexAndPersistRulesIfNeeded(error); |
| 262 | } |
| 263 | |
| 264 | bool UnpackedInstaller::IndexAndPersistRulesIfNeeded(std::string* error) { |
| 265 | DCHECK(extension()); |
Francois Doray | 66bdfd8 | 2017-10-20 13:50:37 | [diff] [blame] | 266 | base::AssertBlockingAllowed(); |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 267 | |
| 268 | const ExtensionResource* resource = |
| 269 | declarative_net_request::DNRManifestData::GetRulesetResource(extension()); |
| 270 | // The extension did not provide a ruleset. |
| 271 | if (!resource) |
| 272 | return true; |
| 273 | |
| 274 | // TODO(crbug.com/761107): Change this so that we don't need to parse JSON |
| 275 | // in the browser process. |
| 276 | JSONFileValueDeserializer deserializer(resource->GetFilePath()); |
Karan Bhatia | 71f6a62 | 2017-10-02 19:39:10 | [diff] [blame] | 277 | std::unique_ptr<base::Value> root = deserializer.Deserialize(nullptr, error); |
| 278 | if (!root) |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 279 | return false; |
| 280 | |
Karan Bhatia | 71f6a62 | 2017-10-02 19:39:10 | [diff] [blame] | 281 | if (!root->is_list()) { |
| 282 | *error = manifest_errors::kDeclarativeNetRequestListNotPassed; |
| 283 | return false; |
| 284 | } |
| 285 | |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 286 | std::vector<InstallWarning> warnings; |
Karandeep Bhatia | a893065 | 2017-10-11 17:41:12 | [diff] [blame] | 287 | int ruleset_checksum; |
| 288 | if (!declarative_net_request::IndexAndPersistRules( |
| 289 | *base::ListValue::From(std::move(root)), *extension(), error, |
| 290 | &warnings, &ruleset_checksum)) { |
| 291 | return false; |
| 292 | } |
| 293 | |
| 294 | dnr_ruleset_checksum_ = ruleset_checksum; |
Karan Bhatia | 328e31a | 2017-09-18 21:46:16 | [diff] [blame] | 295 | extension_->AddInstallWarnings(warnings); |
Karandeep Bhatia | a893065 | 2017-10-11 17:41:12 | [diff] [blame] | 296 | return true; |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 297 | } |
| 298 | |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 299 | bool UnpackedInstaller::IsLoadingUnpackedAllowed() const { |
[email protected] | e8dad9b | 2013-06-04 04:43:45 | [diff] [blame] | 300 | if (!service_weak_.get()) |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 301 | return true; |
| 302 | // If there is a "*" in the extension blacklist, then no extensions should be |
| 303 | // allowed at all (except explicitly whitelisted extensions). |
binjin | 1569c9b | 2014-09-05 13:33:18 | [diff] [blame] | 304 | return !ExtensionManagementFactory::GetForBrowserContext( |
| 305 | service_weak_->profile())->BlacklistedByDefault(); |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 306 | } |
| 307 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 308 | void UnpackedInstaller::GetAbsolutePath() { |
Francois Doray | 66bdfd8 | 2017-10-20 13:50:37 | [diff] [blame] | 309 | base::AssertBlockingAllowed(); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 310 | |
[email protected] | 1547693 | 2013-04-12 05:17:15 | [diff] [blame] | 311 | extension_path_ = base::MakeAbsoluteFilePath(extension_path_); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 312 | |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 313 | BrowserThread::PostTask( |
| 314 | BrowserThread::UI, FROM_HERE, |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 315 | base::BindOnce(&UnpackedInstaller::CheckExtensionFileAccess, this)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 316 | } |
| 317 | |
| 318 | void UnpackedInstaller::CheckExtensionFileAccess() { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 319 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | e8dad9b | 2013-06-04 04:43:45 | [diff] [blame] | 320 | if (!service_weak_.get()) |
[email protected] | 8e7b2cf4 | 2012-04-18 14:26:58 | [diff] [blame] | 321 | return; |
| 322 | |
| 323 | if (!IsLoadingUnpackedAllowed()) { |
| 324 | ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError); |
| 325 | return; |
| 326 | } |
| 327 | |
Istiaque Ahmed | 81ff01e | 2017-08-09 16:00:59 | [diff] [blame] | 328 | GetExtensionFileTaskRunner()->PostTask( |
| 329 | FROM_HERE, |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 330 | base::BindOnce(&UnpackedInstaller::LoadWithFileAccess, this, GetFlags())); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 331 | } |
| 332 | |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 333 | void UnpackedInstaller::LoadWithFileAccess(int flags) { |
Francois Doray | 66bdfd8 | 2017-10-20 13:50:37 | [diff] [blame] | 334 | base::AssertBlockingAllowed(); |
[email protected] | b7462f3 | 2012-09-02 15:18:12 | [diff] [blame] | 335 | |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 336 | std::string error; |
Karan Bhatia | fe12281a | 2017-09-16 02:38:18 | [diff] [blame] | 337 | if (!LoadExtension(Manifest::UNPACKED, flags, &error)) { |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 338 | BrowserThread::PostTask( |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 339 | BrowserThread::UI, FROM_HERE, |
| 340 | base::BindOnce(&UnpackedInstaller::ReportExtensionLoadError, this, |
| 341 | error)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 342 | return; |
| 343 | } |
| 344 | |
[email protected] | 849749d | 2013-05-06 17:30:45 | [diff] [blame] | 345 | BrowserThread::PostTask( |
tzik | 8d880ee | 2017-04-20 19:46:24 | [diff] [blame] | 346 | BrowserThread::UI, FROM_HERE, |
Karan Bhatia | f70d840b | 2017-11-22 19:21:09 | [diff] [blame] | 347 | base::BindOnce(&UnpackedInstaller::StartInstallChecks, this)); |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 348 | } |
| 349 | |
| 350 | void UnpackedInstaller::ReportExtensionLoadError(const std::string &error) { |
yoz | 416ae9f | 2015-02-24 19:40:41 | [diff] [blame] | 351 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 500c7bb | 2014-04-26 22:44:33 | [diff] [blame] | 352 | |
[email protected] | 1f072244 | 2014-05-01 17:26:02 | [diff] [blame] | 353 | if (service_weak_.get()) { |
Devlin Cronin | 9722a72 | 2017-12-16 03:35:10 | [diff] [blame] | 354 | LoadErrorReporter::GetInstance()->ReportLoadError( |
| 355 | extension_path_, error, service_weak_->profile(), be_noisy_on_failure_); |
[email protected] | 1f072244 | 2014-05-01 17:26:02 | [diff] [blame] | 356 | } |
rdevlin.cronin | f6ea63a | 2015-03-04 17:51:04 | [diff] [blame] | 357 | |
| 358 | if (!callback_.is_null()) { |
| 359 | callback_.Run(nullptr, extension_path_, error); |
| 360 | callback_.Reset(); |
| 361 | } |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 362 | } |
| 363 | |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 364 | void UnpackedInstaller::InstallExtension() { |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 365 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 0d90431 | 2012-01-25 23:00:16 | [diff] [blame] | 366 | |
asargent | 1e46c51 | 2016-09-16 00:46:09 | [diff] [blame] | 367 | if (!service_weak_.get()) { |
| 368 | callback_.Reset(); |
| 369 | return; |
| 370 | } |
| 371 | |
[email protected] | 0d90431 | 2012-01-25 23:00:16 | [diff] [blame] | 372 | PermissionsUpdater perms_updater(service_weak_->profile()); |
gpdavis.chromium | 48f08c4 | 2014-09-18 22:09:34 | [diff] [blame] | 373 | perms_updater.InitializePermissions(extension()); |
[email protected] | 253fc2bb | 2014-07-10 04:21:18 | [diff] [blame] | 374 | perms_updater.GrantActivePermissions(extension()); |
[email protected] | 9d02fa1 | 2013-02-19 05:12:57 | [diff] [blame] | 375 | |
Karandeep Bhatia | a893065 | 2017-10-11 17:41:12 | [diff] [blame] | 376 | service_weak_->OnExtensionInstalled(extension(), syncer::StringOrdinal(), |
| 377 | kInstallFlagInstallImmediately, |
| 378 | dnr_ruleset_checksum_); |
rdevlin.cronin | f6ea63a | 2015-03-04 17:51:04 | [diff] [blame] | 379 | |
| 380 | if (!callback_.is_null()) { |
| 381 | callback_.Run(extension(), extension_path_, std::string()); |
| 382 | callback_.Reset(); |
| 383 | } |
[email protected] | d8c8f25f | 2011-11-02 18:18:01 | [diff] [blame] | 384 | } |
| 385 | |
| 386 | } // namespace extensions |