diff options
author | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 11:23:35 +0000 |
---|---|---|
committer | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 11:23:35 +0000 |
commit | f2a4351bb986766e774341b411516306d3e96b2b (patch) | |
tree | 1eba2451530187903eb6f97404319bfecfca80ba | |
parent | 6bfad0e644a71f527292ea245f0582d073831de3 (diff) | |
download | chromium_src-f2a4351bb986766e774341b411516306d3e96b2b.zip chromium_src-f2a4351bb986766e774341b411516306d3e96b2b.tar.gz chromium_src-f2a4351bb986766e774341b411516306d3e96b2b.tar.bz2 |
Adds a bubble that asks a user whether to integrate the Spelling service.
This change implements the final UI that integrates the Spelling service into Chrome on Windows to measure actual QPS to the spelling service with Windows Chrome. This UI updatee consists of three parts:
* Add a context-menu item "Ask Google for spelling suggestions";
* Show a bubble when a user chosses the item, and;
* Hide the suggestions from the Spelling service if it is in the suggestion list of the local spellchecker.
BUG=93746
TEST=manual
Review URL: http://codereview.chromium.org/8422006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108096 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/chrome_command_ids.h | 1 | ||||
-rw-r--r-- | chrome/app/generated_resources.grd | 36 | ||||
-rw-r--r-- | chrome/browser/profiles/profile.cc | 4 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_context_menu.cc | 37 | ||||
-rw-r--r-- | chrome/browser/tab_contents/spellchecker_submenu_observer.cc | 41 | ||||
-rw-r--r-- | chrome/browser/tab_contents/spellchecker_submenu_observer.h | 3 | ||||
-rw-r--r-- | chrome/browser/tab_contents/spelling_bubble_model.cc | 50 | ||||
-rw-r--r-- | chrome/browser/tab_contents/spelling_bubble_model.h | 34 | ||||
-rw-r--r-- | chrome/browser/tab_contents/spelling_menu_observer.cc | 121 | ||||
-rw-r--r-- | chrome/browser/tab_contents/spelling_menu_observer.h | 6 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 |
11 files changed, 253 insertions, 82 deletions
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index f00d9c0..19e3929 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h @@ -269,6 +269,7 @@ #define IDC_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY 50154 #define IDC_CONTENT_CONTEXT_NO_SPELLING_SUGGESTIONS 50155 #define IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION 50156 +#define IDC_CONTENT_CONTEXT_SPELLING_TOGGLE 50157 // Frame items. #define IDC_CONTENT_CONTEXT_RELOADFRAME 50160 #define IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE 50161 diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 7108fa2..cbcfba7 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -484,12 +484,24 @@ are declared in build/common.gypi. <message name="IDS_CONTENT_CONTEXT_NO_SPELLING_SUGGESTIONS" desc="The name of the No Spelling Suggestions display in the content area context menu"> &No spelling suggestions </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_ASK_GOOGLE" desc="The context-menu item that asks whether to integrate the spelling service of Google to Chrome. This text is also used as the title of a bubble which confirms it."> + Ask Google for spelling suggestions + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_TEXT" desc="The text of a bubble that confirms users allows integrating the spelling service of Google to Chrome."> + Google Chrome can provide even better spell-checking by sending what you type in the browser to Google servers, allowing you to use the same spell-checking technology used by Google search. + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_ENABLE" desc="The button text that allows integrating the spelling service of Google."> + Enable + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_DISABLE" desc="The button text that disallows integrating the spelling service of Google."> + No thanks + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_STOP_ASKING_GOOGLE" desc="The context-menu item that stops integrating the spelling service."> + Stop asking Google for spelling suggestions + </message> <message name="IDS_CONTENT_CONTEXT_SPELLING_CHECKING" desc="The place-holder message shown while the Spelling service is checking text"> Loading spelling suggestion </message> - <message name="IDS_CONTENT_CONTEXT_SPELLING_CORRECT" desc="The message shown when the selection text is correct."> - No suggestions found - </message> <message name="IDS_CONTENT_CONTEXT_SPELLCHECK_MENU" desc="The name of the Spellcheck Options submenu in the content area context menu"> &Spell-checker options </message> @@ -684,12 +696,24 @@ are declared in build/common.gypi. <message name="IDS_CONTENT_CONTEXT_NO_SPELLING_SUGGESTIONS" desc="In Title Case: The name of the No Spelling Suggestions display in the content area context menu"> &No Spelling Suggestions </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_ASK_GOOGLE" desc="The context-menu item that asks whether to integrate the spelling service of Google to Chrome. This text is also used as the title of a bubble which confirms it."> + Ask Google for spelling suggestions + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_TEXT" desc="The text of a bubble that confirms users allows integrating the spelling service of Google to Chrome."> + Google Chrome can provide even better spell-checking by sending what you type in the browser to Google servers, allowing you to use the same spell-checking technology used by Google search. + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_ENABLE" desc="The button text that allows integrating the spelling service of Google."> + Enable + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_DISABLE" desc="The button text that disallows integrating the spelling service of Google."> + No thanks + </message> + <message name="IDS_CONTENT_CONTEXT_SPELLING_STOP_ASKING_GOOGLE" desc="The context-menu item that stops integrating the spelling service."> + Stop asking Google for spelling suggestions + </message> <message name="IDS_CONTENT_CONTEXT_SPELLING_CHECKING" desc="The place-holder message shown while the Spelling service is checking text"> Loading spelling suggestion </message> - <message name="IDS_CONTENT_CONTEXT_SPELLING_CORRECT" desc="The message shown when the selection text is correct."> - No suggestions found - </message> <message name="IDS_CONTENT_CONTEXT_SPELLCHECK_MENU" desc="In Title Case: The name of the Spellcheck Options submenu in the content area context menu"> &Spell-checker Options </message> diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index f6c93d4..d80ce7e 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc @@ -131,11 +131,7 @@ void Profile::RegisterUserPrefs(PrefService* prefs) { IDS_SPELLCHECK_DICTIONARY, PrefService::UNSYNCABLE_PREF); prefs->RegisterBooleanPref(prefs::kSpellCheckUseSpellingService, -#if defined(GOOGLE_CHROME_BUILD) - true, -#else false, -#endif PrefService::UNSYNCABLE_PREF); prefs->RegisterBooleanPref(prefs::kEnableSpellCheck, true, diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc index a137dea..15880ad 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.cc +++ b/chrome/browser/tab_contents/render_view_context_menu.cc @@ -576,17 +576,14 @@ void RenderViewContextMenu::InitMenu() { if (params_.is_editable) { // Add a menu item that shows suggestions. if (!spelling_menu_observer_.get()) { - spelling_menu_observer_.reset( - new SpellingMenuObserver(this)); + spelling_menu_observer_.reset(new SpellingMenuObserver(this)); } - if (spelling_menu_observer_.get()) + if (spelling_menu_observer_.get()) { observers_.AddObserver(spelling_menu_observer_.get()); + spelling_menu_observer_->InitMenu(params_); + } } - // Ask our observers to add their menu items. - FOR_EACH_OBSERVER(RenderViewContextMenuObserver, observers_, - InitMenu(params_)); - if (params_.is_editable) AppendEditableItems(); else if (has_selection) @@ -838,13 +835,6 @@ void RenderViewContextMenu::AppendSearchProvider() { } void RenderViewContextMenu::AppendEditableItems() { - // Append Dictionary spell check suggestions. - for (size_t i = 0; i < params_.dictionary_suggestions.size() && - IDC_SPELLCHECK_SUGGESTION_0 + i <= IDC_SPELLCHECK_SUGGESTION_LAST; - ++i) { - menu_model_.AddItem(IDC_SPELLCHECK_SUGGESTION_0 + static_cast<int>(i), - params_.dictionary_suggestions[i]); - } if (!params_.dictionary_suggestions.empty()) { menu_model_.AddSeparator(); @@ -1234,11 +1224,6 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { case IDC_CONTENT_CONTEXT_SEARCHWEBFOR: case IDC_CONTENT_CONTEXT_GOTOURL: - case IDC_SPELLCHECK_SUGGESTION_0: - case IDC_SPELLCHECK_SUGGESTION_1: - case IDC_SPELLCHECK_SUGGESTION_2: - case IDC_SPELLCHECK_SUGGESTION_3: - case IDC_SPELLCHECK_SUGGESTION_4: case IDC_SPELLPANEL_TOGGLE: #if !defined(OS_MACOSX) // TODO(jeremy): re-enable - http://crbug.com/34512 . @@ -1689,20 +1674,6 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { break; } - case IDC_SPELLCHECK_SUGGESTION_0: - case IDC_SPELLCHECK_SUGGESTION_1: - case IDC_SPELLCHECK_SUGGESTION_2: - case IDC_SPELLCHECK_SUGGESTION_3: - case IDC_SPELLCHECK_SUGGESTION_4: { - rvh->Replace( - params_.dictionary_suggestions[id - IDC_SPELLCHECK_SUGGESTION_0]); - // GetSpellCheckHost() can return null when the suggested word is - // provided by Web SpellCheck API. - SpellCheckHost* spellcheck_host = profile_->GetSpellCheckHost(); - if (spellcheck_host && spellcheck_host->GetMetrics()) - spellcheck_host->GetMetrics()->RecordReplacedWordStats(1); - break; - } case IDC_SPELLCHECK_ADD_TO_DICTIONARY: { // GetSpellCheckHost() can return null when the suggested word is // provided by Web SpellCheck API. diff --git a/chrome/browser/tab_contents/spellchecker_submenu_observer.cc b/chrome/browser/tab_contents/spellchecker_submenu_observer.cc index d568309..1cecb57 100644 --- a/chrome/browser/tab_contents/spellchecker_submenu_observer.cc +++ b/chrome/browser/tab_contents/spellchecker_submenu_observer.cc @@ -12,9 +12,11 @@ #include "chrome/browser/spellchecker/spellcheck_host.h" #include "chrome/browser/spellchecker/spellchecker_platform_engine.h" #include "chrome/browser/tab_contents/render_view_context_menu.h" +#include "chrome/browser/tab_contents/spelling_bubble_model.h" #include "chrome/common/pref_names.h" #include "chrome/common/spellcheck_messages.h" #include "content/browser/renderer_host/render_view_host.h" +#include "content/browser/renderer_host/render_widget_host_view.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/simple_menu_model.h" @@ -26,6 +28,7 @@ SpellCheckerSubMenuObserver::SpellCheckerSubMenuObserver( : proxy_(proxy), submenu_model_(delegate), spellcheck_enabled_(false), + integrate_spelling_service_(false), language_group_(group), language_selected_(0) { DCHECK(proxy_); @@ -78,6 +81,20 @@ void SpellCheckerSubMenuObserver::InitMenu(const ContextMenuParams& params) { IDS_CONTENT_CONTEXT_SHOW_SPELLING_PANEL)); } +#if defined(OS_WIN) + // If we have not integrated the spelling service, we show an "Ask Google for + // spelling suggestions" item. On the other hand, if we have integrated the + // spelling service, we show "Stop asking Google for spelling suggestions" + // item. + integrate_spelling_service_ = + profile->GetPrefs()->GetBoolean(prefs::kSpellCheckUseSpellingService); + int spelling_message = integrate_spelling_service_ ? + IDS_CONTENT_CONTEXT_SPELLING_STOP_ASKING_GOOGLE : + IDS_CONTENT_CONTEXT_SPELLING_ASK_GOOGLE; + submenu_model_.AddCheckItem(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, + l10n_util::GetStringUTF16(spelling_message)); +#endif + proxy_->AddSubMenu( IDC_SPELLCHECK_MENU, l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLCHECK_MENU), @@ -100,6 +117,7 @@ bool SpellCheckerSubMenuObserver::IsCommandIdSupported(int command_id) { case IDC_CHECK_SPELLING_OF_THIS_FIELD: case IDC_SPELLPANEL_TOGGLE: case IDC_SPELLCHECK_MENU: + case IDC_CONTENT_CONTEXT_SPELLING_TOGGLE: return true; } @@ -143,9 +161,8 @@ bool SpellCheckerSubMenuObserver::IsCommandIdEnabled(int command_id) { return pref->GetBoolean(prefs::kEnableSpellCheck); case IDC_SPELLPANEL_TOGGLE: - return true; - case IDC_SPELLCHECK_MENU: + case IDC_CONTENT_CONTEXT_SPELLING_TOGGLE: return true; } @@ -180,5 +197,25 @@ void SpellCheckerSubMenuObserver::ExecuteCommand(int command_id) { rvh->Send(new SpellCheckMsg_ToggleSpellPanel( rvh->routing_id(), SpellCheckerPlatform::SpellingPanelVisible())); break; + +#if defined(OS_WIN) + case IDC_CONTENT_CONTEXT_SPELLING_TOGGLE: + // When a user chooses the "Ask Google for spelling suggestions" item, we + // show a bubble to confirm it. On the other hand, when a user chooses the + // "Stop asking Google for spelling suggestions" item, we directly update + // the profile and stop integrating the spelling service immediately. + if (!integrate_spelling_service_) { + gfx::Rect bounds = rvh->view()->GetViewBounds(); + bounds.Inset(bounds.width() / 2, 0); + ConfirmBubbleModel::Show(rvh->view()->GetNativeView(), bounds.origin(), + new SpellingBubbleModel(proxy_->GetProfile())); + } else { + Profile* profile = proxy_->GetProfile(); + if (profile) + profile->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, + false); + } + break; +#endif } } diff --git a/chrome/browser/tab_contents/spellchecker_submenu_observer.h b/chrome/browser/tab_contents/spellchecker_submenu_observer.h index c87cce6..9837d68 100644 --- a/chrome/browser/tab_contents/spellchecker_submenu_observer.h +++ b/chrome/browser/tab_contents/spellchecker_submenu_observer.h @@ -44,6 +44,9 @@ class SpellCheckerSubMenuObserver : public RenderViewContextMenuObserver { // Whether spellchecking is enabled in the focused element or not. bool spellcheck_enabled_; + // Whether we integrate the spelling service to Chrome. + bool integrate_spelling_service_; + // The radio items representing languages available for spellchecking. int language_group_; int language_selected_; diff --git a/chrome/browser/tab_contents/spelling_bubble_model.cc b/chrome/browser/tab_contents/spelling_bubble_model.cc new file mode 100644 index 0000000..0646b22 --- /dev/null +++ b/chrome/browser/tab_contents/spelling_bubble_model.cc @@ -0,0 +1,50 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/tab_contents/spelling_bubble_model.h" + +#include "base/logging.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image.h" + +SpellingBubbleModel::SpellingBubbleModel(Profile* profile) + : profile_(profile) { +} + +SpellingBubbleModel::~SpellingBubbleModel() { +} + +string16 SpellingBubbleModel::GetTitle() const { + return l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_ASK_GOOGLE); +} + +string16 SpellingBubbleModel::GetMessageText() const { + return l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_TEXT); +} + +gfx::Image* SpellingBubbleModel::GetIcon() const { + return &ResourceBundle::GetSharedInstance().GetImageNamed( + IDR_PRODUCT_LOGO_16); +} + +string16 SpellingBubbleModel::GetButtonLabel(BubbleButton button) const { + return l10n_util::GetStringUTF16(button == BUTTON_OK ? + IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_ENABLE : + IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_DISABLE); +} + +void SpellingBubbleModel::Accept() { + PrefService* pref = profile_->GetPrefs(); + DCHECK(pref); + pref->SetBoolean(prefs::kSpellCheckUseSpellingService, true); +} + +void SpellingBubbleModel::Cancel() { +} diff --git a/chrome/browser/tab_contents/spelling_bubble_model.h b/chrome/browser/tab_contents/spelling_bubble_model.h new file mode 100644 index 0000000..dd0cf58 --- /dev/null +++ b/chrome/browser/tab_contents/spelling_bubble_model.h @@ -0,0 +1,34 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_TAB_CONTENTS_SPELLING_BUBBLE_MODEL_H_ +#define CHROME_BROWSER_TAB_CONTENTS_SPELLING_BUBBLE_MODEL_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "base/string16.h" +#include "chrome/browser/ui/confirm_bubble_model.h" + +class Profile; + +// A class that implements a bubble menu shown when we confirm a user allows +// integrating the spelling service of Google to Chrome. +class SpellingBubbleModel : public ConfirmBubbleModel { + public: + explicit SpellingBubbleModel(Profile* profile); + virtual ~SpellingBubbleModel(); + + // ConfirmBubbleModel implementation. + virtual string16 GetTitle() const OVERRIDE; + virtual string16 GetMessageText() const OVERRIDE; + virtual gfx::Image* GetIcon() const OVERRIDE; + virtual string16 GetButtonLabel(BubbleButton button) const OVERRIDE; + virtual void Accept() OVERRIDE; + virtual void Cancel() OVERRIDE; + + private: + Profile* profile_; +}; + +#endif // CHROME_BROWSER_TAB_CONTENTS_SPELLING_BUBBLE_MODEL_H_ diff --git a/chrome/browser/tab_contents/spelling_menu_observer.cc b/chrome/browser/tab_contents/spelling_menu_observer.cc index aa68904..3555806 100644 --- a/chrome/browser/tab_contents/spelling_menu_observer.cc +++ b/chrome/browser/tab_contents/spelling_menu_observer.cc @@ -14,6 +14,8 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/spellchecker/spellcheck_host.h" +#include "chrome/browser/spellchecker/spellcheck_host_metrics.h" #include "chrome/browser/tab_contents/render_view_context_menu.h" #include "chrome/common/pref_names.h" #include "content/browser/renderer_host/render_view_host.h" @@ -55,45 +57,87 @@ void SpellingMenuObserver::InitMenu(const ContextMenuParams& params) { if (!profile || !profile->GetRequestContext()) return; - // Retrieve the misspelled word to be sent to the Spelling service. - string16 text = params.misspelled_word; - if (text.empty()) - return; + PrefService* pref = profile->GetPrefs(); + if (pref->GetBoolean(prefs::kEnableSpellCheck) && + pref->GetBoolean(prefs::kSpellCheckUseSpellingService)) { + // Retrieve the misspelled word to be sent to the Spelling service. + string16 text = params.misspelled_word; + if (text.empty()) + return; + + // Initialize variables used in OnURLFetchComplete(). We copy the input text + // to the result text so we can replace its misspelled regions with + // suggestions. + loading_frame_ = 0; + succeeded_ = false; + result_ = text; + + // Add a placeholder item. This item will be updated when we receive a + // response from the Spelling service. (We do not have to disable this item + // now since Chrome will call IsCommandIdEnabled() and disable it.) + loading_message_ = + l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CHECKING); + proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, + loading_message_); + + // Invoke a JSON-RPC call to the Spelling service in the background so we + // can update the placeholder item when we receive its response. It also + // starts the animation timer so we can show animation until we receive it. + const PrefService* pref = profile->GetPrefs(); + std::string language = + pref ? pref->GetString(prefs::kSpellCheckDictionary) : "en-US"; + Invoke(text, language, profile->GetRequestContext()); + } - // Initialize variables used in OnURLFetchComplete(). We copy the input text - // to the result text so we can replace its misspelled regions with - // suggestions. - loading_frame_ = 0; - succeeded_ = false; - result_ = text; - - // Add a placeholder item. This item will be updated when we receive a - // response from the Spelling service. (We do not have to disable this item - // now since Chrome will call IsCommandIdEnabled() and disable it.) - loading_message_ = - l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CHECKING); - proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, - loading_message_); - - // Invoke a JSON-RPC call to the Spelling service in the background so we can - // update the placeholder item when we receive its response. It also starts - // the animation timer so we can show animation until we receive it. - const PrefService* pref = profile->GetPrefs(); - std::string language = - pref ? pref->GetString(prefs::kSpellCheckDictionary) : "en-US"; - Invoke(text, language, profile->GetRequestContext()); + // Append Dictionary spell check suggestions. + suggestions_ = params.dictionary_suggestions; + for (size_t i = 0; i < params.dictionary_suggestions.size() && + IDC_SPELLCHECK_SUGGESTION_0 + i <= IDC_SPELLCHECK_SUGGESTION_LAST; + ++i) { + proxy_->AddMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + static_cast<int>(i), + params.dictionary_suggestions[i]); + } } bool SpellingMenuObserver::IsCommandIdSupported(int command_id) { + if (command_id >= IDC_SPELLCHECK_SUGGESTION_0 && + command_id <= IDC_SPELLCHECK_SUGGESTION_4) + return true; + return command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION; } bool SpellingMenuObserver::IsCommandIdEnabled(int command_id) { - return command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION && succeeded_; + DCHECK(IsCommandIdSupported(command_id)); + + if (command_id >= IDC_SPELLCHECK_SUGGESTION_0 && + command_id <= IDC_SPELLCHECK_SUGGESTION_4) + return true; + + if (command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION) + return succeeded_; + return false; } void SpellingMenuObserver::ExecuteCommand(int command_id) { - if (IsCommandIdEnabled(command_id)) + DCHECK(IsCommandIdSupported(command_id)); + + if (command_id >= IDC_SPELLCHECK_SUGGESTION_0 && + command_id <= IDC_SPELLCHECK_SUGGESTION_4) { + proxy_->GetRenderViewHost()->Replace( + suggestions_[command_id - IDC_SPELLCHECK_SUGGESTION_0]); + // GetSpellCheckHost() can return null when the suggested word is + // provided by Web SpellCheck API. + Profile* profile = proxy_->GetProfile(); + if (profile) { + SpellCheckHost* spellcheck_host = profile->GetSpellCheckHost(); + if (spellcheck_host && spellcheck_host->GetMetrics()) + spellcheck_host->GetMetrics()->RecordReplacedWordStats(1); + } + return; + } + + if (command_id == IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION) proxy_->GetRenderViewHost()->Replace(result_); } @@ -163,16 +207,11 @@ void SpellingMenuObserver::OnURLFetchComplete( std::string data; source->GetResponseAsString(&data); succeeded_ = ParseResponse(source->GetResponseCode(), data); - if (!succeeded_) - result_ = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CORRECT); - - // Update the menu item with the result text. We enable this item only when - // the request text has misspelled words. (We disable this item not only when - // we receive a server error but also when the input text consists only of - // well-spelled words. For either case, we do not need to replace the input - // text.) + + // Update the menu item with the result text. We disable this item and hide it + // when the spelling service does not provide valid suggestions. proxy_->UpdateMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, succeeded_, - false, result_); + !succeeded_, result_); } bool SpellingMenuObserver::ParseResponse(int response, @@ -255,6 +294,14 @@ bool SpellingMenuObserver::ParseResponse(int response, result_.replace(start, length, text); } + // If the above result text is included in the suggestion list provided by the + // local spellchecker, we return false to hide this item. + for (std::vector<string16>::const_iterator it = suggestions_.begin(); + it != suggestions_.end(); ++it) { + if (result_ == *it) + return false; + } + return true; } diff --git a/chrome/browser/tab_contents/spelling_menu_observer.h b/chrome/browser/tab_contents/spelling_menu_observer.h index cb49917..76faa28 100644 --- a/chrome/browser/tab_contents/spelling_menu_observer.h +++ b/chrome/browser/tab_contents/spelling_menu_observer.h @@ -7,6 +7,7 @@ #pragma once #include <string> +#include <vector> #include "base/memory/scoped_ptr.h" #include "base/string16.h" @@ -74,6 +75,11 @@ class SpellingMenuObserver : public RenderViewContextMenuObserver, // this interface to avoid accesing context-menu items directly. RenderViewContextMenuProxy* proxy_; + // Suggested words from the local spellchecker. If the spelling service + // returns a word in this list, we hide the context-menu item to prevent + // showing the same word twice. + std::vector<string16> suggestions_; + // The string used for animation until we receive a response from the Spelling // service. The current animation just adds periods at the end of this string: // 'Loading' -> 'Loading.' -> 'Loading..' -> 'Loading...' (-> 'Loading') diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 6449db7..fc6a23e 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2332,6 +2332,8 @@ 'browser/tab_contents/thumbnail_generator.h', 'browser/tab_contents/spellchecker_submenu_observer.cc', 'browser/tab_contents/spellchecker_submenu_observer.h', + 'browser/tab_contents/spelling_bubble_model.cc', + 'browser/tab_contents/spelling_bubble_model.h', 'browser/tab_contents/spelling_menu_observer.cc', 'browser/tab_contents/spelling_menu_observer.h', 'browser/tab_contents/web_drag_bookmark_handler_gtk.cc', |