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

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