summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extensions_service.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extensions_service.cc')
-rw-r--r--chrome/browser/extensions/extensions_service.cc82
1 files changed, 68 insertions, 14 deletions
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 2d1807e..05815a3 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -128,10 +128,39 @@ void ExtensionsService::InstallExtension(const FilePath& extension_path) {
scoped_refptr<ExtensionsServiceFrontendInterface>(this)));
}
+void ExtensionsService::UninstallExtension(const std::string& extension_id) {
+ Extension* extension = NULL;
+
+ ExtensionList::iterator iter;
+ for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+ if ((*iter)->id() == extension_id) {
+ extension = *iter;
+ break;
+ }
+ }
+
+ // Remove the extension from our list.
+ extensions_.erase(iter);
+
+ // Callers should check existence and that the extension is internal before
+ // calling us.
+ DCHECK(extension);
+ DCHECK(extension->is_uninstallable());
+
+ // Tell other services the extension is gone.
+ NotificationService::current()->Notify(NotificationType::EXTENSION_UNLOADED,
+ NotificationService::AllSources(),
+ Details<Extension>(extension));
+
+ // Tell the file thread to start deleting.
+ g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(backend_.get(),
+ &ExtensionsServiceBackend::UninstallExtension, extension_id));
+
+ delete extension;
+}
+
void ExtensionsService::LoadExtension(const FilePath& extension_path) {
- // TODO(aa): This message loop should probably come from a backend
- // interface, similar to how the message loop for the frontend comes
- // from the frontend interface.
g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(backend_.get(),
&ExtensionsServiceBackend::LoadSingleExtension,
@@ -261,7 +290,7 @@ void ExtensionsServiceBackend::LoadExtensionsFromInstallDirectory(
if (CheckExternalUninstall(extension_path, extension_id)) {
// TODO(erikkay): Possibly defer this operation to avoid slowing initial
// load of extensions.
- UninstallExtension(extension_path);
+ UninstallExtension(extension_id);
// No error needs to be reported. The extension effectively doesn't
// exist.
@@ -295,6 +324,7 @@ void ExtensionsServiceBackend::LoadSingleExtension(
Extension* extension = LoadExtension(extension_path,
false); // don't require ID
if (extension) {
+ extension->set_location(Extension::LOAD);
ExtensionList* extensions = new ExtensionList;
extensions->push_back(extension);
ReportExtensionsLoaded(extensions);
@@ -348,6 +378,12 @@ Extension* ExtensionsServiceBackend::LoadExtension(
return NULL;
}
+ FilePath external_marker = extension_path.AppendASCII(kExternalInstallFile);
+ if (file_util::PathExists(external_marker))
+ extension->set_location(Extension::EXTERNAL);
+ else
+ extension->set_location(Extension::INTERNAL);
+
// TODO(glen): Add theme resource validation here. http://crbug.com/11678
// Validate that claimed script resources actually exist.
for (size_t i = 0; i < extension->content_scripts().size(); ++i) {
@@ -795,6 +831,8 @@ void ExtensionsServiceBackend::CheckForExternalUpdates(
frontend_ = frontend;
#if defined(OS_WIN)
+ // TODO(port): Pull this out into an interface. That will also allow us to
+ // test the behavior of external extensions.
HKEY reg_root = HKEY_LOCAL_MACHINE;
RegistryKeyIterator iterator(reg_root, kRegistryExtensions);
while (iterator.Valid()) {
@@ -861,18 +899,34 @@ bool ExtensionsServiceBackend::CheckExternalUninstall(const FilePath& path,
}
// Assumes that the extension isn't currently loaded or in use.
-void ExtensionsServiceBackend::UninstallExtension(const FilePath& path) {
- FilePath parent = path.DirName();
- FilePath version =
- parent.AppendASCII(ExtensionsService::kCurrentVersionFileName);
- bool version_exists = file_util::PathExists(version);
- DCHECK(version_exists);
- if (!version_exists) {
- LOG(WARNING) << "Asked to uninstall bogus extension dir " << parent.value();
+void ExtensionsServiceBackend::UninstallExtension(
+ const std::string& extension_id) {
+ // First, delete the Current Version file. If the directory delete fails, then
+ // at least the extension won't be loaded again.
+ FilePath extension_directory = install_directory_.AppendASCII(extension_id);
+
+ if (!file_util::PathExists(extension_directory)) {
+ LOG(WARNING) << "Asked to remove a non-existent extension " << extension_id;
return;
}
- if (!file_util::Delete(parent, true)) {
- LOG(WARNING) << "Failed to delete " << parent.value();
+
+ FilePath current_version_file = extension_directory.AppendASCII(
+ ExtensionsService::kCurrentVersionFileName);
+ if (!file_util::PathExists(current_version_file)) {
+ LOG(WARNING) << "Extension " << extension_id
+ << " does not have a Current Version file.";
+ } else {
+ if (!file_util::Delete(current_version_file, false)) {
+ LOG(WARNING) << "Could not delete Current Version file for extension "
+ << extension_id;
+ return;
+ }
+ }
+
+ // Ok, now try and delete the entire rest of the directory.
+ if (!file_util::Delete(extension_directory, true)) {
+ LOG(WARNING) << "Could not delete directory for extension "
+ << extension_id;
}
}