extension_assets_manager_chromeos.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/profiles/profile_helper.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/extension_constants.h" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/manifest_url_handler.h" 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chromeos/chromeos_switches.h" 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h" 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/browser/extension_prefs.h" 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_system.h" 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/extension.h" 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/file_util.h" 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/manifest.h" 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using content::BrowserThread; 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace extensions { 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Path to shared extensions install dir. 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kSharedExtensionsDir[] = "/var/cache/shared_extensions"; 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Shared install dir overrider for tests only. 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const base::FilePath* g_shared_install_dir_override = NULL; 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This helper class lives on UI thread only. Main purpose of this class is to 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// track shared installation in progress between multiple profiles. 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ExtensionAssetsManagerHelper { 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Info about pending install request. 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) struct PendingInstallInfo { 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath unpacked_extension_root; 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath local_install_dir; 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile; 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManager::InstallExtensionCallback callback; 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef std::vector<PendingInstallInfo> PendingInstallList; 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static ExtensionAssetsManagerHelper* GetInstance() { 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return Singleton<ExtensionAssetsManagerHelper>::get(); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Remember that shared install is in progress. Return true if there is no 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // other installs for given id and version. 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool RecordSharedInstall( 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManager::InstallExtensionCallback callback) { 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PendingInstallInfo install_info; 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.unpacked_extension_root = unpacked_extension_root; 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.local_install_dir = local_install_dir; 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.profile = profile; 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_info.callback = callback; 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<PendingInstallInfo>& callbacks = 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_queue_[InstallQueue::key_type(id, version)]; 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callbacks.push_back(install_info); 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return callbacks.size() == 1; 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Remove record about shared installation in progress and return 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |pending_installs|. 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SharedInstallDone(const std::string& id, 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PendingInstallList* pending_installs) { 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallQueue::iterator it = install_queue_.find( 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallQueue::key_type(id, version)); 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(it != install_queue_.end()); 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_installs->swap(it->second); 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_queue_.erase(it); 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) friend struct DefaultSingletonTraits<ExtensionAssetsManagerHelper>; 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper() {} 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ~ExtensionAssetsManagerHelper() {} 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Extension ID + version pair. 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef std::pair<std::string, std::string> InstallItem; 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Queue of pending installs in progress. 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef std::map<InstallItem, std::vector<PendingInstallInfo> > InstallQueue; 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallQueue install_queue_; 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExtensionAssetsManagerHelper); 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char ExtensionAssetsManagerChromeOS::kSharedExtensions[] = 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "SharedExtensions"; 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char ExtensionAssetsManagerChromeOS::kSharedExtensionPath[] = "path"; 11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char ExtensionAssetsManagerChromeOS::kSharedExtensionUsers[] = "users"; 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ExtensionAssetsManagerChromeOS::ExtensionAssetsManagerChromeOS() { } 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ExtensionAssetsManagerChromeOS::~ExtensionAssetsManagerChromeOS() { 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (g_shared_install_dir_override) { 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delete g_shared_install_dir_override; 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) g_shared_install_dir_override = NULL; 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ExtensionAssetsManagerChromeOS* ExtensionAssetsManagerChromeOS::GetInstance() { 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return Singleton<ExtensionAssetsManagerChromeOS>::get(); 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::RegisterPrefs( 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefRegistrySimple* registry) { 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registry->RegisterDictionaryPref(kSharedExtensions); 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallExtension( 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension, 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallExtensionCallback callback) { 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!CanShareAssets(extension, unpacked_extension_root)) { 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallLocalExtension(extension->id(), 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->VersionString(), 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) local_install_dir, 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback); 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::CheckSharedExtension, 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->id(), 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->VersionString(), 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) local_install_dir, 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile, 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback)); 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::UninstallExtension( 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& extension_root) { 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (local_install_dir.IsParent(extension_root)) { 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) file_util::UninstallExtension(local_install_dir, id); 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetSharedInstallDir().IsParent(extension_root)) { 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // In some test extensions installed outside local_install_dir emulate 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // previous behavior that just do nothing in this case. 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused, 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile)); 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)base::FilePath ExtensionAssetsManagerChromeOS::GetSharedInstallDir() { 18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (g_shared_install_dir_override) 19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return *g_shared_install_dir_override; 19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) else 19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return base::FilePath(kSharedExtensionsDir); 19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ExtensionAssetsManagerChromeOS::IsSharedInstall( 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension) { 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return GetSharedInstallDir().IsParent(extension->path()); 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static 20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ExtensionAssetsManagerChromeOS::CleanUpSharedExtensions( 20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::multimap<std::string, base::FilePath>* live_extension_paths) { 20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // It happens in many unit tests. 20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!local_state) 20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions); 21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<std::string> extensions; 21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extensions.reserve(shared_extensions->size()); 21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (base::DictionaryValue::Iterator it(*shared_extensions); 21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !it.IsAtEnd(); it.Advance()) { 21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extensions.push_back(it.key()); 21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (std::vector<std::string>::iterator it = extensions.begin(); 22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != extensions.end(); it++) { 22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::DictionaryValue* extension_info = NULL; 22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!shared_extensions->GetDictionary(*it, &extension_info)) { 22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NOTREACHED(); 22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!CleanUpExtension(*it, extension_info, live_extension_paths)) { 22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension_info->size()) 23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) shared_extensions->RemoveWithoutPathExpansion(*it, NULL); 23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting( 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& install_dir) { 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!g_shared_install_dir_override); 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) g_shared_install_dir_override = new base::FilePath(install_dir); 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::SequencedTaskRunner* ExtensionAssetsManagerChromeOS::GetFileTaskRunner( 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile) { 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionService* extension_service = 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionSystem::Get(profile)->extension_service(); 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return extension_service->GetFileTaskRunner(); 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ExtensionAssetsManagerChromeOS::CanShareAssets( 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension, 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::FilePath& unpacked_extension_root) { 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!CommandLine::ForCurrentProcess()->HasSwitch( 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chromeos::switches::kEnableExtensionAssetsSharing)) { 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL update_url = ManifestURL::GetUpdateURL(extension); 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!update_url.is_empty() && 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !extension_urls::IsWebstoreUpdateUrl(update_url)) { 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Chrome caches crx files for installed by default apps so sharing assets is 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // also possible. User specific apps should be excluded to not expose apps 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // unique for the user outside of user's cryptohome. 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return Manifest::IsExternalLocation(extension->location()); 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::CheckSharedExtension( 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile, 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallExtensionCallback callback) { 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& user_id = profile->GetProfileName(); 2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) user_manager::UserManager* user_manager = user_manager::UserManager::Get(); 28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!user_manager) { 28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NOTREACHED(); 28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (user_manager->IsUserNonCryptohomeDataEphemeral(user_id) || 29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !user_manager->IsLoggedInAsRegularUser()) { 29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Don't cache anything in shared location for ephemeral user or special 29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // user types. 29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( 29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension, 29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) id, 29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) version, 29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) unpacked_extension_root, 30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_install_dir, 30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) callback)); 30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions); 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* extension_info = NULL; 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* version_info = NULL; 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* users = NULL; 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string shared_path; 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (shared_extensions->GetDictionary(id, &extension_info) && 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info->GetDictionaryWithoutPathExpansion( 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version, &version_info) && 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->GetString(kSharedExtensionPath, &shared_path) && 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->GetList(kSharedExtensionUsers, &users)) { 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This extension version already in shared location. 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t users_size = users->GetSize(); 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool user_found = false; 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < users_size; i++) { 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string temp; 32146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (users->GetString(i, &temp) && temp == user_id) { 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Re-installation for the same user. 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) user_found = true; 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!user_found) 32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) users->AppendString(user_id); 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // unpacked_extension_root will be deleted by CrxInstaller. 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(callback, base::FilePath(shared_path))); 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Desired version is not found in shared location. 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper* helper = 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::GetInstance(); 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (helper->RecordSharedInstall(id, version, unpacked_extension_root, 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) local_install_dir, profile, callback)) { 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // There is no install in progress for given <id, version> so run install. 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::InstallSharedExtension, 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version, 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root)); 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallSharedExtension( 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root) { 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath shared_install_dir = GetSharedInstallDir(); 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath shared_version_dir = file_util::InstallExtension( 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, id, version, shared_install_dir); 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::InstallSharedExtensionDone, 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, version, shared_version_dir)); 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallSharedExtensionDone( 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& shared_version_dir) { 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper* helper = 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::GetInstance(); 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::PendingInstallList pending_installs; 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) helper->SharedInstallDone(id, version, &pending_installs); 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (shared_version_dir.empty()) { 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Installation to shared location failed, try local dir. 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(dpolukhin): add UMA stats reporting. 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < pending_installs.size(); i++) { 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::PendingInstallInfo& info = 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_installs[i]; 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(info.profile)->PostTask( 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension, 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) id, 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version, 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) info.unpacked_extension_root, 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) info.local_install_dir, 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) info.callback)); 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions); 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* extension_info = NULL; 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!shared_extensions->GetDictionary(id, &extension_info)) { 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info = new base::DictionaryValue; 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shared_extensions->Set(id, extension_info); 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(!shared_extensions->HasKey(version)); 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* version_info = new base::DictionaryValue; 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info->SetWithoutPathExpansion(version, version_info); 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->SetString(kSharedExtensionPath, shared_version_dir.value()); 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* users = new base::ListValue; 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_info->Set(kSharedExtensionUsers, users); 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < pending_installs.size(); i++) { 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerHelper::PendingInstallInfo& info = 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pending_installs[i]; 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) users->AppendString(info.profile->GetProfileName()); 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(info.profile)->PostTask( 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(info.callback, shared_version_dir)); 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::InstallLocalExtension( 422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& version, 424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& unpacked_extension_root, 425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& local_install_dir, 426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InstallExtensionCallback callback) { 427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback.Run(file_util::InstallExtension( 428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unpacked_extension_root, id, version, local_install_dir)); 429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused( 433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& id, 434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Profile* profile) { 435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions); 439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* extension_info = NULL; 440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!shared_extensions->GetDictionary(id, &extension_info)) { 441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<std::string> versions; 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) versions.reserve(extension_info->size()); 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (base::DictionaryValue::Iterator it(*extension_info); 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !it.IsAtEnd(); 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) it.Advance()) { 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) versions.push_back(it.key()); 451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::StringValue user_name(profile->GetProfileName()); 454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::vector<std::string>::const_iterator it = versions.begin(); 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) it != versions.end(); it++) { 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* version_info = NULL; 457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!extension_info->GetDictionaryWithoutPathExpansion(*it, 458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &version_info)) { 459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* users = NULL; 463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!version_info->GetList(kSharedExtensionUsers, &users)) { 464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (users->Remove(user_name, NULL) && !users->GetSize()) { 468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string shared_path; 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!version_info->GetString(kSharedExtensionPath, &shared_path)) { 470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( 474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ExtensionAssetsManagerChromeOS::DeleteSharedVersion, 476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath(shared_path))); 477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_info->RemoveWithoutPathExpansion(*it, NULL); 478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 48046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension_info->size()) { 48146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) shared_extensions->RemoveWithoutPathExpansion(id, NULL); 48246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Don't remove extension dir in shared location. It will be removed by GC 48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // when it is safe to do so, and this avoids a race condition between 48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // concurrent uninstall by one user and install by another. 48546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAssetsManagerChromeOS::DeleteSharedVersion( 490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& shared_version_dir) { 491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(GetSharedInstallDir().IsParent(shared_version_dir)); 492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DeleteFile(shared_version_dir, true); // recursive. 493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 49546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ExtensionAssetsManagerChromeOS::CleanUpExtension( 49746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& id, 49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::DictionaryValue* extension_info, 49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::multimap<std::string, base::FilePath>* live_extension_paths) { 5006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) user_manager::UserManager* user_manager = user_manager::UserManager::Get(); 50146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!user_manager) { 50246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NOTREACHED(); 50346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 50446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 50546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 50646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<std::string> versions; 50746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) versions.reserve(extension_info->size()); 50846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (base::DictionaryValue::Iterator it(*extension_info); 50946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !it.IsAtEnd(); it.Advance()) { 51046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) versions.push_back(it.key()); 51146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 51246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 51346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (std::vector<std::string>::const_iterator it = versions.begin(); 51446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != versions.end(); it++) { 51546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::DictionaryValue* version_info = NULL; 51646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::ListValue* users = NULL; 51746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string shared_path; 51846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension_info->GetDictionaryWithoutPathExpansion(*it, 51946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &version_info) || 52046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !version_info->GetList(kSharedExtensionUsers, &users) || 52146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !version_info->GetString(kSharedExtensionPath, &shared_path)) { 52246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NOTREACHED(); 52346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 52446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 52546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 52646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t num_users = users->GetSize(); 52746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (size_t i = 0; i < num_users; i++) { 52846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string user_id; 52946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!users->GetString(i, &user_id)) { 53046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NOTREACHED(); 53146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 53246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const user_manager::User* user = user_manager->FindUser(user_id); 53446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool not_used = false; 53546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!user) { 53646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) not_used = true; 53746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } else if (user->is_logged_in()) { 53846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // For logged in user also check that this path is actually used as 53946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // installed extension or as delayed install. 540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Profile* profile = 5416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); 54246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile); 54346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension_prefs || extension_prefs->pref_service()->ReadOnly()) 54446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 54546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 54646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<ExtensionInfo> info = 54746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_prefs->GetInstalledExtensionInfo(id); 54846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!info || info->extension_path != base::FilePath(shared_path)) { 54946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) info = extension_prefs->GetDelayedInstallInfo(id); 55046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!info || info->extension_path != base::FilePath(shared_path)) { 55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) not_used = true; 55246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 55346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 55446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 55546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 55646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (not_used) { 55746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) users->Remove(i, NULL); 55846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 55946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) i--; 56046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) num_users--; 56146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 56246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 56346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 56446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (num_users) { 56546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) live_extension_paths->insert( 56646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::make_pair(id, base::FilePath(shared_path))); 56746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } else { 56846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_info->RemoveWithoutPathExpansion(*it, NULL); 56946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 57046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 57146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 57246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 57346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 57446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace extensions 576