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