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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/bind_helpers.h" | 6 #include "base/bind_helpers.h" |
| 7 #include "base/files/file_enumerator.h" | 7 #include "base/files/file_enumerator.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/message_loop/message_loop_proxy.h" | 11 #include "base/message_loop/message_loop_proxy.h" |
| 12 #include "base/sequenced_task_runner.h" | 12 #include "base/sequenced_task_runner.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "base/version.h" | 15 #include "base/version.h" |
| 16 // TODO(ddorwin): Find a better place for ReadManifest. | 16 // TODO(ddorwin): Find a better place for ReadManifest. |
| 17 #include "components/component_updater/component_updater_service.h" | 17 #include "components/component_updater/component_updater_service.h" |
| 18 #include "components/component_updater/default_component_installer.h" | 18 #include "components/component_updater/default_component_installer.h" |
| 19 #include "components/update_client/component_unpacker.h" | 19 #include "components/update_client/component_unpacker.h" |
| 20 #include "components/update_client/update_client.h" | 20 #include "components/update_client/utils.h" |
| 21 | 21 |
| 22 using update_client::CrxComponent; | 22 using update_client::CrxComponent; |
| 23 | 23 |
| 24 namespace component_updater { | 24 namespace component_updater { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | |
| 27 // Version "0" corresponds to no installed version. By the server's conventions, | 28 // Version "0" corresponds to no installed version. By the server's conventions, |
| 28 // we represent it as a dotted quad. | 29 // we represent it as a dotted quad. |
| 29 const char kNullVersion[] = "0.0.0.0"; | 30 const char kNullVersion[] = "0.0.0.0"; |
| 31 | |
| 32 void UninstallOnTaskRunner(const base::FilePath& base_dir) { | |
| 33 std::vector<base::FilePath> paths; | |
| 34 base::FileEnumerator file_enumerator( | |
| 35 base_dir, false, base::FileEnumerator::DIRECTORIES); | |
| 36 for (base::FilePath path = file_enumerator.Next(); | |
| 37 !path.value().empty(); | |
| 38 path = file_enumerator.Next()) { | |
| 39 base::Version version(path.BaseName().MaybeAsASCII()); | |
| 40 | |
| 41 // Ignore folders that don't have valid version names. These folders are not | |
| 42 // managed by the component installer, so do not try to remove them. | |
| 43 if (!version.IsValid()) | |
| 44 continue; | |
| 45 | |
| 46 if (!base::DeleteFile(path, true)) | |
| 47 DLOG(ERROR) << "Couldn't delete " << path.value(); | |
| 48 } | |
| 49 | |
| 50 // Delete the base directory if it's empty now. | |
| 51 if (base::IsDirectoryEmpty(base_dir)) { | |
| 52 if (base::DeleteFile(base_dir, false)) | |
| 53 DLOG(ERROR) << "Couldn't delete " << base_dir.value(); | |
| 54 } | |
| 55 } | |
| 56 | |
| 30 } // namespace | 57 } // namespace |
| 31 | 58 |
| 32 ComponentInstallerTraits::~ComponentInstallerTraits() { | 59 ComponentInstallerTraits::~ComponentInstallerTraits() { |
| 33 } | 60 } |
| 34 | 61 |
| 35 DefaultComponentInstaller::DefaultComponentInstaller( | 62 DefaultComponentInstaller::DefaultComponentInstaller( |
| 36 scoped_ptr<ComponentInstallerTraits> installer_traits) | 63 scoped_ptr<ComponentInstallerTraits> installer_traits) |
| 37 : current_version_(kNullVersion), | 64 : current_version_(kNullVersion), |
| 65 should_uninstall_on_destruction_(false), | |
| 38 main_task_runner_(base::MessageLoopProxy::current()) { | 66 main_task_runner_(base::MessageLoopProxy::current()) { |
| 39 installer_traits_ = installer_traits.Pass(); | 67 installer_traits_ = installer_traits.Pass(); |
| 40 } | 68 } |
| 41 | 69 |
| 42 DefaultComponentInstaller::~DefaultComponentInstaller() { | 70 DefaultComponentInstaller::~DefaultComponentInstaller() { |
| 43 DCHECK(thread_checker_.CalledOnValidThread()); | 71 DCHECK(thread_checker_.CalledOnValidThread()); |
| 72 if (should_uninstall_on_destruction_) { | |
|
Sorin Jianu
2015/02/05 22:55:35
If Chrome is on the exit path, it is possible that
Bernhard Bauer
2015/02/05 23:57:35
No, SupervisedUserWhitelistService keeps track of
Sorin Jianu
2015/02/06 00:22:04
I think cleaning up on startup could be wise. I do
Bernhard Bauer
2015/02/06 16:05:05
OK. Something for a followup CL maybe?
| |
| 73 task_runner_->PostTask(FROM_HERE, | |
| 74 base::Bind(&UninstallOnTaskRunner, | |
| 75 installer_traits_->GetBaseDirectory())); | |
| 76 } | |
| 44 } | 77 } |
| 45 | 78 |
| 46 void DefaultComponentInstaller::Register(ComponentUpdateService* cus) { | 79 void DefaultComponentInstaller::Register(ComponentUpdateService* cus) { |
| 47 DCHECK(thread_checker_.CalledOnValidThread()); | 80 DCHECK(thread_checker_.CalledOnValidThread()); |
| 48 task_runner_ = cus->GetSequencedTaskRunner(); | 81 task_runner_ = cus->GetSequencedTaskRunner(); |
| 49 | 82 |
| 50 if (!installer_traits_) { | 83 if (!installer_traits_) { |
| 51 NOTREACHED() << "A DefaultComponentInstaller has been created but " | 84 NOTREACHED() << "A DefaultComponentInstaller has been created but " |
| 52 << "has no installer traits."; | 85 << "has no installer traits."; |
| 53 return; | 86 return; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 70 return false; | 103 return false; |
| 71 if (!installer_traits_->OnCustomInstall(manifest, install_path)) | 104 if (!installer_traits_->OnCustomInstall(manifest, install_path)) |
| 72 return false; | 105 return false; |
| 73 if (!installer_traits_->VerifyInstallation(manifest, install_path)) | 106 if (!installer_traits_->VerifyInstallation(manifest, install_path)) |
| 74 return false; | 107 return false; |
| 75 return true; | 108 return true; |
| 76 } | 109 } |
| 77 | 110 |
| 78 bool DefaultComponentInstaller::Install(const base::DictionaryValue& manifest, | 111 bool DefaultComponentInstaller::Install(const base::DictionaryValue& manifest, |
| 79 const base::FilePath& unpack_path) { | 112 const base::FilePath& unpack_path) { |
| 113 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 114 | |
| 80 std::string manifest_version; | 115 std::string manifest_version; |
| 81 manifest.GetStringASCII("version", &manifest_version); | 116 manifest.GetStringASCII("version", &manifest_version); |
| 82 base::Version version(manifest_version.c_str()); | 117 base::Version version(manifest_version.c_str()); |
| 83 if (!version.IsValid()) | 118 if (!version.IsValid()) |
| 84 return false; | 119 return false; |
| 85 if (current_version_.CompareTo(version) > 0) | 120 if (current_version_.CompareTo(version) > 0) |
| 86 return false; | 121 return false; |
| 87 base::FilePath install_path = | 122 base::FilePath install_path = |
| 88 installer_traits_->GetBaseDirectory().AppendASCII(version.GetString()); | 123 installer_traits_->GetBaseDirectory().AppendASCII(version.GetString()); |
| 89 if (base::PathExists(install_path)) { | 124 if (base::PathExists(install_path)) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 112 base::FilePath* installed_file) { | 147 base::FilePath* installed_file) { |
| 113 if (current_version_.Equals(base::Version(kNullVersion))) | 148 if (current_version_.Equals(base::Version(kNullVersion))) |
| 114 return false; // No component has been installed yet. | 149 return false; // No component has been installed yet. |
| 115 | 150 |
| 116 *installed_file = installer_traits_->GetBaseDirectory() | 151 *installed_file = installer_traits_->GetBaseDirectory() |
| 117 .AppendASCII(current_version_.GetString()) | 152 .AppendASCII(current_version_.GetString()) |
| 118 .AppendASCII(file); | 153 .AppendASCII(file); |
| 119 return true; | 154 return true; |
| 120 } | 155 } |
| 121 | 156 |
| 157 void DefaultComponentInstaller::Unregister(ComponentUpdateService* cus) { | |
| 158 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 159 | |
| 160 CrxComponent crx; | |
| 161 installer_traits_->GetHash(&crx.pk_hash); | |
| 162 ComponentUpdateService::Status status = | |
| 163 cus->UnregisterComponent(GetCrxComponentID(crx)); | |
| 164 DCHECK_EQ(ComponentUpdateService::kOk, status); | |
| 165 | |
| 166 // Wait with uninstallation until all references have been dropped. | |
| 167 should_uninstall_on_destruction_ = true; | |
|
Sorin Jianu
2015/02/05 22:55:35
Would it be possible to run the uninstall code her
Bernhard Bauer
2015/02/05 23:57:35
The problem with that is that when this method is
Sorin Jianu
2015/02/06 00:22:04
Right. I wonder if this would work. ComponentInsta
Bernhard Bauer
2015/02/06 16:05:05
Done.
| |
| 168 } | |
| 169 | |
| 122 void DefaultComponentInstaller::StartRegistration(ComponentUpdateService* cus) { | 170 void DefaultComponentInstaller::StartRegistration(ComponentUpdateService* cus) { |
| 123 DCHECK(task_runner_.get()); | 171 DCHECK(task_runner_.get()); |
| 124 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 172 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 125 base::FilePath base_dir = installer_traits_->GetBaseDirectory(); | 173 base::FilePath base_dir = installer_traits_->GetBaseDirectory(); |
| 126 if (!base::PathExists(base_dir) && !base::CreateDirectory(base_dir)) { | 174 if (!base::PathExists(base_dir) && !base::CreateDirectory(base_dir)) { |
| 127 NOTREACHED() << "Could not create the base directory for " | 175 NOTREACHED() << "Could not create the base directory for " |
| 128 << installer_traits_->GetName() << " (" | 176 << installer_traits_->GetName() << " (" |
| 129 << base_dir.MaybeAsASCII() << ")."; | 177 << base_dir.MaybeAsASCII() << ")."; |
| 130 return; | 178 return; |
| 131 } | 179 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 ComponentReady(manifest_copy.Pass()); | 276 ComponentReady(manifest_copy.Pass()); |
| 229 } | 277 } |
| 230 | 278 |
| 231 void DefaultComponentInstaller::ComponentReady( | 279 void DefaultComponentInstaller::ComponentReady( |
| 232 scoped_ptr<base::DictionaryValue> manifest) { | 280 scoped_ptr<base::DictionaryValue> manifest) { |
| 233 installer_traits_->ComponentReady( | 281 installer_traits_->ComponentReady( |
| 234 current_version_, GetInstallDirectory(), manifest.Pass()); | 282 current_version_, GetInstallDirectory(), manifest.Pass()); |
| 235 } | 283 } |
| 236 | 284 |
| 237 } // namespace component_updater | 285 } // namespace component_updater |
| OLD | NEW |