Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 } | |
| OLD | NEW |