summaryrefslogtreecommitdiffstats
path: root/chrome/browser
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 /chrome/browser
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
Diffstat (limited to 'chrome/browser')
-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
17 files changed, 345 insertions, 61 deletions
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;