// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_CUSTOM_DICTIONARY_H_ #define CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_CUSTOM_DICTIONARY_H_ #include <string> #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "chrome/browser/spellchecker/spellcheck_dictionary.h" #include "chrome/common/spellcheck_common.h" #include "sync/api/syncable_service.h" // Defines a custom dictionary where users can add their own words. All words // must be UTF8, between 1 and 99 bytes long, and without leading or trailing // ASCII whitespace. The dictionary contains its own checksum when saved on // disk. Example dictionary file contents: // // bar // foo // checksum_v1 = ec3df4034567e59e119fcf87f2d9bad4 // class SpellcheckCustomDictionary : public SpellcheckDictionary, public syncer::SyncableService { public: // A change to the dictionary. class Change { public: Change(); Change(const Change& other); explicit Change(const chrome::spellcheck_common::WordList& to_add); ~Change(); // Adds |word| in this change. void AddWord(const std::string& word); // Removes |word| in this change. void RemoveWord(const std::string& word); // Prepares this change to be applied to |words| by removing duplicate and // invalid words from words to be added, removing missing words from words // to be removed, and sorting both lists of words. Assumes that |words| is // sorted. Returns a bitmap of |ChangeSanitationResult| values. int Sanitize(const chrome::spellcheck_common::WordSet& words); // Returns the words to be added in this change. const chrome::spellcheck_common::WordList& to_add() const; // Returns the words to be removed in this change. const chrome::spellcheck_common::WordList& to_remove() const; // Returns true if there are no changes to be made. Otherwise returns false. bool empty() const; private: // The words to be added. chrome::spellcheck_common::WordList to_add_; // The words to be removed. chrome::spellcheck_common::WordList to_remove_; }; // Interface to implement for dictionary load and change observers. class Observer { public: // Called when the custom dictionary has been loaded. virtual void OnCustomDictionaryLoaded() = 0; // Called when the custom dictionary has been changed. virtual void OnCustomDictionaryChanged(const Change& dictionary_change) = 0; }; explicit SpellcheckCustomDictionary(const base::FilePath& path); virtual ~SpellcheckCustomDictionary(); // Returns the in-memory cache of words in the custom dictionary. const chrome::spellcheck_common::WordSet& GetWords() const; // Adds |word| to the dictionary, schedules a write to disk, and notifies // observers of the change. Returns true if |word| is valid and not a // duplicate. Otherwise returns false. bool AddWord(const std::string& word); // Removes |word| from the dictionary, schedules a write to disk, and notifies // observers of the change. Returns true if |word| was found. Otherwise // returns false. bool RemoveWord(const std::string& word); // Returns true if the dictionary contains |word|. Otherwise returns false. bool HasWord(const std::string& word) const; // Adds |observer| to be notified of dictionary events and changes. void AddObserver(Observer* observer); // Removes |observer| to stop notifications of dictionary events and changes. void RemoveObserver(Observer* observer); // Returns true if the dictionary has been loaded. Otherwise returns false. bool IsLoaded(); // Returns true if the dictionary is being synced. Otherwise returns false. bool IsSyncing(); // Overridden from SpellcheckDictionary: virtual void Load() OVERRIDE; // Overridden from syncer::SyncableService: virtual syncer::SyncMergeResult MergeDataAndStartSyncing( syncer::ModelType type, const syncer::SyncDataList& initial_sync_data, scoped_ptr<syncer::SyncChangeProcessor> sync_processor, scoped_ptr<syncer::SyncErrorFactory> sync_error_handler) OVERRIDE; virtual void StopSyncing(syncer::ModelType type) OVERRIDE; virtual syncer::SyncDataList GetAllSyncData( syncer::ModelType type) const OVERRIDE; virtual syncer::SyncError ProcessSyncChanges( const tracked_objects::Location& from_here, const syncer::SyncChangeList& change_list) OVERRIDE; private: friend class DictionarySyncIntegrationTestHelper; friend class SpellcheckCustomDictionaryTest; // Returns the list of words in the custom spellcheck dictionary at |path|. // Makes sure that the custom dictionary file does not have duplicates and // contains only valid words. static chrome::spellcheck_common::WordList LoadDictionaryFile( const base::FilePath& path); // Applies the change in |dictionary_change| to the custom spellcheck // dictionary. Assumes that |dictionary_change| has been sanitized. static void UpdateDictionaryFile( const Change& dictionary_change, const base::FilePath& path); // The reply point for PostTaskAndReplyWithResult, called when // LoadDictionaryFile finishes reading the dictionary file. Does not modify // |custom_words|, but cannot be a const-ref due to the signature of // PostTaskAndReplyWithResult. void OnLoaded(chrome::spellcheck_common::WordList custom_words); // Applies the |dictionary_change| to the in-memory copy of the dictionary. // Assumes that words in |dictionary_change| are sorted. void Apply(const Change& dictionary_change); // Schedules a write of |dictionary_change| to disk. Assumes that words in // |dictionary_change| are sorted. void Save(const Change& dictionary_change); // Notifies the sync service of the |dictionary_change|. Syncs up to the // maximum syncable words on the server. Disables syncing of this dictionary // if the server contains the maximum number of syncable words. syncer::SyncError Sync(const Change& dictionary_change); // Notifies observers of the dictionary change if the dictionary has been // changed. void Notify(const Change& dictionary_change); // In-memory cache of the custom words file. chrome::spellcheck_common::WordSet words_; // A path for custom dictionary. base::FilePath custom_dictionary_path_; // Observers for changes in dictionary load status and content changes. ObserverList<Observer> observers_; // Used to send local changes to the sync infrastructure. scoped_ptr<syncer::SyncChangeProcessor> sync_processor_; // Used to send sync-related errors to the sync infrastructure. scoped_ptr<syncer::SyncErrorFactory> sync_error_handler_; // True if the dictionary has been loaded. Otherwise false. bool is_loaded_; // Used to create weak pointers for an instance of this class. base::WeakPtrFactory<SpellcheckCustomDictionary> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SpellcheckCustomDictionary); }; #endif // CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_CUSTOM_DICTIONARY_H_