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

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: Rebased. 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 } 56 }
57 57
58 Service::~Service() { 58 Service::~Service() {
59 extension_registry_->RemoveObserver(this); 59 extension_registry_->RemoveObserver(this);
60 RememberFileSystems();
61 60
61 // Provided file systems should be already unmounted because of receiving
62 // OnExtensionUnload calls for each installed extension. However, for tests
63 // we may still have mounted extensions.
64 // TODO(mtomasz): Create a TestingService class and remove this code.
62 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); 65 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
63 while (it != file_system_map_.end()) { 66 while (it != file_system_map_.end()) {
64 const std::string file_system_id = 67 const std::string file_system_id =
65 it->second->GetFileSystemInfo().file_system_id(); 68 it->second->GetFileSystemInfo().file_system_id();
66 const std::string extension_id = 69 const std::string extension_id =
67 it->second->GetFileSystemInfo().extension_id(); 70 it->second->GetFileSystemInfo().extension_id();
68 ++it; 71 ++it;
69 const bool unmount_result = UnmountFileSystem(extension_id, file_system_id); 72 const bool unmount_result = UnmountFileSystem(
73 extension_id, file_system_id, UNMOUNT_REASON_SHUTDOWN);
70 DCHECK(unmount_result); 74 DCHECK(unmount_result);
71 } 75 }
72 76
73 DCHECK_EQ(0u, file_system_map_.size()); 77 DCHECK_EQ(0u, file_system_map_.size());
74 STLDeleteValues(&file_system_map_); 78 STLDeleteValues(&file_system_map_);
75 } 79 }
76 80
77 // static 81 // static
78 Service* Service::Get(content::BrowserContext* context) { 82 Service* Service::Get(content::BrowserContext* context) {
79 return ServiceFactory::Get(context); 83 return ServiceFactory::Get(context);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // mount_path = /provided/b33f1337-41-5aa5 154 // mount_path = /provided/b33f1337-41-5aa5
151 ProvidedFileSystemInfo file_system_info( 155 ProvidedFileSystemInfo file_system_info(
152 extension_id, file_system_id, display_name, mount_path); 156 extension_id, file_system_id, display_name, mount_path);
153 157
154 ProvidedFileSystemInterface* file_system = 158 ProvidedFileSystemInterface* file_system =
155 file_system_factory_.Run(profile_, file_system_info); 159 file_system_factory_.Run(profile_, file_system_info);
156 DCHECK(file_system); 160 DCHECK(file_system);
157 file_system_map_[FileSystemKey(extension_id, file_system_id)] = file_system; 161 file_system_map_[FileSystemKey(extension_id, file_system_id)] = file_system;
158 mount_point_name_to_key_map_[mount_point_name] = 162 mount_point_name_to_key_map_[mount_point_name] =
159 FileSystemKey(extension_id, file_system_id); 163 FileSystemKey(extension_id, file_system_id);
164 RememberFileSystem(file_system_info);
160 165
161 FOR_EACH_OBSERVER( 166 FOR_EACH_OBSERVER(
162 Observer, 167 Observer,
163 observers_, 168 observers_,
164 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK)); 169 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK));
165 170
166 return true; 171 return true;
167 } 172 }
168 173
169 bool Service::UnmountFileSystem(const std::string& extension_id, 174 bool Service::UnmountFileSystem(const std::string& extension_id,
170 const std::string& file_system_id) { 175 const std::string& file_system_id,
176 UnmountReason reason) {
171 DCHECK(thread_checker_.CalledOnValidThread()); 177 DCHECK(thread_checker_.CalledOnValidThread());
172 178
173 const ProvidedFileSystemMap::iterator file_system_it = 179 const ProvidedFileSystemMap::iterator file_system_it =
174 file_system_map_.find(FileSystemKey(extension_id, file_system_id)); 180 file_system_map_.find(FileSystemKey(extension_id, file_system_id));
175 if (file_system_it == file_system_map_.end()) { 181 if (file_system_it == file_system_map_.end()) {
176 const ProvidedFileSystemInfo empty_file_system_info; 182 const ProvidedFileSystemInfo empty_file_system_info;
177 FOR_EACH_OBSERVER( 183 FOR_EACH_OBSERVER(
178 Observer, 184 Observer,
179 observers_, 185 observers_,
180 OnProvidedFileSystemUnmount(empty_file_system_info, 186 OnProvidedFileSystemUnmount(empty_file_system_info,
(...skipping 19 matching lines...) Expand all
200 return false; 206 return false;
201 } 207 }
202 208
203 FOR_EACH_OBSERVER( 209 FOR_EACH_OBSERVER(
204 Observer, 210 Observer,
205 observers_, 211 observers_,
206 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); 212 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK));
207 213
208 mount_point_name_to_key_map_.erase(mount_point_name); 214 mount_point_name_to_key_map_.erase(mount_point_name);
209 215
216 if (reason == UNMOUNT_REASON_USER) {
217 ForgetFileSystem(file_system_info.extension_id(),
218 file_system_info.file_system_id());
219 }
220
210 delete file_system_it->second; 221 delete file_system_it->second;
211 file_system_map_.erase(file_system_it); 222 file_system_map_.erase(file_system_it);
212 223
213 return true; 224 return true;
214 } 225 }
215 226
216 bool Service::RequestUnmount(const std::string& extension_id, 227 bool Service::RequestUnmount(const std::string& extension_id,
217 const std::string& file_system_id) { 228 const std::string& file_system_id) {
218 DCHECK(thread_checker_.CalledOnValidThread()); 229 DCHECK(thread_checker_.CalledOnValidThread());
219 230
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 if (file_system_it == file_system_map_.end()) 262 if (file_system_it == file_system_map_.end())
252 return NULL; 263 return NULL;
253 264
254 return file_system_it->second; 265 return file_system_it->second;
255 } 266 }
256 267
257 void Service::OnExtensionUnloaded( 268 void Service::OnExtensionUnloaded(
258 content::BrowserContext* browser_context, 269 content::BrowserContext* browser_context,
259 const extensions::Extension* extension, 270 const extensions::Extension* extension,
260 extensions::UnloadedExtensionInfo::Reason reason) { 271 extensions::UnloadedExtensionInfo::Reason reason) {
261 // If the reason is not a profile shutdown, then forget the mounted file
262 // systems from preferences.
263 if (reason != extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN)
264 ForgetFileSystems(extension->id());
265
266 // Unmount all of the provided file systems associated with this extension. 272 // Unmount all of the provided file systems associated with this extension.
267 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); 273 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
268 while (it != file_system_map_.end()) { 274 while (it != file_system_map_.end()) {
269 const ProvidedFileSystemInfo& file_system_info = 275 const ProvidedFileSystemInfo& file_system_info =
270 it->second->GetFileSystemInfo(); 276 it->second->GetFileSystemInfo();
271 // Advance the iterator beforehand, otherwise it will become invalidated 277 // Advance the iterator beforehand, otherwise it will become invalidated
272 // by the UnmountFileSystem() call. 278 // by the UnmountFileSystem() call.
273 ++it; 279 ++it;
274 if (file_system_info.extension_id() == extension->id()) { 280 if (file_system_info.extension_id() == extension->id()) {
275 const bool unmount_result = UnmountFileSystem( 281 const bool unmount_result = UnmountFileSystem(
276 file_system_info.extension_id(), file_system_info.file_system_id()); 282 file_system_info.extension_id(),
283 file_system_info.file_system_id(),
284 reason == extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN
285 ? UNMOUNT_REASON_SHUTDOWN
286 : UNMOUNT_REASON_USER);
277 DCHECK(unmount_result); 287 DCHECK(unmount_result);
278 } 288 }
279 } 289 }
280 } 290 }
281 291
282 void Service::OnExtensionLoaded(content::BrowserContext* browser_context, 292 void Service::OnExtensionLoaded(content::BrowserContext* browser_context,
283 const extensions::Extension* extension) { 293 const extensions::Extension* extension) {
284 RestoreFileSystems(extension->id()); 294 RestoreFileSystems(extension->id());
285 } 295 }
286 296
(...skipping 20 matching lines...) Expand all
307 // Notify observers about failure in unmounting, since mount() will not be 317 // Notify observers about failure in unmounting, since mount() will not be
308 // called by the provided file system. In case of success mount() will be 318 // called by the provided file system. In case of success mount() will be
309 // invoked, and observers notified, so there is no need to call them now. 319 // invoked, and observers notified, so there is no need to call them now.
310 if (error != base::File::FILE_OK) { 320 if (error != base::File::FILE_OK) {
311 FOR_EACH_OBSERVER(Observer, 321 FOR_EACH_OBSERVER(Observer,
312 observers_, 322 observers_,
313 OnProvidedFileSystemUnmount(file_system_info, error)); 323 OnProvidedFileSystemUnmount(file_system_info, error));
314 } 324 }
315 } 325 }
316 326
317 void Service::RememberFileSystems() { 327 void Service::RememberFileSystem(
318 base::DictionaryValue extensions; 328 const ProvidedFileSystemInfo& file_system_info) {
319 const std::vector<ProvidedFileSystemInfo> file_system_info_list = 329 base::DictionaryValue* file_system = new base::DictionaryValue();
320 GetProvidedFileSystemInfoList(); 330 file_system->SetStringWithoutPathExpansion(kPrefKeyFileSystemId,
331 file_system_info.file_system_id());
332 file_system->SetStringWithoutPathExpansion(kPrefKeyDisplayName,
333 file_system_info.display_name());
321 334
322 for (std::vector<ProvidedFileSystemInfo>::const_iterator it = 335 PrefService* const pref_service = profile_->GetPrefs();
323 file_system_info_list.begin(); 336 DCHECK(pref_service);
324 it != file_system_info_list.end();
325 ++it) {
326 base::ListValue* file_systems = NULL;
327 if (!extensions.GetList(it->extension_id(), &file_systems)) {
328 file_systems = new base::ListValue();
329 extensions.Set(it->extension_id(), file_systems);
330 }
331 337
332 base::DictionaryValue* file_system = new base::DictionaryValue(); 338 DictionaryPrefUpdate dict_update(pref_service,
333 file_system->SetString(kPrefKeyFileSystemId, it->file_system_id()); 339 prefs::kFileSystemProviderMounted);
334 file_system->SetString(kPrefKeyDisplayName, it->display_name()); 340
335 file_systems->Append(file_system); 341 base::DictionaryValue* file_systems_per_extension = NULL;
342 if (!dict_update->GetDictionaryWithoutPathExpansion(
343 file_system_info.extension_id(), &file_systems_per_extension)) {
344 file_systems_per_extension = new base::DictionaryValue();
345 dict_update->SetWithoutPathExpansion(file_system_info.extension_id(),
346 file_systems_per_extension);
336 } 347 }
337 348
338 PrefService* pref_service = profile_->GetPrefs(); 349 file_systems_per_extension->SetWithoutPathExpansion(
339 DCHECK(pref_service); 350 file_system_info.file_system_id(), file_system);
340 pref_service->Set(prefs::kFileSystemProviderMounted, extensions);
341 pref_service->CommitPendingWrite();
342 } 351 }
343 352
344 void Service::ForgetFileSystems(const std::string& extension_id) { 353 void Service::ForgetFileSystem(const std::string& extension_id,
345 PrefService* pref_service = profile_->GetPrefs(); 354 const std::string& file_system_id) {
355 PrefService* const pref_service = profile_->GetPrefs();
346 DCHECK(pref_service); 356 DCHECK(pref_service);
347 357
348 DictionaryPrefUpdate update(pref_service, prefs::kFileSystemProviderMounted); 358 DictionaryPrefUpdate dict_update(pref_service,
349 base::DictionaryValue* extensions = update.Get(); 359 prefs::kFileSystemProviderMounted);
350 DCHECK(extensions);
351 360
352 extensions->Remove(extension_id, NULL); 361 base::DictionaryValue* file_systems_per_extension = NULL;
362 if (!dict_update->GetDictionaryWithoutPathExpansion(
363 extension_id, &file_systems_per_extension))
364 return; // Nothing to forget.
365
366 file_systems_per_extension->RemoveWithoutPathExpansion(file_system_id, NULL);
367 if (!file_systems_per_extension->size())
368 dict_update->Remove(extension_id, NULL);
353 } 369 }
354 370
355 void Service::RestoreFileSystems(const std::string& extension_id) { 371 void Service::RestoreFileSystems(const std::string& extension_id) {
356 PrefService* pref_service = profile_->GetPrefs(); 372 PrefService* const pref_service = profile_->GetPrefs();
357 DCHECK(pref_service); 373 DCHECK(pref_service);
358 374
359 const base::DictionaryValue* extensions = 375 const base::DictionaryValue* const file_systems =
360 pref_service->GetDictionary(prefs::kFileSystemProviderMounted); 376 pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
361 DCHECK(extensions); 377 DCHECK(file_systems);
362 378
363 const base::ListValue* file_systems = NULL; 379 const base::DictionaryValue* file_systems_per_extension = NULL;
380 if (!file_systems->GetDictionaryWithoutPathExpansion(
381 extension_id, &file_systems_per_extension))
382 return; // Nothing to restore.
364 383
365 if (!extensions->GetList(extension_id, &file_systems)) 384 // Use a copy of the dictionary, since the original one may be modified while
366 return; 385 // iterating over it.
386 scoped_ptr<const base::DictionaryValue> file_systems_per_extension_copy(
387 file_systems_per_extension->DeepCopy());
367 388
368 for (size_t i = 0; i < file_systems->GetSize(); ++i) { 389 for (base::DictionaryValue::Iterator it(*file_systems_per_extension_copy);
390 !it.IsAtEnd();
391 it.Advance()) {
392 const base::Value* file_system_value = NULL;
369 const base::DictionaryValue* file_system = NULL; 393 const base::DictionaryValue* file_system = NULL;
370 file_systems->GetDictionary(i, &file_system); 394 file_systems_per_extension_copy->GetWithoutPathExpansion(
371 DCHECK(file_system); 395 it.key(), &file_system_value);
396 DCHECK(file_system_value);
372 397
373 std::string file_system_id; 398 std::string file_system_id;
374 file_system->GetString(kPrefKeyFileSystemId, &file_system_id);
375 DCHECK(!file_system_id.empty());
376
377 std::string display_name; 399 std::string display_name;
378 file_system->GetString(kPrefKeyDisplayName, &display_name); 400 if (file_system_value->GetAsDictionary(&file_system)) {
379 DCHECK(!display_name.empty()); 401 file_system->GetStringWithoutPathExpansion(kPrefKeyFileSystemId,
402 &file_system_id);
403 file_system->GetStringWithoutPathExpansion(kPrefKeyDisplayName,
404 &display_name);
405 }
380 406
381 if (file_system_id.empty() || display_name.empty()) { 407 if (file_system_id.empty() || display_name.empty()) {
382 LOG(ERROR) 408 LOG(ERROR)
383 << "Malformed provided file system information in preferences."; 409 << "Malformed provided file system information in preferences.";
384 continue; 410 continue;
385 } 411 }
386 412
387 const bool result = 413 const bool result =
388 MountFileSystem(extension_id, file_system_id, display_name); 414 MountFileSystem(extension_id, file_system_id, display_name);
389 if (!result) { 415 if (!result) {
390 LOG(ERROR) << "Failed to restore a provided file system from " 416 LOG(ERROR) << "Failed to restore a provided file system from "
391 << "preferences: " << extension_id << ", " << file_system_id 417 << "preferences: " << extension_id << ", " << file_system_id
392 << ", " << display_name << "."; 418 << ", " << display_name << ".";
419 // In case of remounting during startup, forget the file system from
hashimoto 2014/07/09 08:36:39 What does this comment mean?
mtomasz 2014/07/09 09:18:17 RestoreFileSystems() is called during startup. If
420 // preferences.
421 ForgetFileSystem(extension_id, file_system_id);
hashimoto 2014/07/09 08:36:39 Is it OK to forget the file system which is actual
mtomasz 2014/07/09 09:18:17 This case can't happen. RestoreFileSystems() is ca
393 } 422 }
394 } 423 }
395 } 424 }
396 425
397 } // namespace file_system_provider 426 } // namespace file_system_provider
398 } // namespace chromeos 427 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698