190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "apps/saved_files_service.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <algorithm> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "apps/saved_files_service_factory.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/basictypes.h" 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h" 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/value_conversions.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_service.h" 1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_util.h" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h" 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "extensions/common/permissions/api_permission.h" 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/permissions/permission_set.h" 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace apps { 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using extensions::APIPermission; 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using extensions::Extension; 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using extensions::ExtensionHost; 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using extensions::ExtensionPrefs; 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Preference keys 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// The file entries that the app has permission to access. 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kFileEntries[] = "file_entries"; 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// The path to a file entry that the app had permission to access. 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kFileEntryPath[] = "path"; 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Whether or not the the entry refers to a directory. 43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kFileEntryIsDirectory[] = "is_directory"; 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// The sequence number in the LRU of the file entry. 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kFileEntrySequenceNumber[] = "sequence_number"; 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const size_t kMaxSavedFileEntries = 500; 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kMaxSequenceNumber = kint32max; 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// These might be different to the constant values in tests. 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t g_max_saved_file_entries = kMaxSavedFileEntries; 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int g_max_sequence_number = kMaxSequenceNumber; 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Persists a SavedFileEntry in ExtensionPrefs. 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void AddSavedFileEntry(ExtensionPrefs* prefs, 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id, 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const SavedFileEntry& file_entry) { 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs::ScopedDictionaryUpdate update( 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prefs, extension_id, kFileEntries); 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* file_entries = update.Get(); 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!file_entries) 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entries = update.Create(); 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(!file_entries->GetDictionaryWithoutPathExpansion(file_entry.id, NULL)); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* file_entry_dict = new base::DictionaryValue(); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry_dict->Set(kFileEntryPath, CreateFilePathValue(file_entry.path)); 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) file_entry_dict->SetBoolean(kFileEntryIsDirectory, file_entry.is_directory); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry_dict->SetInteger(kFileEntrySequenceNumber, 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry.sequence_number); 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entries->SetWithoutPathExpansion(file_entry.id, file_entry_dict); 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Updates the sequence_number of a SavedFileEntry persisted in ExtensionPrefs. 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void UpdateSavedFileEntry(ExtensionPrefs* prefs, 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id, 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const SavedFileEntry& file_entry) { 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs::ScopedDictionaryUpdate update( 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prefs, extension_id, kFileEntries); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* file_entries = update.Get(); 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(file_entries); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* file_entry_dict = NULL; 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entries->GetDictionaryWithoutPathExpansion(file_entry.id, 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &file_entry_dict); 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(file_entry_dict); 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry_dict->SetInteger(kFileEntrySequenceNumber, 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry.sequence_number); 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Removes a SavedFileEntry from ExtensionPrefs. 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void RemoveSavedFileEntry(ExtensionPrefs* prefs, 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id, 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& file_entry_id) { 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs::ScopedDictionaryUpdate update( 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prefs, extension_id, kFileEntries); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* file_entries = update.Get(); 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!file_entries) 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entries = update.Create(); 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entries->RemoveWithoutPathExpansion(file_entry_id, NULL); 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Clears all SavedFileEntry for the app from ExtensionPrefs. 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ClearSavedFileEntries(ExtensionPrefs* prefs, 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id) { 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prefs->UpdateExtensionPref(extension_id, kFileEntries, NULL); 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returns all SavedFileEntries for the app. 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<SavedFileEntry> GetSavedFileEntries( 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs* prefs, 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id) { 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<SavedFileEntry> result; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* file_entries = NULL; 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!prefs->ReadPrefAsDictionary(extension_id, kFileEntries, &file_entries)) 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return result; 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator it(*file_entries); !it.IsAtEnd(); 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it.Advance()) { 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* file_entry = NULL; 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!it.value().GetAsDictionary(&file_entry)) 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::Value* path_value; 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!file_entry->Get(kFileEntryPath, &path_value)) 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::FilePath file_path; 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!GetValueAsFilePath(*path_value, &file_path)) 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_directory = false; 129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) file_entry->GetBoolean(kFileEntryIsDirectory, &is_directory); 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int sequence_number = 0; 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!file_entry->GetInteger(kFileEntrySequenceNumber, &sequence_number)) 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!sequence_number) 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) result.push_back( 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SavedFileEntry(it.key(), file_path, is_directory, sequence_number)); 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return result; 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 143424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SavedFileEntry::SavedFileEntry() : is_directory(false), sequence_number(0) {} 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SavedFileEntry::SavedFileEntry(const std::string& id, 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::FilePath& path, 147424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_directory, 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int sequence_number) 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : id(id), 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) path(path), 151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) is_directory(is_directory), 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sequence_number(sequence_number) {} 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SavedFilesService::SavedFiles { 15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SavedFiles(Profile* profile, const std::string& extension_id); 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ~SavedFiles(); 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void RegisterFileEntry(const std::string& id, 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::FilePath& file_path, 161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_directory); 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void EnqueueFileEntry(const std::string& id); 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool IsRegistered(const std::string& id) const; 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const SavedFileEntry* GetFileEntry(const std::string& id) const; 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<SavedFileEntry> GetAllFileEntries() const; 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Compacts sequence numbers if the largest sequence number is 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // g_max_sequence_number. Outside of testing, it is set to kint32max, so this 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // will almost never do any real work. 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void MaybeCompactSequenceNumbers(); 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void LoadSavedFileEntriesFromPreferences(); 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Profile* profile_; 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string extension_id_; 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Contains all file entries that have been registered, keyed by ID. Owns 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // values. 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::hash_map<std::string, SavedFileEntry*> registered_file_entries_; 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) STLValueDeleter<base::hash_map<std::string, SavedFileEntry*> > 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registered_file_entries_deleter_; 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The queue of file entries that have been retained, keyed by 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // sequence_number. Values are a subset of values in registered_file_entries_. 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This should be kept in sync with file entries stored in extension prefs. 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::map<int, SavedFileEntry*> saved_file_lru_; 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SavedFiles); 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SavedFilesService* SavedFilesService::Get(Profile* profile) { 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return SavedFilesServiceFactory::GetForProfile(profile); 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SavedFilesService::SavedFilesService(Profile* profile) 19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : extension_id_to_saved_files_deleter_(&extension_id_to_saved_files_), 19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) profile_(profile) { 20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registrar_.Add(this, 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::NotificationService::AllSources()); 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registrar_.Add(this, 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::NOTIFICATION_APP_TERMINATING, 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::NotificationService::AllSources()); 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SavedFilesService::~SavedFilesService() {} 20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::Observe(int type, 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const content::NotificationSource& source, 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const content::NotificationDetails& details) { 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (type) { 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED: { 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const Extension* extension = host->extension(); 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (extension) { 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ClearQueueIfNoRetainPermission(extension); 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Clear(extension->id()); 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case chrome::NOTIFICATION_APP_TERMINATING: { 22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Stop listening to NOTIFICATION_EXTENSION_HOST_DESTROYED in particular 22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // as all extension hosts will be destroyed as a result of shutdown. 22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registrar_.RemoveAll(); 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::RegisterFileEntry(const std::string& extension_id, 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& id, 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::FilePath& file_path, 236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_directory) { 237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GetOrInsert(extension_id)->RegisterFileEntry(id, file_path, is_directory); 23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::EnqueueFileEntry(const std::string& extension_id, 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& id) { 24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GetOrInsert(extension_id)->EnqueueFileEntry(id); 24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<SavedFileEntry> SavedFilesService::GetAllFileEntries( 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id) { 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SavedFiles* saved_files = Get(extension_id); 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (saved_files) 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return saved_files->GetAllFileEntries(); 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return GetSavedFileEntries(ExtensionPrefs::Get(profile_), extension_id); 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SavedFilesService::IsRegistered(const std::string& extension_id, 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& id) { 25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetOrInsert(extension_id)->IsRegistered(id); 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const SavedFileEntry* SavedFilesService::GetFileEntry( 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id, 26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& id) { 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetOrInsert(extension_id)->GetFileEntry(id); 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::ClearQueueIfNoRetainPermission( 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const Extension* extension) { 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (extensions::util::IsEphemeralApp(extension->id(), profile_) || 26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !extension->permissions_data()->active_permissions()->HasAPIPermission( 2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch APIPermission::kFileSystemRetainEntries)) { 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ClearQueue(extension); 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SavedFilesService::ClearQueue(const extensions::Extension* extension) { 274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ClearSavedFileEntries(ExtensionPrefs::Get(profile_), extension->id()); 275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Clear(extension->id()); 276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SavedFilesService::SavedFiles* SavedFilesService::Get( 279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& extension_id) const { 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::map<std::string, SavedFiles*>::const_iterator it = 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension_id_to_saved_files_.find(extension_id); 28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (it != extension_id_to_saved_files_.end()) 28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return it->second; 28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return NULL; 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SavedFilesService::SavedFiles* SavedFilesService::GetOrInsert( 289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& extension_id) { 290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SavedFiles* saved_files = Get(extension_id); 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (saved_files) 292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return saved_files; 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) saved_files = new SavedFiles(profile_, extension_id); 29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension_id_to_saved_files_.insert( 29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::make_pair(extension_id, saved_files)); 29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return saved_files; 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::Clear(const std::string& extension_id) { 30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::map<std::string, SavedFiles*>::iterator it = 30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension_id_to_saved_files_.find(extension_id); 30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (it != extension_id_to_saved_files_.end()) { 30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) delete it->second; 30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension_id_to_saved_files_.erase(it); 30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SavedFilesService::SavedFiles::SavedFiles(Profile* profile, 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id) 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : profile_(profile), 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension_id_(extension_id), 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registered_file_entries_deleter_(®istered_file_entries_) { 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LoadSavedFileEntriesFromPreferences(); 31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SavedFilesService::SavedFiles::~SavedFiles() {} 31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::SavedFiles::RegisterFileEntry( 32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& id, 32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::FilePath& file_path, 322424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_directory) { 32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (ContainsKey(registered_file_entries_, id)) 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registered_file_entries_.insert( 327424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::make_pair(id, new SavedFileEntry(id, file_path, is_directory, 0))); 32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::SavedFiles::EnqueueFileEntry(const std::string& id) { 33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::hash_map<std::string, SavedFileEntry*>::iterator it = 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registered_file_entries_.find(id); 33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(it != registered_file_entries_.end()); 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SavedFileEntry* file_entry = it->second; 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int old_sequence_number = file_entry->sequence_number; 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!saved_file_lru_.empty()) { 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Get the sequence number after the last file entry in the LRU. 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::map<int, SavedFileEntry*>::reverse_iterator it = 34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) saved_file_lru_.rbegin(); 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (it->second == file_entry) 34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry->sequence_number = it->first + 1; 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The first sequence number is 1, as 0 means the entry is not in the LRU. 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry->sequence_number = 1; 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) saved_file_lru_.insert( 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::make_pair(file_entry->sequence_number, file_entry)); 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_); 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (old_sequence_number) { 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) saved_file_lru_.erase(old_sequence_number); 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UpdateSavedFileEntry(prefs, extension_id_, *file_entry); 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AddSavedFileEntry(prefs, extension_id_, *file_entry); 35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (saved_file_lru_.size() > g_max_saved_file_entries) { 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::map<int, SavedFileEntry*>::iterator it = saved_file_lru_.begin(); 35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it->second->sequence_number = 0; 36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RemoveSavedFileEntry(prefs, extension_id_, it->second->id); 36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) saved_file_lru_.erase(it); 36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MaybeCompactSequenceNumbers(); 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SavedFilesService::SavedFiles::IsRegistered(const std::string& id) const { 36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return ContainsKey(registered_file_entries_, id); 36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const SavedFileEntry* SavedFilesService::SavedFiles::GetFileEntry( 37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& id) const { 37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::hash_map<std::string, SavedFileEntry*>::const_iterator it = 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registered_file_entries_.find(id); 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (it == registered_file_entries_.end()) 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return NULL; 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return it->second; 37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<SavedFileEntry> SavedFilesService::SavedFiles::GetAllFileEntries() 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const { 38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<SavedFileEntry> result; 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (base::hash_map<std::string, SavedFileEntry*>::const_iterator it = 38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registered_file_entries_.begin(); 38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it != registered_file_entries_.end(); 38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++it) { 38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) result.push_back(*it->second); 38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return result; 39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::SavedFiles::MaybeCompactSequenceNumbers() { 39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(g_max_sequence_number, 0); 39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(static_cast<size_t>(g_max_sequence_number), 39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) g_max_saved_file_entries); 39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::map<int, SavedFileEntry*>::reverse_iterator it = 39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) saved_file_lru_.rbegin(); 39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (it == saved_file_lru_.rend()) 40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Only compact sequence numbers if the last entry's sequence number is the 40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // maximum value. This should almost never be the case. 40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (it->first < g_max_sequence_number) 40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int sequence_number = 0; 40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_); 40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (std::map<int, SavedFileEntry*>::iterator it = saved_file_lru_.begin(); 41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it != saved_file_lru_.end(); 41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++it) { 41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sequence_number++; 41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (it->second->sequence_number == sequence_number) 41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SavedFileEntry* file_entry = it->second; 41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_entry->sequence_number = sequence_number; 41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UpdateSavedFileEntry(prefs, extension_id_, *file_entry); 41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) saved_file_lru_.erase(it++); 42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Provide the following element as an insert hint. While optimized 42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // insertion time with the following element as a hint is only supported by 42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the spec in C++11, the implementations do support this. 42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it = saved_file_lru_.insert( 42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it, std::make_pair(file_entry->sequence_number, file_entry)); 42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::SavedFiles::LoadSavedFileEntriesFromPreferences() { 42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_); 43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<SavedFileEntry> saved_entries = 43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GetSavedFileEntries(prefs, extension_id_); 43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (std::vector<SavedFileEntry>::iterator it = saved_entries.begin(); 43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it != saved_entries.end(); 43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++it) { 43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SavedFileEntry* file_entry = new SavedFileEntry(*it); 43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) registered_file_entries_.insert(std::make_pair(file_entry->id, file_entry)); 43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) saved_file_lru_.insert( 43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::make_pair(file_entry->sequence_number, file_entry)); 43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 44290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static 44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::SetMaxSequenceNumberForTest(int max_value) { 44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) g_max_sequence_number = max_value; 44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static 44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::ClearMaxSequenceNumberForTest() { 44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) g_max_sequence_number = kMaxSequenceNumber; 45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static 45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::SetLruSizeForTest(int size) { 45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) g_max_saved_file_entries = size; 45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 45690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static 45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SavedFilesService::ClearLruSizeForTest() { 45990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) g_max_saved_file_entries = kMaxSavedFileEntries; 46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace apps 463