| OLD | NEW |
| 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/extensions_service.h" | 5 #include "chrome/browser/extensions/extensions_service.h" |
| 6 | 6 |
| 7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/crypto/signature_verifier.h" | 9 #include "base/crypto/signature_verifier.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 // True if we got a response from the utility process and have cleaned up | 208 // True if we got a response from the utility process and have cleaned up |
| 209 // already. | 209 // already. |
| 210 bool got_response_; | 210 bool got_response_; |
| 211 }; | 211 }; |
| 212 | 212 |
| 213 ExtensionsService::ExtensionsService(Profile* profile, | 213 ExtensionsService::ExtensionsService(Profile* profile, |
| 214 const CommandLine* command_line, | 214 const CommandLine* command_line, |
| 215 MessageLoop* frontend_loop, | 215 MessageLoop* frontend_loop, |
| 216 MessageLoop* backend_loop) | 216 MessageLoop* backend_loop) |
| 217 : extension_prefs_(new ExtensionPrefs(profile->GetPrefs())), | 217 : extension_prefs_(new ExtensionPrefs(profile->GetPrefs())), |
| 218 extension_process_manager_(new ExtensionProcessManager(profile)), |
| 218 backend_loop_(backend_loop), | 219 backend_loop_(backend_loop), |
| 219 install_directory_(profile->GetPath().AppendASCII(kInstallDirectoryName)), | 220 install_directory_(profile->GetPath().AppendASCII(kInstallDirectoryName)), |
| 220 extensions_enabled_(false), | 221 extensions_enabled_(false), |
| 221 show_extensions_prompts_(true), | 222 show_extensions_prompts_(true), |
| 222 ready_(false) { | 223 ready_(false) { |
| 223 // Figure out if extension installation should be enabled. | 224 // Figure out if extension installation should be enabled. |
| 224 if (command_line->HasSwitch(switches::kEnableExtensions)) | 225 if (command_line->HasSwitch(switches::kEnableExtensions)) |
| 225 extensions_enabled_ = true; | 226 extensions_enabled_ = true; |
| 226 else if (profile->GetPrefs()->GetBoolean(prefs::kEnableExtensions)) | 227 else if (profile->GetPrefs()->GetBoolean(prefs::kEnableExtensions)) |
| 227 extensions_enabled_ = true; | 228 extensions_enabled_ = true; |
| 228 | 229 |
| 229 // We pass ownership of this object to the Backend. | 230 // We pass ownership of this object to the Backend. |
| 230 DictionaryValue* extensions = extension_prefs_->CopyCurrentExtensions(); | 231 DictionaryValue* extensions = extension_prefs_->CopyCurrentExtensions(); |
| 231 backend_ = new ExtensionsServiceBackend( | 232 backend_ = new ExtensionsServiceBackend( |
| 232 install_directory_, g_browser_process->resource_dispatcher_host(), | 233 install_directory_, g_browser_process->resource_dispatcher_host(), |
| 233 frontend_loop, extensions, extensions_enabled()); | 234 frontend_loop, extensions, extensions_enabled()); |
| 234 } | 235 } |
| 235 | 236 |
| 236 ExtensionsService::~ExtensionsService() { | 237 ExtensionsService::~ExtensionsService() { |
| 237 UnloadAllExtensions(); | 238 UnloadAllExtensions(); |
| 238 } | 239 } |
| 239 | 240 |
| 240 void ExtensionsService::SetExtensionsEnabled(bool enabled) { | 241 void ExtensionsService::SetExtensionsEnabled(bool enabled) { |
| 241 extensions_enabled_ = true; | 242 extensions_enabled_ = true; |
| 242 backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), | 243 backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), |
| 243 &ExtensionsServiceBackend::set_extensions_enabled, enabled)); | 244 &ExtensionsServiceBackend::set_extensions_enabled, enabled)); |
| 244 } | 245 } |
| 245 | 246 |
| 246 void ExtensionsService::Init() { | 247 void ExtensionsService::Init() { |
| 248 DCHECK(!ready_); |
| 247 DCHECK(extensions_.size() == 0); | 249 DCHECK(extensions_.size() == 0); |
| 248 | 250 |
| 249 // Start up the extension event routers. | 251 // Start up the extension event routers. |
| 250 ExtensionBrowserEventRouter::GetInstance()->Init(); | 252 ExtensionBrowserEventRouter::GetInstance()->Init(); |
| 251 | 253 |
| 252 LoadAllExtensions(); | 254 LoadAllExtensions(); |
| 253 | 255 |
| 254 // TODO(erikkay) this should probably be deferred to a future point | 256 // TODO(erikkay) this should probably be deferred to a future point |
| 255 // rather than running immediately at startup. | 257 // rather than running immediately at startup. |
| 256 CheckForUpdates(); | 258 CheckForUpdates(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 } | 320 } |
| 319 | 321 |
| 320 // Callers should not send us nonexistant extensions. | 322 // Callers should not send us nonexistant extensions. |
| 321 CHECK(extension); | 323 CHECK(extension); |
| 322 | 324 |
| 323 // Remove the extension from our list. | 325 // Remove the extension from our list. |
| 324 extensions_.erase(iter); | 326 extensions_.erase(iter); |
| 325 | 327 |
| 326 // Tell other services the extension is gone. | 328 // Tell other services the extension is gone. |
| 327 NotificationService::current()->Notify(NotificationType::EXTENSION_UNLOADED, | 329 NotificationService::current()->Notify(NotificationType::EXTENSION_UNLOADED, |
| 328 NotificationService::AllSources(), | 330 Source<ExtensionsService>(this), |
| 329 Details<Extension>(extension)); | 331 Details<Extension>(extension)); |
| 330 | 332 |
| 331 delete extension; | 333 delete extension; |
| 332 } | 334 } |
| 333 | 335 |
| 334 void ExtensionsService::UnloadAllExtensions() { | 336 void ExtensionsService::UnloadAllExtensions() { |
| 335 ExtensionList::iterator iter; | 337 ExtensionList::iterator iter; |
| 336 for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { | 338 for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) |
| 337 // Tell other services the extension is gone. | |
| 338 NotificationService::current()->Notify(NotificationType::EXTENSION_UNLOADED, | |
| 339 NotificationService::AllSources(), | |
| 340 Details<Extension>(*iter)); | |
| 341 delete *iter; | 339 delete *iter; |
| 342 } | |
| 343 extensions_.clear(); | 340 extensions_.clear(); |
| 341 |
| 342 // TODO(erikkay) should there be a notification for this? We can't use |
| 343 // EXTENSION_UNLOADED since that implies that the extension has been disabled |
| 344 // or uninstalled, and UnloadAll is just part of shutdown. |
| 344 } | 345 } |
| 345 | 346 |
| 346 void ExtensionsService::ReloadExtensions() { | 347 void ExtensionsService::ReloadExtensions() { |
| 347 UnloadAllExtensions(); | 348 UnloadAllExtensions(); |
| 348 LoadAllExtensions(); | 349 LoadAllExtensions(); |
| 349 } | 350 } |
| 350 | 351 |
| 351 void ExtensionsService::GarbageCollectExtensions() { | 352 void ExtensionsService::GarbageCollectExtensions() { |
| 352 backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), | 353 backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), |
| 353 &ExtensionsServiceBackend::GarbageCollectExtensions, | 354 &ExtensionsServiceBackend::GarbageCollectExtensions, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 } else { | 393 } else { |
| 393 // Extensions that get enabled get added to extensions_ and deleted later. | 394 // Extensions that get enabled get added to extensions_ and deleted later. |
| 394 // Anything skipped must be deleted now so we don't leak. | 395 // Anything skipped must be deleted now so we don't leak. |
| 395 delete *iter; | 396 delete *iter; |
| 396 } | 397 } |
| 397 } | 398 } |
| 398 | 399 |
| 399 if (enabled_extensions.size()) { | 400 if (enabled_extensions.size()) { |
| 400 NotificationService::current()->Notify( | 401 NotificationService::current()->Notify( |
| 401 NotificationType::EXTENSIONS_LOADED, | 402 NotificationType::EXTENSIONS_LOADED, |
| 402 NotificationService::AllSources(), | 403 Source<ExtensionsService>(this), |
| 403 Details<ExtensionList>(&enabled_extensions)); | 404 Details<ExtensionList>(&enabled_extensions)); |
| 404 } | 405 } |
| 405 } | 406 } |
| 406 | 407 |
| 407 void ExtensionsService::OnExtensionInstalled(Extension* extension, | 408 void ExtensionsService::OnExtensionInstalled(Extension* extension, |
| 408 Extension::InstallType install_type) { | 409 Extension::InstallType install_type) { |
| 409 extension_prefs_->OnExtensionInstalled(extension); | 410 extension_prefs_->OnExtensionInstalled(extension); |
| 410 | 411 |
| 411 // If the extension is a theme, tell the profile (and therefore ThemeProvider) | 412 // If the extension is a theme, tell the profile (and therefore ThemeProvider) |
| 412 // to apply it. | 413 // to apply it. |
| 413 if (extension->IsTheme()) { | 414 if (extension->IsTheme()) { |
| 414 NotificationService::current()->Notify( | 415 NotificationService::current()->Notify( |
| 415 NotificationType::THEME_INSTALLED, | 416 NotificationType::THEME_INSTALLED, |
| 416 NotificationService::AllSources(), | 417 Source<ExtensionsService>(this), |
| 417 Details<Extension>(extension)); | 418 Details<Extension>(extension)); |
| 418 } else { | 419 } else { |
| 419 NotificationService::current()->Notify( | 420 NotificationService::current()->Notify( |
| 420 NotificationType::EXTENSION_INSTALLED, | 421 NotificationType::EXTENSION_INSTALLED, |
| 421 NotificationService::AllSources(), | 422 Source<ExtensionsService>(this), |
| 422 Details<Extension>(extension)); | 423 Details<Extension>(extension)); |
| 423 } | 424 } |
| 424 } | 425 } |
| 425 | 426 |
| 426 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { | 427 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { |
| 427 Extension* extension = GetExtensionById(id); | 428 Extension* extension = GetExtensionById(id); |
| 428 if (extension && extension->IsTheme()) { | 429 if (extension && extension->IsTheme()) { |
| 429 NotificationService::current()->Notify( | 430 NotificationService::current()->Notify( |
| 430 NotificationType::THEME_INSTALLED, | 431 NotificationType::THEME_INSTALLED, |
| 431 NotificationService::AllSources(), | 432 Source<ExtensionsService>(this), |
| 432 Details<Extension>(extension)); | 433 Details<Extension>(extension)); |
| 433 } | 434 } |
| 434 } | 435 } |
| 435 | 436 |
| 436 Extension* ExtensionsService::GetExtensionById(const std::string& id) { | 437 Extension* ExtensionsService::GetExtensionById(const std::string& id) { |
| 437 for (ExtensionList::const_iterator iter = extensions_.begin(); | 438 for (ExtensionList::const_iterator iter = extensions_.begin(); |
| 438 iter != extensions_.end(); ++iter) { | 439 iter != extensions_.end(); ++iter) { |
| 439 if ((*iter)->id() == id) | 440 if ((*iter)->id() == id) |
| 440 return *iter; | 441 return *iter; |
| 441 } | 442 } |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1285 Extension::InstallType install_type = | 1286 Extension::InstallType install_type = |
| 1286 CompareToInstalledVersion(id, version->GetString(), ¤t_version); | 1287 CompareToInstalledVersion(id, version->GetString(), ¤t_version); |
| 1287 | 1288 |
| 1288 if (install_type == Extension::DOWNGRADE) | 1289 if (install_type == Extension::DOWNGRADE) |
| 1289 return false; | 1290 return false; |
| 1290 | 1291 |
| 1291 return (install_type == Extension::UPGRADE || | 1292 return (install_type == Extension::UPGRADE || |
| 1292 install_type == Extension::NEW_INSTALL || | 1293 install_type == Extension::NEW_INSTALL || |
| 1293 NeedsReinstall(id, current_version)); | 1294 NeedsReinstall(id, current_version)); |
| 1294 } | 1295 } |
| OLD | NEW |