Bug 1330912 - Part 1. Add async version of SetCurrentDictionary using list. r=Ehsan
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Mon, 10 Apr 2017 18:29:16 +0900
changeset 400471 3facdd7bcabd208b2ebef0fc2630288883399517
parent 400470 b40873875e3b0a196c901ac6ed11f695eeb5e966
child 400472 d813879551cb27fb26d7416708ecee1607bf8a0e
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersEhsan
bugs1330912
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1330912 - Part 1. Add async version of SetCurrentDictionary using list. r=Ehsan Now, mozInlineSpellChecker::UpdateCurrentDictionary uses several sync IPC message to update spellcheck dictionary. So I want async IPC to set dictionary. Also, since nsEditorSpellCheck::DictionaryFetched calls SetCurrentDictionary several times (max: 6 times), so to reduce calls, we should use list of dictionary. MozReview-Commit-ID: EVMAJxpMT2X
editor/txtsvc/nsISpellChecker.h
extensions/spellcheck/hunspell/glue/PRemoteSpellcheckEngine.ipdl
extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.h
extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.cpp
extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.h
extensions/spellcheck/src/mozSpellChecker.cpp
extensions/spellcheck/src/mozSpellChecker.h
--- a/editor/txtsvc/nsISpellChecker.h
+++ b/editor/txtsvc/nsISpellChecker.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 nsISpellChecker_h__
 #define nsISpellChecker_h__
 
+#include "mozilla/MozPromise.h"
 #include "nsISupports.h"
 #include "nsTArray.h"
 
 #define NS_SPELLCHECKER_CONTRACTID "@mozilla.org/spellchecker;1"
 
 #define NS_ISPELLCHECKER_IID                    \
 { /* 27bff957-b486-40ae-9f5d-af0cdd211868 */    \
 0x27bff957, 0xb486, 0x40ae, \
@@ -109,14 +110,21 @@ public:
 
   /**
    * Tells the spellchecker to use a specific dictionary.
    * @param aDictionary a string that is in the list returned
    * by GetDictionaryList() or an empty string. If aDictionary is
    * empty string, spellchecker will be disabled.
    */
   NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) = 0;
+
+  /**
+   * Tells the spellchecker to use a specific dictionary from list.
+   * @param aList  a preferred dictionary list
+   */
+  NS_IMETHOD_(RefPtr<mozilla::GenericPromise>)
+    SetCurrentDictionaryFromList(const nsTArray<nsString>& aList) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsISpellChecker, NS_ISPELLCHECKER_IID)
 
 #endif // nsISpellChecker_h__
 
--- a/extensions/spellcheck/hunspell/glue/PRemoteSpellcheckEngine.ipdl
+++ b/extensions/spellcheck/hunspell/glue/PRemoteSpellcheckEngine.ipdl
@@ -12,11 +12,16 @@ sync protocol PRemoteSpellcheckEngine {
 parent:
   async __delete__();
 
   sync Check(nsString aWord) returns (bool aIsMisspelled);
 
   sync CheckAndSuggest(nsString aWord) returns (bool aIsMisspelled, nsString[] aSuggestions);
 
   sync SetDictionary(nsString aDictionary) returns (bool success);
+
+  async SetDictionaryFromList(nsString[] aList, intptr_t aPromiseId);
+
+child:
+  async NotifyOfCurrentDictionary(nsString aDictionary, intptr_t aPromiseId);
 };
 
 } // namespace mozilla
