blob: 7ea9991617c78f5287df3753dc77c036c61b0eed [file] [log] [blame]
[email protected]5f91b1f2012-10-26 19:17:231// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_CUSTOM_DICTIONARY_H_
6#define CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_CUSTOM_DICTIONARY_H_
7
dcheng4d0d72ef2016-04-14 01:11:338#include <memory>
rouslan7919c152015-06-03 03:12:339#include <set>
[email protected]5f91b1f2012-10-26 19:17:2310#include <string>
[email protected]5f91b1f2012-10-26 19:17:2311
rouslanbd7987c2015-10-06 22:36:0612#include "base/cancelable_callback.h"
[email protected]57999812013-02-24 05:40:5213#include "base/files/file_path.h"
rouslan7919c152015-06-03 03:12:3314#include "base/macros.h"
Francois Dorayce42ef442017-09-14 15:24:2015#include "base/memory/ref_counted.h"
[email protected]1e29db92012-11-14 00:52:3116#include "base/memory/weak_ptr.h"
[email protected]687f0ed2012-12-12 01:53:0517#include "base/observer_list.h"
Francois Dorayce42ef442017-09-14 15:24:2018#include "base/sequenced_task_runner.h"
timvolodine0eec9ec2016-08-17 16:18:4819#include "components/spellcheck/browser/spellcheck_dictionary.h"
skym71603842016-10-10 18:17:3120#include "components/sync/model/sync_data.h"
21#include "components/sync/model/sync_error.h"
22#include "components/sync/model/sync_merge_result.h"
23#include "components/sync/model/syncable_service.h"
[email protected]5f91b1f2012-10-26 19:17:2324
Brett Wilsonabbb9602017-09-11 23:26:3925namespace base {
26class Location;
27}
28
rouslan7919c152015-06-03 03:12:3329namespace syncer {
30class SyncErrorFactory;
31class SyncChangeProcessor;
32}
33
[email protected]687f0ed2012-12-12 01:53:0534// Defines a custom dictionary where users can add their own words. All words
[email protected]255ef652013-01-30 09:49:1235// must be UTF8, between 1 and 99 bytes long, and without leading or trailing
36// ASCII whitespace. The dictionary contains its own checksum when saved on
37// disk. Example dictionary file contents:
[email protected]687f0ed2012-12-12 01:53:0538//
39// bar
40// foo
41// checksum_v1 = ec3df4034567e59e119fcf87f2d9bad4
42//
[email protected]bd5bf922013-01-23 00:37:0943class SpellcheckCustomDictionary : public SpellcheckDictionary,
44 public syncer::SyncableService {
[email protected]5f91b1f2012-10-26 19:17:2345 public:
[email protected]bd5bf922013-01-23 00:37:0946 // A change to the dictionary.
47 class Change {
48 public:
49 Change();
[email protected]bd5bf922013-01-23 00:37:0950 ~Change();
51
52 // Adds |word| in this change.
53 void AddWord(const std::string& word);
54
rouslan7919c152015-06-03 03:12:3355 // Adds |words| in this change.
56 void AddWords(const std::set<std::string>& words);
57
[email protected]bd5bf922013-01-23 00:37:0958 // Removes |word| in this change.
59 void RemoveWord(const std::string& word);
60
61 // Prepares this change to be applied to |words| by removing duplicate and
rouslan7919c152015-06-03 03:12:3362 // invalid words from words to be added and removing missing words from
63 // words to be removed. Returns a bitmap of |ChangeSanitationResult| values.
64 int Sanitize(const std::set<std::string>& words);
[email protected]bd5bf922013-01-23 00:37:0965
66 // Returns the words to be added in this change.
rouslan7919c152015-06-03 03:12:3367 const std::set<std::string>& to_add() const { return to_add_; }
[email protected]bd5bf922013-01-23 00:37:0968
69 // Returns the words to be removed in this change.
rouslan7919c152015-06-03 03:12:3370 const std::set<std::string>& to_remove() const {
71 return to_remove_;
72 }
[email protected]bd5bf922013-01-23 00:37:0973
74 // Returns true if there are no changes to be made. Otherwise returns false.
rouslan7919c152015-06-03 03:12:3375 bool empty() const { return to_add_.empty() && to_remove_.empty(); }
[email protected]bd5bf922013-01-23 00:37:0976
77 private:
78 // The words to be added.
rouslan7919c152015-06-03 03:12:3379 std::set<std::string> to_add_;
[email protected]bd5bf922013-01-23 00:37:0980
81 // The words to be removed.
rouslan7919c152015-06-03 03:12:3382 std::set<std::string> to_remove_;
83
84 DISALLOW_COPY_AND_ASSIGN(Change);
[email protected]bd5bf922013-01-23 00:37:0985 };
86
87 // Interface to implement for dictionary load and change observers.
[email protected]6cc4a8442012-11-20 08:26:4688 class Observer {
89 public:
[email protected]bd5bf922013-01-23 00:37:0990 // Called when the custom dictionary has been loaded.
[email protected]6cc4a8442012-11-20 08:26:4691 virtual void OnCustomDictionaryLoaded() = 0;
[email protected]bd5bf922013-01-23 00:37:0992
93 // Called when the custom dictionary has been changed.
94 virtual void OnCustomDictionaryChanged(const Change& dictionary_change) = 0;
[email protected]6cc4a8442012-11-20 08:26:4695 };
96
rouslanbd7987c2015-10-06 22:36:0697 struct LoadFileResult {
98 LoadFileResult();
99 ~LoadFileResult();
100
101 // The contents of the custom dictionary file or its backup. Does not
102 // contain data that failed checksum. Does not contain invalid words.
103 std::set<std::string> words;
104
105 // True when the custom dictionary file on disk has a valid checksum and
106 // contains only valid words.
107 bool is_valid_file;
108
109 private:
110 DISALLOW_COPY_AND_ASSIGN(LoadFileResult);
111 };
112
rouslan7919c152015-06-03 03:12:33113 // The dictionary will be saved in |dictionary_directory_name|.
114 explicit SpellcheckCustomDictionary(
115 const base::FilePath& dictionary_directory_name);
Daniel Chenga542fca2014-10-21 09:51:29116 ~SpellcheckCustomDictionary() override;
[email protected]5f91b1f2012-10-26 19:17:23117
[email protected]bd5bf922013-01-23 00:37:09118 // Returns the in-memory cache of words in the custom dictionary.
rouslan7919c152015-06-03 03:12:33119 const std::set<std::string>& GetWords() const;
[email protected]bd5bf922013-01-23 00:37:09120
121 // Adds |word| to the dictionary, schedules a write to disk, and notifies
122 // observers of the change. Returns true if |word| is valid and not a
123 // duplicate. Otherwise returns false.
124 bool AddWord(const std::string& word);
125
126 // Removes |word| from the dictionary, schedules a write to disk, and notifies
127 // observers of the change. Returns true if |word| was found. Otherwise
128 // returns false.
129 bool RemoveWord(const std::string& word);
130
[email protected]6da98fc2013-05-29 00:47:54131 // Returns true if the dictionary contains |word|. Otherwise returns false.
[email protected]e0c45d72013-06-25 03:32:10132 bool HasWord(const std::string& word) const;
[email protected]6da98fc2013-05-29 00:47:54133
[email protected]bd5bf922013-01-23 00:37:09134 // Adds |observer| to be notified of dictionary events and changes.
135 void AddObserver(Observer* observer);
136
137 // Removes |observer| to stop notifications of dictionary events and changes.
138 void RemoveObserver(Observer* observer);
139
140 // Returns true if the dictionary has been loaded. Otherwise returns false.
141 bool IsLoaded();
142
143 // Returns true if the dictionary is being synced. Otherwise returns false.
144 bool IsSyncing();
145
[email protected]6cc4a8442012-11-20 08:26:46146 // Overridden from SpellcheckDictionary:
Daniel Chenga542fca2014-10-21 09:51:29147 void Load() override;
[email protected]5f91b1f2012-10-26 19:17:23148
[email protected]bd5bf922013-01-23 00:37:09149 // Overridden from syncer::SyncableService:
Mikel Astiz3777f342019-03-14 13:26:25150 void WaitUntilReadyToSync(base::OnceClosure done) override;
Daniel Chenga542fca2014-10-21 09:51:29151 syncer::SyncMergeResult MergeDataAndStartSyncing(
[email protected]bd5bf922013-01-23 00:37:09152 syncer::ModelType type,
153 const syncer::SyncDataList& initial_sync_data,
dcheng4d0d72ef2016-04-14 01:11:33154 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
155 std::unique_ptr<syncer::SyncErrorFactory> sync_error_handler) override;
Daniel Chenga542fca2014-10-21 09:51:29156 void StopSyncing(syncer::ModelType type) override;
157 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
158 syncer::SyncError ProcessSyncChanges(
Brett Wilsonabbb9602017-09-11 23:26:39159 const base::Location& from_here,
mostynbfb66cb4f2014-10-07 09:15:42160 const syncer::SyncChangeList& change_list) override;
[email protected]1e29db92012-11-14 00:52:31161
[email protected]5f91b1f2012-10-26 19:17:23162 private:
[email protected]bd5bf922013-01-23 00:37:09163 friend class DictionarySyncIntegrationTestHelper;
164 friend class SpellcheckCustomDictionaryTest;
[email protected]6cc4a8442012-11-20 08:26:46165
[email protected]bd5bf922013-01-23 00:37:09166 // Returns the list of words in the custom spellcheck dictionary at |path|.
rouslanbd7987c2015-10-06 22:36:06167 // Validates that the custom dictionary file does not have duplicates and
168 // contains only valid words. Must be called on the FILE thread.
dcheng4d0d72ef2016-04-14 01:11:33169 static std::unique_ptr<LoadFileResult> LoadDictionaryFile(
[email protected]650b2d52013-02-10 03:41:45170 const base::FilePath& path);
[email protected]6cc4a8442012-11-20 08:26:46171
[email protected]bd5bf922013-01-23 00:37:09172 // Applies the change in |dictionary_change| to the custom spellcheck
rouslan7919c152015-06-03 03:12:33173 // dictionary. Assumes that |dictionary_change| has been sanitized. Must be
174 // called on the FILE thread. Takes ownership of |dictionary_change|.
dcheng4d0d72ef2016-04-14 01:11:33175 static void UpdateDictionaryFile(std::unique_ptr<Change> dictionary_change,
rouslan7919c152015-06-03 03:12:33176 const base::FilePath& path);
[email protected]687f0ed2012-12-12 01:53:05177
[email protected]bd5bf922013-01-23 00:37:09178 // The reply point for PostTaskAndReplyWithResult, called when
rouslanbd7987c2015-10-06 22:36:06179 // LoadDictionaryFile finishes reading the dictionary file.
dcheng4d0d72ef2016-04-14 01:11:33180 void OnLoaded(std::unique_ptr<LoadFileResult> result);
[email protected]bd5bf922013-01-23 00:37:09181
182 // Applies the |dictionary_change| to the in-memory copy of the dictionary.
[email protected]bd5bf922013-01-23 00:37:09183 void Apply(const Change& dictionary_change);
184
rouslanbd7987c2015-10-06 22:36:06185 // Schedules a write of the words in |load_file_result| to disk when the
186 // custom dictionary file is invalid.
dcheng4d0d72ef2016-04-14 01:11:33187 void FixInvalidFile(std::unique_ptr<LoadFileResult> load_file_result);
rouslanbd7987c2015-10-06 22:36:06188
rouslan7919c152015-06-03 03:12:33189 // Schedules a write of |dictionary_change| to disk. Takes ownership of
190 // |dictionary_change| to pass it to the FILE thread.
dcheng4d0d72ef2016-04-14 01:11:33191 void Save(std::unique_ptr<Change> dictionary_change);
[email protected]bd5bf922013-01-23 00:37:09192
193 // Notifies the sync service of the |dictionary_change|. Syncs up to the
194 // maximum syncable words on the server. Disables syncing of this dictionary
195 // if the server contains the maximum number of syncable words.
196 syncer::SyncError Sync(const Change& dictionary_change);
197
198 // Notifies observers of the dictionary change if the dictionary has been
199 // changed.
200 void Notify(const Change& dictionary_change);
[email protected]687f0ed2012-12-12 01:53:05201
Francois Dorayce42ef442017-09-14 15:24:20202 // Task runner where the file operations takes place.
203 scoped_refptr<base::SequencedTaskRunner> task_runner_;
204
[email protected]5f91b1f2012-10-26 19:17:23205 // In-memory cache of the custom words file.
rouslan7919c152015-06-03 03:12:33206 std::set<std::string> words_;
[email protected]5f91b1f2012-10-26 19:17:23207
rouslan7919c152015-06-03 03:12:33208 // The path to the custom dictionary file.
[email protected]650b2d52013-02-10 03:41:45209 base::FilePath custom_dictionary_path_;
[email protected]5f91b1f2012-10-26 19:17:23210
rouslan7919c152015-06-03 03:12:33211 // Observers for dictionary load and content changes.
Trent Apteda250ec3ab2018-08-19 08:52:19212 base::ObserverList<Observer>::Unchecked observers_;
[email protected]6cc4a8442012-11-20 08:26:46213
[email protected]bd5bf922013-01-23 00:37:09214 // Used to send local changes to the sync infrastructure.
dcheng4d0d72ef2016-04-14 01:11:33215 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_;
[email protected]bd5bf922013-01-23 00:37:09216
217 // Used to send sync-related errors to the sync infrastructure.
dcheng4d0d72ef2016-04-14 01:11:33218 std::unique_ptr<syncer::SyncErrorFactory> sync_error_handler_;
[email protected]bd5bf922013-01-23 00:37:09219
220 // True if the dictionary has been loaded. Otherwise false.
221 bool is_loaded_;
222
Mikel Astiz3777f342019-03-14 13:26:25223 base::OnceClosure wait_until_ready_to_sync_cb_;
224
rouslanbd7987c2015-10-06 22:36:06225 // A post-startup task to fix the invalid custom dictionary file.
Xiaocheng Hu3e37c3a2018-01-10 19:54:41226 base::CancelableOnceClosure fix_invalid_file_;
rouslanbd7987c2015-10-06 22:36:06227
[email protected]62aec8512013-10-08 20:45:33228 // Used to create weak pointers for an instance of this class.
Jeremy Roman495db682019-07-12 16:03:24229 base::WeakPtrFactory<SpellcheckCustomDictionary> weak_ptr_factory_{this};
[email protected]62aec8512013-10-08 20:45:33230
[email protected]5f91b1f2012-10-26 19:17:23231 DISALLOW_COPY_AND_ASSIGN(SpellcheckCustomDictionary);
232};
233
234#endif // CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_CUSTOM_DICTIONARY_H_