Chromium Code Reviews

Side by Side Diff: components/component_updater/default_component_installer.cc

Issue 1937683002: Implement support in DefaultComponentInstaller for picking up bundled (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ready for review. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
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...)
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...)
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 &current_fingerprint_); 244 &current_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...)
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
OLDNEW

Powered by Google App Engine