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

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

Issue 10533077: Implement a request cache and disble retrieving a sub-region. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 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 | Annotate | Revision Log
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/renderer/spellchecker/spellcheck_provider.h" 5 #include "chrome/renderer/spellchecker/spellcheck_provider.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "chrome/common/chrome_switches.h" 8 #include "chrome/common/chrome_switches.h"
9 #include "chrome/common/spellcheck_messages.h" 9 #include "chrome/common/spellcheck_messages.h"
10 #include "chrome/common/spellcheck_result.h" 10 #include "chrome/common/spellcheck_result.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 // Text check (unified request for grammar and spell check) is only 96 // Text check (unified request for grammar and spell check) is only
97 // available for browser process, so we ask the system spellchecker 97 // available for browser process, so we ask the system spellchecker
98 // over IPC or return an empty result if the checker is not 98 // over IPC or return an empty result if the checker is not
99 // available. 99 // available.
100 Send(new SpellCheckHostMsg_RequestTextCheck( 100 Send(new SpellCheckHostMsg_RequestTextCheck(
101 routing_id(), 101 routing_id(),
102 text_check_completions_.Add(completion), 102 text_check_completions_.Add(completion),
103 document_tag, 103 document_tag,
104 text)); 104 text));
105 #else 105 #else
106 // Send this text to a browser. A browser checks the user profile and send 106 if (text.isEmpty() || !HasWordCharacters(text, 0)) {
107 // this text to the Spelling service only if a user enables this feature.
108 // TODO(hbono) Implement a cache to avoid sending IPC messages.
109 string16 line;
110 int offset = -1;
111 if (!GetRequestLine(text, &line, &offset)) {
112 completion->didCancelCheckingText(); 107 completion->didCancelCheckingText();
113 return; 108 return;
114 } 109 }
115 110 // Cancel this spellcheck request if the cached text is a substring of the
116 last_line_ = line; 111 // given text and the given text is the middle of a possible word.
112 // TODO(hbono): Move this cache code to a new function and add its unit test.
113 string16 request(text);
114 size_t text_length = request.length();
115 size_t last_length = last_request_.length();
116 if (text_length >= last_length &&
117 !request.compare(0, last_length, last_request_)) {
118 if (text_length == last_length || !HasWordCharacters(text, last_length)) {
119 completion->didCancelCheckingText();
120 return;
121 }
122 int code = 0;
123 int length = static_cast<int>(text_length);
124 U16_PREV(text.data(), 0, length, code);
125 UErrorCode error = U_ZERO_ERROR;
126 if (uscript_getScript(code, &error) != USCRIPT_COMMON) {
127 completion->didCancelCheckingText();
128 return;
129 }
130 }
131 // Create a subset of the cached results and return it if the given text is a
132 // substring of the cached text.
133 if (text_length < last_length &&
134 !last_request_.compare(0, text_length, request)) {
135 size_t result_size = 0;
136 for (size_t i = 0; i < last_results_.size(); ++i) {
137 size_t start = last_results_[i].location;
138 size_t end = start + last_results_[i].length;
139 if (start <= text_length && end <= text_length)
140 ++result_size;
141 }
142 if (result_size > 0) {
143 WebKit::WebVector<WebKit::WebTextCheckingResult> results(result_size);
144 for (size_t i = 0; i < result_size; ++i) {
145 results[i].type = last_results_[i].type;
146 results[i].location = last_results_[i].location;
147 results[i].length = last_results_[i].length;
148 results[i].replacement = last_results_[i].replacement;
149 }
150 completion->didFinishCheckingText(results);
151 return;
152 }
153 }
154 // Send this text to a browser. A browser checks the user profile and send
155 // this text to the Spelling service only if a user enables this feature.
156 last_request_.clear();
157 last_results_.assign(WebKit::WebVector<WebKit::WebTextCheckingResult>());
117 Send(new SpellCheckHostMsg_CallSpellingService( 158 Send(new SpellCheckHostMsg_CallSpellingService(
118 routing_id(), 159 routing_id(),
119 text_check_completions_.Add(completion), 160 text_check_completions_.Add(completion),
120 offset, 161 0,
121 line)); 162 request));
122 #endif // !OS_MACOSX 163 #endif // !OS_MACOSX
123 } 164 }
124 165
125 bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) { 166 bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) {
126 bool handled = true; 167 bool handled = true;
127 IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message) 168 IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message)
128 #if !defined(OS_MACOSX) 169 #if !defined(OS_MACOSX)
129 IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondSpellingService, 170 IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondSpellingService,
130 OnRespondSpellingService) 171 OnRespondSpellingService)
131 #endif 172 #endif
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 // Double-check the returned spellchecking results with our spellchecker to 312 // Double-check the returned spellchecking results with our spellchecker to
272 // visualize the differences between ours and the on-line spellchecker. 313 // visualize the differences between ours and the on-line spellchecker.
273 WebKit::WebVector<WebKit::WebTextCheckingResult> textcheck_results; 314 WebKit::WebVector<WebKit::WebTextCheckingResult> textcheck_results;
274 if (chrome_content_renderer_client_) { 315 if (chrome_content_renderer_client_) {
275 chrome_content_renderer_client_->spellcheck()->CreateTextCheckingResults( 316 chrome_content_renderer_client_->spellcheck()->CreateTextCheckingResults(
276 offset, line, results, &textcheck_results); 317 offset, line, results, &textcheck_results);
277 } else { 318 } else {
278 CreateTextCheckingResults(offset, results, &textcheck_results); 319 CreateTextCheckingResults(offset, results, &textcheck_results);
279 } 320 }
280 completion->didFinishCheckingText(textcheck_results); 321 completion->didFinishCheckingText(textcheck_results);
322
323 // Cache the request and the converted results.
324 last_request_ = line;
325 last_results_.swap(textcheck_results);
281 } 326 }
282 327
283 bool SpellCheckProvider::HasWordCharacters(const string16& text, 328 bool SpellCheckProvider::HasWordCharacters(
284 int index) const { 329 const WebKit::WebString& text,
285 const char16* data = text.c_str(); 330 int index) const {
331 const char16* data = text.data();
286 int length = text.length(); 332 int length = text.length();
287 while (index < length) { 333 while (index < length) {
288 uint32 code = 0; 334 uint32 code = 0;
289 U16_NEXT(data, index, length, code); 335 U16_NEXT(data, index, length, code);
290 UErrorCode err = U_ZERO_ERROR; 336 UErrorCode error = U_ZERO_ERROR;
291 if (uscript_getScript(code, &err) == USCRIPT_LATIN) 337 if (uscript_getScript(code, &error) == USCRIPT_LATIN)
292 return true; 338 return true;
293 } 339 }
294 return false; 340 return false;
295 } 341 }
296
297 bool SpellCheckProvider::GetRequestLine(const string16& text,
298 string16* line,
299 int* offset) const {
300 // WebKit sends the line being edited by a user to this class. (It also sends
301 // the previous line when the user is typing its first word.) We send the line
302 // being edited by a user when the input text satisfies all conditions listed
303 // below.
304 // * There is a non-word character at the end of of the input line so this
305 // class can send a request only when a user finishes typing a word.
306 // * There are word characters in the input line.
307 // * There are word characters in the difference between the input line and
308 // the previously-spellchecked line.
309 if (text.empty())
310 return false;
311 UErrorCode err = U_ZERO_ERROR;
312 if (uscript_getScript(*(text.rbegin()), &err) != USCRIPT_COMMON)
313 return false;
314 size_t input_offset = text.find('\n');
315 string16 input_line;
316 if (input_offset != string16::npos && HasWordCharacters(text, input_offset)) {
317 ++input_offset;
318 *offset = static_cast<int>(input_offset);
319 input_line = text.substr(input_offset);
320 } else {
321 if (!HasWordCharacters(text, 0))
322 return false;
323 *offset = 0;
324 input_line = text;
325 }
326 size_t length = last_line_.length();
327 if (length > 0 && !input_line.compare(0, length, last_line_)) {
328 if (!HasWordCharacters(input_line, static_cast<int>(length)))
329 return false;
330 }
331 line->assign(input_line);
332 return true;
333 }
334 #endif 342 #endif
335 343
336 #if defined(OS_MACOSX) 344 #if defined(OS_MACOSX)
337 void SpellCheckProvider::OnAdvanceToNextMisspelling() { 345 void SpellCheckProvider::OnAdvanceToNextMisspelling() {
338 if (!render_view()->GetWebView()) 346 if (!render_view()->GetWebView())
339 return; 347 return;
340 render_view()->GetWebView()->focusedFrame()->executeCommand( 348 render_view()->GetWebView()->focusedFrame()->executeCommand(
341 WebString::fromUTF8("AdvanceToNextMisspelling")); 349 WebString::fromUTF8("AdvanceToNextMisspelling"));
342 } 350 }
343 351
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 // TODO(darin): There's actually no reason for this to be here. We should 387 // TODO(darin): There's actually no reason for this to be here. We should
380 // have the browser side manage the document tag. 388 // have the browser side manage the document tag.
381 #if defined(OS_MACOSX) 389 #if defined(OS_MACOSX)
382 if (!has_document_tag_) { 390 if (!has_document_tag_) {
383 // Make the call to get the tag. 391 // Make the call to get the tag.
384 Send(new SpellCheckHostMsg_GetDocumentTag(routing_id(), &document_tag_)); 392 Send(new SpellCheckHostMsg_GetDocumentTag(routing_id(), &document_tag_));
385 has_document_tag_ = true; 393 has_document_tag_ = true;
386 } 394 }
387 #endif 395 #endif
388 } 396 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698