Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Side by Side Diff: chrome/browser/extensions/crx_installer.cc

Issue 345023: Get rid of MessageLoop* caching in extensions code. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 "chrome/browser/extensions/crx_installer.h" 5 #include "chrome/browser/extensions/crx_installer.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/scoped_temp_dir.h" 9 #include "base/scoped_temp_dir.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "base/task.h" 11 #include "base/task.h"
12 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chrome_thread.h"
13 #include "chrome/browser/extensions/extension_file_util.h" 14 #include "chrome/browser/extensions/extension_file_util.h"
14 #include "chrome/common/extensions/extension_error_reporter.h" 15 #include "chrome/common/extensions/extension_error_reporter.h"
15 #include "chrome/common/notification_service.h" 16 #include "chrome/common/notification_service.h"
16 #include "chrome/common/notification_type.h" 17 #include "chrome/common/notification_type.h"
17 #include "grit/chromium_strings.h" 18 #include "grit/chromium_strings.h"
18 #include "third_party/skia/include/core/SkBitmap.h" 19 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "webkit/glue/image_decoder.h" 20 #include "webkit/glue/image_decoder.h"
20 21
21 namespace { 22 namespace {
22 // Helper function to delete files. This is used to avoid ugly casts which 23 // Helper function to delete files. This is used to avoid ugly casts which
23 // would be necessary with PostMessage since file_util::Delete is overloaded. 24 // would be necessary with PostMessage since file_util::Delete is overloaded.
24 static void DeleteFileHelper(const FilePath& path, bool recursive) { 25 static void DeleteFileHelper(const FilePath& path, bool recursive) {
25 file_util::Delete(path, recursive); 26 file_util::Delete(path, recursive);
26 } 27 }
27 } 28 }
28 29
29 void CrxInstaller::Start(const FilePath& crx_path, 30 void CrxInstaller::Start(const FilePath& crx_path,
30 const FilePath& install_directory, 31 const FilePath& install_directory,
31 Extension::Location install_source, 32 Extension::Location install_source,
32 const std::string& expected_id, 33 const std::string& expected_id,
33 bool delete_crx, 34 bool delete_crx,
34 bool allow_privilege_increase, 35 bool allow_privilege_increase,
35 MessageLoop* file_loop,
36 ExtensionsService* frontend, 36 ExtensionsService* frontend,
37 ExtensionInstallUI* client) { 37 ExtensionInstallUI* client) {
38 // Note: We don't keep a reference because this object manages its own 38 // Note: We don't keep a reference because this object manages its own
39 // lifetime. 39 // lifetime.
40 new CrxInstaller(crx_path, install_directory, install_source, expected_id, 40 new CrxInstaller(crx_path, install_directory, install_source, expected_id,
41 delete_crx, allow_privilege_increase, file_loop, frontend, 41 delete_crx, allow_privilege_increase, frontend, client);
42 client);
43 } 42 }
44 43
45 CrxInstaller::CrxInstaller(const FilePath& crx_path, 44 CrxInstaller::CrxInstaller(const FilePath& crx_path,
46 const FilePath& install_directory, 45 const FilePath& install_directory,
47 Extension::Location install_source, 46 Extension::Location install_source,
48 const std::string& expected_id, 47 const std::string& expected_id,
49 bool delete_crx, 48 bool delete_crx,
50 bool allow_privilege_increase, 49 bool allow_privilege_increase,
51 MessageLoop* file_loop,
52 ExtensionsService* frontend, 50 ExtensionsService* frontend,
53 ExtensionInstallUI* client) 51 ExtensionInstallUI* client)
54 : crx_path_(crx_path), 52 : crx_path_(crx_path),
55 install_directory_(install_directory), 53 install_directory_(install_directory),
56 install_source_(install_source), 54 install_source_(install_source),
57 expected_id_(expected_id), 55 expected_id_(expected_id),
58 delete_crx_(delete_crx), 56 delete_crx_(delete_crx),
59 allow_privilege_increase_(allow_privilege_increase), 57 allow_privilege_increase_(allow_privilege_increase),
60 file_loop_(file_loop),
61 ui_loop_(MessageLoop::current()),
62 frontend_(frontend), 58 frontend_(frontend),
63 client_(client) { 59 client_(client) {
64 60
65 extensions_enabled_ = frontend_->extensions_enabled(); 61 extensions_enabled_ = frontend_->extensions_enabled();
66 62
67 unpacker_ = new SandboxedExtensionUnpacker( 63 unpacker_ = new SandboxedExtensionUnpacker(
68 crx_path, g_browser_process->resource_dispatcher_host(), this); 64 crx_path, g_browser_process->resource_dispatcher_host(), this);
69 65
70 file_loop->PostTask(FROM_HERE, NewRunnableMethod(unpacker_, 66 ChromeThread::PostTask(
71 &SandboxedExtensionUnpacker::Start)); 67 ChromeThread::FILE, FROM_HERE,
68 NewRunnableMethod(unpacker_, &SandboxedExtensionUnpacker::Start));
72 } 69 }
73 70
74 CrxInstaller::~CrxInstaller() { 71 CrxInstaller::~CrxInstaller() {
75 // Delete the temp directory and crx file as necessary. Note that the 72 // Delete the temp directory and crx file as necessary. Note that the
76 // destructor might be called on any thread, so we post a task to the file 73 // destructor might be called on any thread, so we post a task to the file
77 // thread to make sure the delete happens there. 74 // thread to make sure the delete happens there.
78 if (!temp_dir_.value().empty()) { 75 if (!temp_dir_.value().empty()) {
79 file_loop_->PostTask(FROM_HERE, NewRunnableFunction(&DeleteFileHelper, 76 ChromeThread::PostTask(
80 temp_dir_, true)); // recursive delete 77 ChromeThread::FILE, FROM_HERE,
78 NewRunnableFunction(&DeleteFileHelper, temp_dir_, true));
81 } 79 }
82 80
83 if (delete_crx_) { 81 if (delete_crx_) {
84 file_loop_->PostTask(FROM_HERE, NewRunnableFunction(&DeleteFileHelper, 82 ChromeThread::PostTask(
85 crx_path_, false)); // non-recursive delete 83 ChromeThread::FILE, FROM_HERE,
84 NewRunnableFunction(&DeleteFileHelper, crx_path_, false));
86 } 85 }
87 } 86 }
88 87
89 void CrxInstaller::OnUnpackFailure(const std::string& error_message) { 88 void CrxInstaller::OnUnpackFailure(const std::string& error_message) {
90 DCHECK(MessageLoop::current() == file_loop_); 89 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
91 ReportFailureFromFileThread(error_message); 90 ReportFailureFromFileThread(error_message);
92 } 91 }
93 92
94 void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir, 93 void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
95 const FilePath& extension_dir, 94 const FilePath& extension_dir,
96 Extension* extension) { 95 Extension* extension) {
97 DCHECK(MessageLoop::current() == file_loop_); 96 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
98 97
99 // Note: We take ownership of |extension| and |temp_dir|. 98 // Note: We take ownership of |extension| and |temp_dir|.
100 extension_.reset(extension); 99 extension_.reset(extension);
101 temp_dir_ = temp_dir; 100 temp_dir_ = temp_dir;
102 101
103 // The unpack dir we don't have to delete explicity since it is a child of 102 // The unpack dir we don't have to delete explicity since it is a child of
104 // the temp dir. 103 // the temp dir.
105 unpacked_extension_root_ = extension_dir; 104 unpacked_extension_root_ = extension_dir;
106 DCHECK(file_util::ContainsPath(temp_dir_, unpacked_extension_root_)); 105 DCHECK(file_util::ContainsPath(temp_dir_, unpacked_extension_root_));
107 106
(...skipping 13 matching lines...) Expand all
121 extension->id().c_str(), 120 extension->id().c_str(),
122 expected_id_.c_str())); 121 expected_id_.c_str()));
123 return; 122 return;
124 } 123 }
125 124
126 if (client_.get()) { 125 if (client_.get()) {
127 FilePath icon_path = 126 FilePath icon_path =
128 extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE).GetFilePath(); 127 extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE).GetFilePath();
129 DecodeInstallIcon(icon_path, &install_icon_); 128 DecodeInstallIcon(icon_path, &install_icon_);
130 } 129 }
131 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, 130 ChromeThread::PostTask(
132 &CrxInstaller::ConfirmInstall)); 131 ChromeThread::UI, FROM_HERE,
132 NewRunnableMethod(this, &CrxInstaller::ConfirmInstall));
133 } 133 }
134 134
135 // static 135 // static
136 void CrxInstaller::DecodeInstallIcon(const FilePath& large_icon_path, 136 void CrxInstaller::DecodeInstallIcon(const FilePath& large_icon_path,
137 scoped_ptr<SkBitmap>* result) { 137 scoped_ptr<SkBitmap>* result) {
138 if (large_icon_path.empty()) 138 if (large_icon_path.empty())
139 return; 139 return;
140 140
141 std::string file_contents; 141 std::string file_contents;
142 if (!file_util::ReadFileToString(large_icon_path, &file_contents)) { 142 if (!file_util::ReadFileToString(large_icon_path, &file_contents)) {
(...skipping 18 matching lines...) Expand all
161 LOG(ERROR) << "Icon file has unexpected size: " 161 LOG(ERROR) << "Icon file has unexpected size: "
162 << IntToString(decoded->width()) << "x" 162 << IntToString(decoded->width()) << "x"
163 << IntToString(decoded->height()); 163 << IntToString(decoded->height());
164 return; 164 return;
165 } 165 }
166 166
167 result->swap(decoded); 167 result->swap(decoded);
168 } 168 }
169 169
170 void CrxInstaller::ConfirmInstall() { 170 void CrxInstaller::ConfirmInstall() {
171 DCHECK(MessageLoop::current() == ui_loop_); 171 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
172 if (frontend_->extension_prefs()->IsExtensionBlacklisted(extension_->id())) { 172 if (frontend_->extension_prefs()->IsExtensionBlacklisted(extension_->id())) {
173 LOG(INFO) << "This extension: " << extension_->id() 173 LOG(INFO) << "This extension: " << extension_->id()
174 << " is blacklisted. Install failed."; 174 << " is blacklisted. Install failed.";
175 if (client_.get()) { 175 if (client_.get()) {
176 client_->OnInstallFailure("This extension is blacklisted."); 176 client_->OnInstallFailure("This extension is blacklisted.");
177 } 177 }
178 return; 178 return;
179 } 179 }
180 180
181 current_version_ = 181 current_version_ =
182 frontend_->extension_prefs()->GetVersionString(extension_->id()); 182 frontend_->extension_prefs()->GetVersionString(extension_->id());
183 183
184 if (client_.get()) { 184 if (client_.get()) {
185 AddRef(); // balanced in ContinueInstall() and AbortInstall(). 185 AddRef(); // balanced in ContinueInstall() and AbortInstall().
186 client_->ConfirmInstall(this, extension_.get(), install_icon_.get()); 186 client_->ConfirmInstall(this, extension_.get(), install_icon_.get());
187 } else { 187 } else {
188 file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, 188 ChromeThread::PostTask(
189 &CrxInstaller::CompleteInstall)); 189 ChromeThread::FILE, FROM_HERE,
190 NewRunnableMethod(this, &CrxInstaller::CompleteInstall));
190 } 191 }
191 return; 192 return;
192 } 193 }
193 194
194 void CrxInstaller::ContinueInstall() { 195 void CrxInstaller::ContinueInstall() {
195 file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, 196 ChromeThread::PostTask(
196 &CrxInstaller::CompleteInstall)); 197 ChromeThread::FILE, FROM_HERE,
198 NewRunnableMethod(this, &CrxInstaller::CompleteInstall));
197 199
198 Release(); // balanced in ConfirmInstall(). 200 Release(); // balanced in ConfirmInstall().
199 } 201 }
200 202
201 void CrxInstaller::AbortInstall() { 203 void CrxInstaller::AbortInstall() {
202 // Kill the theme loading bubble. 204 // Kill the theme loading bubble.
203 NotificationService* service = NotificationService::current(); 205 NotificationService* service = NotificationService::current();
204 service->Notify(NotificationType::NO_THEME_DETECTED, 206 service->Notify(NotificationType::NO_THEME_DETECTED,
205 Source<CrxInstaller>(this), 207 Source<CrxInstaller>(this),
206 NotificationService::NoDetails()); 208 NotificationService::NoDetails());
207 Release(); // balanced in ConfirmInstall(). 209 Release(); // balanced in ConfirmInstall().
208 210
209 // We're done. Since we don't post any more tasks to ourself, our ref count 211 // We're done. Since we don't post any more tasks to ourself, our ref count
210 // should go to zero and we die. The destructor will clean up the temp dir. 212 // should go to zero and we die. The destructor will clean up the temp dir.
211 } 213 }
212 214
213 void CrxInstaller::CompleteInstall() { 215 void CrxInstaller::CompleteInstall() {
214 DCHECK(MessageLoop::current() == file_loop_); 216 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
215 217
216 FilePath version_dir; 218 FilePath version_dir;
217 Extension::InstallType install_type = 219 Extension::InstallType install_type =
218 extension_file_util::CompareToInstalledVersion( 220 extension_file_util::CompareToInstalledVersion(
219 install_directory_, extension_->id(), current_version_, 221 install_directory_, extension_->id(), current_version_,
220 extension_->VersionString(), &version_dir); 222 extension_->VersionString(), &version_dir);
221 223
222 if (install_type == Extension::DOWNGRADE) { 224 if (install_type == Extension::DOWNGRADE) {
223 ReportFailureFromFileThread("Attempted to downgrade extension."); 225 ReportFailureFromFileThread("Attempted to downgrade extension.");
224 return; 226 return;
(...skipping 20 matching lines...) Expand all
245 std::string error; 247 std::string error;
246 extension_.reset(extension_file_util::LoadExtension(version_dir, true, 248 extension_.reset(extension_file_util::LoadExtension(version_dir, true,
247 &error)); 249 &error));
248 DCHECK(error.empty()); 250 DCHECK(error.empty());
249 extension_->set_location(install_source_); 251 extension_->set_location(install_source_);
250 252
251 ReportSuccessFromFileThread(); 253 ReportSuccessFromFileThread();
252 } 254 }
253 255
254 void CrxInstaller::ReportFailureFromFileThread(const std::string& error) { 256 void CrxInstaller::ReportFailureFromFileThread(const std::string& error) {
255 DCHECK(MessageLoop::current() == file_loop_); 257 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
256 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, 258 ChromeThread::PostTask(
257 &CrxInstaller::ReportFailureFromUIThread, error)); 259 ChromeThread::UI, FROM_HERE,
260 NewRunnableMethod(this, &CrxInstaller::ReportFailureFromUIThread, error));
258 } 261 }
259 262
260 void CrxInstaller::ReportFailureFromUIThread(const std::string& error) { 263 void CrxInstaller::ReportFailureFromUIThread(const std::string& error) {
261 DCHECK(MessageLoop::current() == ui_loop_); 264 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
262 265
263 NotificationService* service = NotificationService::current(); 266 NotificationService* service = NotificationService::current();
264 service->Notify(NotificationType::EXTENSION_INSTALL_ERROR, 267 service->Notify(NotificationType::EXTENSION_INSTALL_ERROR,
265 Source<CrxInstaller>(this), 268 Source<CrxInstaller>(this),
266 Details<const std::string>(&error)); 269 Details<const std::string>(&error));
267 270
268 // This isn't really necessary, it is only used because unit tests expect to 271 // This isn't really necessary, it is only used because unit tests expect to
269 // see errors get reported via this interface. 272 // see errors get reported via this interface.
270 // 273 //
271 // TODO(aa): Need to go through unit tests and clean them up too, probably get 274 // TODO(aa): Need to go through unit tests and clean them up too, probably get
272 // rid of this line. 275 // rid of this line.
273 ExtensionErrorReporter::GetInstance()->ReportError(error, false); // quiet 276 ExtensionErrorReporter::GetInstance()->ReportError(error, false); // quiet
274 277
275 if (client_.get()) 278 if (client_.get())
276 client_->OnInstallFailure(error); 279 client_->OnInstallFailure(error);
277 } 280 }
278 281
279 void CrxInstaller::ReportOverinstallFromFileThread() { 282 void CrxInstaller::ReportOverinstallFromFileThread() {
280 DCHECK(MessageLoop::current() == file_loop_); 283 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
281 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, 284 ChromeThread::PostTask(
282 &CrxInstaller::ReportOverinstallFromUIThread)); 285 ChromeThread::UI, FROM_HERE,
286 NewRunnableMethod(this, &CrxInstaller::ReportOverinstallFromUIThread));
283 } 287 }
284 288
285 void CrxInstaller::ReportOverinstallFromUIThread() { 289 void CrxInstaller::ReportOverinstallFromUIThread() {
286 DCHECK(MessageLoop::current() == ui_loop_); 290 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
287 291
288 NotificationService* service = NotificationService::current(); 292 NotificationService* service = NotificationService::current();
289 service->Notify(NotificationType::EXTENSION_OVERINSTALL_ERROR, 293 service->Notify(NotificationType::EXTENSION_OVERINSTALL_ERROR,
290 Source<CrxInstaller>(this), 294 Source<CrxInstaller>(this),
291 Details<const FilePath>(&extension_->path())); 295 Details<const FilePath>(&extension_->path()));
292 296
293 if (client_.get()) 297 if (client_.get())
294 client_->OnOverinstallAttempted(extension_.get()); 298 client_->OnOverinstallAttempted(extension_.get());
295 299
296 frontend_->OnExtensionOverinstallAttempted(extension_->id()); 300 frontend_->OnExtensionOverinstallAttempted(extension_->id());
297 } 301 }
298 302
299 void CrxInstaller::ReportSuccessFromFileThread() { 303 void CrxInstaller::ReportSuccessFromFileThread() {
300 DCHECK(MessageLoop::current() == file_loop_); 304 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
301 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, 305 ChromeThread::PostTask(
302 &CrxInstaller::ReportSuccessFromUIThread)); 306 ChromeThread::UI, FROM_HERE,
307 NewRunnableMethod(this, &CrxInstaller::ReportSuccessFromUIThread));
303 } 308 }
304 309
305 void CrxInstaller::ReportSuccessFromUIThread() { 310 void CrxInstaller::ReportSuccessFromUIThread() {
306 DCHECK(MessageLoop::current() == ui_loop_); 311 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
307 312
308 // If there is a client, tell the client about installation. 313 // If there is a client, tell the client about installation.
309 if (client_.get()) 314 if (client_.get())
310 client_->OnInstallSuccess(extension_.get()); 315 client_->OnInstallSuccess(extension_.get());
311 316
312 // Tell the frontend about the installation and hand off ownership of 317 // Tell the frontend about the installation and hand off ownership of
313 // extension_ to it. 318 // extension_ to it.
314 frontend_->OnExtensionInstalled(extension_.release(), 319 frontend_->OnExtensionInstalled(extension_.release(),
315 allow_privilege_increase_); 320 allow_privilege_increase_);
316 321
317 // We're done. We don't post any more tasks to ourselves so we are deleted 322 // We're done. We don't post any more tasks to ourselves so we are deleted
318 // soon. 323 // soon.
319 } 324 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/crx_installer.h ('k') | chrome/browser/extensions/extension_disabled_infobar_delegate.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698