Commit e3d7e30c authored by Noel Gordon's avatar Noel Gordon Committed by Commit Bot

Convert render process component common Spellcheck IPC to mojo

Add a render process mojo interface exposed to the browser for
receiving process-wide spellcheck control and updates from the
browser process.

Fold the enable IPC into the Initialize() mojo API (the enable
IPC was only ever called right after an Init IPC) by adding an
|enable| argument. Mojo does not support set<> so use vector<>
instead on the mojo APIs. Use a binding set on the server-side
to automate mojo request disconnect and clean-up.

Update the browser test to use mojo instead of IPC in the mock
renderer and add a test for a custom dictionary update. Change
the InitSpellcheck helper: spellcheck->InitForRenderer() isn't
needed (creating a SpellcheckService does that for us).

Bug:714480

Change-Id: I5365c42fc10c7766054c5b80fb366ceaa4d59159
Reviewed-on: https://chromium-review.googlesource.com/487341Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Reviewed-by: default avatarMartin Barbella <mbarbella@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: default avatarSam McNally <sammc@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@chromium.org>
Commit-Queue: Noel Gordon <noel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#471125}
parent 6b54cbfc
......@@ -4,7 +4,8 @@
"service_manager:connector": {
"provides": {
"browser": [
"chrome::mojom::ResourceUsageReporter"
"chrome::mojom::ResourceUsageReporter",
"spellcheck::mojom::SpellChecker"
]
}
},
......
......@@ -20,9 +20,8 @@
#include "components/spellcheck/browser/spellcheck_host_metrics.h"
#include "components/spellcheck/browser/spellcheck_platform.h"
#include "components/spellcheck/browser/spelling_service_client.h"
#include "components/spellcheck/common/spellcheck_bdict_language.h"
#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_messages.h"
#include "components/spellcheck/spellcheck_build_features.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
......@@ -31,7 +30,6 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "ipc/ipc_platform_file.h"
using content::BrowserThread;
......@@ -174,27 +172,27 @@ void SpellcheckService::InitForRenderer(content::RenderProcessHost* process) {
if (SpellcheckServiceFactory::GetForContext(context) != this)
return;
PrefService* prefs = user_prefs::UserPrefs::Get(context);
std::vector<SpellCheckBDictLanguage> bdict_languages;
const PrefService* prefs = user_prefs::UserPrefs::Get(context);
std::vector<spellcheck::mojom::SpellCheckBDictLanguagePtr> dictionaries;
for (const auto& hunspell_dictionary : hunspell_dictionaries_) {
bdict_languages.push_back(SpellCheckBDictLanguage());
bdict_languages.back().language = hunspell_dictionary->GetLanguage();
bdict_languages.back().file =
hunspell_dictionary->GetDictionaryFile().IsValid()
? IPC::GetPlatformFileForTransit(
hunspell_dictionary->GetDictionaryFile().GetPlatformFile(),
false)
: IPC::InvalidPlatformFileForTransit();
dictionaries.push_back(spellcheck::mojom::SpellCheckBDictLanguage::New(
hunspell_dictionary->GetDictionaryFile().Duplicate(),
hunspell_dictionary->GetLanguage()));
}
bool enabled =
prefs->GetBoolean(spellcheck::prefs::kEnableSpellcheck) &&
!bdict_languages.empty();
process->Send(new SpellCheckMsg_Init(
bdict_languages,
enabled ? custom_dictionary_->GetWords() : std::set<std::string>()));
process->Send(new SpellCheckMsg_EnableSpellCheck(enabled));
bool enable = prefs->GetBoolean(spellcheck::prefs::kEnableSpellcheck) &&
!dictionaries.empty();
std::vector<std::string> custom_words;
if (enable) {
custom_words.assign(custom_dictionary_->GetWords().begin(),
custom_dictionary_->GetWords().end());
}
spellcheck::mojom::SpellCheckerPtr spellchecker;
content::BindInterface(process, &spellchecker);
spellchecker->Initialize(std::move(dictionaries), custom_words, enable);
}
SpellCheckHostMetrics* SpellcheckService::GetMetrics() const {
......@@ -257,13 +255,20 @@ void SpellcheckService::OnCustomDictionaryLoaded() {
}
void SpellcheckService::OnCustomDictionaryChanged(
const SpellcheckCustomDictionary::Change& dictionary_change) {
for (content::RenderProcessHost::iterator i(
content::RenderProcessHost::AllHostsIterator());
!i.IsAtEnd(); i.Advance()) {
i.GetCurrentValue()->Send(new SpellCheckMsg_CustomDictionaryChanged(
dictionary_change.to_add(),
dictionary_change.to_remove()));
const SpellcheckCustomDictionary::Change& change) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto process_hosts(content::RenderProcessHost::AllHostsIterator());
const std::vector<std::string> additions(change.to_add().begin(),
change.to_add().end());
const std::vector<std::string> deletions(change.to_remove().begin(),
change.to_remove().end());
while (!process_hosts.IsAtEnd()) {
spellcheck::mojom::SpellCheckerPtr spellchecker;
content::BindInterface(process_hosts.GetCurrentValue(), &spellchecker);
spellchecker->CustomDictionaryChanged(additions, deletions);
process_hosts.Advance();
}
}
......
......@@ -130,7 +130,7 @@ class SpellcheckService : public KeyedService,
// SpellcheckCustomDictionary::Observer implementation.
void OnCustomDictionaryLoaded() override;
void OnCustomDictionaryChanged(
const SpellcheckCustomDictionary::Change& dictionary_change) override;
const SpellcheckCustomDictionary::Change& change) override;
// SpellcheckHunspellDictionary::Observer implementation.
void OnHunspellDictionaryInitialized(const std::string& language) override;
......
......@@ -29,8 +29,8 @@
#include "chrome/test/base/in_process_browser_test.h"
#include "components/prefs/pref_service.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_messages.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_utils.h"
......@@ -51,32 +51,20 @@ const uint8_t kCorruptedBDICT[] = {
0x49, 0x00, 0x68, 0x02, 0x73, 0x06, 0x74, 0x0b, 0x77, 0x11, 0x79, 0x15,
};
// Clears IPC messages before a preference change. Runs the runloop after the
// preference change.
class ScopedPreferenceChange {
public:
explicit ScopedPreferenceChange(IPC::TestSink* sink) {
sink->ClearMessages();
}
~ScopedPreferenceChange() {
base::RunLoop().RunUntilIdle();
}
private:
DISALLOW_COPY_AND_ASSIGN(ScopedPreferenceChange);
};
} // namespace
class SpellcheckServiceBrowserTest : public InProcessBrowserTest {
class SpellcheckServiceBrowserTest : public InProcessBrowserTest,
public spellcheck::mojom::SpellChecker {
public:
SpellcheckServiceBrowserTest() : binding_(this) {}
void SetUpOnMainThread() override {
renderer_.reset(new content::MockRenderProcessHost(GetContext()));
prefs_ = user_prefs::UserPrefs::Get(GetContext());
}
void TearDownOnMainThread() override {
binding_.Close();
prefs_ = nullptr;
renderer_.reset();
}
......@@ -101,26 +89,43 @@ class SpellcheckServiceBrowserTest : public InProcessBrowserTest {
base::SplitString(multiple_dictionaries, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY));
prefs_->Set(spellcheck::prefs::kSpellCheckDictionaries, dictionaries_value);
SpellcheckService* spellcheck =
SpellcheckServiceFactory::GetForRenderProcessId(renderer_->GetID());
ASSERT_NE(nullptr, spellcheck);
spellcheck->InitForRenderer(renderer_.get());
// Override |renderer_| requests for the spellcheck::mojom::SpellChecker
// interface so we can test the SpellChecker request flow.
renderer_->OverrideBinderForTesting(
spellcheck::mojom::SpellChecker::Name_,
base::Bind(&SpellcheckServiceBrowserTest::Bind,
base::Unretained(this)));
}
void EnableSpellcheck(bool enable_spellcheck) {
ScopedPreferenceChange scope(&renderer_->sink());
prefs_->SetBoolean(spellcheck::prefs::kEnableSpellcheck,
enable_spellcheck);
}
void ChangeCustomDictionary() {
SpellcheckService* spellcheck =
SpellcheckServiceFactory::GetForRenderProcessId(renderer_->GetID());
ASSERT_NE(nullptr, spellcheck);
SpellcheckCustomDictionary::Change change;
change.RemoveWord("1");
change.AddWord("2");
change.AddWord("3");
spellcheck->OnCustomDictionaryChanged(change);
}
void SetSingleLanguageDictionary(const std::string& single_dictionary) {
ScopedPreferenceChange scope(&renderer_->sink());
prefs_->SetString(spellcheck::prefs::kSpellCheckDictionary,
single_dictionary);
}
void SetMultiLingualDictionaries(const std::string& multiple_dictionaries) {
ScopedPreferenceChange scope(&renderer_->sink());
base::ListValue dictionaries_value;
dictionaries_value.AppendStrings(
base::SplitString(multiple_dictionaries, ",", base::TRIM_WHITESPACE,
......@@ -141,35 +146,87 @@ class SpellcheckServiceBrowserTest : public InProcessBrowserTest {
}
void SetAcceptLanguages(const std::string& accept_languages) {
ScopedPreferenceChange scope(&renderer_->sink());
prefs_->SetString(prefs::kAcceptLanguages, accept_languages);
}
// Returns the boolean parameter sent in the first
// SpellCheckMsg_EnableSpellCheck message. For example, if spellcheck service
// sent the SpellCheckMsg_EnableSpellCheck(true) message, then this method
// returns true.
bool GetFirstEnableSpellcheckMessageParam() {
const IPC::Message* message = renderer_->sink().GetFirstMessageMatching(
SpellCheckMsg_EnableSpellCheck::ID);
EXPECT_NE(nullptr, message);
if (!message)
return false;
SpellCheckMsg_EnableSpellCheck::Param param;
bool ok = SpellCheckMsg_EnableSpellCheck::Read(message, &param);
EXPECT_TRUE(ok);
if (!ok)
return false;
return std::get<0>(param);
bool GetEnableSpellcheckState(bool initial_state = false) {
spellcheck_enabled_state_ = initial_state;
RunTestRunLoop();
EXPECT_TRUE(initialize_spellcheck_called_);
EXPECT_TRUE(bound_connection_closed_);
return spellcheck_enabled_state_;
}
bool GetCustomDictionaryChangedState() {
RunTestRunLoop();
EXPECT_TRUE(bound_connection_closed_);
return custom_dictionary_changed_called_;
}
private:
// Spins a RunLoop to deliver the Mojo SpellChecker request flow.
void RunTestRunLoop() {
bound_connection_closed_ = false;
initialize_spellcheck_called_ = false;
custom_dictionary_changed_called_ = false;
base::RunLoop run_loop;
quit_ = run_loop.QuitClosure();
run_loop.Run();
}
// Binds requests for the SpellChecker interface.
void Bind(mojo::ScopedMessagePipeHandle handle) {
binding_.Bind(std::move(handle));
binding_.set_connection_error_handler(
base::Bind(&SpellcheckServiceBrowserTest::BoundConnectionClosed,
base::Unretained(this)));
}
// The requester closes (disconnects) when done.
void BoundConnectionClosed() {
bound_connection_closed_ = true;
binding_.Close();
if (quit_)
std::move(quit_).Run();
}
// spellcheck::mojom::SpellChecker:
void Initialize(
std::vector<spellcheck::mojom::SpellCheckBDictLanguagePtr> dictionaries,
const std::vector<std::string>& custom_words,
bool enable) override {
initialize_spellcheck_called_ = true;
spellcheck_enabled_state_ = enable;
}
void CustomDictionaryChanged(
const std::vector<std::string>& words_added,
const std::vector<std::string>& words_removed) override {
custom_dictionary_changed_called_ = true;
EXPECT_EQ(1u, words_removed.size());
EXPECT_EQ(2u, words_added.size());
}
// Mocked RenderProcessHost.
std::unique_ptr<content::MockRenderProcessHost> renderer_;
// Not owned preferences service.
PrefService* prefs_;
// Binding to receive the SpellChecker request flow.
mojo::Binding<spellcheck::mojom::SpellChecker> binding_;
// Quits the RunLoop on SpellChecker request flow completion.
base::OnceClosure quit_;
// Used to verify the SpellChecker request flow.
bool bound_connection_closed_;
bool custom_dictionary_changed_called_;
bool initialize_spellcheck_called_;
bool spellcheck_enabled_state_;
DISALLOW_COPY_AND_ASSIGN(SpellcheckServiceBrowserTest);
};
// Removing a spellcheck language from accept languages should remove it from
......@@ -195,10 +252,10 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
// spellcheck' message to the renderer.
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, StartWithSpellcheck) {
InitSpellcheck(true, "", "en-US,fr");
EXPECT_TRUE(GetFirstEnableSpellcheckMessageParam());
EXPECT_TRUE(GetEnableSpellcheckState());
EnableSpellcheck(false);
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
EXPECT_FALSE(GetEnableSpellcheckState(true));
}
// Starting with only a single-language spellcheck setting should send the
......@@ -207,10 +264,10 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, StartWithSpellcheck) {
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
StartWithSingularLanguagePreference) {
InitSpellcheck(true, "en-US", "");
EXPECT_TRUE(GetFirstEnableSpellcheckMessageParam());
EXPECT_TRUE(GetEnableSpellcheckState());
SetMultiLingualDictionaries("");
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
EXPECT_FALSE(GetEnableSpellcheckState(true));
}
// Starting with a multi-language spellcheck setting should send the 'enable
......@@ -219,10 +276,10 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
StartWithMultiLanguagePreference) {
InitSpellcheck(true, "", "en-US,fr");
EXPECT_TRUE(GetFirstEnableSpellcheckMessageParam());
EXPECT_TRUE(GetEnableSpellcheckState());
SetMultiLingualDictionaries("");
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
EXPECT_FALSE(GetEnableSpellcheckState(true));
}
// Starting with both single-language and multi-language spellcheck settings
......@@ -231,10 +288,10 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
StartWithBothLanguagePreferences) {
InitSpellcheck(true, "en-US", "en-US,fr");
EXPECT_TRUE(GetFirstEnableSpellcheckMessageParam());
EXPECT_TRUE(GetEnableSpellcheckState());
SetMultiLingualDictionaries("");
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
EXPECT_FALSE(GetEnableSpellcheckState(true));
}
// Starting without spellcheck languages should send the 'disable spellcheck'
......@@ -244,10 +301,10 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
DISABLED_StartWithoutLanguages) {
InitSpellcheck(true, "", "");
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
EXPECT_FALSE(GetEnableSpellcheckState(true));
SetMultiLingualDictionaries("en-US");
EXPECT_TRUE(GetFirstEnableSpellcheckMessageParam());
EXPECT_TRUE(GetEnableSpellcheckState());
}
// Starting with spellcheck disabled should send the 'disable spellcheck'
......@@ -255,10 +312,26 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
// 'enable spellcheck' message to the renderer.
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, StartWithoutSpellcheck) {
InitSpellcheck(false, "", "en-US,fr");
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
EXPECT_FALSE(GetEnableSpellcheckState(true));
EnableSpellcheck(true);
EXPECT_TRUE(GetFirstEnableSpellcheckMessageParam());
EXPECT_TRUE(GetEnableSpellcheckState());
}
// A custom dictionary state change should send a 'custom dictionary changed'
// message to the renderer, regardless of the spellcheck enabled state.
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, CustomDictionaryChanged) {
InitSpellcheck(true, "en-US", "");
EXPECT_TRUE(GetEnableSpellcheckState());
ChangeCustomDictionary();
EXPECT_TRUE(GetCustomDictionaryChangedState());
EnableSpellcheck(false);
EXPECT_FALSE(GetEnableSpellcheckState(true));
ChangeCustomDictionary();
EXPECT_TRUE(GetCustomDictionaryChangedState());
}
// Tests that we can delete a corrupted BDICT file used by hunspell. We do not
......
......@@ -2,9 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//mojo/public/tools/bindings/mojom.gni")
source_set("common") {
sources = [
"spellcheck_bdict_language.h",
"spellcheck_common.cc",
"spellcheck_common.h",
"spellcheck_features.cc",
......@@ -18,11 +19,23 @@ source_set("common") {
]
public_deps = [
":interfaces",
"//components/spellcheck:build_features",
]
deps = [
"//base:i18n",
"//ipc",
"//third_party/icu",
]
}
mojom("interfaces") {
sources = [
"spellcheck.mojom",
]
public_deps = [
"//mojo/common:common_custom_types",
]
}
per-file *_messages*.h=set noparent
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
// Copyright 2017 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.
module spellcheck.mojom;
import "mojo/common/file.mojom";
// Render process interface exposed to the browser for receiving process-
// wide spellcheck control and updates from the browser process.
//
interface SpellChecker {
// Initialize the render process spellchecker. Called after startup and
// also in response to a render process RequestDictionary request.
Initialize(array<SpellCheckBDictLanguage> dictionaries,
array<string> custom_words,
bool enable);
// Custom dictionary words have been added or removed: update the local
// custom word list.
CustomDictionaryChanged(array<string> words_added,
array<string> words_removed);
};
struct SpellCheckBDictLanguage {
mojo.common.mojom.File? file;
string language;
};
// Copyright 2015 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 COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_BDICT_LANGUAGE_H_
#define COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_BDICT_LANGUAGE_H_
#include <string>
#include "ipc/ipc_platform_file.h"
struct SpellCheckBDictLanguage {
IPC::PlatformFileForTransit file;
std::string language;
};
#endif // COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_BDICT_LANGUAGE_H_
......@@ -7,11 +7,9 @@
#include <stdint.h>
#include "components/spellcheck/common/spellcheck_bdict_language.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "components/spellcheck/spellcheck_build_features.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
#if !BUILDFLAG(ENABLE_SPELLCHECK)
#error "Spellcheck should be enabled"
......@@ -28,28 +26,8 @@ IPC_STRUCT_TRAITS_BEGIN(SpellCheckResult)
IPC_STRUCT_TRAITS_MEMBER(replacement)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(SpellCheckBDictLanguage)
IPC_STRUCT_TRAITS_MEMBER(file)
IPC_STRUCT_TRAITS_MEMBER(language)
IPC_STRUCT_TRAITS_END()
// Messages sent from the browser to the renderer.
IPC_MESSAGE_CONTROL1(SpellCheckMsg_EnableSpellCheck, bool)
// Passes some initialization params from the browser to the renderer's
// spellchecker. This can be called directly after startup or in (async)
// response to a RequestDictionary ViewHost message.
IPC_MESSAGE_CONTROL2(SpellCheckMsg_Init,
std::vector<SpellCheckBDictLanguage> /* bdict_languages */,
std::set<std::string> /* custom_dict_words */)
// Words have been added and removed in the custom dictionary; update the local
// custom word list.
IPC_MESSAGE_CONTROL2(SpellCheckMsg_CustomDictionaryChanged,
std::set<std::string> /* words_added */,
std::set<std::string> /* words_removed */)
#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
// Sends text-check results from the Spelling service when the service finishes
// checking text received by a SpellCheckHostMsg_CallSpellingService message.
......
......@@ -46,8 +46,10 @@ source_set("renderer") {
deps = [
"//base:i18n",
"//components/spellcheck/common",
"//content/public/common",
"//content/public/renderer",
"//ipc",
"//services/service_manager/public/cpp",
"//third_party/WebKit/public:blink",
"//third_party/icu",
]
......
include_rules = [
"+content/public/common",
"+content/public/renderer",
"+ipc",
"+third_party/WebKit/public",
"+mojo/public/cpp/bindings",
"+services/service_manager/public/cpp",
"+third_party/hunspell",
"+third_party/WebKit/public",
]
......@@ -20,16 +20,18 @@
#include "build/build_config.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_features.h"
#include "components/spellcheck/common/spellcheck_messages.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "components/spellcheck/common/spellcheck_switches.h"
#include "components/spellcheck/renderer/spellcheck_language.h"
#include "components/spellcheck/renderer/spellcheck_provider.h"
#include "components/spellcheck/spellcheck_build_features.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/simple_connection_filter.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_visitor.h"
#include "content/public/renderer/render_thread.h"
#include "ipc/ipc_platform_file.h"
#include "services/service_manager/public/cpp/bind_source_info.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
......@@ -149,7 +151,22 @@ class SpellCheck::SpellcheckRequest {
// and as such the SpellCheckProviders will never be notified of different
// values.
// TODO(groby): Simplify this.
SpellCheck::SpellCheck() : spellcheck_enabled_(true) {}
SpellCheck::SpellCheck() : spellcheck_enabled_(true) {
if (!content::ChildThread::Get())
return; // Can be NULL in tests.
auto* service_manager_connection =
content::ChildThread::Get()->GetServiceManagerConnection();
DCHECK(service_manager_connection);
auto registry = base::MakeUnique<service_manager::BinderRegistry>();
registry->AddInterface(
base::Bind(&SpellCheck::SpellCheckerRequest, base::Unretained(this)),
base::ThreadTaskRunnerHandle::Get());
service_manager_connection->AddConnectionFilter(
base::MakeUnique<content::SimpleConnectionFilter>(std::move(registry)));
}
SpellCheck::~SpellCheck() {
}
......@@ -183,51 +200,46 @@ void SpellCheck::FillSuggestions(
}
}
bool SpellCheck::OnControlMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(SpellCheck, message)
IPC_MESSAGE_HANDLER(SpellCheckMsg_Init, OnInit)
IPC_MESSAGE_HANDLER(SpellCheckMsg_CustomDictionaryChanged,
OnCustomDictionaryChanged)
IPC_MESSAGE_HANDLER(SpellCheckMsg_EnableSpellCheck, OnEnableSpellCheck)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
void SpellCheck::SpellCheckerRequest(
const service_manager::BindSourceInfo& source_info,
spellcheck::mojom::SpellCheckerRequest request) {
spellchecker_bindings_.AddBinding(this, std::move(request));
}
void SpellCheck::OnInit(
const std::vector<SpellCheckBDictLanguage>& bdict_languages,
const std::set<std::string>& custom_words) {
void SpellCheck::Initialize(
std::vector<spellcheck::mojom::SpellCheckBDictLanguagePtr> dictionaries,
const std::vector<std::string>& custom_words,
bool enable) {
languages_.clear();
for (const auto& bdict_language : bdict_languages) {
AddSpellcheckLanguage(
IPC::PlatformFileForTransitToFile(bdict_language.file),
bdict_language.language);
}
custom_dictionary_.Init(custom_words);
for (const auto& dictionary : dictionaries)
AddSpellcheckLanguage(std::move(dictionary->file), dictionary->language);
custom_dictionary_.Init(
std::set<std::string>(custom_words.begin(), custom_words.end()));
#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
PostDelayedSpellCheckTask(pending_request_param_.release());
#endif
}
void SpellCheck::OnCustomDictionaryChanged(
const std::set<std::string>& words_added,
const std::set<std::string>& words_removed) {
custom_dictionary_.OnCustomDictionaryChanged(words_added, words_removed);
if (words_added.empty())
return;
DocumentMarkersRemover markersRemover(words_added);
content::RenderFrame::ForEach(&markersRemover);
}
void SpellCheck::OnEnableSpellCheck(bool enable) {
spellcheck_enabled_ = enable;
UpdateSpellcheckEnabled updater(enable);
content::RenderFrame::ForEach(&updater);
}
void SpellCheck::CustomDictionaryChanged(
const std::vector<std::string>& words_added,
const std::vector<std::string>& words_removed) {
const std::set<std::string> added(words_added.begin(), words_added.end());
custom_dictionary_.OnCustomDictionaryChanged(
added, std::set<std::string>(words_removed.begin(), words_removed.end()));
if (added.empty())
return;
DocumentMarkersRemover markersRemover(added);
content::RenderFrame::ForEach(&markersRemover);
}
// TODO(groby): Make sure we always have a spelling engine, even before
// AddSpellcheckLanguage() is called.
void SpellCheck::AddSpellcheckLanguage(base::File file,
......
......@@ -15,11 +15,12 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/renderer/custom_dictionary_engine.h"
#include "components/spellcheck/spellcheck_build_features.h"
#include "content/public/renderer/render_thread_observer.h"
#include "mojo/public/cpp/bindings/binding_set.h"
struct SpellCheckBDictLanguage;
class SpellcheckLanguage;
struct SpellCheckResult;
......@@ -29,8 +30,8 @@ struct WebTextCheckingResult;
template <typename T> class WebVector;
}
namespace IPC {
class Message;
namespace service_manager {
struct BindSourceInfo;
}
// TODO(morrita): Needs reorg with SpellCheckProvider.
......@@ -38,7 +39,8 @@ class Message;
// Shared spellchecking logic/data for a RenderProcess. All RenderViews use
// this object to perform spellchecking tasks.
class SpellCheck : public content::RenderThreadObserver,
public base::SupportsWeakPtr<SpellCheck> {
public base::SupportsWeakPtr<SpellCheck>,
public spellcheck::mojom::SpellChecker {
public:
// TODO(groby): I wonder if this can be private, non-mac only.
class SpellcheckRequest;
......@@ -121,15 +123,18 @@ class SpellCheck : public content::RenderThreadObserver,
const std::vector<std::vector<base::string16>>& suggestions_list,
std::vector<base::string16>* optional_suggestions);
// RenderThreadObserver implementation:
bool OnControlMessageReceived(const IPC::Message& message) override;
// Binds requests for the SpellChecker interface.
void SpellCheckerRequest(const service_manager::BindSourceInfo& source_info,
spellcheck::mojom::SpellCheckerRequest request);
// Message handlers.
void OnInit(const std::vector<SpellCheckBDictLanguage>& bdict_languages,
const std::set<std::string>& custom_words);
void OnCustomDictionaryChanged(const std::set<std::string>& words_added,
const std::set<std::string>& words_removed);
void OnEnableSpellCheck(bool enable);
// spellcheck::mojom::SpellChecker:
void Initialize(
std::vector<spellcheck::mojom::SpellCheckBDictLanguagePtr> dictionaries,
const std::vector<std::string>& custom_words,
bool enable) override;
void CustomDictionaryChanged(
const std::vector<std::string>& words_added,
const std::vector<std::string>& words_removed) override;
#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
// Posts delayed spellcheck task and clear it if any.
......@@ -147,6 +152,9 @@ class SpellCheck : public content::RenderThreadObserver,
std::unique_ptr<SpellcheckRequest> pending_request_param_;
#endif
// Bindings for SpellChecker clients.
mojo::BindingSet<spellcheck::mojom::SpellChecker> spellchecker_bindings_;
// A vector of objects used to actually check spelling, one for each enabled
// language.
std::vector<std::unique_ptr<SpellcheckLanguage>> languages_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment