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::LoadSystemInstallation() { | |
Sorin Jianu
2016/05/03 21:51:24
This is mostly finding the system install. Maybe r
waffles
2016/05/03 22:14:05
Done.
| |
156 base::FilePath path; | |
157 if (!PathService::Get(DIR_COMPONENT_SYSTEM, &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 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 a system-wide installation. | |
185 if (LoadSystemInstallation()) | |
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()) |
Sorin Jianu
2016/05/03 21:51:24
was this a bug?
waffles
2016/05/03 22:14:05
I believe it was safe, as the latest_manifest and
| |
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 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 |