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

Side by Side Diff: chrome/renderer/spellchecker/hunspell_engine.cc

Issue 11445002: Sync user's custom spellcheck dictionary (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Merge master Created 7 years, 11 months 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 "hunspell_engine.h" 5 #include "hunspell_engine.h"
6 6
7 #include <algorithm>
8 #include <iterator>
9
7 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
8 #include "base/time.h" 11 #include "base/time.h"
9 #include "chrome/common/spellcheck_common.h" 12 #include "chrome/common/spellcheck_common.h"
10 #include "chrome/common/spellcheck_messages.h" 13 #include "chrome/common/spellcheck_messages.h"
11 #include "content/public/renderer/render_thread.h" 14 #include "content/public/renderer/render_thread.h"
12 #include "third_party/hunspell/src/hunspell/hunspell.hxx" 15 #include "third_party/hunspell/src/hunspell/hunspell.hxx"
13 16
14 using base::TimeTicks; 17 using base::TimeTicks;
15 using content::RenderThread; 18 using content::RenderThread;
16 19
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 65
63 bdict_file_.reset(new file_util::MemoryMappedFile); 66 bdict_file_.reset(new file_util::MemoryMappedFile);
64 67
65 if (bdict_file_->Initialize(file_)) { 68 if (bdict_file_->Initialize(file_)) {
66 TimeTicks debug_start_time = base::Histogram::DebugNow(); 69 TimeTicks debug_start_time = base::Histogram::DebugNow();
67 70
68 hunspell_.reset( 71 hunspell_.reset(
69 new Hunspell(bdict_file_->data(), bdict_file_->length())); 72 new Hunspell(bdict_file_->data(), bdict_file_->length()));
70 73
71 // Add custom words to Hunspell. 74 // Add custom words to Hunspell.
72 chrome::spellcheck_common::WordList::iterator it; 75 AddWordsToHunspell(custom_words_);
73 for (it = custom_words_.begin(); it != custom_words_.end(); ++it)
74 AddWordToHunspell(*it);
75 76
76 DHISTOGRAM_TIMES("Spellcheck.InitTime", 77 DHISTOGRAM_TIMES("Spellcheck.InitTime",
77 base::Histogram::DebugNow() - debug_start_time); 78 base::Histogram::DebugNow() - debug_start_time);
78 } else { 79 } else {
79 NOTREACHED() << "Could not mmap spellchecker dictionary."; 80 NOTREACHED() << "Could not mmap spellchecker dictionary.";
80 } 81 }
81 } 82 }
82 83
83 void HunspellEngine::AddWordToHunspell(const std::string& word) { 84 void HunspellEngine::AddWordsToHunspell(const std::vector<std::string>& words) {
84 if (!word.empty() && word.length() < MAXWORDLEN) 85 std::string word;
85 hunspell_->add(word.c_str()); 86 for (chrome::spellcheck_common::WordList::const_iterator it = words.begin();
87 it != words.end();
88 ++it) {
89 word = *it;
90 if (!word.empty() &&
91 word.length() <=
92 chrome::spellcheck_common::MAX_CUSTOM_DICTIONARY_WORD_BYTES) {
93 hunspell_->add(word.c_str());
94 }
95 }
86 } 96 }
87 97
88 void HunspellEngine::RemoveWordFromHunspell(const std::string& word) { 98 void HunspellEngine::RemoveWordsFromHunspell(
89 if (!word.empty() && word.length() < MAXWORDLEN) 99 const std::vector<std::string>& words) {
90 hunspell_->remove(word.c_str()); 100 std::string word;
101 for (std::vector<std::string>::const_iterator it = words.begin();
102 it != words.end();
103 ++it) {
104 word = *it;
105 if (!word.empty() &&
106 word.length() <=
107 chrome::spellcheck_common::MAX_CUSTOM_DICTIONARY_WORD_BYTES) {
108 hunspell_->remove(word.c_str());
109 }
110 }
91 } 111 }
92 112
93 bool HunspellEngine::CheckSpelling(const string16& word_to_check, int tag) { 113 bool HunspellEngine::CheckSpelling(const string16& word_to_check, int tag) {
94 bool word_correct = false; 114 bool word_correct = false;
95 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check)); 115 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check));
96 // Hunspell shouldn't let us exceed its max, but check just in case 116 // Hunspell shouldn't let us exceed its max, but check just in case
97 if (word_to_check_utf8.length() < kMaxCheckedLen) { 117 if (word_to_check_utf8.length() < kMaxCheckedLen) {
98 if (hunspell_.get()) { 118 if (hunspell_.get()) {
99 // |hunspell_->spell| returns 0 if the word is spelled correctly and 119 // |hunspell_->spell| returns 0 if the word is spelled correctly and
100 // non-zero otherwsie. 120 // non-zero otherwise.
101 word_correct = (hunspell_->spell(word_to_check_utf8.c_str()) != 0); 121 word_correct = (hunspell_->spell(word_to_check_utf8.c_str()) != 0);
102 } else { 122 } else {
103 // If |hunspell_| is NULL here, an error has occurred, but it's better 123 // If |hunspell_| is NULL here, an error has occurred, but it's better
104 // to check rather than crash. 124 // to check rather than crash.
105 word_correct = true; 125 word_correct = true;
106 } 126 }
107 } 127 }
108 128
109 return word_correct; 129 return word_correct;
110 } 130 }
(...skipping 18 matching lines...) Expand all
129 // Populate the vector of WideStrings. 149 // Populate the vector of WideStrings.
130 for (int i = 0; i < number_of_suggestions; ++i) { 150 for (int i = 0; i < number_of_suggestions; ++i) {
131 if (i < chrome::spellcheck_common::kMaxSuggestions) 151 if (i < chrome::spellcheck_common::kMaxSuggestions)
132 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i])); 152 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i]));
133 free(suggestions[i]); 153 free(suggestions[i]);
134 } 154 }
135 if (suggestions != NULL) 155 if (suggestions != NULL)
136 free(suggestions); 156 free(suggestions);
137 } 157 }
138 158
139 void HunspellEngine::OnWordAdded(const std::string& word) { 159 void HunspellEngine::OnCustomDictionaryChanged(
160 const std::vector<std::string>& words_added,
161 const std::vector<std::string>& words_removed) {
140 if (!hunspell_.get()) { 162 if (!hunspell_.get()) {
141 // Save it for later---add it when hunspell is initialized. 163 // Save it for later---add it when hunspell is initialized.
142 custom_words_.push_back(word); 164 custom_words_.insert(custom_words_.end(),
165 words_added.begin(),
166 words_added.end());
167 // Remove words.
168 std::vector<std::string> words_removed_copy(words_removed);
169 std::sort(words_removed_copy.begin(), words_removed_copy.end());
170 std::sort(custom_words_.begin(), custom_words_.end());
171 std::vector<std::string> updated_custom_words;
172 std::set_difference(custom_words_.begin(),
173 custom_words_.end(),
174 words_removed_copy.begin(),
175 words_removed_copy.end(),
176 std::back_inserter(updated_custom_words));
177 std::swap(custom_words_, updated_custom_words);
143 } else { 178 } else {
144 AddWordToHunspell(word); 179 AddWordsToHunspell(words_added);
180 RemoveWordsFromHunspell(words_removed);
145 } 181 }
146 } 182 }
147 183
148 void HunspellEngine::OnWordRemoved(const std::string& word) {
149 if (!hunspell_.get()) {
150 chrome::spellcheck_common::WordList::iterator it = std::find(
151 custom_words_.begin(), custom_words_.end(), word);
152 if (it != custom_words_.end())
153 custom_words_.erase(it);
154 } else {
155 RemoveWordFromHunspell(word);
156 }
157 }
158
159 bool HunspellEngine::InitializeIfNeeded() { 184 bool HunspellEngine::InitializeIfNeeded() {
160 if (!initialized_ && !dictionary_requested_) { 185 if (!initialized_ && !dictionary_requested_) {
161 // RenderThread will not exist in test. 186 // RenderThread will not exist in test.
162 if (RenderThread::Get()) 187 if (RenderThread::Get())
163 RenderThread::Get()->Send(new SpellCheckHostMsg_RequestDictionary); 188 RenderThread::Get()->Send(new SpellCheckHostMsg_RequestDictionary);
164 dictionary_requested_ = true; 189 dictionary_requested_ = true;
165 return true; 190 return true;
166 } 191 }
167 192
168 // Don't initialize if hunspell is disabled. 193 // Don't initialize if hunspell is disabled.
169 if (file_ != base::kInvalidPlatformFileValue) 194 if (file_ != base::kInvalidPlatformFileValue)
170 InitializeHunspell(); 195 InitializeHunspell();
171 196
172 return !initialized_; 197 return !initialized_;
173 } 198 }
174 199
175 bool HunspellEngine::IsEnabled() { 200 bool HunspellEngine::IsEnabled() {
176 return file_ != base::kInvalidPlatformFileValue; 201 return file_ != base::kInvalidPlatformFileValue;
177 } 202 }
OLDNEW
« no previous file with comments | « chrome/renderer/spellchecker/hunspell_engine.h ('k') | chrome/renderer/spellchecker/spellcheck.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698