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

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: 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" 8 #include "base/lazy_instance.h"
9 #include "base/string_split.h" 9 #include "base/string_split.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 14 matching lines...) Expand all
25 custom_dictionary_path_(), 25 custom_dictionary_path_(),
26 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 26 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
27 DCHECK(profile); 27 DCHECK(profile);
28 custom_dictionary_path_ = 28 custom_dictionary_path_ =
29 profile_->GetPath().Append(chrome::kCustomDictionaryFileName); 29 profile_->GetPath().Append(chrome::kCustomDictionaryFileName);
30 } 30 }
31 31
32 SpellcheckCustomDictionary::~SpellcheckCustomDictionary() { 32 SpellcheckCustomDictionary::~SpellcheckCustomDictionary() {
33 } 33 }
34 34
35 void SpellcheckCustomDictionary::Load() {
36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
37 BrowserThread::PostTaskAndReplyWithResult<WordList*>(
38 BrowserThread::FILE,
39 FROM_HERE,
40 base::Bind(&SpellcheckCustomDictionary::LoadDictionary,
41 base::Unretained(this)),
42 base::Bind(&SpellcheckCustomDictionary::SetCustomWordList,
43 weak_ptr_factory_.GetWeakPtr()));
44 }
45
46 const WordList& SpellcheckCustomDictionary::GetWords() const {
47 return words_;
48 }
49
50 WordList* SpellcheckCustomDictionary::LoadDictionary() {
51 WordList* custom_words = new WordList;
52 LoadDictionaryIntoCustomWordList(custom_words);
53 return custom_words;
54 }
55
35 void SpellcheckCustomDictionary::LoadDictionaryIntoCustomWordList( 56 void SpellcheckCustomDictionary::LoadDictionaryIntoCustomWordList(
rpetterson 2012/11/14 19:47:09 Why doesn't this function notify observers of OnCu
please use gerrit instead 2012/11/14 22:54:46 This method does not modify the private member var
36 WordList* custom_words) { 57 WordList* custom_words) {
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
38 59
39 std::string contents; 60 std::string contents;
40 file_util::ReadFileToString(custom_dictionary_path_, &contents); 61 file_util::ReadFileToString(custom_dictionary_path_, &contents);
41 if (contents.empty()) 62 if (contents.empty())
42 return; 63 return;
43 64
44 base::SplitString(contents, '\n', custom_words); 65 base::SplitString(contents, '\n', custom_words);
45 // Clear out empty words. 66 // Clear out empty words.
46 custom_words->erase(remove_if(custom_words->begin(), custom_words->end(), 67 custom_words->erase(remove_if(custom_words->begin(), custom_words->end(),
47 mem_fun_ref(&std::string::empty)), custom_words->end()); 68 mem_fun_ref(&std::string::empty)), custom_words->end());
48 } 69 }
49 70
50 void SpellcheckCustomDictionary::Load() { 71 void SpellcheckCustomDictionary::SetCustomWordList(WordList* custom_words) {
rpetterson 2012/11/14 19:47:09 Does this need to be called on the UI thread? If s
please use gerrit instead 2012/11/14 22:54:46 Adding dchecks for the correct browser thread in a
51 custom_words_.clear(); 72 words_.clear();
52 // We are not guaranteed to be on the FILE thread so post the task. 73 if (custom_words)
53 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( 74 std::swap(words_, *custom_words);
54 &SpellcheckCustomDictionary::LoadDictionaryIntoCustomWordList, 75 std::vector<Observer*>::iterator it;
55 base::Unretained(this), &custom_words_)); 76 for (it = observers_.begin(); it != observers_.end(); ++it)
77 (*it)->OnCustomDictionaryLoaded();
78 }
79
80 void SpellcheckCustomDictionary::AddWord(const std::string& word) {
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82
83 CustomWordAddedLocally(word);
84
85 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
86 base::Bind(&SpellcheckCustomDictionary::WriteWordToCustomDictionary,
87 base::Unretained(this), word),
88 base::Bind(&SpellcheckCustomDictionary::AddWordComplete,
89 weak_ptr_factory_.GetWeakPtr(), word));
90 }
91
92 void SpellcheckCustomDictionary::CustomWordAddedLocally(
93 const std::string& word) {
94 words_.push_back(word);
95 // TODO(rlp): record metrics on custom word size
56 } 96 }
57 97
58 void SpellcheckCustomDictionary::WriteWordToCustomDictionary( 98 void SpellcheckCustomDictionary::WriteWordToCustomDictionary(
59 const std::string& word) { 99 const std::string& word) {
60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
61 101
62 // Stored in UTF-8. 102 // Stored in UTF-8.
63 DCHECK(IsStringUTF8(word)); 103 DCHECK(IsStringUTF8(word));
64 104
65 std::string word_to_add(word + "\n"); 105 std::string word_to_add(word + "\n");
66 if (!file_util::PathExists(custom_dictionary_path_)) { 106 if (!file_util::PathExists(custom_dictionary_path_)) {
67 file_util::WriteFile(custom_dictionary_path_, word_to_add.c_str(), 107 file_util::WriteFile(custom_dictionary_path_, word_to_add.c_str(),
68 word_to_add.length()); 108 word_to_add.length());
69 } else { 109 } else {
70 file_util::AppendToFile(custom_dictionary_path_, word_to_add.c_str(), 110 file_util::AppendToFile(custom_dictionary_path_, word_to_add.c_str(),
71 word_to_add.length()); 111 word_to_add.length());
72 } 112 }
73 } 113 }
74 114
75 void SpellcheckCustomDictionary::CustomWordAddedLocally(
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));
95
96 CustomWordAddedLocally(word);
97
98 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
99 base::Bind(&SpellcheckCustomDictionary::WriteWordToCustomDictionary,
100 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) { 115 void SpellcheckCustomDictionary::AddWordComplete(const std::string& word) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107 117
108 for (content::RenderProcessHost::iterator i( 118 for (content::RenderProcessHost::iterator i(
109 content::RenderProcessHost::AllHostsIterator()); 119 content::RenderProcessHost::AllHostsIterator());
110 !i.IsAtEnd(); i.Advance()) { 120 !i.IsAtEnd(); i.Advance()) {
111 i.GetCurrentValue()->Send(new SpellCheckMsg_WordAdded(word)); 121 i.GetCurrentValue()->Send(new SpellCheckMsg_WordAdded(word));
112 } 122 }
123 std::vector<Observer*>::iterator it;
124 for (it = observers_.begin(); it != observers_.end(); ++it)
125 (*it)->OnCustomDictionaryWordAdded(word);
113 } 126 }
114 127
128 void SpellcheckCustomDictionary::RemoveWord(const std::string& word) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115 130
131 CustomWordRemovedLocally(word);
132
133 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
134 base::Bind(&SpellcheckCustomDictionary::EraseWordFromCustomDictionary,
135 base::Unretained(this), word),
136 base::Bind(&SpellcheckCustomDictionary::RemoveWordComplete,
137 weak_ptr_factory_.GetWeakPtr(), word));
138 }
139
140 void SpellcheckCustomDictionary::CustomWordRemovedLocally(
141 const std::string& word) {
142 WordList::iterator it = std::find(words_.begin(), words_.end(), word);
143 if (it != words_.end())
144 words_.erase(it);
145 }
146
147 void SpellcheckCustomDictionary::EraseWordFromCustomDictionary(
148 const std::string& word) {
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
150 DCHECK(IsStringUTF8(word));
151
rpetterson 2012/11/14 19:47:09 Replace the next 8 lines with LoadDictionaryIntoCu
please use gerrit instead 2012/11/14 22:54:46 Done.
152 std::string contents;
153 file_util::ReadFileToString(custom_dictionary_path_, &contents);
154 if (contents.empty())
155 return;
156
157 WordList custom_words;
158 base::SplitString(contents, '\n', &custom_words);
159 custom_words.erase(remove_if(custom_words.begin(), custom_words.end(),
160 mem_fun_ref(&std::string::empty)), custom_words.end());
161
162 char empty[] = {'\0'};
163 char separator[] = {'\n', '\0'};
164 file_util::WriteFile(custom_dictionary_path_, empty, 0);
165 for (WordList::iterator it = custom_words.begin();
166 it != custom_words.end();
167 ++it) {
168 std::string word_to_add = *it;
169 if (word.compare(word_to_add) != 0) {
170 file_util::AppendToFile(custom_dictionary_path_, word_to_add.c_str(),
171 word_to_add.length());
172 file_util::AppendToFile(custom_dictionary_path_, separator, 1);
173 }
174 }
175 }
176
177 void SpellcheckCustomDictionary::RemoveWordComplete(const std::string& word) {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
179
180 for (content::RenderProcessHost::iterator i(
181 content::RenderProcessHost::AllHostsIterator());
182 !i.IsAtEnd(); i.Advance()) {
183 i.GetCurrentValue()->Send(new SpellCheckMsg_WordRemoved(word));
184 }
185 std::vector<Observer*>::iterator it;
186 for (it = observers_.begin(); it != observers_.end(); ++it)
187 (*it)->OnCustomDictionaryWordRemoved(word);
188 }
189
190 void SpellcheckCustomDictionary::AddObserver(Observer* observer) {
191 observers_.push_back(observer);
192 }
193
194 void SpellcheckCustomDictionary::RemoveObserver(Observer* observer) {
195 std::vector<Observer*>::iterator it = std::find(observers_.begin(),
196 observers_.end(),
197 observer);
198 if (it != observers_.end())
199 observers_.erase(it);
200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698