summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-09 21:16:05 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-09 21:16:05 +0000
commit98324891649cf5fa7430c2e231ad5493fdb76c8e (patch)
tree4c48f7d44d002691e717526bdb2d7870296b10df
parent1edc999cee504ed756ee798dfb1bfd95f53b4262 (diff)
downloadchromium_src-98324891649cf5fa7430c2e231ad5493fdb76c8e.zip
chromium_src-98324891649cf5fa7430c2e231ad5493fdb76c8e.tar.gz
chromium_src-98324891649cf5fa7430c2e231ad5493fdb76c8e.tar.bz2
Adds support for the os x spelling panel to chromium. Users can
now access it from the main menu and context menu and use it to perform spelling tasks. For more detail, see http://code.google.com/p/chromium/wiki/SpellingPanelPlanningDoc Patch from pwicks86@gmail.com (Paul Wicks). BUG=None TEST=The spelling panel should work in os x. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25786 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/chrome_dll_resource.h1
-rw-r--r--chrome/app/generated_resources.grd6
-rw-r--r--chrome/browser/cocoa/rwhvm_editcommand_helper.mm1
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc4
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc12
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h9
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h2
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm53
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc36
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h8
-rw-r--r--chrome/browser/spellcheck_unittest.cc99
-rw-r--r--chrome/browser/spellchecker.cc17
-rw-r--r--chrome/browser/spellchecker.h9
-rw-r--r--chrome/browser/spellchecker_linux.cc29
-rw-r--r--chrome/browser/spellchecker_mac.mm57
-rw-r--r--chrome/browser/spellchecker_platform_engine.h26
-rw-r--r--chrome/browser/spellchecker_win.cc29
-rw-r--r--chrome/browser/tab_contents/render_view_context_menu.cc14
-rw-r--r--chrome/common/render_messages_internal.h30
-rw-r--r--chrome/renderer/render_view.cc60
-rw-r--r--chrome/renderer/render_view.h16
-rw-r--r--webkit/glue/editor_client_impl.cc32
-rw-r--r--webkit/glue/webframe_impl.cc6
-rw-r--r--webkit/glue/webview.h3
-rw-r--r--webkit/glue/webview_delegate.h15
-rw-r--r--webkit/glue/webview_impl.cc8
-rw-r--r--webkit/glue/webview_impl.h6
28 files changed, 509 insertions, 80 deletions
diff --git a/chrome/app/chrome_dll_resource.h b/chrome/app/chrome_dll_resource.h
index 932ab01..769e4cc 100644
--- a/chrome/app/chrome_dll_resource.h
+++ b/chrome/app/chrome_dll_resource.h
@@ -192,6 +192,7 @@
#define IDC_SPELLCHECK_LANGUAGES_LAST 41106
#define IDC_CHECK_SPELLING_OF_THIS_FIELD 41107
#define IDC_SYNC_BOOKMARKS 41108
+#define IDC_SPELLPANEL_TOGGLE 41109
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8adef54..6537f04 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -467,6 +467,12 @@ each locale. aa1 -->
<message name="IDS_CONTENT_CONTEXT_CHECK_SPELLING_OF_THIS_FIELD" desc="The name of the Check the spelling of this field command in the content area context menu">
&amp;Check the spelling of this field
</message>
+ <message name="IDS_CONTENT_CONTEXT_SHOW_SPELLING_PANEL" desc="The name of the Show Spelling Panel command in the content area context menu">
+ &amp;Show Spelling Panel
+ </message>
+ <message name="IDS_CONTENT_CONTEXT_HIDE_SPELLING_PANEL" desc="The name of the Hide Spelling Panel command in the content area context menu">
+ &amp;Hide Spelling Panel
+ </message>
<message name="IDS_CONTENT_CONTEXT_SELECTALL" desc="The name of the Select All command in the content area context menu">
Select &amp;all
</message>
diff --git a/chrome/browser/cocoa/rwhvm_editcommand_helper.mm b/chrome/browser/cocoa/rwhvm_editcommand_helper.mm
index 87956b0..c4b1efd 100644
--- a/chrome/browser/cocoa/rwhvm_editcommand_helper.mm
+++ b/chrome/browser/cocoa/rwhvm_editcommand_helper.mm
@@ -95,6 +95,7 @@ const char* kEditCommands[] = {
"selectToMark",
"selectWord",
"setMark",
+ "showGuessPanel",
"subscript",
"superscript",
"swapWithMark",
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 9085996..64fc364 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -558,6 +558,10 @@ void RenderViewHost::SelectAll() {
Send(new ViewMsg_SelectAll(routing_id()));
}
+void RenderViewHost::ToggleSpellPanel(bool is_currently_visible) {
+ Send(new ViewMsg_ToggleSpellPanel(routing_id(), is_currently_visible));
+}
+
int RenderViewHost::DownloadFavIcon(const GURL& url, int image_size) {
if (!url.is_valid()) {
NOTREACHED();
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 81637aa..28cadfe 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -275,6 +275,7 @@ class RenderViewHost : public RenderWidgetHost,
void AddToDictionary(const std::wstring& word);
void Delete();
void SelectAll();
+ void ToggleSpellPanel(bool is_currently_visible);
// Downloads an image notifying the FavIcon delegate appropriately. The
// returned integer uniquely identifies the download for the lifetime of the
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index e28b006..473f129 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -877,3 +877,15 @@ void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap,
backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect,
dx, dy, clip_rect, view_size);
}
+
+void RenderWidgetHost::ToggleSpellPanel(bool is_currently_visible) {
+ Send(new ViewMsg_ToggleSpellPanel(routing_id(), is_currently_visible));
+}
+
+void RenderWidgetHost::ReplaceWord(const std::wstring& word) {
+ Send(new ViewMsg_Replace(routing_id_, word));
+}
+
+void RenderWidgetHost::AdvanceToNextMisspelling() {
+ Send(new ViewMsg_AdvanceToNextMisspelling(routing_id_));
+}
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index b06bce3..90e0b9c 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -328,6 +328,15 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// And to also expose it to the RenderWidgetHostView.
virtual gfx::Rect GetRootWindowResizerRect() const;
+ // Makes an IPC call to toggle the spelling panel.
+ void ToggleSpellPanel(bool is_currently_visible);
+
+ // Makes an IPC call to tell webkit to replace the currently selected word.
+ void ReplaceWord(const std::wstring& word);
+
+ // Makes an IPC call to tell webkit to advance to the next misspelling.
+ void AdvanceToNextMisspelling();
+
// Sets the active state (i.e., control tints).
virtual void SetActive(bool active);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index 1633a52..b8f4146 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -30,7 +30,7 @@ class RWHVMEditCommandHelper;
// when it's removed from the view system.
@interface RenderWidgetHostViewCocoa
- : BaseView <RenderWidgetHostViewMacOwner, NSTextInput> {
+ : BaseView <RenderWidgetHostViewMacOwner, NSTextInput, NSChangeSpelling> {
@private
RenderWidgetHostViewMac* renderWidgetHostView_;
BOOL canBeKeyView_;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index fef480b..3587616 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -12,6 +12,7 @@
#include "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "skia/ext/platform_canvas.h"
#include "webkit/api/public/mac/WebInputEventFactory.h"
@@ -690,6 +691,58 @@ void RenderWidgetHostViewMac::SetActive(bool active) {
return ([event type] == NSKeyDown) ? YES : NO;
}
+// Spellchecking methods
+// The next three methods are implemented here since this class is the first
+// responder for anything in the browser.
+
+// This message is sent whenever the user specifies that a word should be
+// changed from the spellChecker.
+- (void)changeSpelling:(id)sender {
+ // Grab the currently selected word from the spell panel, as this is the word
+ // that we want to replace the selected word in the text with.
+ NSString* newWord = [[sender selectedCell] stringValue];
+ if (newWord != nil) {
+ RenderWidgetHostViewMac* thisHostView = [self renderWidgetHostViewMac];
+ thisHostView->GetRenderWidgetHost()->ReplaceWord(
+ base::SysNSStringToWide(newWord));
+ }
+}
+
+// This message is sent by NSSpellChecker whenever the next word should be
+// advanced to, either after a correction or clicking the "Find Next" button.
+// This isn't documented anywhere useful, like in NSSpellProtocol.h with the
+// other spelling panel methods. This is probably because Apple assumes that the
+// the spelling panel will be used with an NSText, which will automatically
+// catch this and advance to the next word for you. Thanks Apple.
+- (void)checkSpelling:(id)sender {
+ RenderWidgetHostViewMac* thisHostView = [self renderWidgetHostViewMac];
+ thisHostView->GetRenderWidgetHost()->AdvanceToNextMisspelling();
+}
+
+// This message is sent by the spelling panel whenever a word is ignored.
+- (void)ignoreSpelling:(id)sender {
+ // Ideally, we would ask the current RenderView for its tag, but that would
+ // mean making a blocking IPC call from the browser. Instead,
+ // SpellCheckerPlatform::CheckSpelling remembers the last tag and
+ // SpellCheckerPlatform::IgnoreWord assumes that is the correct tag.
+ NSString* wordToIgnore = [sender stringValue];
+ if (wordToIgnore != nil) {
+ SpellCheckerPlatform::IgnoreWord(base::SysNSStringToUTF8(wordToIgnore));
+
+ // Strangely, the spellingPanel doesn't send checkSpelling after a word is
+ // ignored, so we have to explicitly call AdvanceToNextMisspelling here.
+ RenderWidgetHostViewMac* thisHostView = [self renderWidgetHostViewMac];
+ thisHostView->GetRenderWidgetHost()->AdvanceToNextMisspelling();
+ }
+}
+
+- (void)showGuessPanel:(id)sender {
+ RenderWidgetHostViewMac* thisHostView = [self renderWidgetHostViewMac];
+ thisHostView->GetRenderWidgetHost()->ToggleSpellPanel(
+ SpellCheckerPlatform::SpellingPanelVisible());
+}
+
+// END Spellchecking methods
// Below is the nasty tooltip stuff -- copied from WebKit's WebHTMLView.mm
// with minor modifications for code style and commenting.
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 5a21f34..1190fd3 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -27,6 +27,7 @@
#include "chrome/browser/renderer_host/file_system_accessor.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/browser/spellchecker.h"
+#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/browser/worker_host/message_port_dispatcher.h"
#include "chrome/browser/worker_host/worker_service.h"
#include "chrome/common/appcache/appcache_dispatcher_host.h"
@@ -296,8 +297,15 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker,
OnForwardToWorker)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SpellCheck, OnSpellCheck)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDocumentTag,
+ OnGetDocumentTag)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentWithTagClosed,
+ OnDocumentWithTagClosed)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetAutoCorrectWord,
OnGetAutoCorrectWord)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowSpellingPanel, OnShowSpellingPanel)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateSpellingPanelWithMisspelledWord,
+ OnUpdateSpellingPanelWithMisspelledWord)
IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch)
IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms,
OnRendererHistograms)
@@ -376,7 +384,7 @@ void ResourceMessageFilter::OnReceiveContextMenuMsg(const IPC::Message& msg) {
int misspell_location, misspell_length;
bool is_misspelled = !spellchecker_->SpellCheckWord(
params.misspelled_word.c_str(),
- static_cast<int>(params.misspelled_word.length()),
+ static_cast<int>(params.misspelled_word.length()), 0,
&misspell_location, &misspell_length,
&params.dictionary_suggestions);
@@ -870,14 +878,14 @@ Clipboard* ResourceMessageFilter::GetClipboard() {
// spellings are correct.
//
// Note: This is called in the IO thread.
-void ResourceMessageFilter::OnSpellCheck(const std::wstring& word,
+void ResourceMessageFilter::OnSpellCheck(const std::wstring& word, int tag,
IPC::Message* reply_msg) {
int misspell_location = 0;
int misspell_length = 0;
if (spellchecker_ != NULL) {
spellchecker_->SpellCheckWord(word.c_str(),
- static_cast<int>(word.length()),
+ static_cast<int>(word.length()), tag,
&misspell_location, &misspell_length, NULL);
}
@@ -887,12 +895,23 @@ void ResourceMessageFilter::OnSpellCheck(const std::wstring& word,
return;
}
+void ResourceMessageFilter::OnGetDocumentTag(IPC::Message* reply_msg) {
+ int tag = SpellCheckerPlatform::GetDocumentTag();
+ ViewHostMsg_GetDocumentTag::WriteReplyParams(reply_msg, tag);
+ Send(reply_msg);
+ return;
+}
+
+void ResourceMessageFilter::OnDocumentWithTagClosed(int tag) {
+ SpellCheckerPlatform::CloseDocumentWithTag(tag);
+}
void ResourceMessageFilter::OnGetAutoCorrectWord(const std::wstring& word,
+ int tag,
IPC::Message* reply_msg) {
std::wstring autocorrect_word;
if (spellchecker_ != NULL) {
- spellchecker_->GetAutoCorrectionWord(word, &autocorrect_word);
+ spellchecker_->GetAutoCorrectionWord(word, tag, &autocorrect_word);
}
ViewHostMsg_GetAutoCorrectWord::WriteReplyParams(reply_msg,
@@ -901,6 +920,15 @@ void ResourceMessageFilter::OnGetAutoCorrectWord(const std::wstring& word,
return;
}
+void ResourceMessageFilter::OnShowSpellingPanel(bool show) {
+ SpellCheckerPlatform::ShowSpellingPanel(show);
+}
+
+void ResourceMessageFilter::OnUpdateSpellingPanelWithMisspelledWord(
+ const std::wstring& word) {
+ SpellCheckerPlatform::UpdateSpellingPanelWithMisspelledWord(word);
+}
+
void ResourceMessageFilter::Observe(NotificationType type,
const NotificationSource &source,
const NotificationDetails &details) {
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 4c467c6..743b7f6 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -159,10 +159,14 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnDownloadUrl(const IPC::Message& message,
const GURL& url,
const GURL& referrer);
- void OnSpellCheck(const std::wstring& word,
+ void OnSpellCheck(const std::wstring& word, int tag,
IPC::Message* reply_msg);
- void OnGetAutoCorrectWord(const std::wstring& word,
+ void OnGetDocumentTag(IPC::Message* reply_msg);
+ void OnDocumentWithTagClosed(int tag);
+ void OnGetAutoCorrectWord(const std::wstring& word, int tag,
IPC::Message* reply_msg);
+ void OnShowSpellingPanel(bool show);
+ void OnUpdateSpellingPanelWithMisspelledWord(const std::wstring& word);
void OnDnsPrefetch(const std::vector<std::string>& hostnames);
void OnRendererHistograms(int sequence_number,
const std::vector<std::string>& histogram_info);
diff --git a/chrome/browser/spellcheck_unittest.cc b/chrome/browser/spellcheck_unittest.cc
index 8d97e9e..8c048b2 100644
--- a/chrome/browser/spellcheck_unittest.cc
+++ b/chrome/browser/spellcheck_unittest.cc
@@ -7,7 +7,9 @@
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
+#include "base/sys_string_conversions.h"
#include "chrome/browser/spellchecker.h"
+#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/common/chrome_paths.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -280,6 +282,7 @@ TEST_F(SpellCheckTest, SpellCheckStrings_EN_US) {
int misspelling_length;
bool result = spell_checker->SpellCheckWord(kTestCases[i].input,
static_cast<int>(input_length),
+ 0,
&misspelling_start,
&misspelling_length, NULL);
@@ -377,9 +380,7 @@ TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) {
{L"compitition", false, 0,0,L"competition"},
{L"conceed", false, 0,0,L"concede"},
{L"congradulate", false, 0,0,L"congratulate"},
- // TODO(pwicks): This fails as a result of 13432.
- // Once that is fixed, uncomment this.
- // {L"consciencious", false, 0,0,L"conscientious"},
+ {L"consciencious", false, 0, 0, L"conscientious"},
{L"concious", false, 0,0,L"conscious"},
{L"concensus", false, 0,0,L"consensus"},
{L"contraversy", false, 0,0,L"controversy"},
@@ -452,9 +453,7 @@ TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) {
{L"imediately", false, 0,0,L"immediately"},
{L"incidently", false, 0,0,L"incidentally"},
{L"independant", false, 0,0,L"independent"},
- // TODO(pwicks): This fails as a result of 13432.
- // Once that is fixed, uncomment this.
- // {L"indispensible", false, 0,0,L"indispensable"},
+ {L"indispensible", false, 0, 0, L"indispensable"},
{L"innoculate", false, 0,0,L"inoculate"},
{L"inteligence", false, 0,0,L"intelligence"},
{L"intresting", false, 0,0,L"interesting"},
@@ -533,9 +532,7 @@ TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) {
{L"proffesional", false, 0,0,L"professional"},
{L"professer", false, 0,0,L"professor"},
{L"promiss", false, 0,0,L"promise"},
- // TODO(pwicks): This fails as a result of 13432.
- // Once that is fixed, uncomment this.
- // {L"pronounciation", false, 0,0,L"pronunciation"},
+ {L"pronounciation", false, 0, 0, L"pronunciation"},
{L"prufe", false, 0,0,L"proof"},
{L"psycology", false, 0,0,L"psychology"},
{L"publically", false, 0,0,L"publicly"},
@@ -631,6 +628,7 @@ TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) {
int misspelling_length;
bool result = spell_checker->SpellCheckWord(kTestCases[i].input,
static_cast<int>(input_length),
+ 0,
&misspelling_start,
&misspelling_length,
&suggestions);
@@ -899,6 +897,7 @@ TEST_F(SpellCheckTest, SpellCheckText) {
int misspelling_length = 0;
bool result = spell_checker->SpellCheckWord(kTestCases[i].input,
static_cast<int>(input_length),
+ 0,
&misspelling_start,
&misspelling_length, NULL);
@@ -940,6 +939,7 @@ TEST_F(SpellCheckTest, DISABLED_SpellCheckAddToDictionary_EN_US) {
int misspelling_length;
bool result = spell_checker->SpellCheckWord(kTestCases[i].word_to_add,
static_cast<int>(input_length),
+ 0,
&misspelling_start,
&misspelling_length,
&suggestions);
@@ -964,6 +964,7 @@ TEST_F(SpellCheckTest, DISABLED_SpellCheckAddToDictionary_EN_US) {
bool result = spell_checker_new->SpellCheckWord(
kTestCases[i].word_to_add,
static_cast<int>(input_length),
+ 0,
&misspelling_start,
&misspelling_length,
&suggestions);
@@ -1030,6 +1031,7 @@ TEST_F(SpellCheckTest, DISABLED_SpellCheckSuggestionsAddToDictionary_EN_US) {
int misspelling_length;
bool result = spell_checker->SpellCheckWord(kTestCasesToBeTested[i].input,
static_cast<int>(input_length),
+ 0,
&misspelling_start,
&misspelling_length,
&suggestions);
@@ -1081,9 +1083,86 @@ TEST_F(SpellCheckTest, GetAutoCorrectionWord_EN_US) {
std::wstring misspelled_word(kTestCases[i].input);
std::wstring expected_autocorrect_word(kTestCases[i].expected_result);
std::wstring autocorrect_word;
- spell_checker->GetAutoCorrectionWord(misspelled_word, &autocorrect_word);
+ spell_checker->GetAutoCorrectionWord(misspelled_word, 0, &autocorrect_word);
// Check for spelling.
EXPECT_EQ(expected_autocorrect_word, autocorrect_word);
}
}
+
+#if defined(OS_MACOSX)
+// Tests that words are properly ignored. Currently only enabled on OS X as it
+// is the only platform to support ignoring words. Note that in this test, we
+// supply a non-zero doc_tag, in order to test that ignored words are matched to
+// the correct document.
+TEST_F(SpellCheckTest, IgnoreWords_EN_US) {
+ static const struct {
+ // A misspelled word.
+ const wchar_t* input;
+ bool input_result;
+ } kTestCases[] = {
+ {L"teh",false},
+ {L"moer", false},
+ {L"watre",false},
+ {L"noen", false},
+ };
+
+ FilePath hunspell_directory = GetHunspellDirectory();
+ ASSERT_FALSE(hunspell_directory.empty());
+
+ scoped_refptr<SpellChecker> spell_checker(new SpellChecker(
+ hunspell_directory, "en-US", NULL, FilePath()));
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ std::wstring word(kTestCases[i].input);
+ std::string misspelled_word = base::SysWideToUTF8(word);
+ std::vector<std::wstring> suggestions;
+ size_t input_length = 0;
+ if (kTestCases[i].input != NULL) {
+ input_length = wcslen(kTestCases[i].input);
+ }
+ int misspelling_start;
+ int misspelling_length;
+
+ int doc_tag = SpellCheckerPlatform::GetDocumentTag();
+ bool result = spell_checker->SpellCheckWord(kTestCases[i].input,
+ static_cast<int>(input_length),
+ doc_tag,
+ &misspelling_start,
+ &misspelling_length,
+ &suggestions);
+
+ // The word should show up as misspelled.
+ EXPECT_EQ(kTestCases[i].input_result, result);
+
+ // Ignore the word.
+ SpellCheckerPlatform::IgnoreWord(misspelled_word);
+
+ // Spellcheck again.
+ result = spell_checker->SpellCheckWord(kTestCases[i].input,
+ static_cast<int>(input_length),
+ doc_tag,
+ &misspelling_start,
+ &misspelling_length,
+ &suggestions);
+
+ // The word should now show up as correctly spelled.
+ EXPECT_EQ(!(kTestCases[i].input_result), result);
+
+ // Close the docuemnt. Any words that we had previously ignored should no
+ // longer be ignored and thus should show up as misspelled.
+ SpellCheckerPlatform::CloseDocumentWithTag(doc_tag);
+
+ // Spellcheck one more time.
+ result = spell_checker->SpellCheckWord(kTestCases[i].input,
+ static_cast<int>(input_length),
+ doc_tag,
+ &misspelling_start,
+ &misspelling_length,
+ &suggestions);
+
+ // The word should now show be spelled wrong again
+ EXPECT_EQ(kTestCases[i].input_result, result);
+ }
+} // Test IgnoreWords_EN_US
+#endif // OS_MACOSX
diff --git a/chrome/browser/spellchecker.cc b/chrome/browser/spellchecker.cc
index b6e43fb..0a9f03e 100644
--- a/chrome/browser/spellchecker.cc
+++ b/chrome/browser/spellchecker.cc
@@ -533,7 +533,7 @@ bool SpellChecker::Initialize() {
return false;
}
-void SpellChecker::GetAutoCorrectionWord(const std::wstring& word,
+void SpellChecker::GetAutoCorrectionWord(const std::wstring& word, int tag,
std::wstring* autocorrect_word) {
autocorrect_word->clear();
if (!auto_spell_correct_turned_on_)
@@ -560,7 +560,7 @@ void SpellChecker::GetAutoCorrectionWord(const std::wstring& word,
// Check spelling.
misspelling_start = misspelling_len = 0;
- SpellCheckWord(misspelled_word, word_length, &misspelling_start,
+ SpellCheckWord(misspelled_word, word_length, tag, &misspelling_start,
&misspelling_len, NULL);
// Make decision: if only one swap produced a valid word, then we want to
@@ -604,7 +604,7 @@ void SpellChecker::AddCustomWordsToHunspell() {
// This function is a fall-back when the SpellcheckWordIterator class
// returns a concatenated word which is not in the selected dictionary
// (e.g. "in'n'out") but each word is valid.
-bool SpellChecker::IsValidContraction(const string16& contraction) {
+bool SpellChecker::IsValidContraction(const string16& contraction, int tag) {
SpellcheckWordIterator word_iterator;
word_iterator.Initialize(&character_attributes_, contraction.c_str(),
contraction.length(), false);
@@ -613,7 +613,7 @@ bool SpellChecker::IsValidContraction(const string16& contraction) {
int word_start;
int word_length;
while (word_iterator.GetNextWord(&word, &word_start, &word_length)) {
- if (!CheckSpelling(UTF16ToUTF8(word)))
+ if (!CheckSpelling(UTF16ToUTF8(word), tag))
return false;
}
return true;
@@ -622,6 +622,7 @@ bool SpellChecker::IsValidContraction(const string16& contraction) {
bool SpellChecker::SpellCheckWord(
const wchar_t* in_word,
int in_word_len,
+ int tag,
int* misspelling_start,
int* misspelling_len,
std::vector<std::wstring>* optional_suggestions) {
@@ -665,13 +666,13 @@ bool SpellChecker::SpellCheckWord(
// Found a word (or a contraction) that the spellchecker can check the
// spelling of.
std::string encoded_word = UTF16ToUTF8(word);
- bool word_ok = CheckSpelling(encoded_word);
+ bool word_ok = CheckSpelling(encoded_word, tag);
if (word_ok)
continue;
// If the given word is a concatenated word of two or more valid words
// (e.g. "hello:hello"), we should treat it as a valid word.
- if (IsValidContraction(word))
+ if (IsValidContraction(word, tag))
continue;
*misspelling_start = word_start;
@@ -739,12 +740,12 @@ void SpellChecker::AddWord(const std::wstring& word) {
write_word_task->Run();
}
-bool SpellChecker::CheckSpelling(const std::string& word_to_check) {
+bool SpellChecker::CheckSpelling(const std::string& word_to_check, int tag) {
bool word_correct = false;
TimeTicks begin_time = TimeTicks::Now();
if (is_using_platform_spelling_engine_) {
- word_correct = SpellCheckerPlatform::CheckSpelling(word_to_check);
+ word_correct = SpellCheckerPlatform::CheckSpelling(word_to_check, tag);
} else {
// |hunspell_->spell| returns 0 if the word is spelled correctly and
// non-zero otherwsie.
diff --git a/chrome/browser/spellchecker.h b/chrome/browser/spellchecker.h
index fa1b156..48e4153 100644
--- a/chrome/browser/spellchecker.h
+++ b/chrome/browser/spellchecker.h
@@ -64,6 +64,8 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>,
// SpellCheck a word.
// Returns true if spelled correctly, false otherwise.
// If the spellchecker failed to initialize, always returns true.
+ // The |tag| parameter should either be a unique identifier for the document
+ // that the word came from (if the current platform requires it), or 0.
// In addition, finds the suggested words for a given word
// and puts them into |*optional_suggestions|.
// If the word is spelled correctly, the vector is empty.
@@ -71,6 +73,7 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>,
// Note that Doing suggest lookups can be slow.
bool SpellCheckWord(const wchar_t* in_word,
int in_word_len,
+ int tag,
int* misspelling_start,
int* misspelling_len,
std::vector<std::wstring>* optional_suggestions);
@@ -78,7 +81,7 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>,
// Find a possible correctly spelled word for a misspelled word. Computes an
// empty string if input misspelled word is too long, there is ambiguity, or
// the correct spelling cannot be determined.
- void GetAutoCorrectionWord(const std::wstring& word,
+ void GetAutoCorrectionWord(const std::wstring& word, int tag,
std::wstring* autocorrect_word);
// Turn auto spell correct support ON or OFF.
@@ -124,7 +127,7 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>,
// When called, relays the request to check the spelling to the proper
// backend, either hunspell or a platform-specific backend.
- bool CheckSpelling(const std::string& word_to_check);
+ bool CheckSpelling(const std::string& word_to_check, int tag);
// When called, relays the request to fill the list with suggestions to
// the proper backend, either hunspell or a platform-specific backend.
@@ -144,7 +147,7 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>,
// Returns whether or not the given word is a contraction of valid words
// (e.g. "word:word").
- bool IsValidContraction(const string16& word);
+ bool IsValidContraction(const string16& word, int tag);
// Return the file name of the dictionary, including the path and the version
// numbers.
diff --git a/chrome/browser/spellchecker_linux.cc b/chrome/browser/spellchecker_linux.cc
index 1452f74..1596b50 100644
--- a/chrome/browser/spellchecker_linux.cc
+++ b/chrome/browser/spellchecker_linux.cc
@@ -28,28 +28,33 @@ bool SpellCheckerProvidesPanel() {
return false;
}
-bool SpellCheckerPanelVisible() {
+bool SpellingPanelVisible() {
return false;
}
-void Init() {
-}
+void ShowSpellingPanel(bool show) { }
-void SetLanguage(const std::string& lang_to_set) {
-}
+void UpdateSpellingPanelWithMisspelledWord(const std::wstring& word) { }
+
+void Init() { }
-bool CheckSpelling(const std::string& word_to_check) {
+void SetLanguage(const std::string& lang_to_set) { }
+
+bool CheckSpelling(const std::string& word_to_check, int tag) {
return false;
}
void FillSuggestionList(const std::string& wrong_word,
- std::vector<std::wstring>* optional_suggestions) {
-}
+ std::vector<std::wstring>* optional_suggestions) { }
-void AddWord(const std::wstring& word) {
-}
+void AddWord(const std::wstring& word) { }
-void RemoveWord(const std::wstring& word) {
-}
+void RemoveWord(const std::wstring& word) { }
+
+int GetDocumentTag() { return 0; }
+
+void IgnoreWord(const std::string& word) { }
+
+void CloseDocumentWithTag(int tag) { }
} // namespace SpellCheckerPlatform
diff --git a/chrome/browser/spellchecker_mac.mm b/chrome/browser/spellchecker_mac.mm
index f9bfac6..4fe6458 100644
--- a/chrome/browser/spellchecker_mac.mm
+++ b/chrome/browser/spellchecker_mac.mm
@@ -7,11 +7,12 @@
#import <Cocoa/Cocoa.h>
-#include "chrome/browser/spellchecker_common.h"
-#include "chrome/browser/spellchecker_platform_engine.h"
+#include "base/logging.h"
#include "base/time.h"
#include "base/histogram.h"
#include "base/sys_string_conversions.h"
+#include "chrome/browser/spellchecker_common.h"
+#include "chrome/browser/spellchecker_platform_engine.h"
using base::TimeTicks;
namespace {
@@ -92,9 +93,30 @@ bool SpellCheckerProvidesPanel() {
return true;
}
-bool SpellCheckerPanelVisible() {
- return [[[NSSpellChecker sharedSpellChecker] spellingPanel]
- isVisible] ? true : false;
+bool SpellingPanelVisible() {
+ // This should only be called from the main thread.
+ DCHECK([NSThread currentThread] == [NSThread mainThread]);
+ return [[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible];
+}
+
+void ShowSpellingPanel(bool show) {
+ if (show) {
+ [[[NSSpellChecker sharedSpellChecker] spellingPanel]
+ performSelectorOnMainThread:@selector(makeKeyAndOrderFront:)
+ withObject:nil
+ waitUntilDone:YES];
+ } else {
+ [[[NSSpellChecker sharedSpellChecker] spellingPanel]
+ performSelectorOnMainThread:@selector(close)
+ withObject:nil
+ waitUntilDone:YES];
+ }
+}
+
+void UpdateSpellingPanelWithMisspelledWord(const std::wstring& word) {
+ NSString * word_to_display = base::SysWideToNSString(word);
+ [[NSSpellChecker sharedSpellChecker]
+ updateSpellingPanelWithMisspelledWord:word_to_display];
}
void Init() {
@@ -121,7 +143,11 @@ void SetLanguage(const std::string& lang_to_set) {
[[NSSpellChecker sharedSpellChecker] setLanguage:NS_lang_to_set];
}
-bool CheckSpelling(const std::string& word_to_check) {
+static int last_seen_tag_;
+
+bool CheckSpelling(const std::string& word_to_check, int tag) {
+ last_seen_tag_ = tag;
+
// [[NSSpellChecker sharedSpellChecker] checkSpellingOfString] returns an
// NSRange that we can look at to determine if a word is misspelled.
NSRange spell_range = {0,0};
@@ -130,7 +156,9 @@ bool CheckSpelling(const std::string& word_to_check) {
NSString* NS_word_to_check = base::SysUTF8ToNSString(word_to_check);
// Check the spelling, starting at the beginning of the word.
spell_range = [[NSSpellChecker sharedSpellChecker]
- checkSpellingOfString:NS_word_to_check startingAt:0];
+ checkSpellingOfString:NS_word_to_check startingAt:0
+ language:nil wrap:NO inSpellDocumentWithTag:tag
+ wordCount:NULL];
// If the length of the misspelled word == 0,
// then there is no misspelled word.
@@ -165,5 +193,20 @@ void RemoveWord(const std::wstring& word) {
NSString *word_to_remove = base::SysWideToNSString(word);
[[NSSpellChecker sharedSpellChecker] unlearnWord:word_to_remove];
}
+
+int GetDocumentTag() {
+ NSInteger doc_tag = [NSSpellChecker uniqueSpellDocumentTag];
+ return static_cast<int>(doc_tag);
+}
+
+void IgnoreWord(const std::string& word) {
+ [[NSSpellChecker sharedSpellChecker] ignoreWord:base::SysUTF8ToNSString(word)
+ inSpellDocumentWithTag:last_seen_tag_];
+}
+
+void CloseDocumentWithTag(int tag) {
+ [[NSSpellChecker sharedSpellChecker]
+ closeSpellDocumentWithTag:static_cast<NSInteger>(tag)];
+}
} // namespace SpellCheckerPlatform
diff --git a/chrome/browser/spellchecker_platform_engine.h b/chrome/browser/spellchecker_platform_engine.h
index ddfe64b..bf5eb94 100644
--- a/chrome/browser/spellchecker_platform_engine.h
+++ b/chrome/browser/spellchecker_platform_engine.h
@@ -26,7 +26,14 @@ bool SpellCheckerAvailable();
bool SpellCheckerProvidesPanel();
// Returns true if the platform spellchecker panel is visible.
-bool SpellCheckerPanelVisible();
+bool SpellingPanelVisible();
+
+// Shows the spelling panel if |show| is true and hides it if it is not.
+void ShowSpellingPanel(bool show);
+
+// Changes the word show in the spelling panel to be |word|. Note that the
+// spelling panel need not be displayed for this to work.
+void UpdateSpellingPanelWithMisspelledWord(const std::wstring& word);
// Do any initialization needed for spellchecker.
void Init();
@@ -43,7 +50,7 @@ void SetLanguage(const std::string& lang_to_set);
// Checks the spelling of the given string, using the platform-specific
// spellchecker. Returns true if the word is spelled correctly.
-bool CheckSpelling(const std::string& word_to_check);
+bool CheckSpelling(const std::string& word_to_check, int tag);
// Fills the given vector |optional_suggestions| with a number (up to
// kMaxSuggestions, which is defined in spellchecker_common.h) of suggestions
@@ -56,6 +63,21 @@ void AddWord(const std::wstring& word);
// Remove a given word from the platform dictionary.
void RemoveWord(const std::wstring& word);
+
+// Gets a unique tag to identify a document. Used in ignoring words.
+int GetDocumentTag();
+
+// Tells the platform spellchecker to ignore a word. This doesn't take a tag
+// because in most of the situations in which it is called, the only way to know
+// the tag for sure is to ask the renderer, which would mean blocking in the
+// browser, so (on the mac, anyway) we remember the most recent tag and use
+// it, since it should always be from the same document.
+void IgnoreWord(const std::string& word);
+
+// Tells the platform spellchecker that a document associated with a tag has
+// closed. Generally, this means that any ignored words associated with that
+// document can now be forgotten.
+void CloseDocumentWithTag(int tag);
}
#endif // CHROME_BROWSER_SPELLCHECKER_PLATFORM_ENGINE_H_
diff --git a/chrome/browser/spellchecker_win.cc b/chrome/browser/spellchecker_win.cc
index 73db800..4fd2dfa 100644
--- a/chrome/browser/spellchecker_win.cc
+++ b/chrome/browser/spellchecker_win.cc
@@ -28,28 +28,33 @@ bool SpellCheckerProvidesPanel() {
return false;
}
-bool SpellCheckerPanelVisible() {
+bool SpellingPanelVisible() {
return false;
}
-void Init() {
-}
+void ShowSpellingPanel(bool show) { }
-void SetLanguage(const std::string& lang_to_set) {
-}
+void UpdateSpellingPanelWithMisspelledWord(const std::wstring& word) { }
+
+void Init() { }
-bool CheckSpelling(const std::string& word_to_check) {
+void SetLanguage(const std::string& lang_to_set) { }
+
+bool CheckSpelling(const std::string& word_to_check, int tag) {
return false;
}
void FillSuggestionList(const std::string& wrong_word,
- std::vector<std::wstring>* optional_suggestions) {
-}
+ std::vector<std::wstring>* optional_suggestions) { }
-void AddWord(const std::wstring& word) {
-}
+void AddWord(const std::wstring& word) { }
-void RemoveWord(const std::wstring& word) {
-}
+void RemoveWord(const std::wstring& word) { }
+
+int GetDocumentTag() { return 0; }
+
+void IgnoreWord(const std::string& word) { }
+
+void CloseDocumentWithTag(int tag) { }
} // namespace SpellCheckerPlatform
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index b86001a..2b4345a 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/spellchecker.h"
+#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
@@ -258,6 +259,15 @@ void RenderViewContextMenu::AppendEditableItems() {
l10n_util::GetStringUTF16(
IDS_CONTENT_CONTEXT_CHECK_SPELLING_OF_THIS_FIELD));
+ // Add option for showing the spelling panel if the platfrom spellchecker
+ // supports it.
+ if (SpellCheckerPlatform::SpellCheckerAvailable() &&
+ SpellCheckerPlatform::SpellCheckerProvidesPanel()) {
+ AppendCheckboxMenuItem(IDC_SPELLPANEL_TOGGLE, l10n_util::GetStringUTF16(
+ SpellCheckerPlatform::SpellingPanelVisible() ?
+ IDS_CONTENT_CONTEXT_HIDE_SPELLING_PANEL :
+ IDS_CONTENT_CONTEXT_SHOW_SPELLING_PANEL));
+ }
FinishSubMenu();
AppendSeparator();
@@ -700,6 +710,10 @@ void RenderViewContextMenu::ExecuteItemCommand(int id) {
LANGUAGES_PAGE, profile_);
break;
+ case IDC_SPELLPANEL_TOGGLE:
+ source_tab_contents_->render_view_host()->ToggleSpellPanel(
+ SpellCheckerPlatform::SpellingPanelVisible());
+ break;
case IDS_CONTENT_CONTEXT_ADDSEARCHENGINE: // Not implemented.
default:
break;
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 22f273d..4a2e5b0 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -184,6 +184,11 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_ROUTED0(ViewMsg_ToggleSpellCheck)
IPC_MESSAGE_ROUTED0(ViewMsg_Delete)
IPC_MESSAGE_ROUTED0(ViewMsg_SelectAll)
+ IPC_MESSAGE_ROUTED1(ViewMsg_ToggleSpellPanel, bool)
+
+ // This message tells the renderer to advance to the next misspelling. It is
+ // sent when the user clicks the "Find Next" button on the spelling panel.
+ IPC_MESSAGE_ROUTED0(ViewMsg_AdvanceToNextMisspelling)
// Copies the image at location x, y to the clipboard (if there indeed is an
// image at that location).
@@ -928,13 +933,34 @@ IPC_BEGIN_MESSAGES(ViewHost)
std::string /* actual mime type for url */)
// Requests spellcheck for a word.
- IPC_SYNC_MESSAGE_ROUTED1_2(ViewHostMsg_SpellCheck,
+ IPC_SYNC_MESSAGE_ROUTED2_2(ViewHostMsg_SpellCheck,
std::wstring /* word to check */,
+ int /* document tag*/,
int /* misspell location */,
int /* misspell length */)
- IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_GetAutoCorrectWord,
+ // Asks the browser for a unique document tag.
+ IPC_SYNC_MESSAGE_ROUTED0_1(ViewHostMsg_GetDocumentTag,
+ int /* the tag */)
+
+
+ // This message tells the spellchecker that a document, identified by an int
+ // tag, has been closed and all of the ignored words for that document can be
+ // forgotten.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DocumentWithTagClosed,
+ int /* the tag */)
+
+ // Tells the browser to display or not display the SpellingPanel
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowSpellingPanel,
+ bool /* if true, then show it, otherwise hide it*/)
+
+ // Tells the browser to update the spelling panel with the given word.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateSpellingPanelWithMisspelledWord,
+ std::wstring /* the word to update the panel with */)
+
+ IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_GetAutoCorrectWord,
std::wstring /* word to check */,
+ int /* tag for the document containg the word */,
std::wstring /* autocorrected word */)
// Initiate a download based on user actions like 'ALT+click'.
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index e91936e..e99f961 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -212,7 +212,9 @@ RenderView::RenderView(RenderThreadBase* render_thread,
determine_page_text_after_loading_stops_(false),
view_type_(ViewType::INVALID),
browser_window_id_(-1),
- last_top_level_navigation_page_id_(-1),
+ last_top_level_navigation_page_id_(-1),
+ has_spell_checker_document_tag_(false),
+ document_tag_(0),
webkit_preferences_(webkit_preferences) {
Singleton<RenderViewSet>()->render_view_set_.insert(this);
}
@@ -222,6 +224,9 @@ RenderView::~RenderView() {
if (decrement_shared_popup_at_destruction_)
shared_popup_counter_->data--;
+ // Tell the spellchecker that the document is closed.
+ Send(new ViewHostMsg_DocumentWithTagClosed(routing_id_, document_tag_));
+
render_thread_->RemoveFilter(audio_message_filter_);
}
@@ -346,6 +351,9 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
+ IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellPanel, OnToggleSpellPanel)
+ IPC_MESSAGE_HANDLER(ViewMsg_AdvanceToNextMisspelling,
+ OnAdvanceToNextMisspelling)
IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellCheck, OnToggleSpellCheck)
IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
@@ -828,6 +836,23 @@ void RenderView::OnReplace(const std::wstring& text) {
webview()->GetFocusedFrame()->replaceSelection(WideToUTF16Hack(text));
}
+void RenderView::OnAdvanceToNextMisspelling() {
+ if (!webview())
+ return;
+ webview()->GetFocusedFrame()->executeCommand(
+ WebString::fromUTF8("AdvanceToNextMisspelling"));
+}
+
+void RenderView::OnToggleSpellPanel(bool is_currently_visible) {
+ if (!webview())
+ return;
+ // We need to tell the webView whether the spelling panel is visible or not so
+ // that it won't need to make ipc calls later.
+ webview()->SetSpellingPanelVisibility(is_currently_visible);
+ webview()->GetFocusedFrame()->executeCommand(
+ WebString::fromUTF8("ToggleSpellPanel"));
+}
+
void RenderView::OnToggleSpellCheck() {
if (!webview())
return;
@@ -2520,24 +2545,45 @@ bool RenderView::WasOpenedByUserGesture() const {
return opened_by_user_gesture_;
}
-void RenderView::SpellCheck(const std::wstring& word, int* misspell_location,
- int* misspell_length) {
- Send(new ViewHostMsg_SpellCheck(routing_id_, word, misspell_location,
- misspell_length));
+void RenderView::SpellCheck(const std::wstring& word, int tag,
+ int* misspell_location,
+ int* misspell_length) {
+ Send(new ViewHostMsg_SpellCheck(routing_id_, word, tag,
+ misspell_location, misspell_length));
}
std::wstring RenderView::GetAutoCorrectWord(
- const std::wstring& misspelled_word) {
+ const std::wstring& misspelled_word, int tag) {
std::wstring autocorrect_word;
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kAutoSpellCorrect)) {
- Send(new ViewHostMsg_GetAutoCorrectWord(routing_id_, misspelled_word,
+ Send(new ViewHostMsg_GetAutoCorrectWord(routing_id_, misspelled_word, tag,
&autocorrect_word));
}
return autocorrect_word;
}
+void RenderView::ShowSpellingUI(bool show) {
+ Send(new ViewHostMsg_ShowSpellingPanel(routing_id_, show));
+}
+
+int RenderView::SpellCheckerDocumentTag() {
+ if (!has_spell_checker_document_tag_) {
+ // Make the call to get the tag.
+ int tag;
+ Send(new ViewHostMsg_GetDocumentTag(routing_id_, &tag));
+ document_tag_ = tag;
+ has_spell_checker_document_tag_ = true;
+ }
+ return document_tag_;
+}
+
+void RenderView::UpdateSpellingUIWithMisspelledWord(const std::wstring& word) {
+ Send(new ViewHostMsg_UpdateSpellingPanelWithMisspelledWord(
+ routing_id_, word));
+}
+
void RenderView::ScriptedPrint(WebFrame* frame) {
DCHECK(webview());
if (webview()) {
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 3274d44..b094f30 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -321,9 +321,13 @@ class RenderView : public RenderWidget,
const WebKit::WebRect& selection);
virtual bool WasOpenedByUserGesture() const;
virtual void FocusAccessibilityObject(WebCore::AccessibilityObject* acc_obj);
- virtual void SpellCheck(const std::wstring& word, int* misspell_location,
+ virtual void SpellCheck(const std::wstring& word, int tag,
+ int* misspell_location,
int* misspell_length);
- virtual std::wstring GetAutoCorrectWord(const std::wstring& word);
+ virtual std::wstring GetAutoCorrectWord(const std::wstring& word, int tag);
+ virtual void UpdateSpellingUIWithMisspelledWord(const std::wstring& word);
+ virtual void ShowSpellingUI(bool show);
+ virtual int SpellCheckerDocumentTag();
virtual void ScriptedPrint(WebKit::WebFrame* frame);
virtual void UserMetricsRecordAction(const std::wstring& action);
virtual void DnsPrefetch(const std::vector<std::string>& host_names);
@@ -529,6 +533,8 @@ class RenderView : public RenderWidget,
void OnCopy();
void OnPaste();
void OnReplace(const std::wstring& text);
+ void OnAdvanceToNextMisspelling();
+ void OnToggleSpellPanel(bool is_currently_visible);
void OnToggleSpellCheck();
void OnDelete();
void OnSelectAll();
@@ -894,6 +900,12 @@ class RenderView : public RenderWidget,
// page id for the last navigation sent to the browser.
int32 last_top_level_navigation_page_id_;
+ // True if the current RenderView has been assigned a document tag.
+ bool has_spell_checker_document_tag_;
+
+ // Document tag for this RenderView.
+ int document_tag_;
+
// The settings this render view initialized WebKit with.
WebPreferences webkit_preferences_;
diff --git a/webkit/glue/editor_client_impl.cc b/webkit/glue/editor_client_impl.cc
index a090eb7..f7d2561 100644
--- a/webkit/glue/editor_client_impl.cc
+++ b/webkit/glue/editor_client_impl.cc
@@ -152,7 +152,13 @@ void EditorClientImpl::toggleGrammarChecking() {
}
int EditorClientImpl::spellCheckerDocumentTag() {
+#if defined(OS_MACOSX)
+ WebViewDelegate* d = web_view_->delegate();
+ if (d)
+ return d->SpellCheckerDocumentTag();
+#else
NOTIMPLEMENTED();
+#endif // OS_MACOSX
return 0;
}
@@ -838,7 +844,8 @@ void EditorClientImpl::checkSpellingOfString(const UChar* str, int length,
if (isContinuousSpellCheckingEnabled() && d) {
std::wstring word =
webkit_glue::StringToStdWString(WebCore::String(str, length));
- d->SpellCheck(word, &spell_location, &spell_length);
+ d->SpellCheck(word, spellCheckerDocumentTag(),
+ &spell_location, &spell_length);
} else {
spell_location = 0;
spell_length = 0;
@@ -867,7 +874,8 @@ WebCore::String EditorClientImpl::getAutoCorrectSuggestionForMisspelledWord(
return WebCore::String();
}
- std::wstring autocorrect_word = d->GetAutoCorrectWord(word);
+ std::wstring autocorrect_word =
+ d->GetAutoCorrectWord(word, spellCheckerDocumentTag());
return webkit_glue::StdWStringToString(autocorrect_word);
}
@@ -887,16 +895,28 @@ void EditorClientImpl::updateSpellingUIWithGrammarString(const WebCore::String&,
NOTIMPLEMENTED();
}
-void EditorClientImpl::updateSpellingUIWithMisspelledWord(const WebCore::String&) {
- NOTIMPLEMENTED();
+void EditorClientImpl::updateSpellingUIWithMisspelledWord(
+ const WebCore::String& misspelled_word) {
+ std::wstring word = webkit_glue::StringToStdWString(misspelled_word);
+ WebViewDelegate* d = web_view_->delegate();
+ if (d) {
+ d->UpdateSpellingUIWithMisspelledWord(word);
+ }
}
void EditorClientImpl::showSpellingUI(bool show) {
- NOTIMPLEMENTED();
+ WebViewDelegate* d = web_view_->delegate();
+ if (d) {
+ d->ShowSpellingUI(show);
+ }
}
bool EditorClientImpl::spellingUIIsShowing() {
- return false;
+ // SpellingPanel visibility is stored in the web_view_ every time a toggle
+ // message is sent from the browser. If we were to send a message to the
+ // browser and ask for the visibility, then we run into problems accessing
+ // cocoa methods on the UI thread.
+ return web_view_->GetSpellingPanelVisibility();
}
void EditorClientImpl::getGuessesForWord(const WebCore::String&,
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index 7521532..e52075c 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -973,6 +973,12 @@ bool WebFrameImpl::executeCommand(const WebString& name) {
rv = frame()->editor()->command(AtomicString("BackwardDelete")).execute();
} else if (EqualsASCII(command, "DeleteForward")) {
rv = frame()->editor()->command(AtomicString("ForwardDelete")).execute();
+ } else if (EqualsASCII(command, "AdvanceToNextMisspelling")) {
+ // False must be passed here, or the currently selected word will never be
+ // skipped.
+ frame()->editor()->advanceToNextMisspelling(false);
+ } else if (EqualsASCII(command, "ToggleSpellPanel")) {
+ frame()->editor()->showSpellingGuessPanel();
} else {
rv = frame()->editor()->command(AtomicString(command.c_str())).execute();
}
diff --git a/webkit/glue/webview.h b/webkit/glue/webview.h
index 0cd33fc..db4e6fb 100644
--- a/webkit/glue/webview.h
+++ b/webkit/glue/webview.h
@@ -243,6 +243,9 @@ class WebView : public WebKit::WebWidget {
virtual void SetIsTransparent(bool is_transparent) = 0;
virtual bool GetIsTransparent() const = 0;
+ virtual void SetSpellingPanelVisibility(bool is_visible) = 0;
+ virtual bool GetSpellingPanelVisibility() = 0;
+
// Performs an action from a context menu for the node at the given
// location.
virtual void MediaPlayerActionAt(int x,
diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h
index 99d9be36..3bbdf02 100644
--- a/webkit/glue/webview_delegate.h
+++ b/webkit/glue/webview_delegate.h
@@ -729,17 +729,28 @@ class WebViewDelegate : virtual public WebKit::WebWidgetClient {
// indices (inclusive) will be filled with the offsets of the boundary of the
// word within the given buffer. The out pointers must be specified. If the
// word is correctly spelled (returns true), they will be set to (0,0).
- virtual void SpellCheck(const std::wstring& word, int* misspell_location,
+ virtual void SpellCheck(const std::wstring& word, int tag,
+ int* misspell_location,
int* misspell_length) {
*misspell_location = *misspell_length = 0;
}
// Computes an auto correct word for a misspelled word. If no word is found,
// empty string is computed.
- virtual std::wstring GetAutoCorrectWord(const std::wstring& misspelled_word) {
+ virtual std::wstring GetAutoCorrectWord(const std::wstring& misspelled_word,
+ int tag) {
return std::wstring();
}
+ // Returns the document tag for the current WebView.
+ virtual int SpellCheckerDocumentTag() { return 0; }
+
+ // Switches the spelling panel to be displayed or not based on |show|.
+ virtual void ShowSpellingUI(bool show) { }
+
+ // Update the spelling panel with the |word|.
+ virtual void UpdateSpellingUIWithMisspelledWord(const std::wstring& word) { }
+
// Asks the user to print the page or a specific frame. Called in response to
// a window.print() call.
virtual void ScriptedPrint(WebKit::WebFrame* frame) { }
diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc
index f3cf268..effb17d 100644
--- a/webkit/glue/webview_impl.cc
+++ b/webkit/glue/webview_impl.cc
@@ -1934,3 +1934,11 @@ HitTestResult WebViewImpl::HitTestResultForWindowPos(const IntPoint& pos) {
return page_->mainFrame()->eventHandler()->
hitTestResultAtPoint(doc_point, false);
}
+
+void WebViewImpl::SetSpellingPanelVisibility(bool is_visible) {
+ spelling_panel_is_visible_ = is_visible;
+}
+
+bool WebViewImpl::GetSpellingPanelVisibility() {
+ return spelling_panel_is_visible_;
+}
diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h
index 3c753ac..7bc66e9 100644
--- a/webkit/glue/webview_impl.h
+++ b/webkit/glue/webview_impl.h
@@ -242,6 +242,9 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> {
// the underlying Node for them.
WebCore::Node* GetNodeForWindowPos(int x, int y);
+ virtual void SetSpellingPanelVisibility(bool is_visible);
+ virtual bool GetSpellingPanelVisibility();
+
#if ENABLE(NOTIFICATIONS)
// Returns the provider of desktop notifications.
WebKit::NotificationPresenterImpl* GetNotificationPresenter();
@@ -394,6 +397,9 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> {
// Whether the webview is rendering transparently.
bool is_transparent_;
+ // Whether the spelling panel is currently being displayed or not.
+ bool spelling_panel_is_visible_;
+
// Inspector settings.
std::wstring inspector_settings_;