diff options
-rw-r--r-- | chrome/browser/renderer_host/browser_render_process_host.cc | 1 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 16 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 2 | ||||
-rw-r--r-- | chrome/browser/spellcheck_unittest.cc | 33 | ||||
-rw-r--r-- | chrome/browser/spellchecker.cc | 44 | ||||
-rw-r--r-- | chrome/browser/spellchecker.h | 6 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 4 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 3 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 4 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 2 | ||||
-rw-r--r-- | webkit/glue/editor_client_impl.cc | 12 | ||||
-rw-r--r-- | webkit/glue/editor_client_impl.h | 2 | ||||
-rw-r--r-- | webkit/glue/webview_delegate.h | 6 |
14 files changed, 143 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index f43e06ba..fce7128 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -264,6 +264,7 @@ bool BrowserRenderProcessHost::Init() { switches::kEnableStatsTable, switches::kEnableExtensions, switches::kEnableOutOfProcessDevTools, + switches::kAutoSpellCorrect, switches::kDisableAudio, switches::kSimpleDataSource, }; diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 0b86265..594163f 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -253,6 +253,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, OnForwardToWorker) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SpellCheck, OnSpellCheck) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetAutoCorrectWord, + OnGetAutoCorrectWord) IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch) IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms, OnRendererHistograms) @@ -794,6 +796,20 @@ void ResourceMessageFilter::OnSpellCheck(const std::wstring& word, return; } + +void ResourceMessageFilter::OnGetAutoCorrectWord(const std::wstring& word, + IPC::Message* reply_msg) { + std::wstring autocorrect_word; + if (spellchecker_ != NULL) { + spellchecker_->GetAutoCorrectionWord(word, &autocorrect_word); + } + + ViewHostMsg_GetAutoCorrectWord::WriteReplyParams(reply_msg, + autocorrect_word); + Send(reply_msg); + return; +} + 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 c28618b..8a406f0 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -146,6 +146,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, const GURL& referrer); void OnSpellCheck(const std::wstring& word, IPC::Message* reply_msg); + void OnGetAutoCorrectWord(const std::wstring& word, + IPC::Message* reply_msg); void OnDnsPrefetch(const std::vector<std::string>& hostnames); void OnRendererHistograms(const std::vector<std::string>& histogram_info); void OnReceiveContextMenuMsg(const IPC::Message& msg); diff --git a/chrome/browser/spellcheck_unittest.cc b/chrome/browser/spellcheck_unittest.cc index 8a9731f..aa76bf0 100644 --- a/chrome/browser/spellcheck_unittest.cc +++ b/chrome/browser/spellcheck_unittest.cc @@ -495,3 +495,36 @@ TEST_F(SpellCheckTest, DISABLED_SpellCheckSuggestionsAddToDictionary_EN_US) { // Remove the temp custom dictionary file. file_util::Delete(custom_dictionary_file, false); } + +TEST_F(SpellCheckTest, GetAutoCorrectionWord_EN_US) { + static const struct { + // A misspelled word. + const wchar_t* input; + + // An expected result for this test case. + // Should be an empty string if there are no suggestions for auto correct. + const wchar_t* expected_result; + } kTestCases[] = { + {L"teh", L"the"}, + {L"moer", L"more"}, + {L"watre", L"water"}, + {L"noen", L""}, + {L"what", L""}, + }; + + 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 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); + + // Check for spelling. + EXPECT_EQ(expected_autocorrect_word, autocorrect_word); + } +} diff --git a/chrome/browser/spellchecker.cc b/chrome/browser/spellchecker.cc index 1a28cf1..75ef204 100644 --- a/chrome/browser/spellchecker.cc +++ b/chrome/browser/spellchecker.cc @@ -30,6 +30,7 @@ using base::TimeTicks; static const int kMaxSuggestions = 5; // Max number of dictionary suggestions. +static const int kMaxAutoCorrectWordSize = 8; namespace { @@ -475,6 +476,49 @@ bool SpellChecker::Initialize() { return false; } +void SpellChecker::GetAutoCorrectionWord(const std::wstring& word, + std::wstring* autocorrect_word) { + autocorrect_word->clear(); + int word_length = static_cast<int>(word.size()); + if (word_length < 2 || word_length > kMaxAutoCorrectWordSize) + return; + + wchar_t misspelled_word[kMaxAutoCorrectWordSize + 1]; + const wchar_t* word_char = word.c_str(); + for (int i = 0; i <= kMaxAutoCorrectWordSize; i++) { + if (i >= word_length) + misspelled_word[i] = NULL; + else + misspelled_word[i] = word_char[i]; + } + + // Swap adjacent characters and spellcheck. + int misspelling_start, misspelling_len; + for (int i = 0; i < word_length - 1; i++) { + // Swap. + std::swap(misspelled_word[i], misspelled_word[i + 1]); + + // Check spelling. + misspelling_start = misspelling_len = 0; + SpellCheckWord(misspelled_word, word_length, &misspelling_start, + &misspelling_len, NULL); + + // Make decision: if only one swap produced a valid word, then we want to + // return it. If we found two or more, we don't do autocorrection. + if (misspelling_len == 0) { + if (autocorrect_word->empty()) { + autocorrect_word->assign(misspelled_word); + } else { + autocorrect_word->clear(); + return; + } + } + + // Restore the swapped characters. + std::swap(misspelled_word[i], misspelled_word[i + 1]); + } +} + void SpellChecker::AddCustomWordsToHunspell() { // Add custom words to Hunspell. // This should be done in File Loop, but since Hunspell is in this IO Loop, diff --git a/chrome/browser/spellchecker.h b/chrome/browser/spellchecker.h index 2827991..0c0b535 100644 --- a/chrome/browser/spellchecker.h +++ b/chrome/browser/spellchecker.h @@ -75,6 +75,12 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker> { int* misspelling_len, std::vector<std::wstring>* optional_suggestions); + // 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, + std::wstring* autocorrect_word); + // Add custom word to the dictionary, which means: // a) Add it to the current hunspell object for immediate use, // b) Add the word to a file in disk for custom dictionary. diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 3954f77..45e4e97 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -428,9 +428,11 @@ const wchar_t kWebWorkerShareProcesses[] = L"web-worker-share-processes"; // Enables the bookmark menu. const wchar_t kBookmarkMenu[] = L"bookmark-menu"; +// Enables auto spell correction. +const wchar_t kAutoSpellCorrect[] = L"auto-spell-correct"; + // Enables StatsTable, logging statistics to a global named shared memory table. const wchar_t kEnableStatsTable[] = L"enable-stats-table"; - // Enables the Omnibox2 popup and functionality. const wchar_t kEnableOmnibox2[] = L"enable-omnibox2"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index f5228121..ef3f796 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -162,8 +162,11 @@ extern const wchar_t kWebWorkerProcessPerCore[]; extern const wchar_t kWebWorkerShareProcesses[]; extern const wchar_t kBookmarkMenu[]; + extern const wchar_t kEnableStatsTable[]; +extern const wchar_t kAutoSpellCorrect[]; + extern const wchar_t kEnableOmnibox2[]; extern const wchar_t kDisableAudio[]; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 1966f9e..90882c1 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -815,6 +815,10 @@ IPC_BEGIN_MESSAGES(ViewHost) int /* misspell location */, int /* misspell length */) + IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_GetAutoCorrectWord, + std::wstring /* word to check */, + std::wstring /* autocorrected word */) + // Initiate a download based on user actions like 'ALT+click'. IPC_MESSAGE_ROUTED2(ViewHostMsg_DownloadUrl, GURL /* url */, diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 99e662b..979f74f 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -2298,6 +2298,15 @@ void RenderView::SpellCheck(const std::wstring& word, int& misspell_location, &misspell_length)); } +void RenderView::GetAutoCorrectWord(const std::wstring& misspelled_word, + std::wstring& autocorrect_word) { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kAutoSpellCorrect)) { + Send(new ViewHostMsg_GetAutoCorrectWord(routing_id_, misspelled_word, + &autocorrect_word)); + } +} + void RenderView::SetInputMethodState(bool enabled) { // Save the updated IME status and mark the input focus has been updated. // The IME status is to be sent to a browser process next time when diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 7b5665d..a993327 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -309,6 +309,8 @@ class RenderView : public RenderWidget, virtual bool WasOpenedByUserGesture() const; virtual void SpellCheck(const std::wstring& word, int& misspell_location, int& misspell_length); + virtual void GetAutoCorrectWord(const std::wstring& misspelled_word, + std::wstring& autocorrect_word); virtual void SetInputMethodState(bool enabled); virtual void ScriptedPrint(WebFrame* frame); virtual void WebInspectorOpened(int num_resources); diff --git a/webkit/glue/editor_client_impl.cc b/webkit/glue/editor_client_impl.cc index c64a3cf..7216e4f 100644 --- a/webkit/glue/editor_client_impl.cc +++ b/webkit/glue/editor_client_impl.cc @@ -843,6 +843,18 @@ void EditorClientImpl::checkSpellingOfString(const UChar* str, int length, *misspellingLength = spell_length; } +WebCore::String EditorClientImpl::getAutoCorrectSuggestionForMisspelledWord( + const WebCore::String& misspelledWord) { + WebViewDelegate* d = web_view_->delegate(); + std::wstring autocorrect_word; + if (isContinuousSpellCheckingEnabled() && d) { + std::wstring word = webkit_glue::StringToStdWString(misspelledWord); + d->GetAutoCorrectWord(word, autocorrect_word); + } + + return webkit_glue::StdWStringToString(autocorrect_word); +} + void EditorClientImpl::checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, diff --git a/webkit/glue/editor_client_impl.h b/webkit/glue/editor_client_impl.h index 4104a4b..0778b48 100644 --- a/webkit/glue/editor_client_impl.h +++ b/webkit/glue/editor_client_impl.h @@ -92,6 +92,8 @@ class EditorClientImpl : public WebCore::EditorClient { WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); + virtual WebCore::String getAutoCorrectSuggestionForMisspelledWord( + const WebCore::String& misspelledWord); virtual void updateSpellingUIWithGrammarString(const WebCore::String&, const WebCore::GrammarDetail& detail); virtual void updateSpellingUIWithMisspelledWord(const WebCore::String&); diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h index 193aef4..186940b 100644 --- a/webkit/glue/webview_delegate.h +++ b/webkit/glue/webview_delegate.h @@ -761,6 +761,12 @@ class WebViewDelegate : virtual public WebWidgetDelegate { misspell_location = misspell_length = 0; } + // Computes an auto correct word for a misspelled word. If no word is found, + // empty string is computed. + virtual void GetAutoCorrectWord(const std::wstring& misspelled_word, + std::wstring& autocorrect_word) { + } + // Changes the state of the input method editor. virtual void SetInputMethodState(bool enabled) { } |