Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: chrome/browser/spellchecker/spellcheck_custom_dictionary.cc

Issue 11362063: Editing the custom spelling dictionary (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Exclude custom dictionary WebUI from mac Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h" 5 #include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/lazy_instance.h"
9 #include "base/string_split.h" 8 #include "base/string_split.h"
10 #include "base/string_util.h"
11 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/spellchecker/spellcheck_service.h"
13 #include "chrome/common/chrome_constants.h" 10 #include "chrome/common/chrome_constants.h"
14 #include "chrome/common/spellcheck_messages.h" 11 #include "chrome/common/spellcheck_messages.h"
15 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/render_process_host.h" 13 #include "content/public/browser/render_process_host.h"
17 14
18 #include <functional>
19
20 using content::BrowserThread; 15 using content::BrowserThread;
21 using chrome::spellcheck_common::WordList; 16 using chrome::spellcheck_common::WordList;
22 17
23 SpellcheckCustomDictionary::SpellcheckCustomDictionary(Profile* profile) 18 SpellcheckCustomDictionary::SpellcheckCustomDictionary(Profile* profile)
24 : SpellcheckDictionary(profile), 19 : SpellcheckDictionary(profile),
25 custom_dictionary_path_(), 20 custom_dictionary_path_(),
26 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 21 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
27 DCHECK(profile); 22 DCHECK(profile);
28 custom_dictionary_path_ = 23 custom_dictionary_path_ =
29 profile_->GetPath().Append(chrome::kCustomDictionaryFileName); 24 profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
30 } 25 }
31 26
32 SpellcheckCustomDictionary::~SpellcheckCustomDictionary() { 27 SpellcheckCustomDictionary::~SpellcheckCustomDictionary() {
33 } 28 }
34 29
30 void SpellcheckCustomDictionary::Load() {
31 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
32
33 BrowserThread::PostTaskAndReplyWithResult<WordList*>(
34 BrowserThread::FILE,
35 FROM_HERE,
36 base::Bind(&SpellcheckCustomDictionary::LoadDictionary,
37 base::Unretained(this)),
38 base::Bind(&SpellcheckCustomDictionary::SetCustomWordListAndDelete,
39 weak_ptr_factory_.GetWeakPtr()));
40 }
41
42 const WordList& SpellcheckCustomDictionary::GetWords() const {
43 return words_;
44 }
45
35 void SpellcheckCustomDictionary::LoadDictionaryIntoCustomWordList( 46 void SpellcheckCustomDictionary::LoadDictionaryIntoCustomWordList(
36 WordList* custom_words) { 47 WordList* custom_words) {
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
38 49
39 std::string contents; 50 std::string contents;
40 file_util::ReadFileToString(custom_dictionary_path_, &contents); 51 file_util::ReadFileToString(custom_dictionary_path_, &contents);
41 if (contents.empty()) 52 if (contents.empty())
42 return; 53 return;
43 54
44 base::SplitString(contents, '\n', custom_words); 55 base::SplitString(contents, '\n', custom_words);
45 // Clear out empty words. 56 // Clear out empty words.
46 custom_words->erase(remove_if(custom_words->begin(), custom_words->end(), 57 custom_words->erase(remove_if(custom_words->begin(), custom_words->end(),
47 mem_fun_ref(&std::string::empty)), custom_words->end()); 58 mem_fun_ref(&std::string::empty)), custom_words->end());
48 } 59 }
49 60
50 void SpellcheckCustomDictionary::Load() { 61 void SpellcheckCustomDictionary::SetCustomWordList(WordList* custom_words) {
51 custom_words_.clear(); 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
52 // We are not guaranteed to be on the FILE thread so post the task. 63
53 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( 64 words_.clear();
54 &SpellcheckCustomDictionary::LoadDictionaryIntoCustomWordList, 65 if (custom_words)
55 base::Unretained(this), &custom_words_)); 66 std::swap(words_, *custom_words);
67
68 std::vector<Observer*>::iterator it;
69 for (it = observers_.begin(); it != observers_.end(); ++it)
70 (*it)->OnCustomDictionaryLoaded();
71 }
72
73 bool SpellcheckCustomDictionary::AddWord(const std::string& word) {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
75
76 if (!CustomWordAddedLocally(word))
77 return false;
78
79 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
80 base::Bind(&SpellcheckCustomDictionary::WriteWordToCustomDictionary,
81 base::Unretained(this), word));
82
83 for (content::RenderProcessHost::iterator i(
84 content::RenderProcessHost::AllHostsIterator());
85 !i.IsAtEnd(); i.Advance()) {
86 i.GetCurrentValue()->Send(new SpellCheckMsg_WordAdded(word));
87 }
88
89 std::vector<Observer*>::iterator it;
90 for (it = observers_.begin(); it != observers_.end(); ++it)
91 (*it)->OnCustomDictionaryWordAdded(word);
92
93 return true;
94 }
95
96 bool SpellcheckCustomDictionary::CustomWordAddedLocally(
97 const std::string& word) {
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
99
100 WordList::iterator it = std::find(words_.begin(), words_.end(), word);
101 if (it == words_.end()) {
102 words_.push_back(word);
103 return true;
104 }
105 return false;
106 // TODO(rlp): record metrics on custom word size
56 } 107 }
57 108
58 void SpellcheckCustomDictionary::WriteWordToCustomDictionary( 109 void SpellcheckCustomDictionary::WriteWordToCustomDictionary(
59 const std::string& word) { 110 const std::string& word) {
60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
61 112
62 // Stored in UTF-8. 113 // Stored in UTF-8.
63 DCHECK(IsStringUTF8(word)); 114 DCHECK(IsStringUTF8(word));
64 115
65 std::string word_to_add(word + "\n"); 116 std::string word_to_add(word + "\n");
66 if (!file_util::PathExists(custom_dictionary_path_)) { 117 if (!file_util::PathExists(custom_dictionary_path_)) {
67 file_util::WriteFile(custom_dictionary_path_, word_to_add.c_str(), 118 file_util::WriteFile(custom_dictionary_path_, word_to_add.c_str(),
68 word_to_add.length()); 119 word_to_add.length());
69 } else { 120 } else {
70 file_util::AppendToFile(custom_dictionary_path_, word_to_add.c_str(), 121 file_util::AppendToFile(custom_dictionary_path_, word_to_add.c_str(),
71 word_to_add.length()); 122 word_to_add.length());
72 } 123 }
73 } 124 }
74 125
75 void SpellcheckCustomDictionary::CustomWordAddedLocally( 126 bool SpellcheckCustomDictionary::RemoveWord(const std::string& word) {
76 const std::string& word) {
77 custom_words_.push_back(word);
78 // TODO(rlp): record metrics on custom word size
79 }
80
81 bool SpellcheckCustomDictionary::SetCustomWordList(WordList* custom_words) {
82 if (!custom_words)
83 return false;
84 custom_words_.clear();
85 std::swap(custom_words_, *custom_words);
86 return true;
87 }
88
89 const WordList& SpellcheckCustomDictionary::GetCustomWords() const {
90 return custom_words_;
91 }
92
93 void SpellcheckCustomDictionary::AddWord(const std::string& word) {
94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
95 128
96 CustomWordAddedLocally(word); 129 if (!CustomWordRemovedLocally(word))
130 return false;
97 131
98 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE, 132 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
99 base::Bind(&SpellcheckCustomDictionary::WriteWordToCustomDictionary, 133 base::Bind(&SpellcheckCustomDictionary::EraseWordFromCustomDictionary,
100 base::Unretained(this), word), 134 base::Unretained(this), word));
101 base::Bind(&SpellcheckCustomDictionary::AddWordComplete,
102 weak_ptr_factory_.GetWeakPtr(), word));
103 }
104
105 void SpellcheckCustomDictionary::AddWordComplete(const std::string& word) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107 135
108 for (content::RenderProcessHost::iterator i( 136 for (content::RenderProcessHost::iterator i(
109 content::RenderProcessHost::AllHostsIterator()); 137 content::RenderProcessHost::AllHostsIterator());
110 !i.IsAtEnd(); i.Advance()) { 138 !i.IsAtEnd(); i.Advance()) {
111 i.GetCurrentValue()->Send(new SpellCheckMsg_WordAdded(word)); 139 i.GetCurrentValue()->Send(new SpellCheckMsg_WordRemoved(word));
140 }
141
142 std::vector<Observer*>::iterator it;
143 for (it = observers_.begin(); it != observers_.end(); ++it)
144 (*it)->OnCustomDictionaryWordRemoved(word);
145
146 return true;
147 }
148
149 bool SpellcheckCustomDictionary::CustomWordRemovedLocally(
150 const std::string& word) {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
152
153 WordList::iterator it = std::find(words_.begin(), words_.end(), word);
154 if (it != words_.end()) {
155 words_.erase(it);
156 return true;
157 }
158 return false;
159 }
160
161 void SpellcheckCustomDictionary::EraseWordFromCustomDictionary(
162 const std::string& word) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
164 DCHECK(IsStringUTF8(word));
165
166 WordList custom_words;
167 LoadDictionaryIntoCustomWordList(&custom_words);
168
169 char empty[] = {'\0'};
170 char separator[] = {'\n', '\0'};
171 file_util::WriteFile(custom_dictionary_path_, empty, 0);
172 for (WordList::iterator it = custom_words.begin();
173 it != custom_words.end();
174 ++it) {
175 std::string word_to_add = *it;
176 if (word.compare(word_to_add) != 0) {
177 file_util::AppendToFile(custom_dictionary_path_, word_to_add.c_str(),
178 word_to_add.length());
179 file_util::AppendToFile(custom_dictionary_path_, separator, 1);
180 }
112 } 181 }
113 } 182 }
114 183
184 void SpellcheckCustomDictionary::AddObserver(Observer* observer) {
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115 186
187 observers_.push_back(observer);
188 }
189
190 void SpellcheckCustomDictionary::RemoveObserver(Observer* observer) {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192
193 std::vector<Observer*>::iterator it = std::find(observers_.begin(),
194 observers_.end(),
195 observer);
196 if (it != observers_.end())
197 observers_.erase(it);
198 }
199
200 WordList* SpellcheckCustomDictionary::LoadDictionary() {
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
202
203 WordList* custom_words = new WordList;
204 LoadDictionaryIntoCustomWordList(custom_words);
205 return custom_words;
206 }
207
208 void SpellcheckCustomDictionary::SetCustomWordListAndDelete(
209 WordList* custom_words) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211
212 SetCustomWordList(custom_words);
213 delete custom_words;
214 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698