Chromium Code Reviews| 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 = | |
| 115 install_path.AppendASCII(installer_traits_->GetASCIIDirectoryName()) | |
| 116 .AppendASCII(version.GetString()); | |
| 111 if (base::PathExists(install_path)) { | 117 if (base::PathExists(install_path)) { |
| 112 if (!base::DeleteFile(install_path, true)) | 118 if (!base::DeleteFile(install_path, true)) |
| 113 return false; | 119 return false; |
| 114 } | 120 } |
| 115 if (!InstallHelper(manifest, unpack_path, install_path)) { | 121 if (!InstallHelper(manifest, unpack_path, install_path)) { |
| 116 base::DeleteFile(install_path, true); | 122 base::DeleteFile(install_path, true); |
| 117 return false; | 123 return false; |
| 118 } | 124 } |
| 119 current_version_ = version; | 125 current_version_ = version; |
| 126 current_install_dir_ = install_path; | |
| 120 // TODO(ddorwin): Change parameter to std::unique_ptr<base::DictionaryValue> | 127 // TODO(ddorwin): Change parameter to std::unique_ptr<base::DictionaryValue> |
| 121 // so we can avoid this DeepCopy. | 128 // so we can avoid this DeepCopy. |
| 122 current_manifest_.reset(manifest.DeepCopy()); | 129 current_manifest_.reset(manifest.DeepCopy()); |
| 123 std::unique_ptr<base::DictionaryValue> manifest_copy( | 130 std::unique_ptr<base::DictionaryValue> manifest_copy( |
| 124 current_manifest_->DeepCopy()); | 131 current_manifest_->DeepCopy()); |
| 125 main_task_runner_->PostTask( | 132 main_task_runner_->PostTask( |
| 126 FROM_HERE, | 133 FROM_HERE, |
| 127 base::Bind(&DefaultComponentInstaller::ComponentReady, | 134 base::Bind(&DefaultComponentInstaller::ComponentReady, |
| 128 this, base::Passed(&manifest_copy))); | 135 this, base::Passed(&manifest_copy))); |
| 129 return true; | 136 return true; |
| 130 } | 137 } |
| 131 | 138 |
| 132 bool DefaultComponentInstaller::GetInstalledFile( | 139 bool DefaultComponentInstaller::GetInstalledFile( |
| 133 const std::string& file, | 140 const std::string& file, |
| 134 base::FilePath* installed_file) { | 141 base::FilePath* installed_file) { |
| 135 if (current_version_ == base::Version(kNullVersion)) | 142 if (current_version_ == base::Version(kNullVersion)) |
| 136 return false; // No component has been installed yet. | 143 return false; // No component has been installed yet. |
| 137 | 144 *installed_file = current_install_dir_.AppendASCII(file); |
| 138 *installed_file = installer_traits_->GetBaseDirectory() | |
| 139 .AppendASCII(current_version_.GetString()) | |
| 140 .AppendASCII(file); | |
| 141 return true; | 145 return true; |
| 142 } | 146 } |
| 143 | 147 |
| 144 bool DefaultComponentInstaller::Uninstall() { | 148 bool DefaultComponentInstaller::Uninstall() { |
| 145 DCHECK(thread_checker_.CalledOnValidThread()); | 149 DCHECK(thread_checker_.CalledOnValidThread()); |
| 146 task_runner_->PostTask( | 150 task_runner_->PostTask( |
| 147 FROM_HERE, | 151 FROM_HERE, |
| 148 base::Bind(&DefaultComponentInstaller::UninstallOnTaskRunner, this)); | 152 base::Bind(&DefaultComponentInstaller::UninstallOnTaskRunner, this)); |
| 149 return true; | 153 return true; |
| 150 } | 154 } |
| 151 | 155 |
| 152 void DefaultComponentInstaller::StartRegistration(ComponentUpdateService* cus) { | 156 void DefaultComponentInstaller::StartRegistration(ComponentUpdateService* cus) { |
| 153 DCHECK(task_runner_.get()); | 157 DCHECK(task_runner_.get()); |
| 154 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 158 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 155 base::FilePath base_dir = installer_traits_->GetBaseDirectory(); | 159 |
| 160 base::Version latest_version(kNullVersion); | |
| 161 | |
| 162 // First check for a system-wide installation. | |
| 163 base::FilePath path; | |
| 164 if (PathService::Get(DIR_COMPONENT_SYSTEM, &path)) { | |
| 165 path = path.AppendASCII(installer_traits_->GetASCIIDirectoryName()); | |
| 166 if (base::PathExists(path)) { | |
| 167 std::unique_ptr<base::DictionaryValue> manifest = | |
| 168 update_client::ReadManifest(path); | |
| 169 if (manifest && installer_traits_->VerifyInstallation(*manifest, path)) { | |
| 170 std::string version_s; | |
|
xhwang
2016/05/02 17:47:00
nit: "Names should be descriptive; eschew abbrevia
waffles
2016/05/03 21:04:22
Done.
| |
| 171 if (manifest->GetStringASCII("version", &version_s)) { | |
| 172 base::Version version(version_s); | |
| 173 if (version.IsValid()) { | |
| 174 current_install_dir_ = path; | |
| 175 current_manifest_ = std::move(manifest); | |
| 176 current_version_ = version; | |
| 177 latest_version = version; | |
| 178 } | |
| 179 } | |
| 180 } | |
| 181 } | |
| 182 } | |
|
xhwang
2016/05/02 17:47:00
nit: It might be clearer to wrap this block into a
waffles
2016/05/03 21:04:22
Done.
| |
| 183 | |
| 184 // Then check for a higher-versioned user-wide installation. | |
| 185 base::FilePath latest_path; | |
| 186 std::unique_ptr<base::DictionaryValue> latest_manifest; | |
| 187 base::FilePath base_dir; | |
| 188 if (!PathService::Get(DIR_COMPONENT_USER, &base_dir)) | |
| 189 return; | |
| 190 base_dir = base_dir.AppendASCII(installer_traits_->GetASCIIDirectoryName()); | |
| 156 if (!base::PathExists(base_dir) && !base::CreateDirectory(base_dir)) { | 191 if (!base::PathExists(base_dir) && !base::CreateDirectory(base_dir)) { |
| 157 PLOG(ERROR) << "Could not create the base directory for " | 192 PLOG(ERROR) << "Could not create the base directory for " |
| 158 << installer_traits_->GetName() << " (" | 193 << installer_traits_->GetName() << " (" |
| 159 << base_dir.MaybeAsASCII() << ")."; | 194 << base_dir.MaybeAsASCII() << ")."; |
| 160 return; | 195 return; |
| 161 } | 196 } |
| 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; | 197 std::vector<base::FilePath> older_paths; |
| 168 base::FileEnumerator file_enumerator( | 198 base::FileEnumerator file_enumerator( |
| 169 base_dir, false, base::FileEnumerator::DIRECTORIES); | 199 base_dir, false, base::FileEnumerator::DIRECTORIES); |
| 170 for (base::FilePath path = file_enumerator.Next(); | 200 for (base::FilePath path = file_enumerator.Next(); |
| 171 !path.value().empty(); | 201 !path.value().empty(); |
| 172 path = file_enumerator.Next()) { | 202 path = file_enumerator.Next()) { |
| 173 base::Version version(path.BaseName().MaybeAsASCII()); | 203 base::Version version(path.BaseName().MaybeAsASCII()); |
| 174 | 204 |
| 175 // Ignore folders that don't have valid version names. These folders are not | 205 // 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. | 206 // 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)) { | 219 if (!manifest || !installer_traits_->VerifyInstallation(*manifest, path)) { |
| 190 PLOG(ERROR) << "Failed to read manifest or verify installation for " | 220 PLOG(ERROR) << "Failed to read manifest or verify installation for " |
| 191 << installer_traits_->GetName() << " (" << path.MaybeAsASCII() | 221 << installer_traits_->GetName() << " (" << path.MaybeAsASCII() |
| 192 << ")."; | 222 << ")."; |
| 193 older_paths.push_back(path); | 223 older_paths.push_back(path); |
| 194 continue; | 224 continue; |
| 195 } | 225 } |
| 196 | 226 |
| 197 // New valid |version| folder found! | 227 // New valid |version| folder found! |
| 198 | 228 |
| 199 if (latest_manifest) { | 229 if (!latest_path.empty()) |
| 200 DCHECK(!latest_path.empty()); | |
| 201 older_paths.push_back(latest_path); | 230 older_paths.push_back(latest_path); |
| 202 } | |
| 203 | 231 |
| 204 latest_path = path; | 232 latest_path = path; |
| 205 latest_version = version; | 233 latest_version = version; |
| 206 latest_manifest = std::move(manifest); | 234 latest_manifest = std::move(manifest); |
| 207 } | 235 } |
| 208 | 236 |
| 209 if (latest_manifest) { | 237 if (latest_manifest) { |
| 210 current_version_ = latest_version; | 238 current_version_ = latest_version; |
| 211 current_manifest_ = std::move(latest_manifest); | 239 current_manifest_ = std::move(latest_manifest); |
| 240 current_install_dir_ = latest_path; | |
| 212 // TODO(ddorwin): Remove these members and pass them directly to | 241 // TODO(ddorwin): Remove these members and pass them directly to |
| 213 // FinishRegistration(). | 242 // FinishRegistration(). |
| 214 base::ReadFileToString(latest_path.AppendASCII("manifest.fingerprint"), | 243 base::ReadFileToString(latest_path.AppendASCII("manifest.fingerprint"), |
| 215 ¤t_fingerprint_); | 244 ¤t_fingerprint_); |
| 216 } | 245 } |
| 217 | 246 |
| 218 // Remove older versions of the component. None should be in use during | 247 // Remove older versions of the component. None should be in use during |
| 219 // browser startup. | 248 // browser startup. |
| 220 for (const auto& older_path : older_paths) | 249 for (const auto& older_path : older_paths) |
| 221 base::DeleteFile(older_path, true); | 250 base::DeleteFile(older_path, true); |
| 222 } | 251 } |
| 223 | 252 |
| 224 void DefaultComponentInstaller::UninstallOnTaskRunner() { | 253 void DefaultComponentInstaller::UninstallOnTaskRunner() { |
| 225 DCHECK(task_runner_.get()); | 254 DCHECK(task_runner_.get()); |
| 226 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 255 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 227 const base::FilePath base_dir = installer_traits_->GetBaseDirectory(); | |
| 228 | 256 |
| 229 base::FileEnumerator file_enumerator(base_dir, false, | 257 // Only try to delete any files that are in our user-level install path. |
| 258 base::FilePath userInstallPath; | |
| 259 if (!PathService::Get(DIR_COMPONENT_USER, &userInstallPath)) | |
| 260 return; | |
| 261 if (!userInstallPath.IsParent(current_install_dir_)) | |
| 262 return; | |
| 263 | |
| 264 base::FileEnumerator file_enumerator(current_install_dir_, false, | |
| 230 base::FileEnumerator::DIRECTORIES); | 265 base::FileEnumerator::DIRECTORIES); |
| 231 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | 266 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
| 232 path = file_enumerator.Next()) { | 267 path = file_enumerator.Next()) { |
| 233 base::Version version(path.BaseName().MaybeAsASCII()); | 268 base::Version version(path.BaseName().MaybeAsASCII()); |
| 234 | 269 |
| 235 // Ignore folders that don't have valid version names. These folders are not | 270 // 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. | 271 // managed by the component installer, so do not try to remove them. |
| 237 if (!version.IsValid()) | 272 if (!version.IsValid()) |
| 238 continue; | 273 continue; |
| 239 | 274 |
| 240 if (!base::DeleteFile(path, true)) | 275 if (!base::DeleteFile(path, true)) |
| 241 DLOG(ERROR) << "Couldn't delete " << path.value(); | 276 DLOG(ERROR) << "Couldn't delete " << path.value(); |
| 242 } | 277 } |
| 243 | 278 |
| 244 // Delete the base directory if it's empty now. | 279 // Delete the base directory if it's empty now. |
| 245 if (base::IsDirectoryEmpty(base_dir)) { | 280 if (base::IsDirectoryEmpty(current_install_dir_)) { |
| 246 if (base::DeleteFile(base_dir, false)) | 281 if (base::DeleteFile(current_install_dir_, false)) |
| 247 DLOG(ERROR) << "Couldn't delete " << base_dir.value(); | 282 DLOG(ERROR) << "Couldn't delete " << current_install_dir_.value(); |
| 248 } | 283 } |
| 249 } | 284 } |
| 250 | 285 |
| 251 base::FilePath DefaultComponentInstaller::GetInstallDirectory() { | |
| 252 return installer_traits_->GetBaseDirectory() | |
| 253 .AppendASCII(current_version_.GetString()); | |
| 254 } | |
| 255 | |
| 256 void DefaultComponentInstaller::FinishRegistration( | 286 void DefaultComponentInstaller::FinishRegistration( |
| 257 ComponentUpdateService* cus, | 287 ComponentUpdateService* cus, |
| 258 const base::Closure& callback) { | 288 const base::Closure& callback) { |
| 259 DCHECK(thread_checker_.CalledOnValidThread()); | 289 DCHECK(thread_checker_.CalledOnValidThread()); |
| 260 if (installer_traits_->CanAutoUpdate()) { | 290 if (installer_traits_->CanAutoUpdate()) { |
| 261 CrxComponent crx; | 291 CrxComponent crx; |
| 262 crx.name = installer_traits_->GetName(); | 292 crx.name = installer_traits_->GetName(); |
| 263 crx.requires_network_encryption = | 293 crx.requires_network_encryption = |
| 264 installer_traits_->RequiresNetworkEncryption(); | 294 installer_traits_->RequiresNetworkEncryption(); |
| 265 crx.installer = this; | 295 crx.installer = this; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 280 return; | 310 return; |
| 281 | 311 |
| 282 std::unique_ptr<base::DictionaryValue> manifest_copy( | 312 std::unique_ptr<base::DictionaryValue> manifest_copy( |
| 283 current_manifest_->DeepCopy()); | 313 current_manifest_->DeepCopy()); |
| 284 ComponentReady(std::move(manifest_copy)); | 314 ComponentReady(std::move(manifest_copy)); |
| 285 } | 315 } |
| 286 | 316 |
| 287 void DefaultComponentInstaller::ComponentReady( | 317 void DefaultComponentInstaller::ComponentReady( |
| 288 std::unique_ptr<base::DictionaryValue> manifest) { | 318 std::unique_ptr<base::DictionaryValue> manifest) { |
| 289 VLOG(1) << "Component ready, version " << current_version_.GetString() | 319 VLOG(1) << "Component ready, version " << current_version_.GetString() |
| 290 << " in " << GetInstallDirectory().value(); | 320 << " in " << current_install_dir_.value(); |
| 291 installer_traits_->ComponentReady(current_version_, GetInstallDirectory(), | 321 installer_traits_->ComponentReady(current_version_, current_install_dir_, |
| 292 std::move(manifest)); | 322 std::move(manifest)); |
| 293 } | 323 } |
| 294 | 324 |
| 295 } // namespace component_updater | 325 } // namespace component_updater |
| OLD | NEW |