From cd7511f5cf8d1ca720ac92d9395bb53be56f68c2 Mon Sep 17 00:00:00 2001 From: Allison Naaktgeboren Date: Tue, 1 Jul 2014 15:24:27 -0700 Subject: [PATCH] Bug 693555 - Update inline spellchecker underlining for multiprocess(e10s).r=ehsan, mrbkap --- browser/base/content/browser-context.inc | 2 +- dom/ipc/ContentChild.cpp | 15 ++++++ dom/ipc/ContentChild.h | 3 ++ dom/ipc/ContentParent.cpp | 16 ++++++ dom/ipc/ContentParent.h | 3 ++ dom/ipc/PContent.ipdl | 3 ++ editor/composer/nsEditorSpellCheck.cpp | 13 ++++- .../hunspell/src/PRemoteSpellcheckEngine.ipdl | 20 ++++++++ .../src/RemoteSpellCheckEngineChild.cpp | 21 ++++++++ .../src/RemoteSpellCheckEngineChild.h | 26 ++++++++++ .../src/RemoteSpellCheckEngineParent.cpp | 49 +++++++++++++++++++ .../src/RemoteSpellCheckEngineParent.h | 31 ++++++++++++ extensions/spellcheck/hunspell/src/moz.build | 15 +++++- extensions/spellcheck/src/moz.build | 6 ++- extensions/spellcheck/src/mozSpellChecker.cpp | 39 ++++++++++++++- extensions/spellcheck/src/mozSpellChecker.h | 9 ++++ toolkit/content/widgets/textbox.xml | 2 +- toolkit/modules/InlineSpellChecker.jsm | 30 ++++++++++-- 18 files changed, 292 insertions(+), 11 deletions(-) create mode 100644 extensions/spellcheck/hunspell/src/PRemoteSpellcheckEngine.ipdl create mode 100644 extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.cpp create mode 100644 extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.h create mode 100644 extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.cpp create mode 100644 extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.h diff --git a/browser/base/content/browser-context.inc b/browser/base/content/browser-context.inc index 3f6d0eb435c2..b7d6d48e52c9 100644 --- a/browser/base/content/browser-context.inc +++ b/browser/base/content/browser-context.inc @@ -376,7 +376,7 @@ label="&spellCheckToggle.label;" type="checkbox" accesskey="&spellCheckToggle.accesskey;" - oncommand="InlineSpellCheckerUI.toggleEnabled();"/> + oncommand="InlineSpellCheckerUI.toggleEnabled(window);"/> GetContentLanguage(fetcher->mRootDocContentLang); - rv = fetcher->Fetch(mEditor); - NS_ENSURE_SUCCESS(rv, rv); + if (XRE_GetProcessType() == GeckoProcessType_Content) { + // Content prefs don't work in E10S (Bug 1027898) pretend that we + // didn't have any & trigger the asynchrous completion. + nsCOMPtr runnable = + NS_NewRunnableMethodWithArg(fetcher, &DictionaryFetcher::HandleCompletion, 0); + NS_DispatchToMainThread(runnable); + } else { + rv = fetcher->Fetch(mEditor); + NS_ENSURE_SUCCESS(rv, rv); + } return NS_OK; } diff --git a/extensions/spellcheck/hunspell/src/PRemoteSpellcheckEngine.ipdl b/extensions/spellcheck/hunspell/src/PRemoteSpellcheckEngine.ipdl new file mode 100644 index 000000000000..44639d245eb6 --- /dev/null +++ b/extensions/spellcheck/hunspell/src/PRemoteSpellcheckEngine.ipdl @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PContent; + +namespace mozilla { + +sync protocol PRemoteSpellcheckEngine { + manager PContent; + +parent: + __delete__(); + + sync CheckForMisspelling(nsString aWord) returns (bool isMisspelled); + + sync SetDictionary(nsString aDictionary) returns (bool success); +}; + +} // namespace mozilla diff --git a/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.cpp b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.cpp new file mode 100644 index 000000000000..5cae3591f59f --- /dev/null +++ b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.cpp @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "RemoteSpellCheckEngineChild.h" + +namespace mozilla { +RemoteSpellcheckEngineChild::RemoteSpellcheckEngineChild(mozSpellChecker *aOwner) + :mOwner(aOwner) +{ +} + +RemoteSpellcheckEngineChild::~RemoteSpellcheckEngineChild() +{ + // null out the owner's SpellcheckEngineChild to prevent state corruption + // during shutdown + mOwner->DeleteRemoteEngine(); + +} + +} //namespace mozilla diff --git a/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.h b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.h new file mode 100644 index 000000000000..c658793caef8 --- /dev/null +++ b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.h @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef RemoteSpellcheckEngineChild_h_ +#define RemoteSpellcheckEngineChild_h_ + +#include "mozilla/PRemoteSpellcheckEngineChild.h" +#include "mozSpellChecker.h" + +class mozSpellChecker; + +namespace mozilla { +class RemoteSpellcheckEngineChild : public mozilla::PRemoteSpellcheckEngineChild +{ +public: + RemoteSpellcheckEngineChild(mozSpellChecker *aOwner); + ~RemoteSpellcheckEngineChild(); + +private: + mozSpellChecker *mOwner; +}; + +} //namespace mozilla + +#endif // RemoteSpellcheckEngineChild_h_ diff --git a/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.cpp b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.cpp new file mode 100644 index 000000000000..ce26ec3abdf1 --- /dev/null +++ b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.cpp @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "RemoteSpellCheckEngineParent.h" +#include "mozISpellCheckingEngine.h" +#include "nsServiceManagerUtils.h" + +#define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1" + +namespace mozilla { + +RemoteSpellcheckEngineParent::RemoteSpellcheckEngineParent() +{ + mEngine = do_GetService(DEFAULT_SPELL_CHECKER); +} + +RemoteSpellcheckEngineParent::~RemoteSpellcheckEngineParent() +{ +} + +bool +RemoteSpellcheckEngineParent::RecvSetDictionary( + const nsString& aDictionary, + bool* success) +{ + nsresult rv = mEngine->SetDictionary(aDictionary.get()); + *success = NS_SUCCEEDED(rv); + return true; +} + +bool +RemoteSpellcheckEngineParent::RecvCheckForMisspelling( + const nsString& aWord, + bool* isMisspelled) +{ + bool isCorrect = false; + mEngine->Check(aWord.get(), &isCorrect); + *isMisspelled = !isCorrect; + return true; +} + +void +RemoteSpellcheckEngineParent::ActorDestroy(ActorDestroyReason aWhy) +{ +} + +} // namespace mozilla + diff --git a/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.h b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.h new file mode 100644 index 000000000000..95bd782e3919 --- /dev/null +++ b/extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.h @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef RemoteSpellcheckEngineParent_h_ +#define RemoteSpellcheckEngineParent_h_ + +#include "mozISpellCheckingEngine.h" +#include "mozilla/PRemoteSpellcheckEngineParent.h" +#include "nsCOMPtr.h" + +namespace mozilla { + +class RemoteSpellcheckEngineParent : public mozilla::PRemoteSpellcheckEngineParent { + +public: + RemoteSpellcheckEngineParent(); + + ~RemoteSpellcheckEngineParent(); + + virtual void ActorDestroy(ActorDestroyReason aWhy); + + bool RecvSetDictionary(const nsString& aDictionary, bool* success); + + bool RecvCheckForMisspelling( const nsString& aWord, bool* isMisspelled); + +private: + nsCOMPtr mEngine; +}; + +} +#endif diff --git a/extensions/spellcheck/hunspell/src/moz.build b/extensions/spellcheck/hunspell/src/moz.build index 123cad787ba4..046b3ee21ed9 100644 --- a/extensions/spellcheck/hunspell/src/moz.build +++ b/extensions/spellcheck/hunspell/src/moz.build @@ -4,9 +4,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -UNIFIED_SOURCES += [ +SOURCES += [ 'mozHunspell.cpp', 'mozHunspellDirProvider.cpp', + 'RemoteSpellCheckEngineChild.cpp', + 'RemoteSpellCheckEngineParent.cpp', ] if not CONFIG['MOZ_NATIVE_HUNSPELL']: @@ -40,3 +42,14 @@ LOCAL_INCLUDES += [ # Suppress warnings in third-party code. if CONFIG['CLANG_CXX']: CXXFLAGS += ['-Wno-unused-private-field'] + +include('/ipc/chromium/chromium-config.mozbuild') + +IPDL_SOURCES = [ + 'PRemoteSpellcheckEngine.ipdl', +] + +EXPORTS.mozilla += [ + 'RemoteSpellCheckEngineChild.h', + 'RemoteSpellCheckEngineParent.h', +] diff --git a/extensions/spellcheck/src/moz.build b/extensions/spellcheck/src/moz.build index 57e8b570017e..0d8ff16b91c4 100644 --- a/extensions/spellcheck/src/moz.build +++ b/extensions/spellcheck/src/moz.build @@ -4,7 +4,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -UNIFIED_SOURCES += [ +include('/ipc/chromium/chromium-config.mozbuild') +SOURCES += [ 'mozEnglishWordUtils.cpp', 'mozGenericWordUtils.cpp', 'mozInlineSpellChecker.cpp', @@ -24,5 +25,8 @@ LOCAL_INCLUDES += [ '/content/base/src', '/editor/libeditor/base', ] +EXPORTS.mozilla += [ + 'mozSpellChecker.h', +] FAIL_ON_WARNINGS = True diff --git a/extensions/spellcheck/src/mozSpellChecker.cpp b/extensions/spellcheck/src/mozSpellChecker.cpp index 1d2b20b5881a..c692f089967a 100644 --- a/extensions/spellcheck/src/mozSpellChecker.cpp +++ b/extensions/spellcheck/src/mozSpellChecker.cpp @@ -10,6 +10,13 @@ #include "nsICategoryManager.h" #include "nsISupportsPrimitives.h" #include "nsISimpleEnumerator.h" +#include "mozilla/PRemoteSpellcheckEngineChild.h" +#include "mozilla/dom/ContentChild.h" +#include "nsXULAppAPI.h" + +using mozilla::dom::ContentChild; +using mozilla::PRemoteSpellcheckEngineChild; +using mozilla::RemoteSpellcheckEngineChild; #define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1" @@ -38,6 +45,10 @@ mozSpellChecker::~mozSpellChecker() } mSpellCheckingEngine = nullptr; mPersonalDictionary = nullptr; + + if(XRE_GetProcessType() == GeckoProcessType_Content) { + mEngine->Send__delete__(mEngine); + } } nsresult @@ -46,6 +57,12 @@ mozSpellChecker::Init() mPersonalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1"); mSpellCheckingEngine = nullptr; + if (XRE_GetProcessType() == GeckoProcessType_Content) { + mozilla::dom::ContentChild* contentChild = mozilla::dom::ContentChild::GetSingleton(); + MOZ_ASSERT(contentChild); + mEngine = new RemoteSpellcheckEngineChild(this); + contentChild->SendPRemoteSpellcheckEngineConstructor(mEngine); + } return NS_OK; } @@ -108,9 +125,16 @@ mozSpellChecker::CheckWord(const nsAString &aWord, bool *aIsMisspelled, nsTArray { nsresult result; bool correct; - if(!mSpellCheckingEngine) - return NS_ERROR_NULL_POINTER; + if (XRE_GetProcessType() == GeckoProcessType_Content) { + nsString wordwrapped = nsString(aWord); + bool rv = mEngine->SendCheckForMisspelling(wordwrapped, aIsMisspelled); + return rv ? NS_OK : NS_ERROR_NOT_AVAILABLE; + } + + if(!mSpellCheckingEngine) { + return NS_ERROR_NULL_POINTER; + } *aIsMisspelled = false; result = mSpellCheckingEngine->Check(PromiseFlatString(aWord).get(), &correct); NS_ENSURE_SUCCESS(result, result); @@ -332,6 +356,13 @@ mozSpellChecker::GetCurrentDictionary(nsAString &aDictionary) NS_IMETHODIMP mozSpellChecker::SetCurrentDictionary(const nsAString &aDictionary) { + if (XRE_GetProcessType() == GeckoProcessType_Content) { + nsString wrappedDict = nsString(aDictionary); + bool isSuccess; + mEngine->SendSetDictionary(wrappedDict, &isSuccess); + return isSuccess ? NS_OK : NS_ERROR_NOT_AVAILABLE; + } + // Calls to mozISpellCheckingEngine::SetDictionary might destroy us nsRefPtr kungFuDeathGrip = this; @@ -528,3 +559,7 @@ mozSpellChecker::GetEngineList(nsCOMArray* aSpellChecki return NS_OK; } + +void mozSpellChecker::DeleteRemoteEngine() { + mEngine = nullptr; +} \ No newline at end of file diff --git a/extensions/spellcheck/src/mozSpellChecker.h b/extensions/spellcheck/src/mozSpellChecker.h index 76f124369976..f28ffe394223 100644 --- a/extensions/spellcheck/src/mozSpellChecker.h +++ b/extensions/spellcheck/src/mozSpellChecker.h @@ -17,6 +17,12 @@ #include "nsTArray.h" #include "mozISpellI18NUtil.h" #include "nsCycleCollectionParticipant.h" +#include "RemoteSpellCheckEngineChild.h" + +namespace mozilla { +class PRemoteSpellcheckEngineChild; +class RemoteSpellcheckEngineChild; +} class mozSpellChecker : public nsISpellChecker { @@ -43,6 +49,7 @@ public: NS_IMETHOD GetCurrentDictionary(nsAString &aDictionary); NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary); NS_IMETHOD CheckCurrentDictionary(); + void DeleteRemoteEngine(); protected: virtual ~mozSpellChecker(); @@ -59,5 +66,7 @@ protected: nsresult GetCurrentBlockIndex(nsITextServicesDocument *aDoc, int32_t *outBlockIndex); nsresult GetEngineList(nsCOMArray *aDictionaryList); + + mozilla::PRemoteSpellcheckEngineChild *mEngine; }; #endif // mozSpellChecker_h__ diff --git a/toolkit/content/widgets/textbox.xml b/toolkit/content/widgets/textbox.xml index c6bff267d784..f7a3cdebe34c 100644 --- a/toolkit/content/widgets/textbox.xml +++ b/toolkit/content/widgets/textbox.xml @@ -541,7 +541,7 @@ + oncommand="this.parentNode.parentNode.spellCheckerUI.toggleEnabled(window);"/> = this.mDictionaryNames.length) return; var spellchecker = this.mInlineSpellChecker.spellChecker; @@ -293,8 +305,20 @@ InlineSpellChecker.prototype = { }, // callback for enabling or disabling spellchecking - toggleEnabled: function() + toggleEnabled: function(aWindow) { + // Avoid a crash in multiprocess until Bug 1030451 lands + // Remove aWindow parameter at that time + const Ci = Components.interfaces; + let chromeFlags = aWindow.QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIWebNavigation). + QueryInterface(Ci.nsIDocShellTreeItem).treeOwner. + QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIXULWindow).chromeFlags; + let chromeRemoteWindow = Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW; + if (chromeFlags & chromeRemoteWindow) { + return; + } this.mEditor.setSpellcheckUserOverride(!this.mInlineSpellChecker.enableRealTimeSpell); },