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

Side by Side Diff: chrome/browser/chromeos/file_system_provider/service.cc

Issue 334263017: [fsp] Remember mounted file systems as soon as possible. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleaned up. Created 6 years, 5 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/file_system_provider/service.h" 5 #include "chrome/browser/chromeos/file_system_provider/service.h"
6 6
7 #include "base/files/file_path.h" 7 #include "base/files/file_path.h"
8 #include "base/prefs/pref_service.h" 8 #include "base/prefs/pref_service.h"
9 #include "base/prefs/scoped_user_pref_update.h" 9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 46 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
47 } 47 }
48 48
49 Service::Service(Profile* profile, 49 Service::Service(Profile* profile,
50 extensions::ExtensionRegistry* extension_registry) 50 extensions::ExtensionRegistry* extension_registry)
51 : profile_(profile), 51 : profile_(profile),
52 extension_registry_(extension_registry), 52 extension_registry_(extension_registry),
53 file_system_factory_(base::Bind(CreateProvidedFileSystem)), 53 file_system_factory_(base::Bind(CreateProvidedFileSystem)),
54 weak_ptr_factory_(this) { 54 weak_ptr_factory_(this) {
55 extension_registry_->AddObserver(this); 55 extension_registry_->AddObserver(this);
56
57 // Store previously mounted file systems in order to be able to remount
58 // them once related extensions are loaded.
59 PrefService* pref_service = profile_->GetPrefs();
60 DCHECK(pref_service);
61
62 const base::DictionaryValue* file_systems =
63 pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
64 DCHECK(file_systems);
65
66 file_systems_to_restore_.reset(file_systems->DeepCopy());
67 pref_service->ClearPref(prefs::kFileSystemProviderMounted);
hashimoto 2014/07/02 08:59:37 Is it OK to clear the pref at this point? Extensio
mtomasz 2014/07/03 05:24:07 Done.
68 pref_service->CommitPendingWrite();
56 } 69 }
57 70
58 Service::~Service() { 71 Service::~Service() {
59 extension_registry_->RemoveObserver(this); 72 extension_registry_->RemoveObserver(this);
60 RememberFileSystems();
61 73
62 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); 74 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
63 while (it != file_system_map_.end()) { 75 while (it != file_system_map_.end()) {
64 const std::string file_system_id = 76 const std::string file_system_id =
65 it->second->GetFileSystemInfo().file_system_id(); 77 it->second->GetFileSystemInfo().file_system_id();
66 const std::string extension_id = 78 const std::string extension_id =
67 it->second->GetFileSystemInfo().extension_id(); 79 it->second->GetFileSystemInfo().extension_id();
68 ++it; 80 ++it;
69 UnmountFileSystem(extension_id, file_system_id); 81 UnmountFileSystem(extension_id, file_system_id, UNMOUNT_MODE_SHUTDOWN);
70 } 82 }
71 83
72 DCHECK_EQ(0u, file_system_map_.size()); 84 DCHECK_EQ(0u, file_system_map_.size());
73 STLDeleteValues(&file_system_map_); 85 STLDeleteValues(&file_system_map_);
74 } 86 }
75 87
76 // static 88 // static
77 Service* Service::Get(content::BrowserContext* context) { 89 Service* Service::Get(content::BrowserContext* context) {
78 return ServiceFactory::Get(context); 90 return ServiceFactory::Get(context);
79 } 91 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 // mount_path = /provided/b33f1337-41-5aa5 161 // mount_path = /provided/b33f1337-41-5aa5
150 ProvidedFileSystemInfo file_system_info( 162 ProvidedFileSystemInfo file_system_info(
151 extension_id, file_system_id, file_system_name, mount_path); 163 extension_id, file_system_id, file_system_name, mount_path);
152 164
153 ProvidedFileSystemInterface* file_system = 165 ProvidedFileSystemInterface* file_system =
154 file_system_factory_.Run(profile_, file_system_info); 166 file_system_factory_.Run(profile_, file_system_info);
155 DCHECK(file_system); 167 DCHECK(file_system);
156 file_system_map_[FileSystemKey(extension_id, file_system_id)] = file_system; 168 file_system_map_[FileSystemKey(extension_id, file_system_id)] = file_system;
157 mount_point_name_to_key_map_[mount_point_name] = 169 mount_point_name_to_key_map_[mount_point_name] =
158 FileSystemKey(extension_id, file_system_id); 170 FileSystemKey(extension_id, file_system_id);
171 RememberFileSystem(file_system_info);
159 172
160 FOR_EACH_OBSERVER( 173 FOR_EACH_OBSERVER(
161 Observer, 174 Observer,
162 observers_, 175 observers_,
163 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK)); 176 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK));
164 177
165 return true; 178 return true;
166 } 179 }
167 180
168 bool Service::UnmountFileSystem(const std::string& extension_id, 181 bool Service::UnmountFileSystem(const std::string& extension_id,
169 const std::string& file_system_id) { 182 const std::string& file_system_id,
183 UnmountMode mode) {
170 DCHECK(thread_checker_.CalledOnValidThread()); 184 DCHECK(thread_checker_.CalledOnValidThread());
171 185
172 const ProvidedFileSystemMap::iterator file_system_it = 186 const ProvidedFileSystemMap::iterator file_system_it =
173 file_system_map_.find(FileSystemKey(extension_id, file_system_id)); 187 file_system_map_.find(FileSystemKey(extension_id, file_system_id));
174 if (file_system_it == file_system_map_.end()) { 188 if (file_system_it == file_system_map_.end()) {
175 const ProvidedFileSystemInfo empty_file_system_info; 189 const ProvidedFileSystemInfo empty_file_system_info;
176 FOR_EACH_OBSERVER( 190 FOR_EACH_OBSERVER(
177 Observer, 191 Observer,
178 observers_, 192 observers_,
179 OnProvidedFileSystemUnmount(empty_file_system_info, 193 OnProvidedFileSystemUnmount(empty_file_system_info,
(...skipping 19 matching lines...) Expand all
199 return false; 213 return false;
200 } 214 }
201 215
202 FOR_EACH_OBSERVER( 216 FOR_EACH_OBSERVER(
203 Observer, 217 Observer,
204 observers_, 218 observers_,
205 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); 219 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK));
206 220
207 mount_point_name_to_key_map_.erase(mount_point_name); 221 mount_point_name_to_key_map_.erase(mount_point_name);
208 222
223 if (mode == UNMOUNT_MODE_USER)
224 ForgetFileSystem(file_system_info);
225
209 delete file_system_it->second; 226 delete file_system_it->second;
210 file_system_map_.erase(file_system_it); 227 file_system_map_.erase(file_system_it);
211 228
212 return true; 229 return true;
213 } 230 }
214 231
215 bool Service::RequestUnmount(const std::string& extension_id, 232 bool Service::RequestUnmount(const std::string& extension_id,
216 const std::string& file_system_id) { 233 const std::string& file_system_id) {
217 DCHECK(thread_checker_.CalledOnValidThread()); 234 DCHECK(thread_checker_.CalledOnValidThread());
218 235
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 if (file_system_it == file_system_map_.end()) 267 if (file_system_it == file_system_map_.end())
251 return NULL; 268 return NULL;
252 269
253 return file_system_it->second; 270 return file_system_it->second;
254 } 271 }
255 272
256 void Service::OnExtensionUnloaded( 273 void Service::OnExtensionUnloaded(
257 content::BrowserContext* browser_context, 274 content::BrowserContext* browser_context,
258 const extensions::Extension* extension, 275 const extensions::Extension* extension,
259 extensions::UnloadedExtensionInfo::Reason reason) { 276 extensions::UnloadedExtensionInfo::Reason reason) {
260 // If the reason is not a profile shutdown, then forget the mounted file
261 // systems from preferences.
262 if (reason != extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN)
263 ForgetFileSystems(extension->id());
264
265 // Unmount all of the provided file systems associated with this extension. 277 // Unmount all of the provided file systems associated with this extension.
266 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); 278 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
267 while (it != file_system_map_.end()) { 279 while (it != file_system_map_.end()) {
268 const ProvidedFileSystemInfo& file_system_info = 280 const ProvidedFileSystemInfo& file_system_info =
269 it->second->GetFileSystemInfo(); 281 it->second->GetFileSystemInfo();
270 // Advance the iterator beforehand, otherwise it will become invalidated 282 // Advance the iterator beforehand, otherwise it will become invalidated
271 // by the UnmountFileSystem() call. 283 // by the UnmountFileSystem() call.
272 ++it; 284 ++it;
273 if (file_system_info.extension_id() == extension->id()) { 285 if (file_system_info.extension_id() == extension->id()) {
274 bool result = UnmountFileSystem(file_system_info.extension_id(), 286 bool result = UnmountFileSystem(
275 file_system_info.file_system_id()); 287 file_system_info.extension_id(),
288 file_system_info.file_system_id(),
289 reason == extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN
hashimoto 2014/07/02 08:59:37 If this method gets called during shutdown, is it
mtomasz 2014/07/03 05:24:07 That's correct but but not in case of unit tests.
hashimoto 2014/07/04 06:38:41 Please add a TODO comment to remove the redundant
mtomasz 2014/07/04 07:50:42 Done.
290 ? UNMOUNT_MODE_SHUTDOWN
291 : UNMOUNT_MODE_USER);
276 DCHECK(result); 292 DCHECK(result);
277 } 293 }
278 } 294 }
279 } 295 }
280 296
281 void Service::OnExtensionLoaded(content::BrowserContext* browser_context, 297 void Service::OnExtensionLoaded(content::BrowserContext* browser_context,
282 const extensions::Extension* extension) { 298 const extensions::Extension* extension) {
283 RestoreFileSystems(extension->id()); 299 RestoreFileSystems(extension->id());
284 } 300 }
285 301
(...skipping 20 matching lines...) Expand all
306 // Notify observers about failure in unmounting, since mount() will not be 322 // Notify observers about failure in unmounting, since mount() will not be
307 // called by the provided file system. In case of success mount() will be 323 // called by the provided file system. In case of success mount() will be
308 // invoked, and observers notified, so there is no need to call them now. 324 // invoked, and observers notified, so there is no need to call them now.
309 if (error != base::File::FILE_OK) { 325 if (error != base::File::FILE_OK) {
310 FOR_EACH_OBSERVER(Observer, 326 FOR_EACH_OBSERVER(Observer,
311 observers_, 327 observers_,
312 OnProvidedFileSystemUnmount(file_system_info, error)); 328 OnProvidedFileSystemUnmount(file_system_info, error));
313 } 329 }
314 } 330 }
315 331
316 void Service::RememberFileSystems() { 332 void Service::RememberFileSystem(
317 base::DictionaryValue extensions; 333 const ProvidedFileSystemInfo& file_system_info) {
318 const std::vector<ProvidedFileSystemInfo> file_system_info_list = 334 base::DictionaryValue* file_system = new base::DictionaryValue();
319 GetProvidedFileSystemInfoList(); 335 file_system->SetString(kPrefKeyFileSystemId,
hashimoto 2014/07/02 08:59:37 Please use one of "FooWithoutPathExpansion" or "Fo
mtomasz 2014/07/03 05:24:07 Currently I'm using WithoutPathExpansion only when
hashimoto 2014/07/04 06:38:41 The problem is that nothing can prevent you and ot
mtomasz 2014/07/04 07:50:42 Do you want me to use WithoutPathExpansion variant
hashimoto 2014/07/07 11:07:46 What Set/Get does is Set/GetWithoutPathExpansion +
mtomasz 2014/07/08 01:52:08 According to code search's xrefs: DictionaryValue:
hashimoto 2014/07/09 08:36:39 So what? Generally speaking, WithoutPathExpansion(
mtomasz 2014/07/09 09:18:17 DictionaryValue::SetString() sounds like a default
hashimoto 2014/07/11 06:09:05 Set() has a shorter name and is popular only becau
mtomasz 2014/07/11 06:10:36 Got it. That makes sense.
320 336 file_system_info.file_system_id());
321 for (std::vector<ProvidedFileSystemInfo>::const_iterator it = 337 file_system->SetString(kPrefKeyFileSystemName,
322 file_system_info_list.begin(); 338 file_system_info.file_system_name());
323 it != file_system_info_list.end();
324 ++it) {
325 base::ListValue* file_systems = NULL;
326 if (!extensions.GetList(it->extension_id(), &file_systems)) {
327 file_systems = new base::ListValue();
328 extensions.Set(it->extension_id(), file_systems);
329 }
330
331 base::DictionaryValue* file_system = new base::DictionaryValue();
332 file_system->SetString(kPrefKeyFileSystemId, it->file_system_id());
333 file_system->SetString(kPrefKeyFileSystemName, it->file_system_name());
334 file_systems->Append(file_system);
335 }
336 339
337 PrefService* pref_service = profile_->GetPrefs(); 340 PrefService* pref_service = profile_->GetPrefs();
338 DCHECK(pref_service); 341 DCHECK(pref_service);
339 pref_service->Set(prefs::kFileSystemProviderMounted, extensions); 342
343 DictionaryPrefUpdate dict_update(pref_service,
344 prefs::kFileSystemProviderMounted);
345
346 base::DictionaryValue* file_systems_per_extension = NULL;
347 if (!dict_update->GetDictionary(file_system_info.extension_id(),
348 &file_systems_per_extension)) {
349 file_systems_per_extension = new base::DictionaryValue();
350 dict_update->Set(file_system_info.extension_id(),
351 file_systems_per_extension);
352 }
353
354 file_systems_per_extension->SetWithoutPathExpansion(
355 file_system_info.file_system_id(), file_system);
340 pref_service->CommitPendingWrite(); 356 pref_service->CommitPendingWrite();
341 } 357 }
342 358
343 void Service::ForgetFileSystems(const std::string& extension_id) { 359 void Service::ForgetFileSystem(const ProvidedFileSystemInfo& file_system_info) {
344 PrefService* pref_service = profile_->GetPrefs(); 360 PrefService* pref_service = profile_->GetPrefs();
345 DCHECK(pref_service); 361 DCHECK(pref_service);
346 362
347 DictionaryPrefUpdate update(pref_service, prefs::kFileSystemProviderMounted); 363 DictionaryPrefUpdate dict_update(pref_service,
348 base::DictionaryValue* extensions = update.Get(); 364 prefs::kFileSystemProviderMounted);
349 DCHECK(extensions);
350 365
351 extensions->Remove(extension_id, NULL); 366 base::DictionaryValue* file_systems_per_extension = NULL;
367 if (!dict_update->GetDictionary(file_system_info.extension_id(),
368 &file_systems_per_extension)) {
369 return; // Nothing to forget.
370 }
371
372 file_systems_per_extension->RemoveWithoutPathExpansion(
373 file_system_info.file_system_id(), NULL);
374 if (!file_systems_per_extension->size())
375 dict_update->Remove(file_system_info.extension_id(), NULL);
376
377 pref_service->CommitPendingWrite();
352 } 378 }
353 379
354 void Service::RestoreFileSystems(const std::string& extension_id) { 380 void Service::RestoreFileSystems(const std::string& extension_id) {
355 PrefService* pref_service = profile_->GetPrefs(); 381 const base::DictionaryValue* file_systems_per_extension = NULL;
356 DCHECK(pref_service); 382 if (!file_systems_to_restore_->GetDictionary(extension_id,
hashimoto 2014/07/02 08:59:37 Is it OK to be unable to read prefs saved by the o
mtomasz 2014/07/03 05:24:07 Yes. The API is not released yet, and it is availa
383 &file_systems_per_extension)) {
384 return; // Nothing to restore.
385 }
357 386
358 const base::DictionaryValue* extensions = 387 base::DictionaryValue::Iterator it(*file_systems_per_extension);
359 pref_service->GetDictionary(prefs::kFileSystemProviderMounted); 388 while (!it.IsAtEnd()) {
hashimoto 2014/07/02 08:59:37 nit: How about "for (base::DicationaryValue::Itera
mtomasz 2014/07/03 05:24:07 Done.
360 DCHECK(extensions); 389 const base::Value* file_system_value = NULL;
361
362 const base::ListValue* file_systems = NULL;
363
364 if (!extensions->GetList(extension_id, &file_systems))
365 return;
366
367 for (size_t i = 0; i < file_systems->GetSize(); ++i) {
368 const base::DictionaryValue* file_system = NULL; 390 const base::DictionaryValue* file_system = NULL;
369 file_systems->GetDictionary(i, &file_system); 391 file_systems_per_extension->GetWithoutPathExpansion(it.key(),
370 DCHECK(file_system); 392 &file_system_value);
393 DCHECK(file_system_value);
371 394
372 std::string file_system_id; 395 std::string file_system_id;
373 file_system->GetString(kPrefKeyFileSystemId, &file_system_id);
374 DCHECK(!file_system_id.empty());
375
376 std::string file_system_name; 396 std::string file_system_name;
377 file_system->GetString(kPrefKeyFileSystemName, &file_system_name); 397 if (file_system_value->GetAsDictionary(&file_system)) {
378 DCHECK(!file_system_name.empty()); 398 file_system->GetString(kPrefKeyFileSystemId, &file_system_id);
399 file_system->GetString(kPrefKeyFileSystemName, &file_system_name);
400 }
379 401
380 if (file_system_id.empty() || file_system_name.empty()) { 402 if (file_system_id.empty() || file_system_name.empty()) {
381 LOG(ERROR) 403 LOG(ERROR)
382 << "Malformed provided file system information in preferences."; 404 << "Malformed provided file system information in preferences.";
383 continue; 405 continue;
384 } 406 }
385 407
386 const bool result = 408 const bool result =
387 MountFileSystem(extension_id, file_system_id, file_system_name); 409 MountFileSystem(extension_id, file_system_id, file_system_name);
388 if (!result) { 410 if (!result) {
389 LOG(ERROR) << "Failed to restore a provided file system from " 411 LOG(ERROR) << "Failed to restore a provided file system from "
390 << "preferences: " << extension_id << ", " << file_system_id 412 << "preferences: " << extension_id << ", " << file_system_id
391 << ", " << file_system_name << "."; 413 << ", " << file_system_name << ".";
392 } 414 }
415
416 it.Advance();
393 } 417 }
418
419 file_systems_to_restore_->Remove(extension_id, NULL);
394 } 420 }
395 421
396 } // namespace file_system_provider 422 } // namespace file_system_provider
397 } // namespace chromeos 423 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698