diff options
author | morrita@chromium.org <morrita@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 09:00:13 +0000 |
---|---|---|
committer | morrita@chromium.org <morrita@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 09:00:13 +0000 |
commit | 5efcef635ea9483b64d4ba096ae3b922b2fa4ec2 (patch) | |
tree | a634f4704419113d707e25925e2076d238c62327 /chrome/renderer/spellchecker | |
parent | 71bb51210b29a5546679b9c8be2990f3254f3d08 (diff) | |
download | chromium_src-5efcef635ea9483b64d4ba096ae3b922b2fa4ec2.zip chromium_src-5efcef635ea9483b64d4ba096ae3b922b2fa4ec2.tar.gz chromium_src-5efcef635ea9483b64d4ba096ae3b922b2fa4ec2.tar.bz2 |
Integrating Mac OS Grammar checker into Chromium.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6392045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75577 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/spellchecker')
-rw-r--r-- | chrome/renderer/spellchecker/spellcheck.h | 8 | ||||
-rw-r--r-- | chrome/renderer/spellchecker/spellcheck_provider.cc | 72 | ||||
-rw-r--r-- | chrome/renderer/spellchecker/spellcheck_provider.h | 66 | ||||
-rw-r--r-- | chrome/renderer/spellchecker/spellcheck_provider_unittest.cc | 178 |
4 files changed, 324 insertions, 0 deletions
diff --git a/chrome/renderer/spellchecker/spellcheck.h b/chrome/renderer/spellchecker/spellcheck.h index 42dde87..243da89 100644 --- a/chrome/renderer/spellchecker/spellcheck.h +++ b/chrome/renderer/spellchecker/spellcheck.h @@ -22,6 +22,8 @@ namespace file_util { class MemoryMappedFile; } +// TODO(morrita): Needs reorg with SpellCheckProvider. +// See http://crbug.com/73699. class SpellCheck { public: SpellCheck(); @@ -65,6 +67,12 @@ class SpellCheck { // |hunspell_| has been initialized. void WordAdded(const std::string& word); + // Returns true if the spellchecker delegate checking to a system-provided + // checker on the browser process. + bool is_using_platform_spelling_engine() const { + return is_using_platform_spelling_engine_; + } + private: // Initializes the Hunspell dictionary, or does nothing if |hunspell_| is // non-null. This blocks. diff --git a/chrome/renderer/spellchecker/spellcheck_provider.cc b/chrome/renderer/spellchecker/spellcheck_provider.cc new file mode 100644 index 0000000..779844d --- /dev/null +++ b/chrome/renderer/spellchecker/spellcheck_provider.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/spellchecker/spellcheck_provider.h" + +#include "chrome/common/render_messages.h" +#include "chrome/renderer/render_thread.h" +#include "chrome/renderer/spellchecker/spellcheck.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCheckingCompletion.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCheckingResult.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" + +using WebKit::WebString; +using WebKit::WebTextCheckingCompletion; +using WebKit::WebTextCheckingResult; + +SpellCheckProvider::SpellCheckProvider(RenderView* render_view, + SpellCheck* spellcheck) + : RenderViewObserver(render_view), + spellcheck_(spellcheck) { +} + +SpellCheckProvider::~SpellCheckProvider() { +} + +void SpellCheckProvider::RequestTextChecking( + const WebString& text, + int document_tag, + WebTextCheckingCompletion* completion) { + // Text check (unified request for grammar and spell check) is only + // available for browser process, so we ask the system sellchecker + // over IPC or return an empty result if the checker is not + // available. + if (!is_using_platform_spelling_engine()) { + completion->didFinishCheckingText + (std::vector<WebTextCheckingResult>()); + return; + } + + Send(new ViewHostMsg_SpellChecker_PlatformRequestTextCheck( + routing_id(), + text_check_completions_.Add(completion), + document_tag, + text)); +} + +void SpellCheckProvider::OnSpellCheckerRespondTextCheck( + int identifier, + int tag, + const std::vector<WebTextCheckingResult>& results) { + WebKit::WebTextCheckingCompletion* completion = + text_check_completions_.Lookup(identifier); + if (!completion) + return; + text_check_completions_.Remove(identifier); + completion->didFinishCheckingText(results); +} + +bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message) + IPC_MESSAGE_HANDLER(ViewMsg_SpellChecker_RespondTextCheck, + OnSpellCheckerRespondTextCheck) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +bool SpellCheckProvider::is_using_platform_spelling_engine() const { + return spellcheck_ && spellcheck_->is_using_platform_spelling_engine(); +} diff --git a/chrome/renderer/spellchecker/spellcheck_provider.h b/chrome/renderer/spellchecker/spellcheck_provider.h new file mode 100644 index 0000000..9496dda --- /dev/null +++ b/chrome/renderer/spellchecker/spellcheck_provider.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_SPELLCHECKER_SPELLCHECK_PROVIDER_H_ +#define CHROME_RENDERER_SPELLCHECKER_SPELLCHECK_PROVIDER_H_ +#pragma once + +#include <vector> + +#include "base/id_map.h" +#include "chrome/renderer/render_view_observer.h" + +class RenderView; +class SpellCheck; + +namespace WebKit { +class WebString; +class WebTextCheckingResult; +class WebTextCheckingCompletion; +} + +// This class deals with invoking browser-side spellcheck mechanism +// which is done asynchronously. +class SpellCheckProvider : public RenderViewObserver { + public: + typedef IDMap<WebKit::WebTextCheckingCompletion> WebTextCheckCompletions; + + SpellCheckProvider(RenderView* render_view, SpellCheck* spellcheck); + virtual ~SpellCheckProvider(); + + // Reqeusts async spell and grammar checker to the platform text + // checker, which is available on the browser process. + void RequestTextChecking( + const WebKit::WebString& text, + int document_tag, + WebKit::WebTextCheckingCompletion* completion); + + // Check the availability of the platform spellchecker. + // Makes this virtual for overriding on the unittest. + virtual bool is_using_platform_spelling_engine() const; + + // The number of ongoing IPC requests. + size_t pending_text_request_size() const { + return text_check_completions_.size(); + } + + // RenderViewObserver implementation. + virtual bool OnMessageReceived(const IPC::Message& message); + + private: + // A message handler that receives async results for RequestTextChecking(). + void OnSpellCheckerRespondTextCheck( + int identifier, + int tag, + const std::vector<WebKit::WebTextCheckingResult>& results); + + // Holds ongoing spellchecking operations, assigns IDs for the IPC routing. + WebTextCheckCompletions text_check_completions_; + // Spellcheck implementation for use. Weak reference. + SpellCheck* spellcheck_; + + DISALLOW_COPY_AND_ASSIGN(SpellCheckProvider); +}; + +#endif // CHROME_RENDERER_SPELLCHECKER_SPELLCHECK_PROVIDER_H_ diff --git a/chrome/renderer/spellchecker/spellcheck_provider_unittest.cc b/chrome/renderer/spellchecker/spellcheck_provider_unittest.cc new file mode 100644 index 0000000..bb63f19 --- /dev/null +++ b/chrome/renderer/spellchecker/spellcheck_provider_unittest.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> + +#include "base/utf_string_conversions.h" +#include "chrome/common/render_messages.h" +#include "chrome/renderer/spellchecker/spellcheck_provider.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCheckingCompletion.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCheckingResult.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" + +namespace { + +// Faked test target, which stores sent message for verification, +// and allows manipulate |is_using_platform_spelling_engine| parameter. +class TestingSpellCheckProvider : public SpellCheckProvider { + public: + TestingSpellCheckProvider() + : SpellCheckProvider(NULL, NULL), + is_using_platform_spelling_engine_(true) { + } + + virtual ~TestingSpellCheckProvider() { + for (std::vector<IPC::Message*>::iterator i = messages_.begin(); + i != messages_.end(); + ++i) { + delete *i; + } + } + + virtual bool Send(IPC::Message* message) { + messages_.push_back(message); + return true; + } + + virtual bool is_using_platform_spelling_engine() const { + return is_using_platform_spelling_engine_; + } + + std::vector<IPC::Message*> messages_; + bool is_using_platform_spelling_engine_; +}; + +// A fake completion object for verification. +class FakeTextCheckingCompletion : public WebKit::WebTextCheckingCompletion { + public: + FakeTextCheckingCompletion() + : completion_count_(0) { + } + + virtual void didFinishCheckingText( + const WebKit::WebVector<WebKit::WebTextCheckingResult>& results) { + completion_count_++; + last_results_ = results; + } + + size_t completion_count_; + WebKit::WebVector<WebKit::WebTextCheckingResult> last_results_; +}; + +class SpellCheckProviderTest : public testing::Test { + public: + SpellCheckProviderTest() { } + virtual ~SpellCheckProviderTest() { } + + protected: + TestingSpellCheckProvider provider_; +}; + +struct MessageParameters { + MessageParameters() + : router_id(0), + request_id(0), + document_tag(0) { } + + int router_id; + int request_id; + int document_tag; + string16 text; +}; + +MessageParameters ReadPlatformRequestTextCheck(IPC::Message* message) { + MessageParameters parameters; + bool ok = ViewHostMsg_SpellChecker_PlatformRequestTextCheck::Read( + message, + ¶meters.router_id, + ¶meters.request_id, + ¶meters.document_tag, + ¶meters.text); + EXPECT_TRUE(ok); + return parameters; +} + +void FakeMessageArrival(SpellCheckProvider* provider, + const MessageParameters& parameters) { + std::vector<WebKit::WebTextCheckingResult> fake_result; + bool handled = provider->OnMessageReceived( + ViewMsg_SpellChecker_RespondTextCheck + (0, + parameters.request_id, + parameters.document_tag, + fake_result)); + EXPECT_TRUE(handled); +} + +TEST_F(SpellCheckProviderTest, SingleRoundtripSuccess) { + FakeTextCheckingCompletion completion; + int document_tag = 123; + + provider_.RequestTextChecking(WebKit::WebString("hello"), + document_tag, + &completion); + EXPECT_EQ(completion.completion_count_, 0U); + EXPECT_EQ(provider_.messages_.size(), 1U); + EXPECT_EQ(provider_.pending_text_request_size(), 1U); + + MessageParameters read_parameters = + ReadPlatformRequestTextCheck(provider_.messages_[0]); + EXPECT_EQ(read_parameters.text, UTF8ToUTF16("hello")); + + FakeMessageArrival(&provider_, read_parameters); + EXPECT_EQ(completion.completion_count_, 1U); + EXPECT_EQ(provider_.pending_text_request_size(), 0U); +} + +TEST_F(SpellCheckProviderTest, TwoRoundtripSuccess) { + int document_tag = 123; + + FakeTextCheckingCompletion completion1; + provider_.RequestTextChecking(WebKit::WebString("hello"), + document_tag, + &completion1); + FakeTextCheckingCompletion completion2; + provider_.RequestTextChecking(WebKit::WebString("bye"), + document_tag, + &completion2); + + EXPECT_EQ(completion1.completion_count_, 0U); + EXPECT_EQ(completion2.completion_count_, 0U); + EXPECT_EQ(provider_.messages_.size(), 2U); + EXPECT_EQ(provider_.pending_text_request_size(), 2U); + + MessageParameters read_parameters1 = + ReadPlatformRequestTextCheck(provider_.messages_[0]); + EXPECT_EQ(read_parameters1.text, UTF8ToUTF16("hello")); + + MessageParameters read_parameters2 = + ReadPlatformRequestTextCheck(provider_.messages_[1]); + EXPECT_EQ(read_parameters2.text, UTF8ToUTF16("bye")); + + FakeMessageArrival(&provider_, read_parameters1); + EXPECT_EQ(completion1.completion_count_, 1U); + EXPECT_EQ(completion2.completion_count_, 0U); + EXPECT_EQ(provider_.pending_text_request_size(), 1U); + + FakeMessageArrival(&provider_, read_parameters2); + EXPECT_EQ(completion1.completion_count_, 1U); + EXPECT_EQ(completion2.completion_count_, 1U); + EXPECT_EQ(provider_.pending_text_request_size(), 0U); +} + +TEST_F(SpellCheckProviderTest, PlatformEngineUnavailable) { + provider_.is_using_platform_spelling_engine_ = false; + + int document_tag = 123; + FakeTextCheckingCompletion completion; + provider_.RequestTextChecking(WebKit::WebString("hello"), + document_tag, + &completion); + EXPECT_EQ(completion.completion_count_, 1U); + EXPECT_EQ(provider_.messages_.size(), 0U); + EXPECT_EQ(provider_.pending_text_request_size(), 0U); +} + +} // namespace |