| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/component_updater/default_component_installer.h" | 5 #include "components/component_updater/default_component_installer.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/files/file_enumerator.h" | 11 #include "base/files/file_enumerator.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 14 #include "base/location.h" | 14 #include "base/location.h" |
| 15 #include "base/path_service.h" |
| 15 #include "base/sequenced_task_runner.h" | 16 #include "base/sequenced_task_runner.h" |
| 16 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
| 17 #include "base/thread_task_runner_handle.h" | 18 #include "base/thread_task_runner_handle.h" |
| 18 #include "base/values.h" | 19 #include "base/values.h" |
| 19 #include "base/version.h" | 20 #include "base/version.h" |
| 21 #include "components/component_updater/component_updater_paths.h" |
| 20 // TODO(ddorwin): Find a better place for ReadManifest. | 22 // TODO(ddorwin): Find a better place for ReadManifest. |
| 21 #include "components/component_updater/component_updater_service.h" | 23 #include "components/component_updater/component_updater_service.h" |
| 22 #include "components/update_client/component_unpacker.h" | 24 #include "components/update_client/component_unpacker.h" |
| 23 #include "components/update_client/utils.h" | 25 #include "components/update_client/utils.h" |
| 24 | 26 |
| 25 using update_client::CrxComponent; | 27 using update_client::CrxComponent; |
| 26 | 28 |
| 27 namespace component_updater { | 29 namespace component_updater { |
| 28 | 30 |
| 29 namespace { | 31 namespace { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 manifest.GetStringASCII("version", &manifest_version); | 101 manifest.GetStringASCII("version", &manifest_version); |
| 100 base::Version version(manifest_version); | 102 base::Version version(manifest_version); |
| 101 | 103 |
| 102 VLOG(1) << "Install: version=" << version.GetString() | 104 VLOG(1) << "Install: version=" << version.GetString() |
| 103 << " current version=" << current_version_.GetString(); | 105 << " current version=" << current_version_.GetString(); |
| 104 | 106 |
| 105 if (!version.IsValid()) | 107 if (!version.IsValid()) |
| 106 return false; | 108 return false; |
| 107 if (current_version_.CompareTo(version) > 0) | 109 if (current_version_.CompareTo(version) > 0) |
| 108 return false; | 110 return false; |
| 109 base::FilePath install_path = | 111 base::FilePath install_path; |
| 110 installer_traits_->GetBaseDirectory().AppendASCII(version.GetString()); | 112 if (!PathService::Get(DIR_COMPONENT_USER, &install_path)) |
| 113 return false; |
| 114 install_path = install_path.Append(installer_traits_->GetRelativeInstallDir()) |
| 115 .AppendASCII(version.GetString()); |
| 111 if (base::PathExists(install_path)) { | 116 if (base::PathExists(install_path)) { |
| 112 if (!base::DeleteFile(install_path, true)) | 117 if (!base::DeleteFile(install_path, true)) |
| 113 return false; | 118 return false; |
| 114 } | 119 } |
| 115 if (!InstallHelper(manifest, unpack_path, install_path)) { | 120 if (!InstallHelper(manifest, unpack_path, install_path)) { |
| 116 base::DeleteFile(install_path, true); | 121 base::DeleteFile(install_path, true); |
| 117 return false; | 122 return false; |
| 118 } | 123 } |
| 119 current_version_ = version; | 124 current_version_ = version; |
| 125 current_install_dir_ = install_path; |
| 120 // TODO(ddorwin): Change parameter to std::unique_ptr<base::DictionaryValue> | 126 // TODO(ddorwin): Change parameter to std::unique_ptr<base::DictionaryValue> |
| 121 // so we can avoid this DeepCopy. | 127 // so we can avoid this DeepCopy. |
| 122 current_manifest_.reset(manifest.DeepCopy()); | 128 current_manifest_.reset(manifest.DeepCopy()); |
| 123 std::unique_ptr<base::DictionaryValue> manifest_copy( | 129 std::unique_ptr<base::DictionaryValue> manifest_copy( |
| 124 current_manifest_->DeepCopy()); | 130 current_manifest_->DeepCopy()); |
| 125 main_task_runner_->PostTask( | 131 main_task_runner_->PostTask( |
| 126 FROM_HERE, | 132 FROM_HERE, |
| 127 base::Bind(&DefaultComponentInstaller::ComponentReady, | 133 base::Bind(&DefaultComponentInstaller::ComponentReady, |
| 128 this, base::Passed(&manifest_copy))); | 134 this, base::Passed(&manifest_copy))); |
| 129 return true; | 135 return true; |
| 130 } | 136 } |
| 131 | 137 |
| 132 bool DefaultComponentInstaller::GetInstalledFile( | 138 bool DefaultComponentInstaller::GetInstalledFile( |
| 133 const std::string& file, | 139 const std::string& file, |
| 134 base::FilePath* installed_file) { | 140 base::FilePath* installed_file) { |
| 135 if (current_version_ == base::Version(kNullVersion)) | 141 if (current_version_ == base::Version(kNullVersion)) |
| 136 return false; // No component has been installed yet. | 142 return false; // No component has been installed yet. |
| 137 | 143 *installed_file = current_install_dir_.AppendASCII(file); |
| 138 *installed_file = installer_traits_->GetBaseDirectory() | |
| 139 .AppendASCII(current_version_.GetString()) | |
| 140 .AppendASCII(file); | |
| 141 return true; | 144 return true; |
| 142 } | 145 } |
| 143 | 146 |
| 144 bool DefaultComponentInstaller::Uninstall() { | 147 bool DefaultComponentInstaller::Uninstall() { |
| 145 DCHECK(thread_checker_.CalledOnValidThread()); | 148 DCHECK(thread_checker_.CalledOnValidThread()); |
| 146 task_runner_->PostTask( | 149 task_runner_->PostTask( |
| 147 FROM_HERE, | 150 FROM_HERE, |
| 148 base::Bind(&DefaultComponentInstaller::UninstallOnTaskRunner, this)); | 151 base::Bind(&DefaultComponentInstaller::UninstallOnTaskRunner, this)); |
| 149 return true; | 152 return true; |
| 150 } | 153 } |
| 151 | 154 |
| 155 bool DefaultComponentInstaller::FindPreinstallation() { |
| 156 base::FilePath path; |
| 157 if (!PathService::Get(DIR_COMPONENT_PREINSTALLED, &path)) |
| 158 return false; |
| 159 path = path.Append(installer_traits_->GetRelativeInstallDir()); |
| 160 if (!base::PathExists(path)) |
| 161 return false; |
| 162 std::unique_ptr<base::DictionaryValue> manifest = |
| 163 update_client::ReadManifest(path); |
| 164 if (!manifest || !installer_traits_->VerifyInstallation(*manifest, path)) |
| 165 return false; |
| 166 std::string version_lexical; |
| 167 if (!manifest->GetStringASCII("version", &version_lexical)) |
| 168 return false; |
| 169 const base::Version version(version_lexical); |
| 170 if (!version.IsValid()) |
| 171 return false; |
| 172 current_install_dir_ = path; |
| 173 current_manifest_ = std::move(manifest); |
| 174 current_version_ = version; |
| 175 return true; |
| 176 } |
| 177 |
| 152 void DefaultComponentInstaller::StartRegistration(ComponentUpdateService* cus) { | 178 void DefaultComponentInstaller::StartRegistration(ComponentUpdateService* cus) { |
| 153 DCHECK(task_runner_.get()); | 179 DCHECK(task_runner_.get()); |
| 154 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 180 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 155 base::FilePath base_dir = installer_traits_->GetBaseDirectory(); | 181 |
| 182 base::Version latest_version(kNullVersion); |
| 183 |
| 184 // First check for an installation set up alongside Chrome itself. |
| 185 if (FindPreinstallation()) |
| 186 latest_version = current_version_; |
| 187 |
| 188 // Then check for a higher-versioned user-wide installation. |
| 189 base::FilePath latest_path; |
| 190 std::unique_ptr<base::DictionaryValue> latest_manifest; |
| 191 base::FilePath base_dir; |
| 192 if (!PathService::Get(DIR_COMPONENT_USER, &base_dir)) |
| 193 return; |
| 194 base_dir = base_dir.Append(installer_traits_->GetRelativeInstallDir()); |
| 156 if (!base::PathExists(base_dir) && !base::CreateDirectory(base_dir)) { | 195 if (!base::PathExists(base_dir) && !base::CreateDirectory(base_dir)) { |
| 157 PLOG(ERROR) << "Could not create the base directory for " | 196 PLOG(ERROR) << "Could not create the base directory for " |
| 158 << installer_traits_->GetName() << " (" | 197 << installer_traits_->GetName() << " (" |
| 159 << base_dir.MaybeAsASCII() << ")."; | 198 << base_dir.MaybeAsASCII() << ")."; |
| 160 return; | 199 return; |
| 161 } | 200 } |
| 162 | |
| 163 base::FilePath latest_path; | |
| 164 base::Version latest_version(kNullVersion); | |
| 165 std::unique_ptr<base::DictionaryValue> latest_manifest; | |
| 166 | |
| 167 std::vector<base::FilePath> older_paths; | 201 std::vector<base::FilePath> older_paths; |
| 168 base::FileEnumerator file_enumerator( | 202 base::FileEnumerator file_enumerator( |
| 169 base_dir, false, base::FileEnumerator::DIRECTORIES); | 203 base_dir, false, base::FileEnumerator::DIRECTORIES); |
| 170 for (base::FilePath path = file_enumerator.Next(); | 204 for (base::FilePath path = file_enumerator.Next(); |
| 171 !path.value().empty(); | 205 !path.value().empty(); |
| 172 path = file_enumerator.Next()) { | 206 path = file_enumerator.Next()) { |
| 173 base::Version version(path.BaseName().MaybeAsASCII()); | 207 base::Version version(path.BaseName().MaybeAsASCII()); |
| 174 | 208 |
| 175 // Ignore folders that don't have valid version names. These folders are not | 209 // Ignore folders that don't have valid version names. These folders are not |
| 176 // managed by component installer so do not try to remove them. | 210 // managed by component installer so do not try to remove them. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 189 if (!manifest || !installer_traits_->VerifyInstallation(*manifest, path)) { | 223 if (!manifest || !installer_traits_->VerifyInstallation(*manifest, path)) { |
| 190 PLOG(ERROR) << "Failed to read manifest or verify installation for " | 224 PLOG(ERROR) << "Failed to read manifest or verify installation for " |
| 191 << installer_traits_->GetName() << " (" << path.MaybeAsASCII() | 225 << installer_traits_->GetName() << " (" << path.MaybeAsASCII() |
| 192 << ")."; | 226 << ")."; |
| 193 older_paths.push_back(path); | 227 older_paths.push_back(path); |
| 194 continue; | 228 continue; |
| 195 } | 229 } |
| 196 | 230 |
| 197 // New valid |version| folder found! | 231 // New valid |version| folder found! |
| 198 | 232 |
| 199 if (latest_manifest) { | 233 if (!latest_path.empty()) |
| 200 DCHECK(!latest_path.empty()); | |
| 201 older_paths.push_back(latest_path); | 234 older_paths.push_back(latest_path); |
| 202 } | |
| 203 | 235 |
| 204 latest_path = path; | 236 latest_path = path; |
| 205 latest_version = version; | 237 latest_version = version; |
| 206 latest_manifest = std::move(manifest); | 238 latest_manifest = std::move(manifest); |
| 207 } | 239 } |
| 208 | 240 |
| 209 if (latest_manifest) { | 241 if (latest_manifest) { |
| 210 current_version_ = latest_version; | 242 current_version_ = latest_version; |
| 211 current_manifest_ = std::move(latest_manifest); | 243 current_manifest_ = std::move(latest_manifest); |
| 244 current_install_dir_ = latest_path; |
| 212 // TODO(ddorwin): Remove these members and pass them directly to | 245 // TODO(ddorwin): Remove these members and pass them directly to |
| 213 // FinishRegistration(). | 246 // FinishRegistration(). |
| 214 base::ReadFileToString(latest_path.AppendASCII("manifest.fingerprint"), | 247 base::ReadFileToString(latest_path.AppendASCII("manifest.fingerprint"), |
| 215 ¤t_fingerprint_); | 248 ¤t_fingerprint_); |
| 216 } | 249 } |
| 217 | 250 |
| 218 // Remove older versions of the component. None should be in use during | 251 // Remove older versions of the component. None should be in use during |
| 219 // browser startup. | 252 // browser startup. |
| 220 for (const auto& older_path : older_paths) | 253 for (const auto& older_path : older_paths) |
| 221 base::DeleteFile(older_path, true); | 254 base::DeleteFile(older_path, true); |
| 222 } | 255 } |
| 223 | 256 |
| 224 void DefaultComponentInstaller::UninstallOnTaskRunner() { | 257 void DefaultComponentInstaller::UninstallOnTaskRunner() { |
| 225 DCHECK(task_runner_.get()); | 258 DCHECK(task_runner_.get()); |
| 226 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 259 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 227 const base::FilePath base_dir = installer_traits_->GetBaseDirectory(); | |
| 228 | 260 |
| 261 // Only try to delete any files that are in our user-level install path. |
| 262 base::FilePath userInstallPath; |
| 263 if (!PathService::Get(DIR_COMPONENT_USER, &userInstallPath)) |
| 264 return; |
| 265 if (!userInstallPath.IsParent(current_install_dir_)) |
| 266 return; |
| 267 |
| 268 const base::FilePath base_dir = current_install_dir_.DirName(); |
| 229 base::FileEnumerator file_enumerator(base_dir, false, | 269 base::FileEnumerator file_enumerator(base_dir, false, |
| 230 base::FileEnumerator::DIRECTORIES); | 270 base::FileEnumerator::DIRECTORIES); |
| 231 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | 271 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
| 232 path = file_enumerator.Next()) { | 272 path = file_enumerator.Next()) { |
| 233 base::Version version(path.BaseName().MaybeAsASCII()); | 273 base::Version version(path.BaseName().MaybeAsASCII()); |
| 234 | 274 |
| 235 // Ignore folders that don't have valid version names. These folders are not | 275 // Ignore folders that don't have valid version names. These folders are not |
| 236 // managed by the component installer, so do not try to remove them. | 276 // managed by the component installer, so do not try to remove them. |
| 237 if (!version.IsValid()) | 277 if (!version.IsValid()) |
| 238 continue; | 278 continue; |
| 239 | 279 |
| 240 if (!base::DeleteFile(path, true)) | 280 if (!base::DeleteFile(path, true)) |
| 241 DLOG(ERROR) << "Couldn't delete " << path.value(); | 281 DLOG(ERROR) << "Couldn't delete " << path.value(); |
| 242 } | 282 } |
| 243 | 283 |
| 244 // Delete the base directory if it's empty now. | 284 // Delete the base directory if it's empty now. |
| 245 if (base::IsDirectoryEmpty(base_dir)) { | 285 if (base::IsDirectoryEmpty(base_dir)) { |
| 246 if (base::DeleteFile(base_dir, false)) | 286 if (base::DeleteFile(base_dir, false)) |
| 247 DLOG(ERROR) << "Couldn't delete " << base_dir.value(); | 287 DLOG(ERROR) << "Couldn't delete " << base_dir.value(); |
| 248 } | 288 } |
| 249 } | 289 } |
| 250 | 290 |
| 251 base::FilePath DefaultComponentInstaller::GetInstallDirectory() { | |
| 252 return installer_traits_->GetBaseDirectory() | |
| 253 .AppendASCII(current_version_.GetString()); | |
| 254 } | |
| 255 | |
| 256 void DefaultComponentInstaller::FinishRegistration( | 291 void DefaultComponentInstaller::FinishRegistration( |
| 257 ComponentUpdateService* cus, | 292 ComponentUpdateService* cus, |
| 258 const base::Closure& callback) { | 293 const base::Closure& callback) { |
| 259 DCHECK(thread_checker_.CalledOnValidThread()); | 294 DCHECK(thread_checker_.CalledOnValidThread()); |
| 260 if (installer_traits_->CanAutoUpdate()) { | 295 if (installer_traits_->CanAutoUpdate()) { |
| 261 CrxComponent crx; | 296 CrxComponent crx; |
| 262 crx.name = installer_traits_->GetName(); | 297 crx.name = installer_traits_->GetName(); |
| 263 crx.requires_network_encryption = | 298 crx.requires_network_encryption = |
| 264 installer_traits_->RequiresNetworkEncryption(); | 299 installer_traits_->RequiresNetworkEncryption(); |
| 265 crx.installer = this; | 300 crx.installer = this; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 280 return; | 315 return; |
| 281 | 316 |
| 282 std::unique_ptr<base::DictionaryValue> manifest_copy( | 317 std::unique_ptr<base::DictionaryValue> manifest_copy( |
| 283 current_manifest_->DeepCopy()); | 318 current_manifest_->DeepCopy()); |
| 284 ComponentReady(std::move(manifest_copy)); | 319 ComponentReady(std::move(manifest_copy)); |
| 285 } | 320 } |
| 286 | 321 |
| 287 void DefaultComponentInstaller::ComponentReady( | 322 void DefaultComponentInstaller::ComponentReady( |
| 288 std::unique_ptr<base::DictionaryValue> manifest) { | 323 std::unique_ptr<base::DictionaryValue> manifest) { |
| 289 VLOG(1) << "Component ready, version " << current_version_.GetString() | 324 VLOG(1) << "Component ready, version " << current_version_.GetString() |
| 290 << " in " << GetInstallDirectory().value(); | 325 << " in " << current_install_dir_.value(); |
| 291 installer_traits_->ComponentReady(current_version_, GetInstallDirectory(), | 326 installer_traits_->ComponentReady(current_version_, current_install_dir_, |
| 292 std::move(manifest)); | 327 std::move(manifest)); |
| 293 } | 328 } |
| 294 | 329 |
| 295 } // namespace component_updater | 330 } // namespace component_updater |
| OLD | NEW |