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

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: Fix compile on some platforms 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 52
50 bdict_file_.reset(new file_util::MemoryMappedFile); 53 bdict_file_.reset(new file_util::MemoryMappedFile);
51 54
52 if (bdict_file_->Initialize(file_)) { 55 if (bdict_file_->Initialize(file_)) {
53 TimeTicks debug_start_time = base::Histogram::DebugNow(); 56 TimeTicks debug_start_time = base::Histogram::DebugNow();
54 57
55 hunspell_.reset( 58 hunspell_.reset(
56 new Hunspell(bdict_file_->data(), bdict_file_->length())); 59 new Hunspell(bdict_file_->data(), bdict_file_->length()));
57 60
58 // Add custom words to Hunspell. 61 // Add custom words to Hunspell.
59 chrome::spellcheck_common::WordList::iterator it; 62 AddWordsToHunspell(custom_words_);
60 for (it = custom_words_.begin(); it != custom_words_.end(); ++it)
61 AddWordToHunspell(*it);
62 63
63 DHISTOGRAM_TIMES("Spellcheck.InitTime", 64 DHISTOGRAM_TIMES("Spellcheck.InitTime",
64 base::Histogram::DebugNow() - debug_start_time); 65 base::Histogram::DebugNow() - debug_start_time);
65 } else { 66 } else {
66 NOTREACHED() << "Could not mmap spellchecker dictionary."; 67 NOTREACHED() << "Could not mmap spellchecker dictionary.";
67 } 68 }
68 } 69 }
69 70
70 void HunspellEngine::AddWordToHunspell(const std::string& word) { 71 void HunspellEngine::AddWordsToHunspell(const std::vector<std::string>& words) {
71 if (!word.empty() && word.length() < MAXWORDLEN) 72 std::string word;
72 hunspell_->add(word.c_str()); 73 for (chrome::spellcheck_common::WordList::const_iterator it = words.begin();
74 it != words.end();
75 ++it) {
76 word = *it;
77 if (!word.empty() &&
78 word.length() <=
79 chrome::spellcheck_common::MAX_CUSTOM_DICTIONARY_WORD_BYTES) {
80 hunspell_->add(word.c_str());
81 }
82 }
73 } 83 }
74 84
75 void HunspellEngine::RemoveWordFromHunspell(const std::string& word) { 85 void HunspellEngine::RemoveWordsFromHunspell(
76 if (!word.empty() && word.length() < MAXWORDLEN) 86 const std::vector<std::string>& words) {
77 hunspell_->remove(word.c_str()); 87 std::string word;
88 for (std::vector<std::string>::const_iterator it = words.begin();
89 it != words.end();
90 ++it) {
91 word = *it;
92 if (!word.empty() &&
93 word.length() <=
94 chrome::spellcheck_common::MAX_CUSTOM_DICTIONARY_WORD_BYTES) {
95 hunspell_->remove(word.c_str());
96 }
97 }
78 } 98 }
79 99
80 bool HunspellEngine::CheckSpelling(const string16& word_to_check, int tag) { 100 bool HunspellEngine::CheckSpelling(const string16& word_to_check, int tag) {
81 bool word_correct = false; 101 bool word_correct = false;
82 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check)); 102 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check));
83 // Hunspell shouldn't let us exceed its max, but check just in case 103 // Hunspell shouldn't let us exceed its max, but check just in case
84 if (word_to_check_utf8.length() < MAXWORDLEN) { 104 if (word_to_check_utf8.length() <=
105 chrome::spellcheck_common::MAX_CUSTOM_DICTIONARY_WORD_BYTES) {
85 if (hunspell_.get()) { 106 if (hunspell_.get()) {
86 // |hunspell_->spell| returns 0 if the word is spelled correctly and 107 // |hunspell_->spell| returns 0 if the word is spelled correctly and
87 // non-zero otherwsie. 108 // non-zero otherwise.
88 word_correct = (hunspell_->spell(word_to_check_utf8.c_str()) != 0); 109 word_correct = (hunspell_->spell(word_to_check_utf8.c_str()) != 0);
89 } else { 110 } else {
90 // If |hunspell_| is NULL here, an error has occurred, but it's better 111 // If |hunspell_| is NULL here, an error has occurred, but it's better
91 // to check rather than crash. 112 // to check rather than crash.
92 word_correct = true; 113 word_correct = true;
93 } 114 }
94 } 115 }
95 116
96 return word_correct; 117 return word_correct;
97 } 118 }
(...skipping 14 matching lines...) Expand all
112 // Populate the vector of WideStrings. 133 // Populate the vector of WideStrings.
113 for (int i = 0; i < number_of_suggestions; ++i) { 134 for (int i = 0; i < number_of_suggestions; ++i) {
114 if (i < chrome::spellcheck_common::kMaxSuggestions) 135 if (i < chrome::spellcheck_common::kMaxSuggestions)
115 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i])); 136 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i]));
116 free(suggestions[i]); 137 free(suggestions[i]);
117 } 138 }
118 if (suggestions != NULL) 139 if (suggestions != NULL)
119 free(suggestions); 140 free(suggestions);
120 } 141 }
121 142
122 void HunspellEngine::OnWordAdded(const std::string& word) { 143 void HunspellEngine::OnCustomDictionaryChanged(
144 const std::vector<std::string>& words_added,
145 const std::vector<std::string>& words_removed) {
123 if (!hunspell_.get()) { 146 if (!hunspell_.get()) {
124 // Save it for later---add it when hunspell is initialized. 147 // Save it for later---add it when hunspell is initialized.
125 custom_words_.push_back(word); 148 custom_words_.insert(custom_words_.end(),
149 words_added.begin(),
150 words_added.end());
151 // Remove words.
152 std::vector<std::string> words_removed_copy(words_removed);
153 std::sort(words_removed_copy.begin(), words_removed_copy.end());
154 std::sort(custom_words_.begin(), custom_words_.end());
155 std::vector<std::string> updated_custom_words;
156 std::set_difference(custom_words_.begin(),
157 custom_words_.end(),
158 words_removed_copy.begin(),
159 words_removed_copy.end(),
160 std::back_inserter(updated_custom_words));
161 std::swap(custom_words_, updated_custom_words);
126 } else { 162 } else {
127 AddWordToHunspell(word); 163 AddWordsToHunspell(words_added);
164 RemoveWordsFromHunspell(words_removed);
128 } 165 }
129 } 166 }
130 167
131 void HunspellEngine::OnWordRemoved(const std::string& word) {
132 if (!hunspell_.get()) {
133 chrome::spellcheck_common::WordList::iterator it = std::find(
134 custom_words_.begin(), custom_words_.end(), word);
135 if (it != custom_words_.end())
136 custom_words_.erase(it);
137 } else {
138 RemoveWordFromHunspell(word);
139 }
140 }
141
142 bool HunspellEngine::InitializeIfNeeded() { 168 bool HunspellEngine::InitializeIfNeeded() {
143 if (!initialized_ && !dictionary_requested_) { 169 if (!initialized_ && !dictionary_requested_) {
144 // RenderThread will not exist in test. 170 // RenderThread will not exist in test.
145 if (RenderThread::Get()) 171 if (RenderThread::Get())
146 RenderThread::Get()->Send(new SpellCheckHostMsg_RequestDictionary); 172 RenderThread::Get()->Send(new SpellCheckHostMsg_RequestDictionary);
147 dictionary_requested_ = true; 173 dictionary_requested_ = true;
148 return true; 174 return true;
149 } 175 }
150 176
151 // Don't initialize if hunspell is disabled. 177 // Don't initialize if hunspell is disabled.
152 if (file_ != base::kInvalidPlatformFileValue) 178 if (file_ != base::kInvalidPlatformFileValue)
153 InitializeHunspell(); 179 InitializeHunspell();
154 180
155 return !initialized_; 181 return !initialized_;
156 } 182 }
157 183
158 bool HunspellEngine::IsEnabled() { 184 bool HunspellEngine::IsEnabled() {
159 return file_ != base::kInvalidPlatformFileValue; 185 return file_ != base::kInvalidPlatformFileValue;
160 } 186 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698