OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |