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

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

Issue 273193006: Install Chrome OS apps to shared location (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added uninstall 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
new file mode 100644
index 0000000000000000000000000000000000000000..126d7402c0b1d7b01ff854110b84affa00b1848f
--- /dev/null
+++ b/chrome/browser/extensions/extension_assets_manager_chromeos.cc
@@ -0,0 +1,333 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/memory/singleton.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/scoped_user_pref_update.h"
+#include "base/sequenced_task_runner.h"
+#include "base/sys_info.h"
+#include "chrome/browser/browser_process.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_system.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/file_util.h"
+#include "extensions/common/manifest.h"
+
+using content::BrowserThread;
+
+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";
+
+} // namespace
+
+namespace extensions {
+
+// Path to shared extensions install dir.
+const char ExtensionAssetsManagerChromeOS::kSharedExtensionsDir[] =
+ "/var/cache/shared_extensions";
+
+ExtensionAssetsManagerChromeOS::ExtensionAssetsManagerChromeOS()
+ : weak_ptr_factory_(this),
+ shared_install_dir_(kSharedExtensionsDir) {
+}
+
+ExtensionAssetsManagerChromeOS::~ExtensionAssetsManagerChromeOS() {
+}
+
+// static
+ExtensionAssetsManagerChromeOS* ExtensionAssetsManagerChromeOS::GetInstance() {
+ return Singleton<ExtensionAssetsManagerChromeOS>::get();
+}
+
+// static
+void ExtensionAssetsManagerChromeOS::RegisterPrefs(
+ PrefRegistrySimple* registry) {
+ registry->RegisterDictionaryPref(kSharedExtensions);
+}
+
+void ExtensionAssetsManagerChromeOS::InstallExtension(
+ const Extension* extension,
+ const base::FilePath& unpacked_extension_root,
+ const base::FilePath& local_install_dir,
+ Profile* profile,
+ InstallExtensionCallback callback) {
+ if (!CanShareAssets(extension)) {
+ ExtensionAssetsManager::InstallExtension(
+ extension,
+ unpacked_extension_root,
+ local_install_dir,
+ profile,
+ callback);
+ return;
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&ExtensionAssetsManagerChromeOS::CheckSharedExtension,
+ weak_ptr_factory_.GetWeakPtr(),
+ extension,
+ unpacked_extension_root,
+ local_install_dir,
+ profile,
+ callback));
+}
+
+void ExtensionAssetsManagerChromeOS::UninstallExtension(
+ const std::string& id,
+ Profile* profile,
+ const base::FilePath& local_install_dir,
+ const base::FilePath& extension_root) {
+ if (local_install_dir.IsParent(extension_root)) {
+ ExtensionAssetsManager::UninstallExtension(
+ id, profile, local_install_dir, extension_root);
+ return;
+ }
+
+ DCHECK(shared_install_dir_.IsParent(extension_root));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused,
+ weak_ptr_factory_.GetWeakPtr(),
+ id,
+ profile));
+}
+
+void ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(
+ const base::FilePath& install_dir) {
+ shared_install_dir_ = install_dir;
+}
+
+// static
+base::SequencedTaskRunner* ExtensionAssetsManagerChromeOS::GetFileTaskRunner(
+ Profile* profile) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ ExtensionService* extension_service =
+ ExtensionSystem::Get(profile)->extension_service();
+ return extension_service->GetFileTaskRunner();
+}
+
+// static
+bool ExtensionAssetsManagerChromeOS::CanShareAssets(
+ const Extension* extension) {
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kEnableExtensionAssetsSharing)) {
+ return false;
+ }
+
+ // Chrome caches crx files for installed by default apps so sharing assets is
+ // also possible. User specific apps should be excluded to don't expose apps
asargent_no_longer_on_chrome 2014/05/16 17:56:19 grammar nit: "should be excluded to don't" -> "sho
Dmitry Polukhin 2014/05/16 22:45:50 Done.
+ // unique for the user outside of user's cryptohome.
+ return Manifest::IsExternalLocation(extension->location());
+}
+
+// static
+void ExtensionAssetsManagerChromeOS::CheckSharedExtension(
+ base::WeakPtr<ExtensionAssetsManagerChromeOS> object,
+ const Extension* extension,
+ const base::FilePath& unpacked_extension_root,
+ const base::FilePath& local_install_dir,
+ Profile* profile,
+ InstallExtensionCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ PrefService* local_state = g_browser_process->local_state();
+ DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
+ base::DictionaryValue* extension_info = NULL;
+ base::DictionaryValue* version_info = NULL;
+ base::ListValue* users = NULL;
+ std::string shared_path;
+ if (shared_extensions->GetDictionary(extension->id(), &extension_info) &&
+ extension_info->GetDictionaryWithoutPathExpansion(
+ extension->VersionString(), &version_info) &&
+ 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) {
+ // Re-installation for the same user.
+ user_found = true;
+ break;
+ }
+ }
+ if (!user_found)
+ users->AppendString(user_name);
+
+ // unpacked_extension_root will be deleted by CrxInstaller.
+ ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
+ FROM_HERE,
+ base::Bind(&ExtensionAssetsManagerChromeOS::SharedExtensionFound,
+ base::FilePath(shared_path),
+ callback));
+ } else {
+ // Desired version not found in shared location.
+ ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
+ FROM_HERE,
+ base::Bind(&ExtensionAssetsManagerChromeOS::SharedExtensionNotFound,
+ object,
+ extension,
+ unpacked_extension_root,
+ local_install_dir,
+ profile,
+ callback));
+ }
+}
+
+// static
+void ExtensionAssetsManagerChromeOS::SharedExtensionFound(
+ const base::FilePath& shared_version_dir,
+ InstallExtensionCallback callback) {
+ callback.Run(shared_version_dir);
+}
+
+// static
+void ExtensionAssetsManagerChromeOS::SharedExtensionNotFound(
+ const Extension* extension,
+ const base::FilePath& unpacked_extension_root,
+ const base::FilePath& local_install_dir,
+ Profile* profile,
+ InstallExtensionCallback callback) {
+ base::FilePath shared_install_dir(shared_install_dir_);
+ base::FilePath shared_version_dir = file_util::InstallExtension(
+ unpacked_extension_root,
+ extension->id(),
+ extension->VersionString(),
+ shared_install_dir);
asargent_no_longer_on_chrome 2014/05/16 17:56:19 Will concurrent user sessions (eg a chromebox allo
Dmitry Polukhin 2014/05/16 22:45:50 Yes, in M37 we enabled multi-profile by default on
asargent_no_longer_on_chrome 2014/05/19 18:25:20 I spent a little time thinking about this and happ
+ if (shared_version_dir.empty()) {
+ // Installation to shared location failed, try local dir.
+ // TODO(dpolukhin): add UMA stats reporting.
+ LOG(ERROR) << "Cannot install extension to shared location "
+ << shared_install_dir.value();
+ callback.Run(file_util::InstallExtension(
+ unpacked_extension_root,
+ extension->id(),
+ extension->VersionString(),
+ local_install_dir));
+ } else {
+ // Mark shared dir as used.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&ExtensionAssetsManagerChromeOS::MarkSharedExtensionUsed,
+ extension->id(),
+ extension->VersionString(),
+ shared_version_dir,
+ profile));
+
+ callback.Run(shared_version_dir);
+ }
+}
+
+// static
+void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUsed(
+ const std::string& id,
+ const std::string& version,
+ const base::FilePath& shared_version_dir,
+ Profile* profile) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ PrefService* local_state = g_browser_process->local_state();
+ DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
+
+ base::DictionaryValue* extension_info = NULL;
+ if (!shared_extensions->GetDictionary(id, &extension_info)) {
+ extension_info = new base::DictionaryValue;
+ shared_extensions->Set(id, extension_info);
+ }
+
+ base::DictionaryValue* version_info = NULL;
+ if (!extension_info->GetDictionaryWithoutPathExpansion(version,
+ &version_info)) {
+ version_info = new base::DictionaryValue;
+ extension_info->SetWithoutPathExpansion(version, version_info);
+ }
+
+ CHECK(!version_info->HasKey(kSharedExtensionPath));
+ version_info->SetString(kSharedExtensionPath, shared_version_dir.value());
+
+ CHECK(!version_info->HasKey(kSharedExtensionUsers));
+ base::ListValue* users = new base::ListValue;
+ users->AppendString(profile->GetProfileName());
+ version_info->Set(kSharedExtensionUsers, users);
+}
+
+// static
+void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused(
+ base::WeakPtr<ExtensionAssetsManagerChromeOS> object,
+ const std::string& id,
+ Profile* profile) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ PrefService* local_state = g_browser_process->local_state();
+ DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
+ base::DictionaryValue* extension_info = NULL;
+ if (!shared_extensions->GetDictionary(id, &extension_info)) {
+ NOTREACHED();
+ return;
+ }
+
+ 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());
+ }
+
+ base::StringValue user_name(profile->GetProfileName());
+ for (std::vector<std::string>::const_iterator it = versions.begin();
+ it != versions.end(); it++) {
+ base::DictionaryValue* version_info = NULL;
+ if (!extension_info->GetDictionaryWithoutPathExpansion(*it,
+ &version_info)) {
+ NOTREACHED();
+ continue;
+ }
+ base::ListValue* users = NULL;
+ if (!version_info->GetList(kSharedExtensionUsers, &users)) {
+ NOTREACHED();
+ continue;
+ }
+ if (users->Remove(user_name, NULL) && !users->GetSize()) {
+ std::string shared_path;
+ if (!version_info->GetString(kSharedExtensionPath, &shared_path)) {
+ NOTREACHED();
+ continue;
+ }
+ ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
+ FROM_HERE,
+ base::Bind(&ExtensionAssetsManagerChromeOS::DeleteSharedVersion,
+ object,
+ base::FilePath(shared_path)));
+ extension_info->RemoveWithoutPathExpansion(*it, NULL);
+ }
+ }
+ if (!extension_info->size())
+ shared_extensions->RemoveWithoutPathExpansion(id, NULL);
+}
+
+void ExtensionAssetsManagerChromeOS::DeleteSharedVersion(
+ const base::FilePath& shared_version_dir) {
+ CHECK(shared_install_dir_.IsParent(shared_version_dir));
+ base::DeleteFile(shared_version_dir, true); // recursive.
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698