| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "apps/saved_files_service.h" | 5 #include "apps/saved_files_service_impl.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <map> | 10 #include <map> |
| 11 #include <unordered_map> | 11 #include <unordered_map> |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "apps/saved_files_service_factory.h" | 14 #include "apps/saved_files_service_factory.h" |
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 16 #include "base/value_conversions.h" | 16 #include "base/value_conversions.h" |
| 17 #include "content/public/browser/browser_context.h" | 17 #include "content/public/browser/browser_context.h" |
| 18 #include "content/public/browser/notification_service.h" | 18 #include "content/public/browser/notification_service.h" |
| 19 #include "extensions/browser/extension_host.h" | 19 #include "extensions/browser/extension_host.h" |
| 20 #include "extensions/browser/extension_prefs.h" | 20 #include "extensions/browser/extension_prefs.h" |
| 21 #include "extensions/browser/extension_system.h" | 21 #include "extensions/browser/extension_system.h" |
| 22 #include "extensions/browser/notification_types.h" | 22 #include "extensions/browser/notification_types.h" |
| 23 #include "extensions/common/permissions/api_permission.h" | 23 #include "extensions/common/permissions/api_permission.h" |
| 24 #include "extensions/common/permissions/permission_set.h" | 24 #include "extensions/common/permissions/permission_set.h" |
| 25 #include "extensions/common/permissions/permissions_data.h" | 25 #include "extensions/common/permissions/permissions_data.h" |
| 26 | 26 |
| 27 namespace apps { | 27 namespace apps { |
| 28 | 28 |
| 29 using extensions::APIPermission; | 29 using extensions::APIPermission; |
| 30 using extensions::Extension; | 30 using extensions::Extension; |
| 31 using extensions::ExtensionHost; | 31 using extensions::ExtensionHost; |
| 32 using extensions::ExtensionPrefs; | 32 using extensions::ExtensionPrefs; |
| 33 using extensions::SavedFilesService; |
| 33 | 34 |
| 34 namespace { | 35 namespace { |
| 35 | 36 |
| 36 // Preference keys | 37 // Preference keys |
| 37 | 38 |
| 38 // The file entries that the app has permission to access. | 39 // The file entries that the app has permission to access. |
| 39 const char kFileEntries[] = "file_entries"; | 40 const char kFileEntries[] = "file_entries"; |
| 40 | 41 |
| 41 // The path to a file entry that the app had permission to access. | 42 // The path to a file entry that the app had permission to access. |
| 42 const char kFileEntryPath[] = "path"; | 43 const char kFileEntryPath[] = "path"; |
| 43 | 44 |
| 44 // Whether or not the the entry refers to a directory. | 45 // Whether or not the the entry refers to a directory. |
| 45 const char kFileEntryIsDirectory[] = "is_directory"; | 46 const char kFileEntryIsDirectory[] = "is_directory"; |
| 46 | 47 |
| 47 // The sequence number in the LRU of the file entry. | 48 // The sequence number in the LRU of the file entry. |
| 48 const char kFileEntrySequenceNumber[] = "sequence_number"; | 49 const char kFileEntrySequenceNumber[] = "sequence_number"; |
| 49 | 50 |
| 50 const size_t kMaxSavedFileEntries = 500; | 51 const size_t kMaxSavedFileEntries = 500; |
| 51 const int kMaxSequenceNumber = INT32_MAX; | 52 const int kMaxSequenceNumber = INT32_MAX; |
| 52 | 53 |
| 53 // These might be different to the constant values in tests. | 54 // These might be different to the constant values in tests. |
| 54 size_t g_max_saved_file_entries = kMaxSavedFileEntries; | 55 size_t g_max_saved_file_entries = kMaxSavedFileEntries; |
| 55 int g_max_sequence_number = kMaxSequenceNumber; | 56 int g_max_sequence_number = kMaxSequenceNumber; |
| 56 | 57 |
| 57 // Persists a SavedFileEntry in ExtensionPrefs. | 58 // Persists a saved file entry in ExtensionPrefs. |
| 58 void AddSavedFileEntry(ExtensionPrefs* prefs, | 59 void AddSavedFileEntry(ExtensionPrefs* prefs, |
| 59 const std::string& extension_id, | 60 const std::string& extension_id, |
| 60 const SavedFileEntry& file_entry) { | 61 const SavedFilesService::Entry& file_entry) { |
| 61 ExtensionPrefs::ScopedDictionaryUpdate update( | 62 ExtensionPrefs::ScopedDictionaryUpdate update(prefs, extension_id, |
| 62 prefs, extension_id, kFileEntries); | 63 kFileEntries); |
| 63 auto file_entries = update.Create(); | 64 auto file_entries = update.Create(); |
| 64 DCHECK(!file_entries->GetDictionaryWithoutPathExpansion(file_entry.id, NULL)); | 65 DCHECK(!file_entries->GetDictionaryWithoutPathExpansion(file_entry.id, NULL)); |
| 65 | 66 |
| 66 std::unique_ptr<base::DictionaryValue> file_entry_dict = | 67 std::unique_ptr<base::DictionaryValue> file_entry_dict = |
| 67 base::MakeUnique<base::DictionaryValue>(); | 68 base::MakeUnique<base::DictionaryValue>(); |
| 68 file_entry_dict->Set(kFileEntryPath, CreateFilePathValue(file_entry.path)); | 69 file_entry_dict->Set(kFileEntryPath, CreateFilePathValue(file_entry.path)); |
| 69 file_entry_dict->SetBoolean(kFileEntryIsDirectory, file_entry.is_directory); | 70 file_entry_dict->SetBoolean(kFileEntryIsDirectory, file_entry.is_directory); |
| 70 file_entry_dict->SetInteger(kFileEntrySequenceNumber, | 71 file_entry_dict->SetInteger(kFileEntrySequenceNumber, |
| 71 file_entry.sequence_number); | 72 file_entry.sequence_number); |
| 72 file_entries->SetWithoutPathExpansion(file_entry.id, | 73 file_entries->SetWithoutPathExpansion(file_entry.id, |
| 73 std::move(file_entry_dict)); | 74 std::move(file_entry_dict)); |
| 74 } | 75 } |
| 75 | 76 |
| 76 // Updates the sequence_number of a SavedFileEntry persisted in ExtensionPrefs. | 77 // Updates the sequence_number of a saved file entry persisted in |
| 78 // ExtensionPrefs. |
| 77 void UpdateSavedFileEntry(ExtensionPrefs* prefs, | 79 void UpdateSavedFileEntry(ExtensionPrefs* prefs, |
| 78 const std::string& extension_id, | 80 const std::string& extension_id, |
| 79 const SavedFileEntry& file_entry) { | 81 const SavedFilesService::Entry& file_entry) { |
| 80 ExtensionPrefs::ScopedDictionaryUpdate update( | 82 ExtensionPrefs::ScopedDictionaryUpdate update(prefs, extension_id, |
| 81 prefs, extension_id, kFileEntries); | 83 kFileEntries); |
| 82 auto file_entries = update.Get(); | 84 auto file_entries = update.Get(); |
| 83 DCHECK(file_entries); | 85 DCHECK(file_entries); |
| 84 std::unique_ptr<prefs::DictionaryValueUpdate> file_entry_dict; | 86 std::unique_ptr<prefs::DictionaryValueUpdate> file_entry_dict; |
| 85 file_entries->GetDictionaryWithoutPathExpansion(file_entry.id, | 87 file_entries->GetDictionaryWithoutPathExpansion(file_entry.id, |
| 86 &file_entry_dict); | 88 &file_entry_dict); |
| 87 DCHECK(file_entry_dict); | 89 DCHECK(file_entry_dict); |
| 88 file_entry_dict->SetInteger(kFileEntrySequenceNumber, | 90 file_entry_dict->SetInteger(kFileEntrySequenceNumber, |
| 89 file_entry.sequence_number); | 91 file_entry.sequence_number); |
| 90 } | 92 } |
| 91 | 93 |
| 92 // Removes a SavedFileEntry from ExtensionPrefs. | 94 // Removes a saved file entry from ExtensionPrefs. |
| 93 void RemoveSavedFileEntry(ExtensionPrefs* prefs, | 95 void RemoveSavedFileEntry(ExtensionPrefs* prefs, |
| 94 const std::string& extension_id, | 96 const std::string& extension_id, |
| 95 const std::string& file_entry_id) { | 97 const std::string& file_entry_id) { |
| 96 ExtensionPrefs::ScopedDictionaryUpdate update( | 98 ExtensionPrefs::ScopedDictionaryUpdate update(prefs, extension_id, |
| 97 prefs, extension_id, kFileEntries); | 99 kFileEntries); |
| 98 auto file_entries = update.Create(); | 100 auto file_entries = update.Create(); |
| 99 file_entries->RemoveWithoutPathExpansion(file_entry_id, NULL); | 101 file_entries->RemoveWithoutPathExpansion(file_entry_id, NULL); |
| 100 } | 102 } |
| 101 | 103 |
| 102 // Clears all SavedFileEntry for the app from ExtensionPrefs. | 104 // Clears all saved file entries for the app from ExtensionPrefs. |
| 103 void ClearSavedFileEntries(ExtensionPrefs* prefs, | 105 void ClearSavedFileEntries(ExtensionPrefs* prefs, |
| 104 const std::string& extension_id) { | 106 const std::string& extension_id) { |
| 105 prefs->UpdateExtensionPref(extension_id, kFileEntries, nullptr); | 107 prefs->UpdateExtensionPref(extension_id, kFileEntries, nullptr); |
| 106 } | 108 } |
| 107 | 109 |
| 108 // Returns all SavedFileEntries for the app. | 110 // Returns all saved file entries for the app. |
| 109 std::vector<SavedFileEntry> GetSavedFileEntries( | 111 std::vector<SavedFilesService::Entry> GetSavedFileEntries( |
| 110 ExtensionPrefs* prefs, | 112 ExtensionPrefs* prefs, |
| 111 const std::string& extension_id) { | 113 const std::string& extension_id) { |
| 112 std::vector<SavedFileEntry> result; | 114 std::vector<SavedFilesService::Entry> result; |
| 113 const base::DictionaryValue* file_entries = NULL; | 115 const base::DictionaryValue* file_entries = NULL; |
| 114 if (!prefs->ReadPrefAsDictionary(extension_id, kFileEntries, &file_entries)) | 116 if (!prefs->ReadPrefAsDictionary(extension_id, kFileEntries, &file_entries)) |
| 115 return result; | 117 return result; |
| 116 | 118 |
| 117 for (base::DictionaryValue::Iterator it(*file_entries); !it.IsAtEnd(); | 119 for (base::DictionaryValue::Iterator it(*file_entries); !it.IsAtEnd(); |
| 118 it.Advance()) { | 120 it.Advance()) { |
| 119 const base::DictionaryValue* file_entry = NULL; | 121 const base::DictionaryValue* file_entry = NULL; |
| 120 if (!it.value().GetAsDictionary(&file_entry)) | 122 if (!it.value().GetAsDictionary(&file_entry)) |
| 121 continue; | 123 continue; |
| 122 const base::Value* path_value; | 124 const base::Value* path_value; |
| 123 if (!file_entry->Get(kFileEntryPath, &path_value)) | 125 if (!file_entry->Get(kFileEntryPath, &path_value)) |
| 124 continue; | 126 continue; |
| 125 base::FilePath file_path; | 127 base::FilePath file_path; |
| 126 if (!GetValueAsFilePath(*path_value, &file_path)) | 128 if (!GetValueAsFilePath(*path_value, &file_path)) |
| 127 continue; | 129 continue; |
| 128 bool is_directory = false; | 130 bool is_directory = false; |
| 129 file_entry->GetBoolean(kFileEntryIsDirectory, &is_directory); | 131 file_entry->GetBoolean(kFileEntryIsDirectory, &is_directory); |
| 130 int sequence_number = 0; | 132 int sequence_number = 0; |
| 131 if (!file_entry->GetInteger(kFileEntrySequenceNumber, &sequence_number)) | 133 if (!file_entry->GetInteger(kFileEntrySequenceNumber, &sequence_number)) |
| 132 continue; | 134 continue; |
| 133 if (!sequence_number) | 135 if (!sequence_number) |
| 134 continue; | 136 continue; |
| 135 result.push_back( | 137 result.push_back(SavedFilesService::Entry(it.key(), file_path, is_directory, |
| 136 SavedFileEntry(it.key(), file_path, is_directory, sequence_number)); | 138 sequence_number)); |
| 137 } | 139 } |
| 138 return result; | 140 return result; |
| 139 } | 141 } |
| 140 | 142 |
| 141 } // namespace | 143 } // namespace |
| 142 | 144 |
| 143 SavedFileEntry::SavedFileEntry() : is_directory(false), sequence_number(0) {} | 145 class SavedFilesServiceImpl::SavedFiles { |
| 144 | |
| 145 SavedFileEntry::SavedFileEntry(const std::string& id, | |
| 146 const base::FilePath& path, | |
| 147 bool is_directory, | |
| 148 int sequence_number) | |
| 149 : id(id), | |
| 150 path(path), | |
| 151 is_directory(is_directory), | |
| 152 sequence_number(sequence_number) {} | |
| 153 | |
| 154 class SavedFilesService::SavedFiles { | |
| 155 public: | 146 public: |
| 156 SavedFiles(content::BrowserContext* context, const std::string& extension_id); | 147 SavedFiles(content::BrowserContext* context, const std::string& extension_id); |
| 157 ~SavedFiles(); | 148 ~SavedFiles(); |
| 158 | 149 |
| 159 void RegisterFileEntry(const std::string& id, | 150 void RegisterFileEntry(const std::string& id, |
| 160 const base::FilePath& file_path, | 151 const base::FilePath& file_path, |
| 161 bool is_directory); | 152 bool is_directory); |
| 162 void EnqueueFileEntry(const std::string& id); | 153 void EnqueueFileEntry(const std::string& id); |
| 163 bool IsRegistered(const std::string& id) const; | 154 bool IsRegistered(const std::string& id) const; |
| 164 const SavedFileEntry* GetFileEntry(const std::string& id) const; | 155 const Entry* GetFileEntry(const std::string& id) const; |
| 165 std::vector<SavedFileEntry> GetAllFileEntries() const; | 156 std::vector<Entry> GetAllFileEntries() const; |
| 166 | 157 |
| 167 private: | 158 private: |
| 168 // Compacts sequence numbers if the largest sequence number is | 159 // Compacts sequence numbers if the largest sequence number is |
| 169 // g_max_sequence_number. Outside of testing, it is set to kint32max, so this | 160 // g_max_sequence_number. Outside of testing, it is set to kint32max, so this |
| 170 // will almost never do any real work. | 161 // will almost never do any real work. |
| 171 void MaybeCompactSequenceNumbers(); | 162 void MaybeCompactSequenceNumbers(); |
| 172 | 163 |
| 173 void LoadSavedFileEntriesFromPreferences(); | 164 void LoadSavedFileEntriesFromPreferences(); |
| 174 | 165 |
| 175 content::BrowserContext* context_; | 166 content::BrowserContext* context_; |
| 176 const std::string extension_id_; | 167 const std::string extension_id_; |
| 177 | 168 |
| 178 // Contains all file entries that have been registered, keyed by ID. | 169 // Contains all file entries that have been registered, keyed by ID. |
| 179 std::unordered_map<std::string, std::unique_ptr<SavedFileEntry>> | 170 std::unordered_map<std::string, std::unique_ptr<Entry>> |
| 180 registered_file_entries_; | 171 registered_file_entries_; |
| 181 | 172 |
| 182 // The queue of file entries that have been retained, keyed by | 173 // The queue of file entries that have been retained, keyed by |
| 183 // sequence_number. Values are a subset of values in registered_file_entries_. | 174 // sequence_number. Values are a subset of values in registered_file_entries_. |
| 184 // This should be kept in sync with file entries stored in extension prefs. | 175 // This should be kept in sync with file entries stored in extension prefs. |
| 185 std::map<int, SavedFileEntry*> saved_file_lru_; | 176 std::map<int, Entry*> saved_file_lru_; |
| 186 | 177 |
| 187 DISALLOW_COPY_AND_ASSIGN(SavedFiles); | 178 DISALLOW_COPY_AND_ASSIGN(SavedFiles); |
| 188 }; | 179 }; |
| 189 | 180 |
| 190 // static | 181 // static |
| 191 SavedFilesService* SavedFilesService::Get(content::BrowserContext* context) { | 182 SavedFilesServiceImpl* SavedFilesServiceImpl::Get( |
| 192 return SavedFilesServiceFactory::GetForBrowserContext(context); | 183 content::BrowserContext* context) { |
| 184 return SavedFilesServiceImplFactory::GetForBrowserContext(context); |
| 193 } | 185 } |
| 194 | 186 |
| 195 SavedFilesService::SavedFilesService(content::BrowserContext* context) | 187 SavedFilesServiceImpl::SavedFilesServiceImpl(content::BrowserContext* context) |
| 196 : context_(context) { | 188 : context_(context) { |
| 197 registrar_.Add(this, | 189 registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
| 198 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, | |
| 199 content::NotificationService::AllSources()); | 190 content::NotificationService::AllSources()); |
| 200 } | 191 } |
| 201 | 192 |
| 202 SavedFilesService::~SavedFilesService() {} | 193 SavedFilesServiceImpl::~SavedFilesServiceImpl() {} |
| 203 | 194 |
| 204 void SavedFilesService::Observe(int type, | 195 void SavedFilesServiceImpl::Observe( |
| 205 const content::NotificationSource& source, | 196 int type, |
| 206 const content::NotificationDetails& details) { | 197 const content::NotificationSource& source, |
| 198 const content::NotificationDetails& details) { |
| 207 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, type); | 199 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, type); |
| 208 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); | 200 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); |
| 209 const Extension* extension = host->extension(); | 201 const Extension* extension = host->extension(); |
| 210 if (extension) { | 202 if (extension) { |
| 211 ClearQueueIfNoRetainPermission(extension); | 203 ClearQueueIfNoRetainPermission(extension); |
| 212 Clear(extension->id()); | 204 Clear(extension->id()); |
| 213 } | 205 } |
| 214 } | 206 } |
| 215 | 207 |
| 216 void SavedFilesService::RegisterFileEntry(const std::string& extension_id, | 208 void SavedFilesServiceImpl::RegisterFileEntry(const std::string& extension_id, |
| 217 const std::string& id, | 209 const std::string& id, |
| 218 const base::FilePath& file_path, | 210 const base::FilePath& file_path, |
| 219 bool is_directory) { | 211 bool is_directory) { |
| 220 GetOrInsert(extension_id)->RegisterFileEntry(id, file_path, is_directory); | 212 GetOrInsert(extension_id)->RegisterFileEntry(id, file_path, is_directory); |
| 221 } | 213 } |
| 222 | 214 |
| 223 void SavedFilesService::EnqueueFileEntry(const std::string& extension_id, | 215 void SavedFilesServiceImpl::EnqueueFileEntry(const std::string& extension_id, |
| 224 const std::string& id) { | 216 const std::string& id) { |
| 225 GetOrInsert(extension_id)->EnqueueFileEntry(id); | 217 GetOrInsert(extension_id)->EnqueueFileEntry(id); |
| 226 } | 218 } |
| 227 | 219 |
| 228 std::vector<SavedFileEntry> SavedFilesService::GetAllFileEntries( | 220 std::vector<SavedFilesService::Entry> SavedFilesServiceImpl::GetAllFileEntries( |
| 229 const std::string& extension_id) { | 221 const std::string& extension_id) { |
| 230 SavedFiles* saved_files = Get(extension_id); | 222 SavedFiles* saved_files = Get(extension_id); |
| 231 if (saved_files) | 223 if (saved_files) |
| 232 return saved_files->GetAllFileEntries(); | 224 return saved_files->GetAllFileEntries(); |
| 233 return GetSavedFileEntries(ExtensionPrefs::Get(context_), extension_id); | 225 return GetSavedFileEntries(ExtensionPrefs::Get(context_), extension_id); |
| 234 } | 226 } |
| 235 | 227 |
| 236 bool SavedFilesService::IsRegistered(const std::string& extension_id, | 228 bool SavedFilesServiceImpl::IsRegistered(const std::string& extension_id, |
| 237 const std::string& id) { | 229 const std::string& id) { |
| 238 return GetOrInsert(extension_id)->IsRegistered(id); | 230 return GetOrInsert(extension_id)->IsRegistered(id); |
| 239 } | 231 } |
| 240 | 232 |
| 241 const SavedFileEntry* SavedFilesService::GetFileEntry( | 233 const SavedFilesService::Entry* SavedFilesServiceImpl::GetFileEntry( |
| 242 const std::string& extension_id, | 234 const std::string& extension_id, |
| 243 const std::string& id) { | 235 const std::string& id) { |
| 244 return GetOrInsert(extension_id)->GetFileEntry(id); | 236 return GetOrInsert(extension_id)->GetFileEntry(id); |
| 245 } | 237 } |
| 246 | 238 |
| 247 void SavedFilesService::ClearQueueIfNoRetainPermission( | 239 void SavedFilesServiceImpl::ClearQueueIfNoRetainPermission( |
| 248 const Extension* extension) { | 240 const Extension* extension) { |
| 249 if (!extension->permissions_data()->active_permissions().HasAPIPermission( | 241 if (!extension->permissions_data()->active_permissions().HasAPIPermission( |
| 250 APIPermission::kFileSystemRetainEntries)) { | 242 APIPermission::kFileSystemRetainEntries)) { |
| 251 ClearQueue(extension); | 243 ClearQueue(extension); |
| 252 } | 244 } |
| 253 } | 245 } |
| 254 | 246 |
| 255 void SavedFilesService::ClearQueue(const extensions::Extension* extension) { | 247 void SavedFilesServiceImpl::ClearQueue(const extensions::Extension* extension) { |
| 256 ClearSavedFileEntries(ExtensionPrefs::Get(context_), extension->id()); | 248 ClearSavedFileEntries(ExtensionPrefs::Get(context_), extension->id()); |
| 257 Clear(extension->id()); | 249 Clear(extension->id()); |
| 258 } | 250 } |
| 259 | 251 |
| 260 void SavedFilesService::OnApplicationTerminating() { | 252 void SavedFilesServiceImpl::OnApplicationTerminating() { |
| 261 // Stop listening to NOTIFICATION_EXTENSION_HOST_DESTROYED in particular | 253 // Stop listening to NOTIFICATION_EXTENSION_HOST_DESTROYED in particular |
| 262 // as all extension hosts will be destroyed as a result of shutdown. | 254 // as all extension hosts will be destroyed as a result of shutdown. |
| 263 registrar_.RemoveAll(); | 255 registrar_.RemoveAll(); |
| 264 } | 256 } |
| 265 | 257 |
| 266 SavedFilesService::SavedFiles* SavedFilesService::Get( | 258 SavedFilesServiceImpl::SavedFiles* SavedFilesServiceImpl::Get( |
| 267 const std::string& extension_id) const { | 259 const std::string& extension_id) const { |
| 268 auto it = extension_id_to_saved_files_.find(extension_id); | 260 auto it = extension_id_to_saved_files_.find(extension_id); |
| 269 if (it != extension_id_to_saved_files_.end()) | 261 if (it != extension_id_to_saved_files_.end()) |
| 270 return it->second.get(); | 262 return it->second.get(); |
| 271 | 263 |
| 272 return NULL; | 264 return NULL; |
| 273 } | 265 } |
| 274 | 266 |
| 275 SavedFilesService::SavedFiles* SavedFilesService::GetOrInsert( | 267 SavedFilesServiceImpl::SavedFiles* SavedFilesServiceImpl::GetOrInsert( |
| 276 const std::string& extension_id) { | 268 const std::string& extension_id) { |
| 277 SavedFiles* saved_files = Get(extension_id); | 269 SavedFiles* saved_files = Get(extension_id); |
| 278 if (saved_files) | 270 if (saved_files) |
| 279 return saved_files; | 271 return saved_files; |
| 280 | 272 |
| 281 std::unique_ptr<SavedFiles> scoped_saved_files( | 273 std::unique_ptr<SavedFiles> scoped_saved_files( |
| 282 new SavedFiles(context_, extension_id)); | 274 new SavedFiles(context_, extension_id)); |
| 283 saved_files = scoped_saved_files.get(); | 275 saved_files = scoped_saved_files.get(); |
| 284 extension_id_to_saved_files_.insert( | 276 extension_id_to_saved_files_.insert( |
| 285 std::make_pair(extension_id, std::move(scoped_saved_files))); | 277 std::make_pair(extension_id, std::move(scoped_saved_files))); |
| 286 return saved_files; | 278 return saved_files; |
| 287 } | 279 } |
| 288 | 280 |
| 289 void SavedFilesService::Clear(const std::string& extension_id) { | 281 void SavedFilesServiceImpl::Clear(const std::string& extension_id) { |
| 290 extension_id_to_saved_files_.erase(extension_id); | 282 extension_id_to_saved_files_.erase(extension_id); |
| 291 } | 283 } |
| 292 | 284 |
| 293 SavedFilesService::SavedFiles::SavedFiles(content::BrowserContext* context, | 285 SavedFilesServiceImpl::SavedFiles::SavedFiles(content::BrowserContext* context, |
| 294 const std::string& extension_id) | 286 const std::string& extension_id) |
| 295 : context_(context), extension_id_(extension_id) { | 287 : context_(context), extension_id_(extension_id) { |
| 296 LoadSavedFileEntriesFromPreferences(); | 288 LoadSavedFileEntriesFromPreferences(); |
| 297 } | 289 } |
| 298 | 290 |
| 299 SavedFilesService::SavedFiles::~SavedFiles() {} | 291 SavedFilesServiceImpl::SavedFiles::~SavedFiles() {} |
| 300 | 292 |
| 301 void SavedFilesService::SavedFiles::RegisterFileEntry( | 293 void SavedFilesServiceImpl::SavedFiles::RegisterFileEntry( |
| 302 const std::string& id, | 294 const std::string& id, |
| 303 const base::FilePath& file_path, | 295 const base::FilePath& file_path, |
| 304 bool is_directory) { | 296 bool is_directory) { |
| 305 auto it = registered_file_entries_.find(id); | 297 auto it = registered_file_entries_.find(id); |
| 306 if (it != registered_file_entries_.end()) | 298 if (it != registered_file_entries_.end()) |
| 307 return; | 299 return; |
| 308 | 300 |
| 309 registered_file_entries_[id] = | 301 registered_file_entries_[id] = |
| 310 base::MakeUnique<SavedFileEntry>(id, file_path, is_directory, 0); | 302 base::MakeUnique<Entry>(id, file_path, is_directory, 0); |
| 311 } | 303 } |
| 312 | 304 |
| 313 void SavedFilesService::SavedFiles::EnqueueFileEntry(const std::string& id) { | 305 void SavedFilesServiceImpl::SavedFiles::EnqueueFileEntry( |
| 306 const std::string& id) { |
| 314 auto it = registered_file_entries_.find(id); | 307 auto it = registered_file_entries_.find(id); |
| 315 DCHECK(it != registered_file_entries_.end()); | 308 DCHECK(it != registered_file_entries_.end()); |
| 316 | 309 |
| 317 SavedFileEntry* file_entry = it->second.get(); | 310 Entry* file_entry = it->second.get(); |
| 318 int old_sequence_number = file_entry->sequence_number; | 311 int old_sequence_number = file_entry->sequence_number; |
| 319 if (!saved_file_lru_.empty()) { | 312 if (!saved_file_lru_.empty()) { |
| 320 // Get the sequence number after the last file entry in the LRU. | 313 // Get the sequence number after the last file entry in the LRU. |
| 321 std::map<int, SavedFileEntry*>::reverse_iterator it = | 314 std::map<int, Entry*>::reverse_iterator it = saved_file_lru_.rbegin(); |
| 322 saved_file_lru_.rbegin(); | |
| 323 if (it->second == file_entry) | 315 if (it->second == file_entry) |
| 324 return; | 316 return; |
| 325 | 317 |
| 326 file_entry->sequence_number = it->first + 1; | 318 file_entry->sequence_number = it->first + 1; |
| 327 } else { | 319 } else { |
| 328 // The first sequence number is 1, as 0 means the entry is not in the LRU. | 320 // The first sequence number is 1, as 0 means the entry is not in the LRU. |
| 329 file_entry->sequence_number = 1; | 321 file_entry->sequence_number = 1; |
| 330 } | 322 } |
| 331 saved_file_lru_.insert( | 323 saved_file_lru_.insert( |
| 332 std::make_pair(file_entry->sequence_number, file_entry)); | 324 std::make_pair(file_entry->sequence_number, file_entry)); |
| 333 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); | 325 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); |
| 334 if (old_sequence_number) { | 326 if (old_sequence_number) { |
| 335 saved_file_lru_.erase(old_sequence_number); | 327 saved_file_lru_.erase(old_sequence_number); |
| 336 UpdateSavedFileEntry(prefs, extension_id_, *file_entry); | 328 UpdateSavedFileEntry(prefs, extension_id_, *file_entry); |
| 337 } else { | 329 } else { |
| 338 AddSavedFileEntry(prefs, extension_id_, *file_entry); | 330 AddSavedFileEntry(prefs, extension_id_, *file_entry); |
| 339 if (saved_file_lru_.size() > g_max_saved_file_entries) { | 331 if (saved_file_lru_.size() > g_max_saved_file_entries) { |
| 340 std::map<int, SavedFileEntry*>::iterator it = saved_file_lru_.begin(); | 332 std::map<int, Entry*>::iterator it = saved_file_lru_.begin(); |
| 341 it->second->sequence_number = 0; | 333 it->second->sequence_number = 0; |
| 342 RemoveSavedFileEntry(prefs, extension_id_, it->second->id); | 334 RemoveSavedFileEntry(prefs, extension_id_, it->second->id); |
| 343 saved_file_lru_.erase(it); | 335 saved_file_lru_.erase(it); |
| 344 } | 336 } |
| 345 } | 337 } |
| 346 MaybeCompactSequenceNumbers(); | 338 MaybeCompactSequenceNumbers(); |
| 347 } | 339 } |
| 348 | 340 |
| 349 bool SavedFilesService::SavedFiles::IsRegistered(const std::string& id) const { | 341 bool SavedFilesServiceImpl::SavedFiles::IsRegistered( |
| 342 const std::string& id) const { |
| 350 auto it = registered_file_entries_.find(id); | 343 auto it = registered_file_entries_.find(id); |
| 351 return it != registered_file_entries_.end(); | 344 return it != registered_file_entries_.end(); |
| 352 } | 345 } |
| 353 | 346 |
| 354 const SavedFileEntry* SavedFilesService::SavedFiles::GetFileEntry( | 347 const SavedFilesService::Entry* SavedFilesServiceImpl::SavedFiles::GetFileEntry( |
| 355 const std::string& id) const { | 348 const std::string& id) const { |
| 356 auto it = registered_file_entries_.find(id); | 349 auto it = registered_file_entries_.find(id); |
| 357 if (it == registered_file_entries_.end()) | 350 if (it == registered_file_entries_.end()) |
| 358 return NULL; | 351 return NULL; |
| 359 | 352 |
| 360 return it->second.get(); | 353 return it->second.get(); |
| 361 } | 354 } |
| 362 | 355 |
| 363 std::vector<SavedFileEntry> SavedFilesService::SavedFiles::GetAllFileEntries() | 356 std::vector<SavedFilesService::Entry> |
| 364 const { | 357 SavedFilesServiceImpl::SavedFiles::GetAllFileEntries() const { |
| 365 std::vector<SavedFileEntry> result; | 358 std::vector<Entry> result; |
| 366 for (auto it = registered_file_entries_.begin(); | 359 for (auto it = registered_file_entries_.begin(); |
| 367 it != registered_file_entries_.end(); ++it) { | 360 it != registered_file_entries_.end(); ++it) { |
| 368 result.push_back(*it->second.get()); | 361 result.push_back(*it->second.get()); |
| 369 } | 362 } |
| 370 return result; | 363 return result; |
| 371 } | 364 } |
| 372 | 365 |
| 373 void SavedFilesService::SavedFiles::MaybeCompactSequenceNumbers() { | 366 void SavedFilesServiceImpl::SavedFiles::MaybeCompactSequenceNumbers() { |
| 374 DCHECK_GE(g_max_sequence_number, 0); | 367 DCHECK_GE(g_max_sequence_number, 0); |
| 375 DCHECK_GE(static_cast<size_t>(g_max_sequence_number), | 368 DCHECK_GE(static_cast<size_t>(g_max_sequence_number), |
| 376 g_max_saved_file_entries); | 369 g_max_saved_file_entries); |
| 377 std::map<int, SavedFileEntry*>::reverse_iterator it = | 370 std::map<int, Entry*>::reverse_iterator it = saved_file_lru_.rbegin(); |
| 378 saved_file_lru_.rbegin(); | |
| 379 if (it == saved_file_lru_.rend()) | 371 if (it == saved_file_lru_.rend()) |
| 380 return; | 372 return; |
| 381 | 373 |
| 382 // Only compact sequence numbers if the last entry's sequence number is the | 374 // Only compact sequence numbers if the last entry's sequence number is the |
| 383 // maximum value. This should almost never be the case. | 375 // maximum value. This should almost never be the case. |
| 384 if (it->first < g_max_sequence_number) | 376 if (it->first < g_max_sequence_number) |
| 385 return; | 377 return; |
| 386 | 378 |
| 387 int sequence_number = 0; | 379 int sequence_number = 0; |
| 388 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); | 380 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); |
| 389 for (std::map<int, SavedFileEntry*>::iterator it = saved_file_lru_.begin(); | 381 for (std::map<int, Entry*>::iterator it = saved_file_lru_.begin(); |
| 390 it != saved_file_lru_.end(); | 382 it != saved_file_lru_.end(); ++it) { |
| 391 ++it) { | |
| 392 sequence_number++; | 383 sequence_number++; |
| 393 if (it->second->sequence_number == sequence_number) | 384 if (it->second->sequence_number == sequence_number) |
| 394 continue; | 385 continue; |
| 395 | 386 |
| 396 SavedFileEntry* file_entry = it->second; | 387 Entry* file_entry = it->second; |
| 397 file_entry->sequence_number = sequence_number; | 388 file_entry->sequence_number = sequence_number; |
| 398 UpdateSavedFileEntry(prefs, extension_id_, *file_entry); | 389 UpdateSavedFileEntry(prefs, extension_id_, *file_entry); |
| 399 saved_file_lru_.erase(it++); | 390 saved_file_lru_.erase(it++); |
| 400 // Provide the following element as an insert hint. While optimized | 391 // Provide the following element as an insert hint. While optimized |
| 401 // insertion time with the following element as a hint is only supported by | 392 // insertion time with the following element as a hint is only supported by |
| 402 // the spec in C++11, the implementations do support this. | 393 // the spec in C++11, the implementations do support this. |
| 403 it = saved_file_lru_.insert( | 394 it = saved_file_lru_.insert( |
| 404 it, std::make_pair(file_entry->sequence_number, file_entry)); | 395 it, std::make_pair(file_entry->sequence_number, file_entry)); |
| 405 } | 396 } |
| 406 } | 397 } |
| 407 | 398 |
| 408 void SavedFilesService::SavedFiles::LoadSavedFileEntriesFromPreferences() { | 399 void SavedFilesServiceImpl::SavedFiles::LoadSavedFileEntriesFromPreferences() { |
| 409 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); | 400 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); |
| 410 std::vector<SavedFileEntry> saved_entries = | 401 std::vector<Entry> saved_entries = GetSavedFileEntries(prefs, extension_id_); |
| 411 GetSavedFileEntries(prefs, extension_id_); | 402 for (std::vector<Entry>::iterator it = saved_entries.begin(); |
| 412 for (std::vector<SavedFileEntry>::iterator it = saved_entries.begin(); | 403 it != saved_entries.end(); ++it) { |
| 413 it != saved_entries.end(); | 404 std::unique_ptr<Entry> file_entry(new Entry(*it)); |
| 414 ++it) { | |
| 415 std::unique_ptr<SavedFileEntry> file_entry(new SavedFileEntry(*it)); | |
| 416 const std::string& id = file_entry->id; | 405 const std::string& id = file_entry->id; |
| 417 saved_file_lru_.insert( | 406 saved_file_lru_.insert( |
| 418 std::make_pair(file_entry->sequence_number, file_entry.get())); | 407 std::make_pair(file_entry->sequence_number, file_entry.get())); |
| 419 registered_file_entries_[id] = std::move(file_entry); | 408 registered_file_entries_[id] = std::move(file_entry); |
| 420 } | 409 } |
| 421 } | 410 } |
| 422 | 411 |
| 423 // static | 412 // static |
| 424 void SavedFilesService::SetMaxSequenceNumberForTest(int max_value) { | 413 void SavedFilesServiceImpl::SetMaxSequenceNumberForTest(int max_value) { |
| 425 g_max_sequence_number = max_value; | 414 g_max_sequence_number = max_value; |
| 426 } | 415 } |
| 427 | 416 |
| 428 // static | 417 // static |
| 429 void SavedFilesService::ClearMaxSequenceNumberForTest() { | 418 void SavedFilesServiceImpl::ClearMaxSequenceNumberForTest() { |
| 430 g_max_sequence_number = kMaxSequenceNumber; | 419 g_max_sequence_number = kMaxSequenceNumber; |
| 431 } | 420 } |
| 432 | 421 |
| 433 // static | 422 // static |
| 434 void SavedFilesService::SetLruSizeForTest(int size) { | 423 void SavedFilesServiceImpl::SetLruSizeForTest(int size) { |
| 435 g_max_saved_file_entries = size; | 424 g_max_saved_file_entries = size; |
| 436 } | 425 } |
| 437 | 426 |
| 438 // static | 427 // static |
| 439 void SavedFilesService::ClearLruSizeForTest() { | 428 void SavedFilesServiceImpl::ClearLruSizeForTest() { |
| 440 g_max_saved_file_entries = kMaxSavedFileEntries; | 429 g_max_saved_file_entries = kMaxSavedFileEntries; |
| 441 } | 430 } |
| 442 | 431 |
| 443 } // namespace apps | 432 } // namespace apps |
| OLD | NEW |