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

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 string16 request(text);
Hajime Morrita 2012/06/11 06:53:21 I hope this early-return-with-cache part to be a m
Hironori Bono 2012/06/11 07:24:14 Unfortunately, this code is a temporary workaround
113 size_t text_length = request.length();
114 size_t last_length = last_request_.length();
115 if (text_length >= last_length &&
116 !request.compare(0, last_length, last_request_)) {
117 if (text_length == last_length || !HasWordCharacters(text, last_length)) {
118 completion->didCancelCheckingText();
Hajime Morrita 2012/06/11 06:53:21 This means that there should be no misspelling, ri
Hironori Bono 2012/06/11 07:24:14 This code means we should not change existing mark
119 return;
120 }
121 int code = 0;
122 int length = static_cast<int>(text_length);
123 U16_PREV(text.data(), 0, length, code);
124 UErrorCode error = U_ZERO_ERROR;
125 if (uscript_getScript(code, &error) != USCRIPT_COMMON) {
126 completion->didCancelCheckingText();
127 return;
128 }
129 }
130 // Create a subset of the cached results and return it if the given text is a
131 // substring of the cached text.
132 if (text_length < last_length &&
133 !last_request_.compare(0, text_length, request)) {
134 size_t result_size = 0;
135 for (size_t i = 0; i < last_results_.size(); ++i) {
136 size_t start = last_results_[i].location;
137 size_t end = start + last_results_[i].length;
138 if (start <= text_length && end <= text_length)
139 ++result_size;
140 }
141 if (result_size > 0) {
142 WebKit::WebVector<WebKit::WebTextCheckingResult> results(result_size);
143 for (size_t i = 0; i < result_size; ++i) {
144 results[i].type = last_results_[i].type;
145 results[i].location = last_results_[i].location;
146 results[i].length = last_results_[i].length;
147 results[i].replacement = last_results_[i].replacement;
148 }
149 completion->didFinishCheckingText(results);
150 return;
151 }
152 }
153 // Send this text to a browser. A browser checks the user profile and send
154 // this text to the Spelling service only if a user enables this feature.
155 last_request_.clear();
156 last_results_.assign(WebKit::WebVector<WebKit::WebTextCheckingResult>());
117 Send(new SpellCheckHostMsg_CallSpellingService( 157 Send(new SpellCheckHostMsg_CallSpellingService(
118 routing_id(), 158 routing_id(),
119 text_check_completions_.Add(completion), 159 text_check_completions_.Add(completion),
120 offset, 160 0,
121 line)); 161 request));
122 #endif // !OS_MACOSX 162 #endif // !OS_MACOSX
123 } 163 }
124 164
125 bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) { 165 bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) {
126 bool handled = true; 166 bool handled = true;
127 IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message) 167 IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message)
128 #if !defined(OS_MACOSX) 168 #if !defined(OS_MACOSX)
129 IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondSpellingService, 169 IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondSpellingService,
130 OnRespondSpellingService) 170 OnRespondSpellingService)
131 #endif 171 #endif
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 // Double-check the returned spellchecking results with our spellchecker to 311 // Double-check the returned spellchecking results with our spellchecker to
272 // visualize the differences between ours and the on-line spellchecker. 312 // visualize the differences between ours and the on-line spellchecker.
273 WebKit::WebVector<WebKit::WebTextCheckingResult> textcheck_results; 313 WebKit::WebVector<WebKit::WebTextCheckingResult> textcheck_results;
274 if (chrome_content_renderer_client_) { 314 if (chrome_content_renderer_client_) {
275 chrome_content_renderer_client_->spellcheck()->CreateTextCheckingResults( 315 chrome_content_renderer_client_->spellcheck()->CreateTextCheckingResults(
276 offset, line, results, &textcheck_results); 316 offset, line, results, &textcheck_results);
277 } else { 317 } else {
278 CreateTextCheckingResults(offset, results, &textcheck_results); 318 CreateTextCheckingResults(offset, results, &textcheck_results);
279 } 319 }
280 completion->didFinishCheckingText(textcheck_results); 320 completion->didFinishCheckingText(textcheck_results);
321
322 // Cache the request and the converted results.
323 last_request_ = line;
324 last_results_.swap(textcheck_results);
281 } 325 }
282 326
283 bool SpellCheckProvider::HasWordCharacters(const string16& text, 327 bool SpellCheckProvider::HasWordCharacters(
284 int index) const { 328 const WebKit::WebString& text,
285 const char16* data = text.c_str(); 329 int index) const {
330 const char16* data = text.data();
286 int length = text.length(); 331 int length = text.length();
287 while (index < length) { 332 while (index < length) {
288 uint32 code = 0; 333 uint32 code = 0;
289 U16_NEXT(data, index, length, code); 334 U16_NEXT(data, index, length, code);
290 UErrorCode err = U_ZERO_ERROR; 335 UErrorCode error = U_ZERO_ERROR;
291 if (uscript_getScript(code, &err) == USCRIPT_LATIN) 336 if (uscript_getScript(code, &error) == USCRIPT_LATIN)
292 return true; 337 return true;
293 } 338 }
294 return false; 339 return false;
295 } 340 }
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 341 #endif
335 342
336 #if defined(OS_MACOSX) 343 #if defined(OS_MACOSX)
337 void SpellCheckProvider::OnAdvanceToNextMisspelling() { 344 void SpellCheckProvider::OnAdvanceToNextMisspelling() {
338 if (!render_view()->GetWebView()) 345 if (!render_view()->GetWebView())
339 return; 346 return;
340 render_view()->GetWebView()->focusedFrame()->executeCommand( 347 render_view()->GetWebView()->focusedFrame()->executeCommand(
341 WebString::fromUTF8("AdvanceToNextMisspelling")); 348 WebString::fromUTF8("AdvanceToNextMisspelling"));
342 } 349 }
343 350
(...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 386 // TODO(darin): There's actually no reason for this to be here. We should
380 // have the browser side manage the document tag. 387 // have the browser side manage the document tag.
381 #if defined(OS_MACOSX) 388 #if defined(OS_MACOSX)
382 if (!has_document_tag_) { 389 if (!has_document_tag_) {
383 // Make the call to get the tag. 390 // Make the call to get the tag.
384 Send(new SpellCheckHostMsg_GetDocumentTag(routing_id(), &document_tag_)); 391 Send(new SpellCheckHostMsg_GetDocumentTag(routing_id(), &document_tag_));
385 has_document_tag_ = true; 392 has_document_tag_ = true;
386 } 393 }
387 #endif 394 #endif
388 } 395 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698