From 8601dc7df551a22ec54a55cb8acd6d45c8e4e838 Mon Sep 17 00:00:00 2001 From: Anthony Tseng Date: Fri, 7 Jul 2017 15:15:17 -0700 Subject: [PATCH] Deprecate electron spellchecker by chromium's Auditors: @bridiver, @bbondy, @bsclifton --- BUILD.gn | 2 - atom/browser/api/atom_api_web_contents.cc | 68 +++++- atom/browser/api/atom_api_web_contents.h | 4 + ...browser_context_keyed_service_factories.cc | 12 ++ atom/browser/ui/atom_menu_model.cc | 1 + .../api/resources/web_frame_bindings.js | 4 - .../content_converter.cc | 1 + .../api/atom_api_spell_check_client.cc | 201 ------------------ .../api/atom_api_spell_check_client.h | 92 -------- brave/browser/brave_content_browser_client.cc | 16 ++ brave/common/extensions/api/web_frame.json | 27 --- .../renderer/brave_content_renderer_client.cc | 30 +++ .../renderer/brave_content_renderer_client.h | 4 + .../renderer/extensions/web_frame_bindings.cc | 33 +-- .../renderer/extensions/web_frame_bindings.h | 9 - chromium_src/BUILD.gn | 34 +++ 16 files changed, 170 insertions(+), 368 deletions(-) delete mode 100644 atom/renderer/api/atom_api_spell_check_client.cc delete mode 100644 atom/renderer/api/atom_api_spell_check_client.h diff --git a/BUILD.gn b/BUILD.gn index a82ec4fb6..dc0f63684 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -278,8 +278,6 @@ source_set("renderer") { ] sources = [ - "atom/renderer/api/atom_api_spell_check_client.cc", - "atom/renderer/api/atom_api_spell_check_client.h", "atom/renderer/content_settings_manager.cc", "atom/renderer/content_settings_manager.h", "brave/renderer/brave_content_renderer_client.cc", diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 30033fe81..535a2703d 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -59,6 +59,8 @@ #include "chrome/browser/printing/print_preview_message_handler.h" #include "chrome/browser/printing/print_view_manager_basic.h" #include "chrome/browser/printing/print_view_manager_common.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -949,7 +951,23 @@ bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) { Emit("pepper-context-menu", std::make_pair(params, web_contents())); web_contents()->NotifyContextMenuClosed(params.custom_context); } else { - Emit("context-menu", std::make_pair(params, web_contents())); + // For forgetting custom dictionary option + content::ContextMenuParams new_params(params); + if (new_params.misspelled_word.empty()) { + auto browser_context = web_contents()->GetBrowserContext(); + if (browser_context) { + SpellcheckService* spellcheck = + SpellcheckServiceFactory::GetForContext(browser_context); + if (spellcheck) { + if (spellcheck->GetCustomDictionary() + ->HasWord(base::UTF16ToUTF8(new_params.selection_text))) { + new_params.misspelled_word = + base::ASCIIToUTF16("match-brave-custom-dictionary"); + } + } + } + } + Emit("context-menu", std::make_pair(new_params, web_contents())); } return true; @@ -971,6 +989,50 @@ void WebContents::AuthorizePlugin(mate::Arguments* args) { web_contents(), true, resource_id); } +void WebContents::AddWord(mate::Arguments* args) { + if (args->Length() != 1) { + args->ThrowError("Wrong number of arguments"); + return; + } + + std::string word; + if (!args->GetNext(&word)) { + args->ThrowError("word is a required field"); + return; + } + + auto browser_context = web_contents()->GetBrowserContext(); + if (browser_context) { + SpellcheckService* spellcheck = + SpellcheckServiceFactory::GetForContext(browser_context); + if (spellcheck) { + spellcheck->GetCustomDictionary()->AddWord(word); + } + } +} + +void WebContents::RemoveWord(mate::Arguments* args) { + if (args->Length() != 1) { + args->ThrowError("Wrong number of arguments"); + return; + } + + std::string word; + if (!args->GetNext(&word)) { + args->ThrowError("word is a required field"); + return; + } + + auto browser_context = web_contents()->GetBrowserContext(); + if (browser_context) { + SpellcheckService* spellcheck = + SpellcheckServiceFactory::GetForContext(browser_context); + if (spellcheck) { + spellcheck->GetCustomDictionary()->RemoveWord(word); + } + } +} + void WebContents::TabPinnedStateChanged(TabStripModel* tab_strip_model, content::WebContents* contents, int index) { @@ -2411,6 +2473,10 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, &WebContents::EnablePreferredSizeMode) .SetMethod("authorizePlugin", &WebContents::AuthorizePlugin) + .SetMethod("addWord", + &WebContents::AddWord) + .SetMethod("removeWord", + &WebContents::RemoveWord) #if BUILDFLAG(ENABLE_EXTENSIONS) .SetMethod("executeScriptInTab", &WebContents::ExecuteScriptInTab) .SetMethod("isBackgroundPage", &WebContents::IsBackgroundPage) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index bc662971f..c6c3447c6 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -330,6 +330,10 @@ class WebContents : public mate::TrackableObject, void AuthorizePlugin(mate::Arguments* args); + void AddWord(mate::Arguments* args); + + void RemoveWord(mate::Arguments* args); + // TabStripModelObserver void TabPinnedStateChanged(TabStripModel* tab_strip_model, content::WebContents* contents, diff --git a/atom/browser/browser_context_keyed_service_factories.cc b/atom/browser/browser_context_keyed_service_factories.cc index 49cc4ac43..6b75b8972 100644 --- a/atom/browser/browser_context_keyed_service_factories.cc +++ b/atom/browser/browser_context_keyed_service_factories.cc @@ -9,6 +9,8 @@ #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "components/spellcheck/spellcheck_build_features.h" #include "extensions/features/features.h" #include "ppapi/features/features.h" #if BUILDFLAG(ENABLE_PLUGINS) @@ -38,6 +40,10 @@ #include "extensions/browser/renderer_startup_helper.h" #endif +#if BUILDFLAG(ENABLE_SPELLCHECK) +#include "chrome/browser/extensions/api/spellcheck/spellcheck_api.h" +#endif + namespace atom { void EnsureBrowserContextKeyedServiceFactoriesBuilt() { @@ -67,6 +73,9 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { extensions::StorageFrontend::GetFactoryInstance(); extensions::WebRequestAPI::GetFactoryInstance(); extensions::AtomExtensionSystemFactory::GetInstance(); +#if BUILDFLAG(ENABLE_SPELLCHECK) + extensions::SpellcheckAPI::GetFactoryInstance(); +#endif #endif CookieSettingsFactory::GetInstance(); HostContentSettingsMapFactory::GetInstance(); @@ -76,6 +85,9 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { ProtocolHandlerRegistryFactory::GetInstance(); HistoryServiceFactory::GetInstance(); PasswordStoreFactory::GetInstance(); +#if BUILDFLAG(ENABLE_SPELLCHECK) + SpellcheckServiceFactory::GetInstance(); +#endif } } // namespace atom diff --git a/atom/browser/ui/atom_menu_model.cc b/atom/browser/ui/atom_menu_model.cc index 1ec6b3c09..4702e6100 100644 --- a/atom/browser/ui/atom_menu_model.cc +++ b/atom/browser/ui/atom_menu_model.cc @@ -5,6 +5,7 @@ #include "atom/browser/ui/atom_menu_model.h" #include "base/stl_util.h" +#include "chrome/browser/renderer_context_menu/spelling_menu_observer.h" namespace atom { diff --git a/atom/common/api/resources/web_frame_bindings.js b/atom/common/api/resources/web_frame_bindings.js index 704f86ecb..597be7d51 100644 --- a/atom/common/api/resources/web_frame_bindings.js +++ b/atom/common/api/resources/web_frame_bindings.js @@ -14,10 +14,6 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { return webFrameNatives.executeJavaScript(code) }) - apiFunctions.setHandleRequest('setSpellCheckProvider', function(lang, autoCorrectEnabled, spellCheckProvider) { - return webFrameNatives.setSpellCheckProvider(lang, autoCorrectEnabled, spellCheckProvider) - }) - apiFunctions.setHandleRequest('setZoomLevel', function(level) { return webFrameNatives.setZoomLevel(level) }) diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc index 0fe1e1b58..a92bbdbcf 100644 --- a/atom/common/native_mate_converters/content_converter.cc +++ b/atom/common/native_mate_converters/content_converter.cc @@ -118,6 +118,7 @@ v8::Local Converter::ToV8( dict.Set("selectionText", params.selection_text); dict.Set("titleText", params.title_text); dict.Set("misspelledWord", params.misspelled_word); + dict.Set("dictionarySuggestions", params.dictionary_suggestions); dict.Set("frameCharset", params.frame_charset); dict.Set("inputFieldType", params.input_field_type); dict.Set("menuSourceType", params.source_type); diff --git a/atom/renderer/api/atom_api_spell_check_client.cc b/atom/renderer/api/atom_api_spell_check_client.cc deleted file mode 100644 index a085fdb40..000000000 --- a/atom/renderer/api/atom_api_spell_check_client.cc +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/renderer/api/atom_api_spell_check_client.h" - -#include -#include - -#include "atom/common/native_mate_converters/string16_converter.h" -#include "base/logging.h" -#include "native_mate/converter.h" -#include "native_mate/dictionary.h" -#include "third_party/icu/source/common/unicode/uscript.h" -#include "third_party/WebKit/public/web/WebTextCheckingCompletion.h" -#include "third_party/WebKit/public/web/WebTextCheckingResult.h" - -namespace atom { - -namespace api { - -namespace { - -bool HasWordCharacters(const base::string16& text, int index) { - const base::char16* data = text.data(); - int length = text.length(); - while (index < length) { - uint32_t code = 0; - U16_NEXT(data, index, length, code); - UErrorCode error = U_ZERO_ERROR; - if (uscript_getScript(code, &error) != USCRIPT_COMMON) - return true; - } - return false; -} - -} // namespace - -SpellCheckClient::SpellCheckClient(const std::string& language, - bool auto_spell_correct_turned_on, - v8::Isolate* isolate, - v8::Local provider) - : isolate_(isolate), - provider_(isolate, provider) { - character_attributes_.SetDefaultLanguage(language); - - // Persistent the method. - mate::Dictionary dict(isolate, provider); - dict.Get("spellCheck", &spell_check_); -} - -SpellCheckClient::~SpellCheckClient() {} - -void SpellCheckClient::CheckSpelling( - const blink::WebString& text, - int& misspelling_start, - int& misspelling_len, - blink::WebVector* optional_suggestions) { - std::vector results; - SpellCheckText(text.Utf16(), true, &results); - if (results.size() == 1) { - misspelling_start = results[0].location; - misspelling_len = results[0].length; - } -} - -void SpellCheckClient::RequestCheckingOfText( - const blink::WebString& wtfText, - blink::WebTextCheckingCompletion* completion) { - base::string16 text = wtfText.Utf16(); - if (text.empty() || !HasWordCharacters(text, 0)) { - if (completion) { - completion->DidCancelCheckingText(); - } - return; - } - - std::vector results; - SpellCheckText(text, false, &results); - completion->DidFinishCheckingText(results); -} - -void SpellCheckClient::ShowSpellingUI(bool show) { -} - -bool SpellCheckClient::IsShowingSpellingUI() { - return false; -} - -void SpellCheckClient::UpdateSpellingUIWithMisspelledWord( - const blink::WebString& word) { -} - -void SpellCheckClient::SpellCheckText( - const base::string16& text, - bool stop_at_first_result, - std::vector* results) { - if (text.length() == 0 || spell_check_.IsEmpty()) - return; - - base::string16 word; - int word_start; - int word_length; - if (!text_iterator_.IsInitialized() && - !text_iterator_.Initialize(&character_attributes_, true)) { - // We failed to initialize text_iterator_, return as spelled correctly. - VLOG(1) << "Failed to initialize SpellcheckWordIterator"; - return; - } - - base::string16 in_word(text); - text_iterator_.SetText(in_word.c_str(), in_word.size()); - SpellcheckWordIterator::WordIteratorStatus status; - while (true) { - status = text_iterator_.GetNextWord(&word, &word_start, &word_length); - if (status == SpellcheckWordIterator::IS_END_OF_TEXT) { - return; - } else if (status == SpellcheckWordIterator::IS_SKIPPABLE) { - continue; - } - - // Found a word (or a contraction) that the spellchecker can check the - // spelling of. - if (SpellCheckWord(word)) - continue; - - // If the given word is a concatenated word of two or more valid words - // (e.g. "hello:hello"), we should treat it as a valid word. - if (IsValidContraction(word)) - continue; - - blink::WebTextCheckingResult result; - result.location = word_start; - result.length = word_length; - results->push_back(result); - - if (stop_at_first_result) - return; - } -} - -bool SpellCheckClient::SpellCheckWord(const base::string16& word_to_check) { - if (spell_check_.IsEmpty()) - return true; - - v8::HandleScope handle_scope(isolate_); - v8::MicrotasksScope microtasks( - isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); - - v8::Local word = mate::ConvertToV8(isolate_, word_to_check); - v8::TryCatch try_catch(isolate_); - v8::Local result = spell_check_.NewHandle()->Call( - provider_.NewHandle(), 1, &word); - - // this can happen if the page navigates away - // while the spell check provider is running - if (try_catch.HasCaught() || try_catch.HasTerminated()) { - return true; - } - - if (result->IsBoolean()) - return result->BooleanValue(); - else - return true; -} - -// Returns whether or not the given string is a valid contraction. -// This function is a fall-back when the SpellcheckWordIterator class -// returns a concatenated word which is not in the selected dictionary -// (e.g. "in'n'out") but each word is valid. -bool SpellCheckClient::IsValidContraction(const base::string16& contraction) { - if (!contraction_iterator_.IsInitialized() && - !contraction_iterator_.Initialize(&character_attributes_, false)) { - // We failed to initialize the word iterator, return as spelled correctly. - VLOG(1) << "Failed to initialize contraction_iterator_"; - return true; - } - - contraction_iterator_.SetText(contraction.c_str(), contraction.length()); - - base::string16 word; - int word_start; - int word_length; - - while (true) { - SpellcheckWordIterator::WordIteratorStatus status = - contraction_iterator_.GetNextWord(&word, &word_start, &word_length); - if (status == SpellcheckWordIterator::IS_END_OF_TEXT) { - return true; - } else if (status == SpellcheckWordIterator::IS_SKIPPABLE) { - return true; - } - if (!SpellCheckWord(word)) - return false; - } - return true; -} - -} // namespace api - -} // namespace atom diff --git a/atom/renderer/api/atom_api_spell_check_client.h b/atom/renderer/api/atom_api_spell_check_client.h deleted file mode 100644 index d3bce399d..000000000 --- a/atom/renderer/api/atom_api_spell_check_client.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_RENDERER_API_ATOM_API_SPELL_CHECK_CLIENT_H_ -#define ATOM_RENDERER_API_ATOM_API_SPELL_CHECK_CLIENT_H_ - -#include -#include - -#include "base/callback.h" -#include "components/spellcheck/renderer/spellcheck.h" -#include "components/spellcheck/renderer/spellcheck_worditerator.h" -#include "native_mate/scoped_persistent.h" -#include "third_party/WebKit/public/web/WebSpellCheckClient.h" -#include "third_party/WebKit/public/web/WebTextCheckClient.h" - -namespace atom { - -namespace api { - -class SpellCheckClient : public blink::WebSpellCheckClient, - public blink::WebTextCheckClient { - public: - SpellCheckClient(const std::string& language, - bool auto_spell_correct_turned_on, - v8::Isolate* isolate, - v8::Local provider); - ~SpellCheckClient() override; - - private: - // blink::WebTextCheckClient: - void CheckSpelling( - const blink::WebString& text, - int& offset, - int& length, - blink::WebVector* optional_suggestions) override; - void RequestCheckingOfText( - const blink::WebString& text, - blink::WebTextCheckingCompletion* completion) override; - void CancelAllPendingRequests() override {}; - - - // blink::WebSpellCheckClient: - void ShowSpellingUI(bool show) override; - bool IsShowingSpellingUI() override; - void UpdateSpellingUIWithMisspelledWord( - const blink::WebString& word) override; - - // Check the spelling of text. - void SpellCheckText(const base::string16& text, - bool stop_at_first_result, - std::vector* results); - - // Call JavaScript to check spelling a word. - bool SpellCheckWord(const base::string16& word_to_check); - - // Find a possible correctly spelled word for a misspelled word. Computes an - // empty string if input misspelled word is too long, there is ambiguity, or - // the correct spelling cannot be determined. - base::string16 GetAutoCorrectionWord(const base::string16& word); - - // Returns whether or not the given word is a contraction of valid words - // (e.g. "word:word"). - bool IsValidContraction(const base::string16& word); - - // Represents character attributes used for filtering out characters which - // are not supported by this SpellCheck object. - SpellcheckCharAttribute character_attributes_; - - // Represents word iterators used in this spellchecker. The |text_iterator_| - // splits text provided by WebKit into words, contractions, or concatenated - // words. The |contraction_iterator_| splits a concatenated word extracted by - // |text_iterator_| into word components so we can treat a concatenated word - // consisting only of correct words as a correct word. - SpellcheckWordIterator text_iterator_; - SpellcheckWordIterator contraction_iterator_; - - bool auto_spell_correct_turned_on_; - - v8::Isolate* isolate_; - mate::ScopedPersistent provider_; - mate::ScopedPersistent spell_check_; - - DISALLOW_COPY_AND_ASSIGN(SpellCheckClient); -}; - -} // namespace api - -} // namespace atom - -#endif // ATOM_RENDERER_API_ATOM_API_SPELL_CHECK_CLIENT_H_ diff --git a/brave/browser/brave_content_browser_client.cc b/brave/browser/brave_content_browser_client.cc index 7afb53382..7dcb1fc23 100644 --- a/brave/browser/brave_content_browser_client.cc +++ b/brave/browser/brave_content_browser_client.cc @@ -37,6 +37,7 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" +#include "components/spellcheck/spellcheck_build_features.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" @@ -67,6 +68,14 @@ #include "ui/views/mus/mus_client.h" #endif +#if BUILDFLAG(ENABLE_SPELLCHECK) +#include "chrome/browser/spellchecker/spellcheck_message_filter.h" +#endif + +#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) +#include "components/spellcheck/browser/spellcheck_message_filter_platform.h" +#endif + using content::BrowserThread; using extensions::AtomBrowserClientExtensionsPart; @@ -245,6 +254,13 @@ void BraveContentBrowserClient::RenderProcessWillLaunch( host->AddFilter(new TtsMessageFilter(host->GetBrowserContext())); host->AddFilter(new PluginInfoMessageFilter(id, profile)); +#if BUILDFLAG(ENABLE_SPELLCHECK) + host->AddFilter(new SpellCheckMessageFilter(id)); +#endif +#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) + host->AddFilter(new SpellCheckMessageFilterPlatform(id)); +#endif + #if BUILDFLAG(ENABLE_EXTENSIONS) extensions_part_->RenderProcessWillLaunch(host); #endif diff --git a/brave/common/extensions/api/web_frame.json b/brave/common/extensions/api/web_frame.json index 97c9f5789..6c927e65a 100644 --- a/brave/common/extensions/api/web_frame.json +++ b/brave/common/extensions/api/web_frame.json @@ -18,33 +18,6 @@ } ] }, - { - "name": "setSpellCheckProvider", - "nocompile": true, - "type": "function", - "parameters": [ - { - "type": "string", - "name": "lang" - }, - { - "type": "boolean", - "name": "autoCorrectEnabled" - }, - { - "type": "object", - "name": "spellCheckProvider", - "properties": { - "spellCheck": { - "type": "function", - "parameters": [ - {"name": "word", "type": "string"} - ] - } - } - } - ] - }, { "name": "setZoomLevel", "nocompile": true, diff --git a/brave/renderer/brave_content_renderer_client.cc b/brave/renderer/brave_content_renderer_client.cc index 389151da4..a377d9d69 100644 --- a/brave/renderer/brave_content_renderer_client.cc +++ b/brave/renderer/brave_content_renderer_client.cc @@ -19,6 +19,7 @@ #include "content/public/common/content_constants.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h" +#include "content/public/renderer/render_view.h" #include "components/autofill/content/renderer/autofill_agent.h" #include "components/autofill/content/renderer/password_autofill_agent.h" #include "components/autofill/content/renderer/password_generation_agent.h" @@ -26,6 +27,7 @@ #include "components/password_manager/content/renderer/credential_manager_client.h" #include "components/plugins/renderer/plugin_placeholder.h" #include "components/printing/renderer/print_web_view_helper.h" +#include "components/spellcheck/spellcheck_build_features.h" #include "components/visitedlink/renderer/visitedlink_slave.h" #include "components/web_cache/renderer/web_cache_impl.h" #include "extensions/features/features.h" @@ -45,6 +47,12 @@ #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h" #endif +#if BUILDFLAG(ENABLE_SPELLCHECK) +#include "components/spellcheck/renderer/spellcheck.h" +#include "components/spellcheck/renderer/spellcheck_panel.h" +#include "components/spellcheck/renderer/spellcheck_provider.h" +#endif + using autofill::AutofillAgent; using autofill::PasswordAutofillAgent; using autofill::PasswordGenerationAgent; @@ -97,6 +105,13 @@ void BraveContentRendererClient::RenderThreadStarted() { WebSecurityPolicy::AddSchemeToBypassSecureContextWhitelist( WebString::FromUTF8(scheme)); } + +#if BUILDFLAG(ENABLE_SPELLCHECK) + if (!spellcheck_) { + spellcheck_.reset(new SpellCheck()); + thread->AddObserver(spellcheck_.get()); + } +#endif } unsigned long long BraveContentRendererClient::VisitedLinkHash( // NOLINT @@ -154,6 +169,10 @@ void BraveContentRendererClient::RenderFrameCreated( new printing::PrintWebViewHelper( render_frame, base::MakeUnique()); #endif + +#if BUILDFLAG(ENABLE_SPELLCHECK) + new SpellCheckProvider(render_frame, spellcheck_.get()); +#endif } void BraveContentRendererClient::RenderViewCreated( @@ -164,6 +183,17 @@ void BraveContentRendererClient::RenderViewCreated( new ChromeRenderViewObserver(render_view, web_cache_impl_.get()); new password_manager::CredentialManagerClient(render_view); + +#if BUILDFLAG(ENABLE_SPELLCHECK) + // This is a workaround keeping the behavior that, the Blink side spellcheck + // enabled state is initialized on RenderView creation. + // TODO(xiaochengh): Design better way to sync between Chrome-side and + // Blink-side spellcheck enabled states. See crbug.com/710097. + if (SpellCheckProvider* provider = + SpellCheckProvider::Get(render_view->GetMainRenderFrame())) + provider->EnableSpellcheck(spellcheck_->IsSpellcheckEnabled()); + new SpellCheckPanel(render_view); +#endif } bool BraveContentRendererClient::OverrideCreatePlugin( diff --git a/brave/renderer/brave_content_renderer_client.h b/brave/renderer/brave_content_renderer_client.h index f11a50639..2328e5b11 100644 --- a/brave/renderer/brave_content_renderer_client.h +++ b/brave/renderer/brave_content_renderer_client.h @@ -31,6 +31,8 @@ namespace content { class RenderFrame; } +class SpellCheck; + namespace brave { class BraveContentRendererClient : public ChromeContentRendererClient { @@ -54,6 +56,8 @@ class BraveContentRendererClient : public ChromeContentRendererClient { private: atom::ContentSettingsManager* content_settings_manager_; // not owned + std::unique_ptr spellcheck_; + std::unique_ptr chrome_observer_; std::unique_ptr web_cache_impl_; diff --git a/brave/renderer/extensions/web_frame_bindings.cc b/brave/renderer/extensions/web_frame_bindings.cc index 61c8261a5..4c3596271 100644 --- a/brave/renderer/extensions/web_frame_bindings.cc +++ b/brave/renderer/extensions/web_frame_bindings.cc @@ -8,13 +8,13 @@ #include #include -#include "atom/renderer/api/atom_api_spell_check_client.h" #include "base/strings/utf_string_conversions.h" #include "content/renderer/browser_plugin/browser_plugin.h" #include "content/renderer/browser_plugin/browser_plugin_manager.h" #include "extensions/renderer/console.h" #include "extensions/renderer/guest_view/extensions_guest_view_container.h" #include "extensions/renderer/script_context.h" +#include "native_mate/scoped_persistent.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebScriptExecutionCallback.h" @@ -46,10 +46,6 @@ WebFrameBindings::WebFrameBindings(extensions::ScriptContext* context) "executeJavaScript", base::Bind(&WebFrameBindings::ExecuteJavaScript, base::Unretained(this))); - RouteFunction( - "setSpellCheckProvider", - base::Bind(&WebFrameBindings::SetSpellCheckProvider, - base::Unretained(this))); RouteFunction( "setZoomLevel", base::Bind(&WebFrameBindings::SetZoomLevel, @@ -71,36 +67,9 @@ WebFrameBindings::~WebFrameBindings() { } void WebFrameBindings::Invalidate() { - // only remove the spell check client when the main frame is invalidated - if (!context()->web_frame()->Parent()) { - context()->web_frame()->View()->SetSpellCheckClient(nullptr); - context()->web_frame()->SetTextCheckClient(nullptr); - spell_check_client_.reset(nullptr); - } ObjectBackedNativeHandler::Invalidate(); } -void WebFrameBindings::SetSpellCheckProvider( - const v8::FunctionCallbackInfo& args) { - if (context()->web_frame()->Parent()) { - extensions::console::AddMessage( - context(), content::CONSOLE_MESSAGE_LEVEL_WARNING, - "spellcheck provider can only be set by the main frame"); - return; - } - - const std::string lang = mate::V8ToString(args[0].As()); - bool auto_spell_correct_turned_on = args[1].As()->Value(); - v8::Local provider = v8::Local::Cast(args[2]); - - std::unique_ptr spell_check_client( - new atom::api::SpellCheckClient( - lang, auto_spell_correct_turned_on, GetIsolate(), provider)); - context()->web_frame()->View()->SetSpellCheckClient(spell_check_client.get()); - context()->web_frame()->SetTextCheckClient(spell_check_client.get()); - spell_check_client_.swap(spell_check_client); -} - void WebFrameBindings::ExecuteJavaScript( const v8::FunctionCallbackInfo& args) { const base::string16 code = base::UTF8ToUTF16(mate::V8ToString(args[0])); diff --git a/brave/renderer/extensions/web_frame_bindings.h b/brave/renderer/extensions/web_frame_bindings.h index 498913ab7..70d131b16 100644 --- a/brave/renderer/extensions/web_frame_bindings.h +++ b/brave/renderer/extensions/web_frame_bindings.h @@ -11,12 +11,6 @@ #include "extensions/renderer/script_context.h" #include "v8/include/v8.h" -namespace atom { -namespace api { -class SpellCheckClient; -} -} - namespace brave { class WebFrameBindings : public extensions::ObjectBackedNativeHandler { @@ -25,7 +19,6 @@ class WebFrameBindings : public extensions::ObjectBackedNativeHandler { virtual ~WebFrameBindings(); void WebFrame(const v8::FunctionCallbackInfo& args); - void SetSpellCheckProvider(const v8::FunctionCallbackInfo& args); void SetZoomLevel(const v8::FunctionCallbackInfo& args); void SetZoomLevelLimits(const v8::FunctionCallbackInfo& args); @@ -38,8 +31,6 @@ class WebFrameBindings : public extensions::ObjectBackedNativeHandler { private: void BindToGC(const v8::FunctionCallbackInfo& args); - std::unique_ptr spell_check_client_; - DISALLOW_COPY_AND_ASSIGN(WebFrameBindings); }; diff --git a/chromium_src/BUILD.gn b/chromium_src/BUILD.gn index 6a1f86c10..5c4d65d07 100644 --- a/chromium_src/BUILD.gn +++ b/chromium_src/BUILD.gn @@ -2,6 +2,7 @@ import("//build/config/features.gni") import("//build/config/ui.gni") import("//build/config/crypto.gni") import("//components/os_crypt/features.gni") +import("//components/spellcheck/spellcheck_build_features.gni") import("//extensions/features/features.gni") import("//media/media_options.gni") import("//ppapi/features/features.gni") @@ -100,8 +101,13 @@ source_set("renderer") { "//content/public/common", "//chrome/renderer", "//components/content_settings/core/common", + "//components/spellcheck:build_features", "//third_party/WebKit/public:blink_headers", ] + + if (enable_spellcheck) { + deps += [ "//components/spellcheck/renderer:renderer" ] + } } source_set("browser") { @@ -129,6 +135,7 @@ source_set("browser") { "//components/data_usage/core", "//components/prefs", "//components/ssl_config", + "//components/spellcheck:build_features", "//content/public/browser", "//electron/atom/browser", ] @@ -383,6 +390,8 @@ source_set("browser") { "//chrome/browser/extensions/api/messaging/native_process_launcher.h", "//chrome/browser/extensions/api/messaging/native_process_launcher_posix.cc", "//chrome/browser/extensions/api/messaging/native_process_launcher_win.cc", + "//chrome/browser/extensions/api/spellcheck/spellcheck_api.cc", + "//chrome/browser/extensions/api/spellcheck/spellcheck_api.h", "//chrome/browser/extensions/api/tabs/tabs_constants.cc", "//chrome/browser/extensions/api/tabs/tabs_constants.h", "//chrome/browser/extensions/chrome_extension_api_frame_id_map_helper.cc", @@ -392,6 +401,7 @@ source_set("browser") { ] deps += [ + "//components/spellcheck/browser", "//extensions/browser", "//rlz/features", ] @@ -408,6 +418,30 @@ source_set("browser") { "//ppapi/proxy", ] } + if (enable_spellcheck) { + sources += [ + "//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc", + "//chrome/browser/spellchecker/spellcheck_custom_dictionary.h", + "//chrome/browser/spellchecker/spellcheck_dictionary.h", + "//chrome/browser/spellchecker/spellcheck_factory.cc", + "//chrome/browser/spellchecker/spellcheck_factory.h", + "//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc", + "//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h", + "//chrome/browser/spellchecker/spellcheck_message_filter.cc", + "//chrome/browser/spellchecker/spellcheck_message_filter.h", + "//chrome/browser/spellchecker/spellcheck_message_filter_platform_mac.cc", + "//chrome/browser/spellchecker/spellcheck_service.cc", + "//chrome/browser/spellchecker/spellcheck_service.h", + ] + deps += [ + "//components/spellcheck/browser", + "//components/spellcheck/common:common", + ] + + if (!is_android) { + deps += [ "//third_party/hunspell" ] + } + } } source_set("menu_bar") {