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

Unified Diff: chrome/browser/extensions/extension_assets_manager_chromeos.cc

Issue 303693011: Add garbage collection for shared extensions on Chrome OS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed Chromium OS valgrind bot Created 6 years, 7 months 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/extension_assets_manager_chromeos.cc
diff --git a/chrome/browser/extensions/extension_assets_manager_chromeos.cc b/chrome/browser/extensions/extension_assets_manager_chromeos.cc
index 4db49938cf7c66f5c50b3e187e9357db88a4ba78..d76d86aed09cbdbf53ffab1fe4c70d7a57a01f15 100644
--- a/chrome/browser/extensions/extension_assets_manager_chromeos.cc
+++ b/chrome/browser/extensions/extension_assets_manager_chromeos.cc
@@ -16,10 +16,12 @@
#include "base/sequenced_task_runner.h"
#include "base/sys_info.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/chromeos_switches.h"
#include "content/public/browser/browser_thread.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/file_util.h"
@@ -30,14 +32,8 @@ using content::BrowserThread;
namespace extensions {
namespace {
-// A dictionary that maps shared extension IDs to version/paths/users.
-const char kSharedExtensions[] = "SharedExtensions";
-
-// Name of path attribute in shared extensions map.
-const char kSharedExtensionPath[] = "path";
-
-// Name of users attribute (list of user emails) in shared extensions map.
-const char kSharedExtensionUsers[] = "users";
+// Path to shared extensions install dir.
+const char kSharedExtensionsDir[] = "/var/cache/shared_extensions";
// Shared install dir overrider for tests only.
static const base::FilePath* g_shared_install_dir_override = NULL;
@@ -113,9 +109,12 @@ class ExtensionAssetsManagerHelper {
} // namespace
-// Path to shared extensions install dir.
-const char ExtensionAssetsManagerChromeOS::kSharedExtensionsDir[] =
- "/var/cache/shared_extensions";
+const char ExtensionAssetsManagerChromeOS::kSharedExtensions[] =
+ "SharedExtensions";
+
+const char ExtensionAssetsManagerChromeOS::kSharedExtensionPath[] = "path";
+
+const char ExtensionAssetsManagerChromeOS::kSharedExtensionUsers[] = "users";
ExtensionAssetsManagerChromeOS::ExtensionAssetsManagerChromeOS() { }
@@ -183,6 +182,49 @@ void ExtensionAssetsManagerChromeOS::UninstallExtension(
}
// static
+base::FilePath ExtensionAssetsManagerChromeOS::GetSharedInstallDir() {
+ if (g_shared_install_dir_override)
+ return *g_shared_install_dir_override;
+ else
+ return base::FilePath(kSharedExtensionsDir);
+}
+
+// static
+bool ExtensionAssetsManagerChromeOS::CleanUpSharedExtensions(
+ std::multimap<std::string, base::FilePath>* live_extension_paths) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ PrefService* local_state = g_browser_process->local_state();
+ // It happens in many unit tests.
+ if (!local_state)
+ return false;
+
+ DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
+ std::vector<std::string> extensions;
+ extensions.reserve(shared_extensions->size());
+ for (base::DictionaryValue::Iterator it(*shared_extensions);
+ !it.IsAtEnd(); it.Advance()) {
+ extensions.push_back(it.key());
+ }
+
+ for (std::vector<std::string>::iterator it = extensions.begin();
+ it != extensions.end(); it++) {
+ base::DictionaryValue* extension_info = NULL;
+ if (!shared_extensions->GetDictionary(*it, &extension_info)) {
+ NOTREACHED();
+ return false;
+ }
+ if (!CleanUpExtension(*it, extension_info, live_extension_paths)) {
+ return false;
+ }
+ if (!extension_info->size())
+ shared_extensions->RemoveWithoutPathExpansion(*it, NULL);
+ }
+
+ return true;
+}
+
+// static
void ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(
const base::FilePath& install_dir) {
DCHECK(!g_shared_install_dir_override);
@@ -199,14 +241,6 @@ base::SequencedTaskRunner* ExtensionAssetsManagerChromeOS::GetFileTaskRunner(
}
// static
-base::FilePath ExtensionAssetsManagerChromeOS::GetSharedInstallDir() {
- if (g_shared_install_dir_override)
- return *g_shared_install_dir_override;
- else
- return base::FilePath(kSharedExtensionsDir);
-}
-
-// static
bool ExtensionAssetsManagerChromeOS::CanShareAssets(
const Extension* extension) {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
@@ -230,6 +264,28 @@ void ExtensionAssetsManagerChromeOS::CheckSharedExtension(
InstallExtensionCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ const std::string& user_id = profile->GetProfileName();
+ chromeos::UserManager* user_manager = chromeos::UserManager::Get();
+ if (!user_manager) {
+ NOTREACHED();
+ return;
+ }
+
+ if (user_manager->IsUserNonCryptohomeDataEphemeral(user_id) ||
+ !user_manager->IsLoggedInAsRegularUser()) {
+ // Don't cache anything in shared location for ephemeral user or special
+ // user types.
+ ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
+ FROM_HERE,
+ base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension,
+ id,
+ version,
+ unpacked_extension_root,
+ local_install_dir,
+ callback));
+ return;
+ }
+
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
base::DictionaryValue* extension_info = NULL;
@@ -242,19 +298,18 @@ void ExtensionAssetsManagerChromeOS::CheckSharedExtension(
version_info->GetString(kSharedExtensionPath, &shared_path) &&
version_info->GetList(kSharedExtensionUsers, &users)) {
// This extension version already in shared location.
- const std::string& user_name = profile->GetProfileName();
size_t users_size = users->GetSize();
bool user_found = false;
for (size_t i = 0; i < users_size; i++) {
std::string temp;
- if (users->GetString(i, &temp) && temp == user_name) {
+ if (users->GetString(i, &temp) && temp == user_id) {
// Re-installation for the same user.
user_found = true;
break;
}
}
if (!user_found)
- users->AppendString(user_name);
+ users->AppendString(user_id);
// unpacked_extension_root will be deleted by CrxInstaller.
ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
@@ -406,9 +461,12 @@ void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused(
extension_info->RemoveWithoutPathExpansion(*it, NULL);
}
}
- // Don't remove extension dir in shared location. It will be removed by GC
- // when it is safe to do so, and this avoids a race condition between
- // concurrent uninstall by one user and install by another.
+ if (!extension_info->size()) {
+ shared_extensions->RemoveWithoutPathExpansion(id, NULL);
+ // Don't remove extension dir in shared location. It will be removed by GC
+ // when it is safe to do so, and this avoids a race condition between
+ // concurrent uninstall by one user and install by another.
+ }
}
// static
@@ -418,4 +476,83 @@ void ExtensionAssetsManagerChromeOS::DeleteSharedVersion(
base::DeleteFile(shared_version_dir, true); // recursive.
}
+// static
+bool ExtensionAssetsManagerChromeOS::CleanUpExtension(
+ const std::string& id,
+ base::DictionaryValue* extension_info,
+ std::multimap<std::string, base::FilePath>* live_extension_paths) {
+ chromeos::UserManager* user_manager = chromeos::UserManager::Get();
+ if (!user_manager) {
+ NOTREACHED();
+ return false;
+ }
+
+ std::vector<std::string> versions;
+ versions.reserve(extension_info->size());
+ for (base::DictionaryValue::Iterator it(*extension_info);
+ !it.IsAtEnd(); it.Advance()) {
+ versions.push_back(it.key());
+ }
+
+ for (std::vector<std::string>::const_iterator it = versions.begin();
+ it != versions.end(); it++) {
+ base::DictionaryValue* version_info = NULL;
+ base::ListValue* users = NULL;
+ std::string shared_path;
+ if (!extension_info->GetDictionaryWithoutPathExpansion(*it,
+ &version_info) ||
+ !version_info->GetList(kSharedExtensionUsers, &users) ||
+ !version_info->GetString(kSharedExtensionPath, &shared_path)) {
+ NOTREACHED();
+ return false;
+ }
+
+ size_t num_users = users->GetSize();
+ for (size_t i = 0; i < num_users; i++) {
+ std::string user_id;
+ if (!users->GetString(i, &user_id)) {
+ NOTREACHED();
+ return false;
+ }
+ const chromeos::User* user = user_manager->FindUser(user_id);
+ bool not_used = false;
+ if (!user) {
+ not_used = true;
+ } else if (user->is_logged_in()) {
+ // For logged in user also check that this path is actually used as
+ // installed extension or as delayed install.
+ Profile* profile = user_manager->GetProfileByUser(user);
+ ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile);
+ if (!extension_prefs || extension_prefs->pref_service()->ReadOnly())
+ return false;
+
+ scoped_ptr<ExtensionInfo> info =
+ extension_prefs->GetInstalledExtensionInfo(id);
+ if (!info || info->extension_path != base::FilePath(shared_path)) {
+ info = extension_prefs->GetDelayedInstallInfo(id);
+ if (!info || info->extension_path != base::FilePath(shared_path)) {
+ not_used = true;
+ }
+ }
+ }
+
+ if (not_used) {
+ users->Remove(i, NULL);
+
+ i--;
+ num_users--;
+ }
+ }
+
+ if (num_users) {
+ live_extension_paths->insert(
+ std::make_pair(id, base::FilePath(shared_path)));
+ } else {
+ extension_info->RemoveWithoutPathExpansion(*it, NULL);
+ }
+ }
+
+ return true;
+}
+
} // namespace extensions
« no previous file with comments | « chrome/browser/extensions/extension_assets_manager_chromeos.h ('k') | chrome/browser/extensions/extension_garbage_collector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698