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

Side by Side Diff: chrome/browser/tab_contents/spelling_menu_observer.cc

Issue 8422006: Adds a bubble that asks a user whether to integrate the Spelling service. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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
« no previous file with comments | « chrome/browser/tab_contents/spelling_menu_observer.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/tab_contents/spelling_menu_observer.h" 5 #include "chrome/browser/tab_contents/spelling_menu_observer.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/json/string_escape.h" 10 #include "base/json/string_escape.h"
11 #include "base/stringprintf.h" 11 #include "base/stringprintf.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/app/chrome_command_ids.h" 14 #include "chrome/app/chrome_command_ids.h"
15 #include "chrome/browser/prefs/pref_service.h" 15 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/spellchecker/spellcheck_host.h"
18 #include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
17 #include "chrome/browser/tab_contents/render_view_context_menu.h" 19 #include "chrome/browser/tab_contents/render_view_context_menu.h"
18 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
19 #include "content/browser/renderer_host/render_view_host.h" 21 #include "content/browser/renderer_host/render_view_host.h"
20 #include "content/public/common/url_fetcher.h" 22 #include "content/public/common/url_fetcher.h"
21 #include "googleurl/src/gurl.h" 23 #include "googleurl/src/gurl.h"
22 #include "grit/generated_resources.h" 24 #include "grit/generated_resources.h"
23 #include "ui/base/l10n/l10n_util.h" 25 #include "ui/base/l10n/l10n_util.h"
24 #include "unicode/uloc.h" 26 #include "unicode/uloc.h"
25 #include "webkit/glue/context_menu.h" 27 #include "webkit/glue/context_menu.h"
26 28
(...skipping 21 matching lines...) Expand all
48 50
49 // Exit if we are not in an editable element because we add a menu item only 51 // Exit if we are not in an editable element because we add a menu item only
50 // for editable elements. 52 // for editable elements.
51 if (!params.is_editable) 53 if (!params.is_editable)
52 return; 54 return;
53 55
54 Profile* profile = proxy_->GetProfile(); 56 Profile* profile = proxy_->GetProfile();
55 if (!profile || !profile->GetRequestContext()) 57 if (!profile || !profile->GetRequestContext())
56 return; 58 return;
57 59
58 // Retrieve the misspelled word to be sent to the Spelling service. 60 PrefService* pref = profile->GetPrefs();
59 string16 text = params.misspelled_word; 61 if (pref->GetBoolean(prefs::kEnableSpellCheck) &&
60 if (text.empty()) 62 pref->GetBoolean(prefs::kSpellCheckUseSpellingService)) {
61 return; 63 // Retrieve the misspelled word to be sent to the Spelling service.
64 string16 text = params.misspelled_word;
65 if (text.empty())
66 return;
62 67
63 // Initialize variables used in OnURLFetchComplete(). We copy the input text 68 // Initialize variables used in OnURLFetchComplete(). We copy the input text
64 // to the result text so we can replace its misspelled regions with 69 // to the result text so we can replace its misspelled regions with
65 // suggestions. 70 // suggestions.
66 loading_frame_ = 0; 71 loading_frame_ = 0;
67 succeeded_ = false; 72 succeeded_ = false;
68 result_ = text; 73 result_ = text;
69 74
70 // Add a placeholder item. This item will be updated when we receive a 75 // Add a placeholder item. This item will be updated when we receive a
71 // response from the Spelling service. (We do not have to disable this item 76 // response from the Spelling service. (We do not have to disable this item
72 // now since Chrome will call IsCommandIdEnabled() and disable it.) 77 // now since Chrome will call IsCommandIdEnabled() and disable it.)
73 loading_message_ = 78 loading_message_ =
74 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CHECKING); 79 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CHECKING);
75 proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, 80 proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION,
76 loading_message_); 81 loading_message_);
77 82
78 // Invoke a JSON-RPC call to the Spelling service in the background so we can 83 // Invoke a JSON-RPC call to the Spelling service in the background so we
79 // update the placeholder item when we receive its response. It also starts 84 // can update the placeholder item when we receive its response. It also
80 // the animation timer so we can show animation until we receive it. 85 // starts the animation timer so we can show animation until we receive it.
81 const PrefService* pref = profile->GetPrefs(); 86 const PrefService* pref = profile->GetPrefs();
82 std::string language = 87 std::string language =
83 pref ? pref->GetString(prefs::kSpellCheckDictionary) : "en-US"; 88 pref ? pref->GetString(prefs::kSpellCheckDictionary) : "en-US";
84 Invoke(text, language, profile->GetRequestContext()); 89 Invoke(text, language, profile->GetRequestContext());
90 }
91
92 // Append Dictionary spell check suggestions.
93 suggestions_ = params.dictionary_suggestions;
94 for (size_t i = 0; i < params.dictionary_suggestions.size() &&
95 IDC_SPELLCHECK_SUGGESTION_0 + i <= IDC_SPELLCHECK_SUGGESTION_LAST;
96 ++i) {
97 proxy_->AddMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + static_cast<int>(i),
98 params.dictionary_suggestions[i]);
99 }
85 } 100 }
86 101
87 bool SpellingMenuObserver::IsCommandIdSupported(int command_id) { 102 bool SpellingMenuObserver::IsCommandIdSupported(int command_id) {
103 if (command_id >= IDC_SPELLCHECK_SUGGESTION_0 &&
104 command_id <= IDC_SPELLCHECK_SUGGESTION_4)
105 return true;
106
88 return command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION; 107 return command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION;
89 } 108 }
90 109
91 bool SpellingMenuObserver::IsCommandIdEnabled(int command_id) { 110 bool SpellingMenuObserver::IsCommandIdEnabled(int command_id) {
92 return command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION && succeeded_; 111 DCHECK(IsCommandIdSupported(command_id));
112
113 if (command_id >= IDC_SPELLCHECK_SUGGESTION_0 &&
114 command_id <= IDC_SPELLCHECK_SUGGESTION_4)
115 return true;
116
117 if (command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION)
118 return succeeded_;
119 return false;
93 } 120 }
94 121
95 void SpellingMenuObserver::ExecuteCommand(int command_id) { 122 void SpellingMenuObserver::ExecuteCommand(int command_id) {
96 if (IsCommandIdEnabled(command_id)) 123 DCHECK(IsCommandIdSupported(command_id));
124
125 if (command_id >= IDC_SPELLCHECK_SUGGESTION_0 &&
126 command_id <= IDC_SPELLCHECK_SUGGESTION_4) {
127 proxy_->GetRenderViewHost()->Replace(
128 suggestions_[command_id - IDC_SPELLCHECK_SUGGESTION_0]);
129 // GetSpellCheckHost() can return null when the suggested word is
130 // provided by Web SpellCheck API.
131 Profile* profile = proxy_->GetProfile();
132 if (profile) {
133 SpellCheckHost* spellcheck_host = profile->GetSpellCheckHost();
134 if (spellcheck_host && spellcheck_host->GetMetrics())
135 spellcheck_host->GetMetrics()->RecordReplacedWordStats(1);
136 }
137 return;
138 }
139
140 if (command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION)
97 proxy_->GetRenderViewHost()->Replace(result_); 141 proxy_->GetRenderViewHost()->Replace(result_);
98 } 142 }
99 143
100 bool SpellingMenuObserver::Invoke(const string16& text, 144 bool SpellingMenuObserver::Invoke(const string16& text,
101 const std::string& locale, 145 const std::string& locale,
102 net::URLRequestContextGetter* context) { 146 net::URLRequestContextGetter* context) {
103 // Create the parameters needed by Spelling API. Spelling API needs three 147 // Create the parameters needed by Spelling API. Spelling API needs three
104 // parameters: ISO language code, ISO3 country code, and text to be checked by 148 // parameters: ISO language code, ISO3 country code, and text to be checked by
105 // the service. On the other hand, Chrome uses an ISO locale ID and it may 149 // the service. On the other hand, Chrome uses an ISO locale ID and it may
106 // not include a country ID, e.g. "fr", "de", etc. To create the input 150 // not include a country ID, e.g. "fr", "de", etc. To create the input
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157 201
158 scoped_ptr<content::URLFetcher> clean_up_fetcher(fetcher_.release()); 202 scoped_ptr<content::URLFetcher> clean_up_fetcher(fetcher_.release());
159 animation_timer_.Stop(); 203 animation_timer_.Stop();
160 204
161 // Parse the response JSON and replace misspelled words in the |result_| text 205 // Parse the response JSON and replace misspelled words in the |result_| text
162 // with their suggestions. 206 // with their suggestions.
163 std::string data; 207 std::string data;
164 source->GetResponseAsString(&data); 208 source->GetResponseAsString(&data);
165 succeeded_ = ParseResponse(source->GetResponseCode(), data); 209 succeeded_ = ParseResponse(source->GetResponseCode(), data);
166 if (!succeeded_)
167 result_ = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CORRECT);
168 210
169 // Update the menu item with the result text. We enable this item only when 211 // Update the menu item with the result text. We disable this item and hide it
170 // the request text has misspelled words. (We disable this item not only when 212 // when the spelling service does not provide valid suggestions.
171 // we receive a server error but also when the input text consists only of
172 // well-spelled words. For either case, we do not need to replace the input
173 // text.)
174 proxy_->UpdateMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, succeeded_, 213 proxy_->UpdateMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, succeeded_,
175 false, result_); 214 !succeeded_, result_);
176 } 215 }
177 216
178 bool SpellingMenuObserver::ParseResponse(int response, 217 bool SpellingMenuObserver::ParseResponse(int response,
179 const std::string& data) { 218 const std::string& data) {
180 // When this JSON-RPC call finishes successfully, the Spelling service returns 219 // When this JSON-RPC call finishes successfully, the Spelling service returns
181 // an JSON object listed below. 220 // an JSON object listed below.
182 // * result - an envelope object representing the result from the APIARY 221 // * result - an envelope object representing the result from the APIARY
183 // server, which is the JSON-API front-end for the Spelling service. This 222 // server, which is the JSON-API front-end for the Spelling service. This
184 // object consists of the following variable: 223 // object consists of the following variable:
185 // - spellingCheckResponse (SpellingCheckResponse). 224 // - spellingCheckResponse (SpellingCheckResponse).
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 // alternative. 287 // alternative.
249 DictionaryValue* suggestion = NULL; 288 DictionaryValue* suggestion = NULL;
250 string16 text; 289 string16 text;
251 if (!suggestions->GetDictionary(0, &suggestion) || 290 if (!suggestions->GetDictionary(0, &suggestion) ||
252 !suggestion->GetString("suggestion", &text)) { 291 !suggestion->GetString("suggestion", &text)) {
253 return false; 292 return false;
254 } 293 }
255 result_.replace(start, length, text); 294 result_.replace(start, length, text);
256 } 295 }
257 296
297 // If the above result text is included in the suggestion list provided by the
298 // local spellchecker, we return false to hide this item.
299 for (std::vector<string16>::const_iterator it = suggestions_.begin();
300 it != suggestions_.end(); ++it) {
301 if (result_ == *it)
302 return false;
303 }
304
258 return true; 305 return true;
259 } 306 }
260 307
261 void SpellingMenuObserver::OnAnimationTimerExpired() { 308 void SpellingMenuObserver::OnAnimationTimerExpired() {
262 if (!fetcher_.get()) 309 if (!fetcher_.get())
263 return; 310 return;
264 311
265 // Append '.' characters to the end of "Checking". 312 // Append '.' characters to the end of "Checking".
266 loading_frame_ = (loading_frame_ + 1) & 3; 313 loading_frame_ = (loading_frame_ + 1) & 3;
267 string16 loading_message = loading_message_; 314 string16 loading_message = loading_message_;
268 for (int i = 0; i < loading_frame_; ++i) 315 for (int i = 0; i < loading_frame_; ++i)
269 loading_message.push_back('.'); 316 loading_message.push_back('.');
270 317
271 // Update the menu item with the text. We disable this item to prevent users 318 // Update the menu item with the text. We disable this item to prevent users
272 // from selecting it. 319 // from selecting it.
273 proxy_->UpdateMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, false, false, 320 proxy_->UpdateMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, false, false,
274 loading_message); 321 loading_message);
275 } 322 }
OLDNEW
« no previous file with comments | « chrome/browser/tab_contents/spelling_menu_observer.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698