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

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: Fixed. 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());
hashimoto 2014/07/04 06:38:42 Do we need this code now? You can read the diction
mtomasz 2014/07/04 07:50:42 It makes things easier. Note, that In #420 we want
hashimoto 2014/07/07 11:07:46 You can save a list of file systems to be removed
mtomasz 2014/07/08 01:52:09 Done.
56 } 67 }
57 68
58 Service::~Service() { 69 Service::~Service() {
59 extension_registry_->RemoveObserver(this); 70 extension_registry_->RemoveObserver(this);
60 RememberFileSystems();
61 71
72 // Provided file systems should be already unmounted because of receiving
73 // OnExtensionUnload calls for each installed extension. However, for tests
74 // we may still have mounted extensions.
62 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); 75 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
63 while (it != file_system_map_.end()) { 76 while (it != file_system_map_.end()) {
64 const std::string file_system_id = 77 const std::string file_system_id =
65 it->second->GetFileSystemInfo().file_system_id(); 78 it->second->GetFileSystemInfo().file_system_id();
66 const std::string extension_id = 79 const std::string extension_id =
67 it->second->GetFileSystemInfo().extension_id(); 80 it->second->GetFileSystemInfo().extension_id();
68 ++it; 81 ++it;
69 const bool unmount_result = UnmountFileSystem(extension_id, file_system_id); 82 const bool unmount_result = UnmountFileSystem(
83 extension_id, file_system_id, UNMOUNT_REASON_SHUTDOWN);
70 DCHECK(unmount_result); 84 DCHECK(unmount_result);
71 } 85 }
72 86
73 DCHECK_EQ(0u, file_system_map_.size()); 87 DCHECK_EQ(0u, file_system_map_.size());
74 STLDeleteValues(&file_system_map_); 88 STLDeleteValues(&file_system_map_);
75 } 89 }
76 90
77 // static 91 // static
78 Service* Service::Get(content::BrowserContext* context) { 92 Service* Service::Get(content::BrowserContext* context) {
79 return ServiceFactory::Get(context); 93 return ServiceFactory::Get(context);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // mount_path = /provided/b33f1337-41-5aa5 164 // mount_path = /provided/b33f1337-41-5aa5
151 ProvidedFileSystemInfo file_system_info( 165 ProvidedFileSystemInfo file_system_info(
152 extension_id, file_system_id, file_system_name, mount_path); 166 extension_id, file_system_id, file_system_name, mount_path);
153 167
154 ProvidedFileSystemInterface* file_system = 168 ProvidedFileSystemInterface* file_system =
155 file_system_factory_.Run(profile_, file_system_info); 169 file_system_factory_.Run(profile_, file_system_info);
156 DCHECK(file_system); 170 DCHECK(file_system);
157 file_system_map_[FileSystemKey(extension_id, file_system_id)] = file_system; 171 file_system_map_[FileSystemKey(extension_id, file_system_id)] = file_system;
158 mount_point_name_to_key_map_[mount_point_name] = 172 mount_point_name_to_key_map_[mount_point_name] =
159 FileSystemKey(extension_id, file_system_id); 173 FileSystemKey(extension_id, file_system_id);
174 RememberFileSystem(file_system_info);
160 175
161 FOR_EACH_OBSERVER( 176 FOR_EACH_OBSERVER(
162 Observer, 177 Observer,
163 observers_, 178 observers_,
164 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK)); 179 OnProvidedFileSystemMount(file_system_info, base::File::FILE_OK));
165 180
166 return true; 181 return true;
167 } 182 }
168 183
169 bool Service::UnmountFileSystem(const std::string& extension_id, 184 bool Service::UnmountFileSystem(const std::string& extension_id,
170 const std::string& file_system_id) { 185 const std::string& file_system_id,
186 UnmountReason reason) {
171 DCHECK(thread_checker_.CalledOnValidThread()); 187 DCHECK(thread_checker_.CalledOnValidThread());
172 188
173 const ProvidedFileSystemMap::iterator file_system_it = 189 const ProvidedFileSystemMap::iterator file_system_it =
174 file_system_map_.find(FileSystemKey(extension_id, file_system_id)); 190 file_system_map_.find(FileSystemKey(extension_id, file_system_id));
175 if (file_system_it == file_system_map_.end()) { 191 if (file_system_it == file_system_map_.end()) {
176 const ProvidedFileSystemInfo empty_file_system_info; 192 const ProvidedFileSystemInfo empty_file_system_info;
177 FOR_EACH_OBSERVER( 193 FOR_EACH_OBSERVER(
178 Observer, 194 Observer,
179 observers_, 195 observers_,
180 OnProvidedFileSystemUnmount(empty_file_system_info, 196 OnProvidedFileSystemUnmount(empty_file_system_info,
(...skipping 19 matching lines...) Expand all
200 return false; 216 return false;
201 } 217 }
202 218
203 FOR_EACH_OBSERVER( 219 FOR_EACH_OBSERVER(
204 Observer, 220 Observer,
205 observers_, 221 observers_,
206 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); 222 OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK));
207 223
208 mount_point_name_to_key_map_.erase(mount_point_name); 224 mount_point_name_to_key_map_.erase(mount_point_name);
209 225
226 if (reason == UNMOUNT_REASON_USER)
hashimoto 2014/07/04 06:38:42 multiple lines should be accommodated with {}.
mtomasz 2014/07/04 07:50:42 Done.
227 ForgetFileSystem(file_system_info.extension_id(),
228 file_system_info.file_system_id());
229
210 delete file_system_it->second; 230 delete file_system_it->second;
211 file_system_map_.erase(file_system_it); 231 file_system_map_.erase(file_system_it);
212 232
213 return true; 233 return true;
214 } 234 }
215 235
216 bool Service::RequestUnmount(const std::string& extension_id, 236 bool Service::RequestUnmount(const std::string& extension_id,
217 const std::string& file_system_id) { 237 const std::string& file_system_id) {
218 DCHECK(thread_checker_.CalledOnValidThread()); 238 DCHECK(thread_checker_.CalledOnValidThread());
219 239
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 if (file_system_it == file_system_map_.end()) 271 if (file_system_it == file_system_map_.end())
252 return NULL; 272 return NULL;
253 273
254 return file_system_it->second; 274 return file_system_it->second;
255 } 275 }
256 276
257 void Service::OnExtensionUnloaded( 277 void Service::OnExtensionUnloaded(
258 content::BrowserContext* browser_context, 278 content::BrowserContext* browser_context,
259 const extensions::Extension* extension, 279 const extensions::Extension* extension,
260 extensions::UnloadedExtensionInfo::Reason reason) { 280 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. 281 // Unmount all of the provided file systems associated with this extension.
267 ProvidedFileSystemMap::iterator it = file_system_map_.begin(); 282 ProvidedFileSystemMap::iterator it = file_system_map_.begin();
268 while (it != file_system_map_.end()) { 283 while (it != file_system_map_.end()) {
269 const ProvidedFileSystemInfo& file_system_info = 284 const ProvidedFileSystemInfo& file_system_info =
270 it->second->GetFileSystemInfo(); 285 it->second->GetFileSystemInfo();
271 // Advance the iterator beforehand, otherwise it will become invalidated 286 // Advance the iterator beforehand, otherwise it will become invalidated
272 // by the UnmountFileSystem() call. 287 // by the UnmountFileSystem() call.
273 ++it; 288 ++it;
274 if (file_system_info.extension_id() == extension->id()) { 289 if (file_system_info.extension_id() == extension->id()) {
275 const bool unmount_result = UnmountFileSystem( 290 const bool unmount_result = UnmountFileSystem(
276 file_system_info.extension_id(), file_system_info.file_system_id()); 291 file_system_info.extension_id(),
292 file_system_info.file_system_id(),
293 reason == extensions::UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN
294 ? UNMOUNT_REASON_SHUTDOWN
295 : UNMOUNT_REASON_USER);
277 DCHECK(unmount_result); 296 DCHECK(unmount_result);
278 } 297 }
279 } 298 }
280 } 299 }
281 300
282 void Service::OnExtensionLoaded(content::BrowserContext* browser_context, 301 void Service::OnExtensionLoaded(content::BrowserContext* browser_context,
283 const extensions::Extension* extension) { 302 const extensions::Extension* extension) {
284 RestoreFileSystems(extension->id()); 303 RestoreFileSystems(extension->id());
285 } 304 }
286 305
(...skipping 20 matching lines...) Expand all
307 // Notify observers about failure in unmounting, since mount() will not be 326 // 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 327 // 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. 328 // invoked, and observers notified, so there is no need to call them now.
310 if (error != base::File::FILE_OK) { 329 if (error != base::File::FILE_OK) {
311 FOR_EACH_OBSERVER(Observer, 330 FOR_EACH_OBSERVER(Observer,
312 observers_, 331 observers_,
313 OnProvidedFileSystemUnmount(file_system_info, error)); 332 OnProvidedFileSystemUnmount(file_system_info, error));
314 } 333 }
315 } 334 }
316 335
317 void Service::RememberFileSystems() { 336 void Service::RememberFileSystem(
318 base::DictionaryValue extensions; 337 const ProvidedFileSystemInfo& file_system_info) {
319 const std::vector<ProvidedFileSystemInfo> file_system_info_list = 338 base::DictionaryValue* file_system = new base::DictionaryValue();
320 GetProvidedFileSystemInfoList(); 339 file_system->SetString(kPrefKeyFileSystemId,
321 340 file_system_info.file_system_id());
322 for (std::vector<ProvidedFileSystemInfo>::const_iterator it = 341 file_system->SetString(kPrefKeyFileSystemName,
323 file_system_info_list.begin(); 342 file_system_info.file_system_name());
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
332 base::DictionaryValue* file_system = new base::DictionaryValue();
333 file_system->SetString(kPrefKeyFileSystemId, it->file_system_id());
334 file_system->SetString(kPrefKeyFileSystemName, it->file_system_name());
335 file_systems->Append(file_system);
336 }
337 343
338 PrefService* pref_service = profile_->GetPrefs(); 344 PrefService* pref_service = profile_->GetPrefs();
339 DCHECK(pref_service); 345 DCHECK(pref_service);
340 pref_service->Set(prefs::kFileSystemProviderMounted, extensions); 346
347 DictionaryPrefUpdate dict_update(pref_service,
348 prefs::kFileSystemProviderMounted);
349
350 base::DictionaryValue* file_systems_per_extension = NULL;
351 if (!dict_update->GetDictionary(file_system_info.extension_id(),
352 &file_systems_per_extension)) {
353 file_systems_per_extension = new base::DictionaryValue();
354 dict_update->Set(file_system_info.extension_id(),
355 file_systems_per_extension);
356 }
357
358 file_systems_per_extension->SetWithoutPathExpansion(
359 file_system_info.file_system_id(), file_system);
341 pref_service->CommitPendingWrite(); 360 pref_service->CommitPendingWrite();
hashimoto 2014/07/04 06:38:42 pref_service.h says CommitPendingWrite() should be
mtomasz 2014/07/04 07:50:42 If a crash happens, then we don't want to lose mou
342 } 361 }
343 362
344 void Service::ForgetFileSystems(const std::string& extension_id) { 363 void Service::ForgetFileSystem(const std::string& extension_id,
364 const std::string& file_system_id) {
345 PrefService* pref_service = profile_->GetPrefs(); 365 PrefService* pref_service = profile_->GetPrefs();
346 DCHECK(pref_service); 366 DCHECK(pref_service);
347 367
348 DictionaryPrefUpdate update(pref_service, prefs::kFileSystemProviderMounted); 368 DictionaryPrefUpdate dict_update(pref_service,
349 base::DictionaryValue* extensions = update.Get(); 369 prefs::kFileSystemProviderMounted);
350 DCHECK(extensions);
351 370
352 extensions->Remove(extension_id, NULL); 371 base::DictionaryValue* file_systems_per_extension = NULL;
372 if (!dict_update->GetDictionary(extension_id, &file_systems_per_extension)) {
373 return; // Nothing to forget.
374 }
375
376 file_systems_per_extension->RemoveWithoutPathExpansion(file_system_id, NULL);
377 if (!file_systems_per_extension->size())
378 dict_update->Remove(extension_id, NULL);
379
380 pref_service->CommitPendingWrite();
hashimoto 2014/07/04 06:38:41 ditto.
mtomasz 2014/07/04 07:50:42 Done.
353 } 381 }
354 382
355 void Service::RestoreFileSystems(const std::string& extension_id) { 383 void Service::RestoreFileSystems(const std::string& extension_id) {
356 PrefService* pref_service = profile_->GetPrefs(); 384 const base::DictionaryValue* file_systems_per_extension = NULL;
357 DCHECK(pref_service); 385 if (!file_systems_to_restore_->GetDictionary(extension_id,
386 &file_systems_per_extension)) {
387 return; // Nothing to restore.
388 }
358 389
359 const base::DictionaryValue* extensions = 390 for (base::DictionaryValue::Iterator it(*file_systems_per_extension);
360 pref_service->GetDictionary(prefs::kFileSystemProviderMounted); 391 !it.IsAtEnd();
361 DCHECK(extensions); 392 it.Advance()) {
362 393 const base::Value* file_system_value = NULL;
363 const base::ListValue* file_systems = NULL;
364
365 if (!extensions->GetList(extension_id, &file_systems))
366 return;
367
368 for (size_t i = 0; i < file_systems->GetSize(); ++i) {
369 const base::DictionaryValue* file_system = NULL; 394 const base::DictionaryValue* file_system = NULL;
370 file_systems->GetDictionary(i, &file_system); 395 file_systems_per_extension->GetWithoutPathExpansion(it.key(),
371 DCHECK(file_system); 396 &file_system_value);
397 DCHECK(file_system_value);
372 398
373 std::string file_system_id; 399 std::string file_system_id;
374 file_system->GetString(kPrefKeyFileSystemId, &file_system_id);
375 DCHECK(!file_system_id.empty());
376
377 std::string file_system_name; 400 std::string file_system_name;
378 file_system->GetString(kPrefKeyFileSystemName, &file_system_name); 401 if (file_system_value->GetAsDictionary(&file_system)) {
379 DCHECK(!file_system_name.empty()); 402 file_system->GetString(kPrefKeyFileSystemId, &file_system_id);
403 file_system->GetString(kPrefKeyFileSystemName, &file_system_name);
404 }
380 405
381 if (file_system_id.empty() || file_system_name.empty()) { 406 if (file_system_id.empty() || file_system_name.empty()) {
382 LOG(ERROR) 407 LOG(ERROR)
383 << "Malformed provided file system information in preferences."; 408 << "Malformed provided file system information in preferences.";
384 continue; 409 continue;
385 } 410 }
386 411
387 const bool result = 412 const bool result =
388 MountFileSystem(extension_id, file_system_id, file_system_name); 413 MountFileSystem(extension_id, file_system_id, file_system_name);
389 if (!result) { 414 if (!result) {
390 LOG(ERROR) << "Failed to restore a provided file system from " 415 LOG(ERROR) << "Failed to restore a provided file system from "
391 << "preferences: " << extension_id << ", " << file_system_id 416 << "preferences: " << extension_id << ", " << file_system_id
392 << ", " << file_system_name << "."; 417 << ", " << file_system_name << ".";
418 // In case of remounting during startup, forget the file system from
419 // preferences.
420 ForgetFileSystem(extension_id, file_system_id);
393 } 421 }
394 } 422 }
423
424 file_systems_to_restore_->Remove(extension_id, NULL);
395 } 425 }
396 426
397 } // namespace file_system_provider 427 } // namespace file_system_provider
398 } // namespace chromeos 428 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698