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

Side by Side Diff: chrome/browser/extensions/extension_assets_manager_chromeos.cc

Issue 273193006: Install Chrome OS apps to shared location (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added uninstall Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
6
7 #include <vector>
8
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/memory/singleton.h"
12 #include "base/prefs/pref_registry_simple.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/prefs/scoped_user_pref_update.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/sys_info.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chromeos/chromeos_switches.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/file_util.h"
25 #include "extensions/common/manifest.h"
26
27 using content::BrowserThread;
28
29 namespace {
30
31 // A dictionary that maps shared extension IDs to version/paths/users.
32 const char kSharedExtensions[] = "SharedExtensions";
33
34 // Name of path attribute in shared extensions map.
35 const char kSharedExtensionPath[] = "path";
36
37 // Name of users attribute (list of user emails) in shared extensions map.
38 const char kSharedExtensionUsers[] = "users";
39
40 } // namespace
41
42 namespace extensions {
43
44 // Path to shared extensions install dir.
45 const char ExtensionAssetsManagerChromeOS::kSharedExtensionsDir[] =
46 "/var/cache/shared_extensions";
47
48 ExtensionAssetsManagerChromeOS::ExtensionAssetsManagerChromeOS()
49 : weak_ptr_factory_(this),
50 shared_install_dir_(kSharedExtensionsDir) {
51 }
52
53 ExtensionAssetsManagerChromeOS::~ExtensionAssetsManagerChromeOS() {
54 }
55
56 // static
57 ExtensionAssetsManagerChromeOS* ExtensionAssetsManagerChromeOS::GetInstance() {
58 return Singleton<ExtensionAssetsManagerChromeOS>::get();
59 }
60
61 // static
62 void ExtensionAssetsManagerChromeOS::RegisterPrefs(
63 PrefRegistrySimple* registry) {
64 registry->RegisterDictionaryPref(kSharedExtensions);
65 }
66
67 void ExtensionAssetsManagerChromeOS::InstallExtension(
68 const Extension* extension,
69 const base::FilePath& unpacked_extension_root,
70 const base::FilePath& local_install_dir,
71 Profile* profile,
72 InstallExtensionCallback callback) {
73 if (!CanShareAssets(extension)) {
74 ExtensionAssetsManager::InstallExtension(
75 extension,
76 unpacked_extension_root,
77 local_install_dir,
78 profile,
79 callback);
80 return;
81 }
82
83 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
84 base::Bind(&ExtensionAssetsManagerChromeOS::CheckSharedExtension,
85 weak_ptr_factory_.GetWeakPtr(),
86 extension,
87 unpacked_extension_root,
88 local_install_dir,
89 profile,
90 callback));
91 }
92
93 void ExtensionAssetsManagerChromeOS::UninstallExtension(
94 const std::string& id,
95 Profile* profile,
96 const base::FilePath& local_install_dir,
97 const base::FilePath& extension_root) {
98 if (local_install_dir.IsParent(extension_root)) {
99 ExtensionAssetsManager::UninstallExtension(
100 id, profile, local_install_dir, extension_root);
101 return;
102 }
103
104 DCHECK(shared_install_dir_.IsParent(extension_root));
105 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
106 base::Bind(&ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused,
107 weak_ptr_factory_.GetWeakPtr(),
108 id,
109 profile));
110 }
111
112 void ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(
113 const base::FilePath& install_dir) {
114 shared_install_dir_ = install_dir;
115 }
116
117 // static
118 base::SequencedTaskRunner* ExtensionAssetsManagerChromeOS::GetFileTaskRunner(
119 Profile* profile) {
120 DCHECK_CURRENTLY_ON(BrowserThread::UI);
121 ExtensionService* extension_service =
122 ExtensionSystem::Get(profile)->extension_service();
123 return extension_service->GetFileTaskRunner();
124 }
125
126 // static
127 bool ExtensionAssetsManagerChromeOS::CanShareAssets(
128 const Extension* extension) {
129 if (!CommandLine::ForCurrentProcess()->HasSwitch(
130 chromeos::switches::kEnableExtensionAssetsSharing)) {
131 return false;
132 }
133
134 // Chrome caches crx files for installed by default apps so sharing assets is
135 // also possible. User specific apps should be excluded to don't expose apps
asargent_no_longer_on_chrome 2014/05/16 17:56:19 grammar nit: "should be excluded to don't" -> "sho
Dmitry Polukhin 2014/05/16 22:45:50 Done.
136 // unique for the user outside of user's cryptohome.
137 return Manifest::IsExternalLocation(extension->location());
138 }
139
140 // static
141 void ExtensionAssetsManagerChromeOS::CheckSharedExtension(
142 base::WeakPtr<ExtensionAssetsManagerChromeOS> object,
143 const Extension* extension,
144 const base::FilePath& unpacked_extension_root,
145 const base::FilePath& local_install_dir,
146 Profile* profile,
147 InstallExtensionCallback callback) {
148 DCHECK_CURRENTLY_ON(BrowserThread::UI);
149
150 PrefService* local_state = g_browser_process->local_state();
151 DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
152 base::DictionaryValue* extension_info = NULL;
153 base::DictionaryValue* version_info = NULL;
154 base::ListValue* users = NULL;
155 std::string shared_path;
156 if (shared_extensions->GetDictionary(extension->id(), &extension_info) &&
157 extension_info->GetDictionaryWithoutPathExpansion(
158 extension->VersionString(), &version_info) &&
159 version_info->GetString(kSharedExtensionPath, &shared_path) &&
160 version_info->GetList(kSharedExtensionUsers, &users)) {
161 // This extension version already in shared location.
162 const std::string& user_name = profile->GetProfileName();
163 size_t users_size = users->GetSize();
164 bool user_found = false;
165 for (size_t i = 0; i < users_size; i++) {
166 std::string temp;
167 if (users->GetString(i, &temp) && temp == user_name) {
168 // Re-installation for the same user.
169 user_found = true;
170 break;
171 }
172 }
173 if (!user_found)
174 users->AppendString(user_name);
175
176 // unpacked_extension_root will be deleted by CrxInstaller.
177 ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
178 FROM_HERE,
179 base::Bind(&ExtensionAssetsManagerChromeOS::SharedExtensionFound,
180 base::FilePath(shared_path),
181 callback));
182 } else {
183 // Desired version not found in shared location.
184 ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
185 FROM_HERE,
186 base::Bind(&ExtensionAssetsManagerChromeOS::SharedExtensionNotFound,
187 object,
188 extension,
189 unpacked_extension_root,
190 local_install_dir,
191 profile,
192 callback));
193 }
194 }
195
196 // static
197 void ExtensionAssetsManagerChromeOS::SharedExtensionFound(
198 const base::FilePath& shared_version_dir,
199 InstallExtensionCallback callback) {
200 callback.Run(shared_version_dir);
201 }
202
203 // static
204 void ExtensionAssetsManagerChromeOS::SharedExtensionNotFound(
205 const Extension* extension,
206 const base::FilePath& unpacked_extension_root,
207 const base::FilePath& local_install_dir,
208 Profile* profile,
209 InstallExtensionCallback callback) {
210 base::FilePath shared_install_dir(shared_install_dir_);
211 base::FilePath shared_version_dir = file_util::InstallExtension(
212 unpacked_extension_root,
213 extension->id(),
214 extension->VersionString(),
215 shared_install_dir);
asargent_no_longer_on_chrome 2014/05/16 17:56:19 Will concurrent user sessions (eg a chromebox allo
Dmitry Polukhin 2014/05/16 22:45:50 Yes, in M37 we enabled multi-profile by default on
asargent_no_longer_on_chrome 2014/05/19 18:25:20 I spent a little time thinking about this and happ
216 if (shared_version_dir.empty()) {
217 // Installation to shared location failed, try local dir.
218 // TODO(dpolukhin): add UMA stats reporting.
219 LOG(ERROR) << "Cannot install extension to shared location "
220 << shared_install_dir.value();
221 callback.Run(file_util::InstallExtension(
222 unpacked_extension_root,
223 extension->id(),
224 extension->VersionString(),
225 local_install_dir));
226 } else {
227 // Mark shared dir as used.
228 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
229 base::Bind(&ExtensionAssetsManagerChromeOS::MarkSharedExtensionUsed,
230 extension->id(),
231 extension->VersionString(),
232 shared_version_dir,
233 profile));
234
235 callback.Run(shared_version_dir);
236 }
237 }
238
239 // static
240 void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUsed(
241 const std::string& id,
242 const std::string& version,
243 const base::FilePath& shared_version_dir,
244 Profile* profile) {
245 DCHECK_CURRENTLY_ON(BrowserThread::UI);
246
247 PrefService* local_state = g_browser_process->local_state();
248 DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
249
250 base::DictionaryValue* extension_info = NULL;
251 if (!shared_extensions->GetDictionary(id, &extension_info)) {
252 extension_info = new base::DictionaryValue;
253 shared_extensions->Set(id, extension_info);
254 }
255
256 base::DictionaryValue* version_info = NULL;
257 if (!extension_info->GetDictionaryWithoutPathExpansion(version,
258 &version_info)) {
259 version_info = new base::DictionaryValue;
260 extension_info->SetWithoutPathExpansion(version, version_info);
261 }
262
263 CHECK(!version_info->HasKey(kSharedExtensionPath));
264 version_info->SetString(kSharedExtensionPath, shared_version_dir.value());
265
266 CHECK(!version_info->HasKey(kSharedExtensionUsers));
267 base::ListValue* users = new base::ListValue;
268 users->AppendString(profile->GetProfileName());
269 version_info->Set(kSharedExtensionUsers, users);
270 }
271
272 // static
273 void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused(
274 base::WeakPtr<ExtensionAssetsManagerChromeOS> object,
275 const std::string& id,
276 Profile* profile) {
277 DCHECK_CURRENTLY_ON(BrowserThread::UI);
278
279 PrefService* local_state = g_browser_process->local_state();
280 DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
281 base::DictionaryValue* extension_info = NULL;
282 if (!shared_extensions->GetDictionary(id, &extension_info)) {
283 NOTREACHED();
284 return;
285 }
286
287 std::vector<std::string> versions;
288 versions.reserve(extension_info->size());
289 for (base::DictionaryValue::Iterator it(*extension_info);
290 !it.IsAtEnd();
291 it.Advance()) {
292 versions.push_back(it.key());
293 }
294
295 base::StringValue user_name(profile->GetProfileName());
296 for (std::vector<std::string>::const_iterator it = versions.begin();
297 it != versions.end(); it++) {
298 base::DictionaryValue* version_info = NULL;
299 if (!extension_info->GetDictionaryWithoutPathExpansion(*it,
300 &version_info)) {
301 NOTREACHED();
302 continue;
303 }
304 base::ListValue* users = NULL;
305 if (!version_info->GetList(kSharedExtensionUsers, &users)) {
306 NOTREACHED();
307 continue;
308 }
309 if (users->Remove(user_name, NULL) && !users->GetSize()) {
310 std::string shared_path;
311 if (!version_info->GetString(kSharedExtensionPath, &shared_path)) {
312 NOTREACHED();
313 continue;
314 }
315 ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask(
316 FROM_HERE,
317 base::Bind(&ExtensionAssetsManagerChromeOS::DeleteSharedVersion,
318 object,
319 base::FilePath(shared_path)));
320 extension_info->RemoveWithoutPathExpansion(*it, NULL);
321 }
322 }
323 if (!extension_info->size())
324 shared_extensions->RemoveWithoutPathExpansion(id, NULL);
325 }
326
327 void ExtensionAssetsManagerChromeOS::DeleteSharedVersion(
328 const base::FilePath& shared_version_dir) {
329 CHECK(shared_install_dir_.IsParent(shared_version_dir));
330 base::DeleteFile(shared_version_dir, true); // recursive.
331 }
332
333 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698