summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@theqtcompany.com>2015-10-08 23:49:26 +0200
committerMichal Klocek <michal.klocek@theqtcompany.com>2016-02-01 15:57:30 +0000
commit4713387c052d54e0f5ea02efaeaa25931d1cd7ee (patch)
tree1ada7f8b38cf4c31ab90468a32b1a6df3c4a362b /src/core
parent1910ddb3e2869e50514da343aa6947e88f734c38 (diff)
Add spell checker support
Integrate chromium spell checker: * add spellchecker and dependencies to build * underline misspelled words in html text areas * right-click context menu shows up to 4 options to correct the misspelled word * toggle spell check from context menu * add new qml and widget api calls to qwebengineprofile to enable/disable spell check, select spell check language, get list of supported languages/dictionaries * register new qml spell check properties for QtWebEngine 1.3 * CONFIG+="no_spellcheck" to remove spellcheck support Change-Id: Ie61434ab9493597d7759a6f33794f6859c4e3a4c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/browser_context_adapter.cpp27
-rw-r--r--src/core/browser_context_adapter.h7
-rw-r--r--src/core/browser_context_qt.cpp79
-rw-r--r--src/core/browser_context_qt.h20
-rw-r--r--src/core/chrome_qt.gyp95
-rw-r--r--src/core/config/embedded_linux.pri1
-rw-r--r--src/core/config/linux.pri3
-rw-r--r--src/core/config/mac_osx.pri3
-rw-r--r--src/core/config/windows.pri3
-rw-r--r--src/core/content_browser_client_qt.cpp11
-rw-r--r--src/core/content_main_delegate_qt.cpp4
-rw-r--r--src/core/renderer/content_renderer_client_qt.cpp11
-rw-r--r--src/core/renderer/content_renderer_client_qt.h5
-rw-r--r--src/core/type_conversion.h11
-rw-r--r--src/core/web_contents_adapter.cpp13
-rw-r--r--src/core/web_contents_adapter.h4
-rw-r--r--src/core/web_contents_adapter_client.h13
-rw-r--r--src/core/web_contents_view_qt.cpp17
-rw-r--r--src/core/web_engine_library_info.cpp30
19 files changed, 348 insertions, 9 deletions
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp
index 0b9c4f3f2..94770f0bb 100644
--- a/src/core/browser_context_adapter.cpp
+++ b/src/core/browser_context_adapter.cpp
@@ -431,4 +431,31 @@ void BrowserContextAdapter::clearHttpCache()
m_browserContext->url_request_getter_->clearHttpCache();
}
+#if defined(ENABLE_SPELLCHECK)
+QStringList BrowserContextAdapter::spellCheckLanguages(const QStringList &acceptLanguages)
+{
+ return m_browserContext->spellCheckLanguages(acceptLanguages);
+}
+
+void BrowserContextAdapter::setSpellCheckLanguage(const QString &language)
+{
+ m_browserContext->setSpellCheckLanguage(language);
+}
+
+QString BrowserContextAdapter::spellCheckLanguage() const
+{
+ return m_browserContext->spellCheckLanguage();
+}
+
+void BrowserContextAdapter::setSpellCheckEnabled(bool enabled)
+{
+ m_browserContext->setSpellCheckEnabled(enabled);
+}
+
+bool BrowserContextAdapter::isSpellCheckEnabled() const
+{
+ return m_browserContext->isSpellCheckEnabled();
+}
+#endif
+
} // namespace QtWebEngineCore
diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h
index 393107940..8eb7631f7 100644
--- a/src/core/browser_context_adapter.h
+++ b/src/core/browser_context_adapter.h
@@ -107,6 +107,13 @@ public:
QString httpUserAgent() const;
void setHttpUserAgent(const QString &userAgent);
+#if defined(ENABLE_SPELLCHECK)
+ QStringList spellCheckLanguages(const QStringList &acceptLanguages);
+ void setSpellCheckLanguage(const QString &language);
+ QString spellCheckLanguage() const;
+ void setSpellCheckEnabled(bool enabled);
+ bool isSpellCheckEnabled() const;
+#endif
// KEEP IN SYNC with API or add mapping layer
enum HttpCacheType {
MemoryHttpCache = 0,
diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp
index 15c73180b..ca772c169 100644
--- a/src/core/browser_context_qt.cpp
+++ b/src/core/browser_context_qt.cpp
@@ -52,12 +52,49 @@
#include "content/public/browser/storage_partition.h"
#include "net/proxy/proxy_config_service.h"
+#if defined(ENABLE_SPELLCHECK)
+#include "base/prefs/pref_member.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/testing_pref_store.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/pref_service_factory.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "components/user_prefs/user_prefs.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/browser/spellchecker/spellcheck_service.h"
+#endif
+
namespace QtWebEngineCore {
+#if defined(ENABLE_SPELLCHECK)
+BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter)
+ : m_adapter(adapter),
+ m_prefStore(new TestingPrefStore())
+{
+ m_prefStore->SetInitializationCompleted();
+ base::PrefServiceFactory factory;
+ factory.set_user_prefs(m_prefStore);
+ scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple());
+
+ // Initial spellcheck settings
+ std::string spellcheckLang("en-US");
+ base::ListValue *dictionaries = new base::ListValue;
+ dictionaries->AppendString(spellcheckLang);
+ registry->RegisterListPref(prefs::kSpellCheckDictionaries, dictionaries);
+ registry->RegisterStringPref(prefs::kAcceptLanguages, spellcheckLang);
+ registry->RegisterStringPref(prefs::kSpellCheckDictionary, spellcheckLang);
+ registry->RegisterBooleanPref(prefs::kSpellCheckUseSpellingService, false);
+ registry->RegisterBooleanPref(prefs::kEnableContinuousSpellcheck, false);
+ registry->RegisterBooleanPref(prefs::kEnableAutoSpellCorrect, false);
+ m_prefService = factory.Create(registry.get()).Pass();
+ user_prefs::UserPrefs::Set(this, m_prefService.get());
+}
+#else
BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter)
: m_adapter(adapter)
{
}
+#endif //ENABLE_SPELLCHECK
BrowserContextQt::~BrowserContextQt()
{
@@ -156,4 +193,46 @@ net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::Pr
return url_request_getter_.get();
}
+
+#if defined(ENABLE_SPELLCHECK)
+QStringList BrowserContextQt::spellCheckLanguages(const QStringList& acceptedLanguages)
+{
+ QStringList result;
+#if !defined(OS_MACOSX) // no SpellcheckService::GetSpellCheckLanguages
+ m_prefService->SetString(prefs::kAcceptLanguages,acceptedLanguages.join(",").toStdString());
+
+ std::vector<std::string> vec;
+ SpellcheckService::GetSpellCheckLanguages(this, &vec);
+
+ for (std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); ++it) {
+ result << QString::fromStdString(*it);
+ }
+#endif
+ return result;
+}
+
+void BrowserContextQt::setSpellCheckLanguage(const QString &language)
+{
+ base::ListValue dictionaries;
+ dictionaries.AppendString(language.toStdString());
+ m_prefService->Set(prefs::kSpellCheckDictionaries, dictionaries);
+}
+
+QString BrowserContextQt::spellCheckLanguage() const
+{
+ std::string dictionary;
+ m_prefService->GetList(prefs::kSpellCheckDictionaries)->GetString(0, &dictionary);
+ return QString::fromStdString(dictionary);
+}
+
+void BrowserContextQt::setSpellCheckEnabled(bool enabled)
+{
+ m_prefService->SetBoolean(prefs::kEnableContinuousSpellcheck, enabled);
+}
+
+bool BrowserContextQt::isSpellCheckEnabled() const
+{
+ return m_prefService->GetBoolean(prefs::kEnableContinuousSpellcheck);
+}
+#endif //ENABLE_SPELLCHECK
} // namespace QtWebEngineCore
diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h
index 1513bf4bc..6a4b65b6b 100644
--- a/src/core/browser_context_qt.h
+++ b/src/core/browser_context_qt.h
@@ -47,6 +47,14 @@
#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
+#if defined(ENABLE_SPELLCHECK)
+QT_BEGIN_NAMESPACE
+class QStringList;
+QT_END_NAMESPACE
+class TestingPrefStore;
+class PrefService;
+#endif
+
namespace QtWebEngineCore {
class BrowserContextAdapter;
@@ -81,6 +89,14 @@ public:
BrowserContextAdapter *adapter() { return m_adapter; }
+#if defined(ENABLE_SPELLCHECK)
+ QStringList spellCheckLanguages(const QStringList &acceptLanguages);
+ void setSpellCheckLanguage(const QString &language);
+ QString spellCheckLanguage() const;
+ void setSpellCheckEnabled(bool enabled);
+ bool isSpellCheckEnabled() const;
+#endif
+
private:
friend class ContentBrowserClientQt;
friend class WebContentsAdapter;
@@ -88,6 +104,10 @@ private:
scoped_refptr<URLRequestContextGetterQt> url_request_getter_;
scoped_ptr<PermissionManagerQt> permissionManager;
BrowserContextAdapter *m_adapter;
+#if defined(ENABLE_SPELLCHECK)
+ scoped_refptr<TestingPrefStore> m_prefStore;
+ scoped_ptr<PrefService> m_prefService;
+#endif
friend class BrowserContextAdapter;
DISALLOW_COPY_AND_ASSIGN(BrowserContextQt);
diff --git a/src/core/chrome_qt.gyp b/src/core/chrome_qt.gyp
index 6c8e0d4d6..626691db4 100644
--- a/src/core/chrome_qt.gyp
+++ b/src/core/chrome_qt.gyp
@@ -1,6 +1,61 @@
{
'variables': {
'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome',
+ 'chrome_spellchecker_sources': [
+ '<(DEPTH)/base/prefs/testing_pref_store.cc',
+ '<(DEPTH)/base/prefs/testing_pref_store.h',
+ '<(DEPTH)/chrome/browser/spellchecker/feedback.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/feedback.h',
+ '<(DEPTH)/chrome/browser/spellchecker/feedback_sender.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/feedback_sender.h',
+ '<(DEPTH)/chrome/browser/spellchecker/misspelling.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/misspelling.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_action.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_action.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_custom_dictionary.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_factory.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_factory.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_host_metrics.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_host_metrics.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_message_filter.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_message_filter.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_message_filter_platform.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_message_filter_platform_mac.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_platform_mac.mm',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_service.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_service.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spelling_service_client.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/spelling_service_client.h',
+ '<(DEPTH)/chrome/browser/spellchecker/word_trimmer.cc',
+ '<(DEPTH)/chrome/browser/spellchecker/word_trimmer.h',
+ '<(DEPTH)/chrome/common/common_message_generator.cc',
+ '<(DEPTH)/chrome/common/pref_names.cc',
+ '<(DEPTH)/chrome/common/pref_names.h',
+ '<(DEPTH)/chrome/common/spellcheck_bdict_language.h',
+ '<(DEPTH)/chrome/common/spellcheck_common.cc',
+ '<(DEPTH)/chrome/common/spellcheck_common.h',
+ '<(DEPTH)/chrome/common/spellcheck_marker.h',
+ '<(DEPTH)/chrome/common/spellcheck_messages.h',
+ '<(DEPTH)/chrome/common/spellcheck_result.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/custom_dictionary_engine.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/custom_dictionary_engine.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/hunspell_engine.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/hunspell_engine.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/platform_spelling_engine.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/platform_spelling_engine.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck_language.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck_language.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck_provider.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck_provider.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck_worditerator.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/spellcheck_worditerator.h',
+ '<(DEPTH)/chrome/renderer/spellchecker/spelling_engine.h',
+ ]
},
'targets': [
{
@@ -20,14 +75,52 @@
'<(SHARED_INTERMEDIATE_DIR)/components/strings',
],
'sources': [
+ '<(DEPTH)/chrome/browser/media/desktop_media_list.h',
'<(DEPTH)/chrome/browser/media/desktop_streams_registry.cc',
'<(DEPTH)/chrome/browser/media/desktop_streams_registry.h',
- '<(DEPTH)/chrome/browser/media/desktop_media_list.h',
'<(DEPTH)/chrome/common/chrome_switches.cc',
'<(DEPTH)/chrome/common/chrome_switches.h',
'<(DEPTH)/chrome/common/localized_error.cc',
'<(DEPTH)/chrome/common/localized_error.h',
],
+ 'conditions': [
+ ['enable_spellcheck==1', {
+ 'sources': [ '<@(chrome_spellchecker_sources)' ],
+ 'include_dirs': [
+ '<(chromium_src_dir)/third_party/WebKit',
+ ],
+ 'dependencies': [
+ '<(chromium_src_dir)/components/components.gyp:keyed_service_content',
+ '<(chromium_src_dir)/components/components.gyp:keyed_service_core',
+ '<(chromium_src_dir)/components/components.gyp:pref_registry',
+ '<(chromium_src_dir)/components/components.gyp:user_prefs',
+ '<(chromium_src_dir)/third_party/hunspell/hunspell.gyp:hunspell',
+ '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
+ '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
+ ],
+ 'defines': [
+ '__STDC_CONSTANT_MACROS',
+ '__STDC_FORMAT_MACROS',
+ ],
+ 'conditions': [
+ ['OS == "win"', {
+ # crbug.com/167187 fix size_t to int truncations
+ 'msvs_disabled_warnings': [4267, ],
+ }],
+ [ 'OS != "mac"', {
+ 'sources/': [
+ ['exclude', '_mac\\.(cc|cpp|mm?)$'],
+ ],
+ }],
+ ['use_browser_spellchecker==0', {
+ 'sources!': [
+ '<(DEPTH)/chrome/renderer/spellchecker/platform_spelling_engine.cc',
+ '<(DEPTH)/chrome/renderer/spellchecker/platform_spelling_engine.h',
+ ],
+ }],
+ ]
+ }],
+ ],
},
{
'target_name': 'chrome_resources',
diff --git a/src/core/config/embedded_linux.pri b/src/core/config/embedded_linux.pri
index 50f94147e..84db049cb 100644
--- a/src/core/config/embedded_linux.pri
+++ b/src/core/config/embedded_linux.pri
@@ -18,7 +18,6 @@ GYP_CONFIG += \
enable_plugins=0 \
enable_printing=0 \
enable_session_service=0 \
- enable_spellcheck=0 \
enable_task_manager=0 \
enable_themes=0 \
enable_webrtc=0 \
diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri
index c3398757e..f2883bc32 100644
--- a/src/core/config/linux.pri
+++ b/src/core/config/linux.pri
@@ -24,6 +24,9 @@ GYP_CONFIG += \
use_openssl_certs=1
}
+no_spellcheck: GYP_CONFIG += enable_spellcheck=0
+else: GYP_CONFIG += enable_spellcheck=1
+
contains(QT_CONFIG, system-zlib): use?(system_minizip): GYP_CONFIG += use_system_zlib=1
contains(QT_CONFIG, system-png): GYP_CONFIG += use_system_libpng=1
contains(QT_CONFIG, system-jpeg): GYP_CONFIG += use_system_libjpeg=1
diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri
index 6532077de..f11dba1b7 100644
--- a/src/core/config/mac_osx.pri
+++ b/src/core/config/mac_osx.pri
@@ -17,5 +17,8 @@ GYP_CONFIG += \
clang_use_chrome_plugins=0 \
enable_widevine=1
+no_spellcheck: GYP_CONFIG += enable_spellcheck=0 use_browser_spellchecker=0
+else: GYP_CONFIG += enable_spellcheck=1 use_browser_spellchecker=1
+
QMAKE_MAC_SDK_PATH = "$$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path)"
exists($$QMAKE_MAC_SDK_PATH): GYP_CONFIG += mac_sdk_path=\"$${QMAKE_MAC_SDK_PATH}\"
diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri
index 92e193422..153a4fe72 100644
--- a/src/core/config/windows.pri
+++ b/src/core/config/windows.pri
@@ -6,6 +6,9 @@ GYP_CONFIG += \
use_ash=0 \
enable_widevine=1
+no_spellcheck: GYP_CONFIG += enable_spellcheck=0
+else: GYP_CONFIG += enable_spellcheck=1
+
# Chromium builds with debug info in release by default but Qt doesn't
CONFIG(release, debug|release):!force_debug_info: GYP_CONFIG += fastbuild=1
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index 25cac53aa..54430b81c 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -41,6 +41,9 @@
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_restrictions.h"
+#if defined(ENABLE_SPELLCHECK)
+#include "chrome/browser/spellchecker/spellcheck_message_filter.h"
+#endif
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/public/browser/browser_main_parts.h"
#include "content/public/browser/child_process_security_policy.h"
@@ -352,10 +355,14 @@ content::BrowserMainParts *ContentBrowserClientQt::CreateBrowserMainParts(const
void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* host)
{
// FIXME: Add a settings variable to enable/disable the file scheme.
- content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(host->GetID(), url::kFileScheme);
+ const int id = host->GetID();
+ content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(id, url::kFileScheme);
static_cast<BrowserContextQt*>(host->GetBrowserContext())->m_adapter->userScriptController()->renderProcessStartedWithHost(host);
#if defined(ENABLE_PEPPER_CDMS)
- host->AddFilter(new BrowserMessageFilterQt(host->GetID()));
+ host->AddFilter(new BrowserMessageFilterQt(id));
+#endif
+#if defined(ENABLE_SPELLCHECK)
+ host->AddFilter(new SpellCheckMessageFilter(id));
#endif
}
diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp
index 3c633600a..2f61e1e5e 100644
--- a/src/core/content_main_delegate_qt.cpp
+++ b/src/core/content_main_delegate_qt.cpp
@@ -103,7 +103,9 @@ bool ContentMainDelegateQt::BasicStartupComplete(int *exit_code)
PathService::Override(base::DIR_QT_LIBRARY_DATA, WebEngineLibraryInfo::getPath(base::DIR_QT_LIBRARY_DATA));
PathService::Override(content::DIR_MEDIA_LIBS, WebEngineLibraryInfo::getPath(content::DIR_MEDIA_LIBS));
PathService::Override(ui::DIR_LOCALES, WebEngineLibraryInfo::getPath(ui::DIR_LOCALES));
-
+#if defined(ENABLE_SPELLCHECK)
+ PathService::Override(base::DIR_APP_DICTIONARIES, WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES));
+#endif
SetContentClient(new ContentClientQt);
return false;
}
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index 5d2882020..36e4f83f1 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -44,6 +44,10 @@
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/localized_error.h"
+#if defined(ENABLE_SPELLCHECK)
+#include "chrome/renderer/spellchecker/spellcheck.h"
+#include "chrome/renderer/spellchecker/spellcheck_provider.h"
+#endif
#include "components/cdm/renderer/widevine_key_systems.h"
#include "components/error_page/common/error_page_params.h"
#include "components/visitedlink/renderer/visitedlink_slave.h"
@@ -93,6 +97,10 @@ void ContentRendererClientQt::RenderThreadStarted()
// mark qrc as a secure scheme (avoids deprecation warnings)
blink::WebSecurityPolicy::registerURLSchemeAsSecure(blink::WebString::fromLatin1(kQrcSchemeQt));
+#if defined(ENABLE_SPELLCHECK)
+ m_spellCheck.reset(new SpellCheck());
+ renderThread->AddObserver(m_spellCheck.data());
+#endif
}
void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view)
@@ -101,6 +109,9 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view
new RenderViewObserverQt(render_view, m_webCacheObserver.data());
new WebChannelIPCTransport(render_view);
UserScriptController::instance()->renderViewCreated(render_view);
+#if defined(ENABLE_SPELLCHECK)
+ new SpellCheckProvider(render_view, m_spellCheck.data());
+#endif
}
void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame)
diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h
index ca4bebe94..c80395140 100644
--- a/src/core/renderer/content_renderer_client_qt.h
+++ b/src/core/renderer/content_renderer_client_qt.h
@@ -52,6 +52,8 @@ namespace web_cache {
class WebCacheRenderProcessObserver;
}
+class SpellCheck;
+
namespace QtWebEngineCore {
class ContentRendererClientQt : public content::ContentRendererClient {
@@ -73,6 +75,9 @@ public:
private:
QScopedPointer<visitedlink::VisitedLinkSlave> m_visitedLinkSlave;
QScopedPointer<web_cache::WebCacheRenderProcessObserver> m_webCacheObserver;
+#if defined(ENABLE_SPELLCHECK)
+ QScopedPointer<SpellCheck> m_spellCheck;
+#endif
};
} // namespace
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index e203697c0..0f3357948 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -250,6 +250,17 @@ inline std::vector<T> toVector(const QStringList &fileList)
int flagsFromModifiers(Qt::KeyboardModifiers modifiers);
+#if defined(ENABLE_SPELLCHECK)
+inline QStringList fromVector(const std::vector<base::string16> &vector)
+{
+ QStringList result;
+ for (auto s: vector) {
+ result.append(toQt(s));
+ }
+ return result;
+}
+#endif
+
} // namespace QtWebEngineCore
#endif // TYPE_CONVERSION_H
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 497221861..bf36a771c 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -1162,6 +1162,19 @@ void WebContentsAdapter::initUpdateDragCursorMessagePollingTimer()
});
}
+#if defined(ENABLE_SPELLCHECK)
+void WebContentsAdapter::replaceMisspelling(const QString &word)
+{
+ Q_D(WebContentsAdapter);
+ d->webContents->ReplaceMisspelling(toString16(word));
+}
+
+void WebContentsAdapter::toogleSpellCheckEnabled()
+{
+ browserContext()->setSpellCheckEnabled(!browserContext()->isSpellCheckEnabled());
+}
+#endif
+
WebContentsAdapterClient::RenderProcessTerminationStatus
WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) {
auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1);
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index cbc7c34fb..e6aef23ec 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -170,6 +170,10 @@ public:
// meant to be used within WebEngineCore only
content::WebContents *webContents() const;
+#if defined(ENABLE_SPELLCHECK)
+ void replaceMisspelling(const QString &word);
+ void toogleSpellCheckEnabled();
+#endif
private:
Q_DISABLE_COPY(WebContentsAdapter)
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index c29abe53f..5e6335584 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -79,6 +79,10 @@ public:
: mediaType(MediaTypeNone)
, hasImageContent(false)
, mediaFlags(0)
+#if defined(ENABLE_SPELLCHECK)
+ , isEditable(false)
+ , isSpellCheckerEnabled(false)
+#endif
{
}
@@ -124,11 +128,14 @@ public:
bool hasImageContent;
uint mediaFlags;
QString suggestedFileName;
+#if defined(ENABLE_SPELLCHECK)
+ bool isEditable;
+ bool isSpellCheckerEnabled;
+ QString misspelledWord;
+ QStringList spellCheckerSuggestions;
+#endif
// Some likely candidates for future additions as we add support for the related actions:
// bool isImageBlocked;
-// bool isEditable;
-// bool isSpellCheckingEnabled;
-// QStringList spellCheckingSuggestions;
// <enum tbd> mediaType;
// ...
};
diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp
index 926e159df..9614aa0f8 100644
--- a/src/core/web_contents_view_qt.cpp
+++ b/src/core/web_contents_view_qt.cpp
@@ -39,7 +39,7 @@
#include "web_contents_view_qt.h"
-#include "browser_context_qt.h"
+#include "browser_context_adapter.h"
#include "content_browser_client_qt.h"
#include "render_widget_host_view_qt_delegate.h"
#include "type_conversion.h"
@@ -162,12 +162,27 @@ static WebEngineContextMenuData fromParams(const content::ContextMenuParams &par
ret.hasImageContent = params.has_image_contents;
ret.mediaFlags = params.media_flags;
ret.suggestedFileName = toQt(params.suggested_filename.data());
+#if defined(ENABLE_SPELLCHECK)
+ ret.isEditable = params.is_editable;
+ ret.misspelledWord = toQt(params.misspelled_word);
+ ret.spellCheckerSuggestions = fromVector(params.dictionary_suggestions);
+#endif
return ret;
}
void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const content::ContextMenuParams &params)
{
WebEngineContextMenuData contextMenuData(fromParams(params));
+#if defined(ENABLE_SPELLCHECK)
+ // Do not use params.spellcheck_enabled, since it is never
+ // correctly initialized for chrome asynchronous spellchecking.
+ // Even fixing the initialization in ContextMenuClientImpl::showContextMenu
+ // will not work. By default SpellCheck::spellcheck_enabled_
+ // must be initialized to true due to the way how the initialization sequence
+ // in SpellCheck works ie. typing the first word triggers the creation
+ // of the SpellcheckService. Use user preference store instead.
+ contextMenuData.isSpellCheckerEnabled = m_client->browserContextAdapter()->isSpellCheckEnabled();
+#endif
m_client->contextMenuRequested(contextMenuData);
}
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index aae86dce8..ee8174af7 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -205,6 +205,32 @@ QString localesPath()
#endif
}
+#if defined(ENABLE_SPELLCHECK)
+QString dictionariesPath()
+{
+#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
+ return getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_dictionaries");
+#else
+ static bool initialized = false;
+ static QString potentialDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+
+ if (!initialized) {
+ initialized = true;
+ if (!QFileInfo::exists(potentialDictionariesPath)) {
+ qWarning("Installed Qt WebEngine dictionaries directory not found at location %s. Trying application directory...", qPrintable(potentialDictionariesPath));
+ potentialDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+ }
+ if (!QFileInfo::exists(potentialDictionariesPath)) {
+ qWarning("Qt WebEngine dictionaries directory not found at location %s. Trying fallback directory... Spellcheck MAY NOT work.", qPrintable(potentialDictionariesPath));
+ potentialDictionariesPath = fallbackDir();
+ }
+ }
+
+ return potentialDictionariesPath;
+#endif
+}
+#endif // ENABLE_SPELLCHECK
+
QString icuDataPath()
{
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
@@ -292,6 +318,10 @@ base::FilePath WebEngineLibraryInfo::getPath(int key)
return toFilePath(pluginsPath());
case ui::DIR_LOCALES:
return toFilePath(localesPath());
+#if defined(ENABLE_SPELLCHECK)
+ case base::DIR_APP_DICTIONARIES:
+ return toFilePath(dictionariesPath());
+#endif
default:
// Note: the path system expects this function to override the default
// behavior. So no need to log an error if we don't support a given