extension_assets_manager_chromeos.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright (c) 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/extension_assets_manager_chromeos.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <map> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/command_line.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/file_util.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/memory/singleton.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_service.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/sequenced_task_runner.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/sys_info.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/browser_process.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chromeos/chromeos_switches.h" 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_system.h" 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/extension.h" 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/file_util.h" 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/manifest.h" 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using content::BrowserThread; 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace extensions { 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// A dictionary that maps shared extension IDs to version/paths/users. 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kSharedExtensions[] = "SharedExtensions"; 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Name of path attribute in shared extensions map. 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kSharedExtensionPath[] = "path"; 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Name of users attribute (list of user emails) in shared extensions map. 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kSharedExtensionUsers[] = "users"; 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Shared install dir overrider for tests only. 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const base::FilePath* g_shared_install_dir_override = NULL; 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This helper class lives on UI thread only. Main purpose of this class is to 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// track shared installation in progress between multiple profiles. 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ExtensionAssetsManagerHelper { 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Info about pending install request. 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) struct PendingInstallInfo { 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath unpacked_extension_root; 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath local_install_dir; 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile; 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManager::InstallExtensionCallback callback; 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef std::vector<PendingInstallInfo> PendingInstallList; 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static ExtensionAssetsManagerHelper* GetInstance() { 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return Singleton<ExtensionAssetsManagerHelper>::get(); 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Remember that shared install is in progress. Return true if there is no 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // other installs for given id and version. 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool RecordSharedInstall( 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManager::InstallExtensionCallback callback) { 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PendingInstallInfo install_info; 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.unpacked_extension_root = unpacked_extension_root; 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.local_install_dir = local_install_dir; 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.profile = profile; 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.callback = callback; 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<PendingInstallInfo>& callbacks = 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_queue_[InstallQueue::key_type(id, version)]; 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callbacks.push_back(install_info); 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return callbacks.size() == 1; 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Remove record about shared installation in progress and return 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |pending_installs|. 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SharedInstallDone(const std::string& id, 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PendingInstallList* pending_installs) { 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallQueue::iterator it = install_queue_.find( 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallQueue::key_type(id, version)); 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(it != install_queue_.end()); 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_installs->swap(it->second); 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_queue_.erase(it); 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) friend struct DefaultSingletonTraits<ExtensionAssetsManagerHelper>; 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper() {} 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ~ExtensionAssetsManagerHelper() {} 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Extension ID + version pair. 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef std::pair<std::string, std::string> InstallItem; 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Queue of pending installs in progress. 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef std::map<InstallItem, std::vector<PendingInstallInfo> > InstallQueue; 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallQueue install_queue_; 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExtensionAssetsManagerHelper); 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Path to shared extensions install dir. 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char ExtensionAssetsManagerChromeOS::kSharedExtensionsDir[] = 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "/var/cache/shared_extensions"; 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ExtensionAssetsManagerChromeOS::ExtensionAssetsManagerChromeOS() { } 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ExtensionAssetsManagerChromeOS::~ExtensionAssetsManagerChromeOS() { 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (g_shared_install_dir_override) { 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delete g_shared_install_dir_override; 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) g_shared_install_dir_override = NULL; 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ExtensionAssetsManagerChromeOS* ExtensionAssetsManagerChromeOS::GetInstance() { 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return Singleton<ExtensionAssetsManagerChromeOS>::get(); 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::RegisterPrefs( 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefRegistrySimple* registry) { 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registry->RegisterDictionaryPref(kSharedExtensions); 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallExtension( 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension, 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallExtensionCallback callback) { 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!CanShareAssets(extension)) { 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallLocalExtension(extension->id(), 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->VersionString(), 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) local_install_dir, 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback); 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::CheckSharedExtension, 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->id(), 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->VersionString(), 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) local_install_dir, 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile, 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback)); 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::UninstallExtension( 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& extension_root) { 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (local_install_dir.IsParent(extension_root)) { 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) file_util::UninstallExtension(local_install_dir, id); 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetSharedInstallDir().IsParent(extension_root)) { 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // In some test extensions installed outside local_install_dir emulate 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // previous behavior that just do nothing in this case. 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused, 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile)); 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting( 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& install_dir) { 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!g_shared_install_dir_override); 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) g_shared_install_dir_override = new base::FilePath(install_dir); 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::SequencedTaskRunner* ExtensionAssetsManagerChromeOS::GetFileTaskRunner( 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile) { 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionService* extension_service = 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionSystem::Get(profile)->extension_service(); 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return extension_service->GetFileTaskRunner(); 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::FilePath ExtensionAssetsManagerChromeOS::GetSharedInstallDir() { 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (g_shared_install_dir_override) 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return *g_shared_install_dir_override; 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return base::FilePath(kSharedExtensionsDir); 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ExtensionAssetsManagerChromeOS::CanShareAssets( 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension) { 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!CommandLine::ForCurrentProcess()->HasSwitch( 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chromeos::switches::kEnableExtensionAssetsSharing)) { 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Chrome caches crx files for installed by default apps so sharing assets is 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // also possible. User specific apps should be excluded to not expose apps 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // unique for the user outside of user's cryptohome. 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return Manifest::IsExternalLocation(extension->location()); 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::CheckSharedExtension( 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallExtensionCallback callback) { 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions); 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* extension_info = NULL; 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* version_info = NULL; 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* users = NULL; 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string shared_path; 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (shared_extensions->GetDictionary(id, &extension_info) && 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info->GetDictionaryWithoutPathExpansion( 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version, &version_info) && 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->GetString(kSharedExtensionPath, &shared_path) && 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->GetList(kSharedExtensionUsers, &users)) { 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This extension version already in shared location. 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& user_name = profile->GetProfileName(); 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t users_size = users->GetSize(); 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool user_found = false; 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < users_size; i++) { 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string temp; 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (users->GetString(i, &temp) && temp == user_name) { 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Re-installation for the same user. 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) user_found = true; 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!user_found) 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) users->AppendString(user_name); 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // unpacked_extension_root will be deleted by CrxInstaller. 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(callback, base::FilePath(shared_path))); 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Desired version is not found in shared location. 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper* helper = 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::GetInstance(); 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (helper->RecordSharedInstall(id, version, unpacked_extension_root, 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) local_install_dir, profile, callback)) { 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // There is no install in progress for given <id, version> so run install. 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::InstallSharedExtension, 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version, 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root)); 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallSharedExtension( 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root) { 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath shared_install_dir = GetSharedInstallDir(); 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath shared_version_dir = file_util::InstallExtension( 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, id, version, shared_install_dir); 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::InstallSharedExtensionDone, 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, version, shared_version_dir)); 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallSharedExtensionDone( 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& shared_version_dir) { 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper* helper = 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::GetInstance(); 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::PendingInstallList pending_installs; 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) helper->SharedInstallDone(id, version, &pending_installs); 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (shared_version_dir.empty()) { 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Installation to shared location failed, try local dir. 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(dpolukhin): add UMA stats reporting. 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < pending_installs.size(); i++) { 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::PendingInstallInfo& info = 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_installs[i]; 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(info.profile)->PostTask( 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension, 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version, 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) info.unpacked_extension_root, 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) info.local_install_dir, 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) info.callback)); 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions); 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* extension_info = NULL; 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!shared_extensions->GetDictionary(id, &extension_info)) { 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info = new base::DictionaryValue; 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shared_extensions->Set(id, extension_info); 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(!shared_extensions->HasKey(version)); 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* version_info = new base::DictionaryValue; 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info->SetWithoutPathExpansion(version, version_info); 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->SetString(kSharedExtensionPath, shared_version_dir.value()); 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* users = new base::ListValue; 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->Set(kSharedExtensionUsers, users); 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < pending_installs.size(); i++) { 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::PendingInstallInfo& info = 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_installs[i]; 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) users->AppendString(info.profile->GetProfileName()); 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(info.profile)->PostTask( 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(info.callback, shared_version_dir)); 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallLocalExtension( 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallExtensionCallback callback) { 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback.Run(file_util::InstallExtension( 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, id, version, local_install_dir)); 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused( 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile) { 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions); 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* extension_info = NULL; 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!shared_extensions->GetDictionary(id, &extension_info)) { 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<std::string> versions; 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) versions.reserve(extension_info->size()); 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (base::DictionaryValue::Iterator it(*extension_info); 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !it.IsAtEnd(); 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) it.Advance()) { 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) versions.push_back(it.key()); 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::StringValue user_name(profile->GetProfileName()); 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::vector<std::string>::const_iterator it = versions.begin(); 384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) it != versions.end(); it++) { 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* version_info = NULL; 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!extension_info->GetDictionaryWithoutPathExpansion(*it, 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &version_info)) { 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* users = NULL; 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!version_info->GetList(kSharedExtensionUsers, &users)) { 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (users->Remove(user_name, NULL) && !users->GetSize()) { 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string shared_path; 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!version_info->GetString(kSharedExtensionPath, &shared_path)) { 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::DeleteSharedVersion, 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath(shared_path))); 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info->RemoveWithoutPathExpansion(*it, NULL); 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Don't remove extension dir in shared location. It will be removed by GC 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // when it is safe to do so, and this avoids a race condition between 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // concurrent uninstall by one user and install by another. 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::DeleteSharedVersion( 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& shared_version_dir) { 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(GetSharedInstallDir().IsParent(shared_version_dir)); 418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DeleteFile(shared_version_dir, true); // recursive. 419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace extensions 422