--- a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
+++ b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
@@ -1,21 +1,55 @@
 /* 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 "mozilla/UniquePtr.h"
 #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();
 }
 
+RefPtr<GenericPromise>
+RemoteSpellcheckEngineChild::SetCurrentDictionaryFromList(
+  const nsTArray<nsString>& aList)
+{
+  MozPromiseHolder<GenericPromise>* promiseHolder =
+    new MozPromiseHolder<GenericPromise>();
+  if (!SendSetDictionaryFromList(
+         aList,
+         reinterpret_cast<intptr_t>(promiseHolder))) {
+    delete promiseHolder;
+    return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+  // promiseHolder will removed by receive message
+  return promiseHolder->Ensure(__func__);
+}
+
+mozilla::ipc::IPCResult
+RemoteSpellcheckEngineChild::RecvNotifyOfCurrentDictionary(
+                               const nsString& aDictionary,
+                               const intptr_t& aId)
+{
+  MozPromiseHolder<GenericPromise>* promiseHolder =
+    reinterpret_cast<MozPromiseHolder<GenericPromise>*>(aId);
+  mOwner->mCurrentDictionary = aDictionary;
+  if (aDictionary.IsEmpty()) {
+    promiseHolder->RejectIfExists(NS_ERROR_NOT_AVAILABLE, __func__);
+  } else {
+    promiseHolder->ResolveIfExists(true, __func__);
+  }
+  delete promiseHolder;
+  return IPC_OK();
+}
+
 } //namespace mozilla
--- a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.h
+++ b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.h
@@ -1,27 +1,35 @@
 /* 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/MozPromise.h"
 #include "mozilla/PRemoteSpellcheckEngineChild.h"
 #include "mozSpellChecker.h"
 
 class mozSpellChecker;
 
 namespace mozilla {
 
 class RemoteSpellcheckEngineChild : public mozilla::PRemoteSpellcheckEngineChild
 {
 public:
   explicit RemoteSpellcheckEngineChild(mozSpellChecker *aOwner);
   virtual ~RemoteSpellcheckEngineChild();
 
+  virtual mozilla::ipc::IPCResult RecvNotifyOfCurrentDictionary(
+                                    const nsString& aDictionary,
+                                    const intptr_t& aPromiseId) override;
+
+  RefPtr<GenericPromise> SetCurrentDictionaryFromList(
+                           const nsTArray<nsString>& aList);
+
 private:
   mozSpellChecker *mOwner;
 };
 
 } //namespace mozilla
 
 #endif // RemoteSpellcheckEngineChild_h_
--- a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.cpp
+++ b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.cpp
@@ -1,14 +1,15 @@
 /* vim: set ts=2 sw=2 sts=2 tw=80: */
 /* 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 "mozilla/Unused.h"
 #include "nsISpellChecker.h"
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 
 RemoteSpellcheckEngineParent::RemoteSpellcheckEngineParent()
 {
   mSpellChecker = do_CreateInstance(NS_SPELLCHECKER_CONTRACTID);
@@ -24,16 +25,33 @@ RemoteSpellcheckEngineParent::RecvSetDic
   bool* success)
 {
   nsresult rv = mSpellChecker->SetCurrentDictionary(aDictionary);
   *success = NS_SUCCEEDED(rv);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+RemoteSpellcheckEngineParent::RecvSetDictionaryFromList(
+                                nsTArray<nsString>&& aList,
+                                const intptr_t& aPromiseId)
+{
+  for (auto& dictionary : aList) {
+    MOZ_ASSERT(!dictionary.IsEmpty());
+    nsresult rv = mSpellChecker->SetCurrentDictionary(dictionary);
+    if (NS_SUCCEEDED(rv)) {
+      Unused << SendNotifyOfCurrentDictionary(dictionary, aPromiseId);
+      return IPC_OK();
+    }
+  }
+  Unused << SendNotifyOfCurrentDictionary(EmptyString(), aPromiseId);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 RemoteSpellcheckEngineParent::RecvCheck(
   const nsString& aWord,
   bool* aIsMisspelled)
 {
   nsresult rv = mSpellChecker->CheckWord(aWord, aIsMisspelled, nullptr);
 
   // If CheckWord failed, we can't tell whether the word is correctly spelled.
   if (NS_FAILED(rv))
--- a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.h
+++ b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.h
@@ -1,16 +1,17 @@
 /* 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 "mozilla/PRemoteSpellcheckEngineParent.h"
 #include "nsCOMPtr.h"
+#include "nsTArray.h"
 
 class nsISpellChecker;
 
 namespace mozilla {
 
 class RemoteSpellcheckEngineParent : public PRemoteSpellcheckEngineParent
 {
 public:
@@ -18,16 +19,20 @@ public:
 
   virtual ~RemoteSpellcheckEngineParent();
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual mozilla::ipc::IPCResult RecvSetDictionary(const nsString& aDictionary,
                                                     bool* success) override;
 
+  virtual mozilla::ipc::IPCResult RecvSetDictionaryFromList(
+                                    nsTArray<nsString>&& aList,
+                                    const intptr_t& aPromiseId) override;
+
   virtual mozilla::ipc::IPCResult RecvCheck(const nsString& aWord, bool* aIsMisspelled) override;
 
   virtual mozilla::ipc::IPCResult RecvCheckAndSuggest(const nsString& aWord,
                                                       bool* aIsMisspelled,
                                                       InfallibleTArray<nsString>* aSuggestions)
       override;
 
 private:
--- a/extensions/spellcheck/src/mozSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozSpellChecker.cpp
@@ -11,16 +11,17 @@
 #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::GenericPromise;
 using mozilla::PRemoteSpellcheckEngineChild;
 using mozilla::RemoteSpellcheckEngineChild;
 
 #define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1"
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellChecker)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozSpellChecker)
 
@@ -424,16 +425,38 @@ mozSpellChecker::SetCurrentDictionary(co
   }
 
   mSpellCheckingEngine = nullptr;
 
   // We could not find any engine with the requested dictionary
   return NS_ERROR_NOT_AVAILABLE;
 }
 
+NS_IMETHODIMP_(RefPtr<GenericPromise>)
+mozSpellChecker::SetCurrentDictionaryFromList(const nsTArray<nsString>& aList)
+{
+  if (aList.IsEmpty()) {
+    return GenericPromise::CreateAndReject(NS_ERROR_INVALID_ARG, __func__);
+  }
+
+  if (XRE_IsContentProcess()) {
+    // mCurrentDictionary will be set by RemoteSpellCheckEngineChild
+    return mEngine->SetCurrentDictionaryFromList(aList);
+  }
+
+  for (auto& dictionary : aList) {
+    nsresult rv = SetCurrentDictionary(dictionary);
+    if (NS_SUCCEEDED(rv)) {
+      return GenericPromise::CreateAndResolve(true, __func__);
+    }
+  }
+  // We could not find any engine with the requested dictionary
+  return GenericPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
+}
+
 nsresult
 mozSpellChecker::SetupDoc(int32_t *outBlockOffset)
 {
   nsresult  rv;
 
   nsITextServicesDocument::TSDBlockSelectionStatus blockStatus;
   int32_t selOffset;
   int32_t selLength;
--- a/extensions/spellcheck/src/mozSpellChecker.h
+++ b/extensions/spellcheck/src/mozSpellChecker.h
@@ -15,17 +15,16 @@
 #include "mozISpellCheckingEngine.h"
 #include "nsClassHashtable.h"
 #include "nsTArray.h"
 #include "mozISpellI18NUtil.h"
 #include "nsCycleCollectionParticipant.h"
 #include "RemoteSpellCheckEngineChild.h"
 
 namespace mozilla {
-class PRemoteSpellcheckEngineChild;
 class RemoteSpellcheckEngineChild;
 } // namespace mozilla
 
 class mozSpellChecker : public nsISpellChecker
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(mozSpellChecker)
@@ -43,16 +42,18 @@ public:
 
   NS_IMETHOD AddWordToPersonalDictionary(const nsAString &aWord) override;
   NS_IMETHOD RemoveWordFromPersonalDictionary(const nsAString &aWord) override;
   NS_IMETHOD GetPersonalDictionary(nsTArray<nsString> *aWordList) override;
 
   NS_IMETHOD GetDictionaryList(nsTArray<nsString> *aDictionaryList) override;
   NS_IMETHOD GetCurrentDictionary(nsAString &aDictionary) override;
   NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) override;
+  NS_IMETHOD_(RefPtr<mozilla::GenericPromise>)
+    SetCurrentDictionaryFromList(const nsTArray<nsString>& aList) override;
 
   void DeleteRemoteEngine() {
     mEngine = nullptr;
   }
 
 protected:
   virtual ~mozSpellChecker();
 
@@ -66,11 +67,13 @@ protected:
   nsString mCurrentDictionary;
 
   nsresult SetupDoc(int32_t *outBlockOffset);
 
   nsresult GetCurrentBlockIndex(nsITextServicesDocument *aDoc, int32_t *outBlockIndex);
 
   nsresult GetEngineList(nsCOMArray<mozISpellCheckingEngine> *aDictionaryList);
 
-  mozilla::PRemoteSpellcheckEngineChild *mEngine;
+  mozilla::RemoteSpellcheckEngineChild *mEngine;
+
+  friend class mozilla::RemoteSpellcheckEngineChild;
 };
 #endif // mozSpellChecker_h__