diff options
author | Michal Klocek <michal.klocek@theqtcompany.com> | 2015-10-08 23:49:26 +0200 |
---|---|---|
committer | Michal Klocek <michal.klocek@theqtcompany.com> | 2016-02-01 15:57:30 +0000 |
commit | 4713387c052d54e0f5ea02efaeaa25931d1cd7ee (patch) | |
tree | 1ada7f8b38cf4c31ab90468a32b1a6df3c4a362b /src/core | |
parent | 1910ddb3e2869e50514da343aa6947e88f734c38 (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.cpp | 27 | ||||
-rw-r--r-- | src/core/browser_context_adapter.h | 7 | ||||
-rw-r--r-- | src/core/browser_context_qt.cpp | 79 | ||||
-rw-r--r-- | src/core/browser_context_qt.h | 20 | ||||
-rw-r--r-- | src/core/chrome_qt.gyp | 95 | ||||
-rw-r--r-- | src/core/config/embedded_linux.pri | 1 | ||||
-rw-r--r-- | src/core/config/linux.pri | 3 | ||||
-rw-r--r-- | src/core/config/mac_osx.pri | 3 | ||||
-rw-r--r-- | src/core/config/windows.pri | 3 | ||||
-rw-r--r-- | src/core/content_browser_client_qt.cpp | 11 | ||||
-rw-r--r-- | src/core/content_main_delegate_qt.cpp | 4 | ||||
-rw-r--r-- | src/core/renderer/content_renderer_client_qt.cpp | 11 | ||||
-rw-r--r-- | src/core/renderer/content_renderer_client_qt.h | 5 | ||||
-rw-r--r-- | src/core/type_conversion.h | 11 | ||||
-rw-r--r-- | src/core/web_contents_adapter.cpp | 13 | ||||
-rw-r--r-- | src/core/web_contents_adapter.h | 4 | ||||
-rw-r--r-- | src/core/web_contents_adapter_client.h | 13 | ||||
-rw-r--r-- | src/core/web_contents_view_qt.cpp | 17 | ||||
-rw-r--r-- | src/core/web_engine_library_info.cpp | 30 |
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 ¶ms) { 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 |