зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1719110 - Add nsIEditorSpellCheck.suggest to get rid of PRemoteSpellcheckEngine.CheckAndSuggest. r=masayuki
When getting suggestions from spellchecker's result, we use sync IPC (`PRemoteSpellcheckEngine.CheckAndSuggest`). This is used by showing context menu only on Gecko. So I think that we can remove this IPC if we add async API to get spellchecker suggestions. And in comm-central's code, `CheckCurrentWord` and `GetSuggestedWord` seems to use on spellchecker dialog (content/dialogs/EdSpellCheck.js in mail and suite) that runs on parent process. So c-c won't use this IPC method. So I would like to add the promise version of getting spellchecker's suggestion. Differential Revision: https://phabricator.services.mozilla.com/D119936
This commit is contained in:
Родитель
ace90e9307
Коммит
a6944a1428
|
@ -60,6 +60,13 @@ interface nsIEditorSpellCheck : nsISupports
|
|||
*/
|
||||
boolean CheckCurrentWord(in AString suggestedWord);
|
||||
|
||||
/**
|
||||
* Check a given word then returns suggestion words via Promise if a given
|
||||
* word is misspelled. If not misspelled, returns empty string array.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
Promise suggest(in AString aCheckingWorkd, in unsigned long aMaxCount);
|
||||
|
||||
/**
|
||||
* Use when modally checking the document to replace a word.
|
||||
*
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/EditorBase.h" // for EditorBase
|
||||
#include "mozilla/HTMLEditor.h" // for HTMLEditor
|
||||
#include "mozilla/dom/Element.h" // for Element
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/dom/StaticRange.h"
|
||||
#include "mozilla/intl/LocaleService.h" // for retrieving app locale
|
||||
|
@ -448,6 +449,36 @@ EditorSpellCheck::CheckCurrentWord(const nsAString& aSuggestedWord,
|
|||
&mSuggestedWordList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorSpellCheck::Suggest(const nsAString& aSuggestedWord, uint32_t aCount,
|
||||
JSContext* aCx, Promise** aPromise) {
|
||||
NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aCx);
|
||||
if (NS_WARN_IF(!globalObject)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
ErrorResult result;
|
||||
RefPtr<Promise> promise = Promise::Create(globalObject, result);
|
||||
if (NS_WARN_IF(result.Failed())) {
|
||||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
mSpellChecker->Suggest(aSuggestedWord, aCount)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[promise](const CopyableTArray<nsString>& aSuggestions) {
|
||||
promise->MaybeResolve(aSuggestions);
|
||||
},
|
||||
[promise](nsresult aError) {
|
||||
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||
});
|
||||
|
||||
promise.forget(aPromise);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<CheckWordPromise> EditorSpellCheck::CheckCurrentWordsNoSuggest(
|
||||
const nsTArray<nsString>& aSuggestedWords) {
|
||||
if (NS_WARN_IF(!mSpellChecker)) {
|
||||
|
|
|
@ -40,3 +40,4 @@ skip-if = e10s
|
|||
[test_bug1418629.html]
|
||||
[test_bug1497480.html]
|
||||
[test_bug1602526.html]
|
||||
[test_suggest.html]
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for nsIEditorSpellChecfker.sugget</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
|
||||
<div contenteditable id="en-US" lang="en-US">missspelled</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
add_task(async function() {
|
||||
await new Promise(resolve => SimpleTest.waitForFocus(resolve));
|
||||
|
||||
let { onSpellCheck } =
|
||||
SpecialPowers.Cu.import(
|
||||
"resource://testing-common/AsyncSpellCheckTestHelper.jsm", null);
|
||||
|
||||
let element = document.getElementById("en-US");
|
||||
element.focus();
|
||||
|
||||
await new Promise(resolve => onSpellCheck(element, resolve));
|
||||
|
||||
let editingSession = SpecialPowers.wrap(window).docShell.editingSession;
|
||||
let editor = editingSession.getEditorForWindow(window);
|
||||
let spellchecker = SpecialPowers.Cu.createSpellChecker();
|
||||
spellchecker.setFilterType(spellchecker.FILTERTYPE_NORMAL);
|
||||
await new Promise(resolve => spellchecker.InitSpellChecker(editor, false, resolve));
|
||||
|
||||
let suggestions = await spellchecker.suggest("misspelled", 5);
|
||||
is(suggestions.length, 0, "\"misspelled\" is correct word");
|
||||
|
||||
suggestions = await spellchecker.suggest("missspelled", 5);
|
||||
is(suggestions.length, 5, "\"missspelled\" isn't correct word");
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -18,6 +18,8 @@ parent:
|
|||
|
||||
sync SetDictionary(nsCString aDictionary) returns (bool success);
|
||||
|
||||
async Suggest(nsString aWord, uint32_t aCount) returns (nsString[] aSuggestions);
|
||||
|
||||
/*
|
||||
* Set current dictionary from list of dictionary name.
|
||||
*
|
||||
|
|
|
@ -64,6 +64,23 @@ mozilla::ipc::IPCResult RemoteSpellcheckEngineParent::RecvCheckAndSuggest(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RemoteSpellcheckEngineParent::RecvSuggest(
|
||||
const nsString& aWord, uint32_t aCount, SuggestResolver&& aResolve) {
|
||||
nsTArray<nsString> suggestions;
|
||||
mSpellChecker->Suggest(aWord, aCount)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[aResolve](CopyableTArray<nsString> aSuggestions) {
|
||||
aResolve(std::move(aSuggestions));
|
||||
},
|
||||
[aResolve](nsresult aError) {
|
||||
// No suggestions due to error
|
||||
nsTArray<nsString> suggestions;
|
||||
aResolve(std::move(suggestions));
|
||||
});
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void RemoteSpellcheckEngineParent::ActorDestroy(ActorDestroyReason aWhy) {}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -33,6 +33,10 @@ class RemoteSpellcheckEngineParent : public PRemoteSpellcheckEngineParent {
|
|||
const nsString& aWord, bool* aIsMisspelled,
|
||||
nsTArray<nsString>* aSuggestions);
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvSuggest(const nsString& aWord,
|
||||
uint32_t aCount,
|
||||
SuggestResolver&& aResolve);
|
||||
|
||||
private:
|
||||
RefPtr<mozSpellChecker> mSpellChecker;
|
||||
};
|
||||
|
|
|
@ -172,6 +172,46 @@ nsresult mozSpellChecker::CheckWord(const nsAString& aWord, bool* aIsMisspelled,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::SuggestionsPromise> mozSpellChecker::Suggest(
|
||||
const nsAString& aWord, uint32_t aMaxCount) {
|
||||
if (XRE_IsContentProcess()) {
|
||||
return mEngine->SendSuggest(nsString(aWord), aMaxCount)
|
||||
->Then(
|
||||
mozilla::GetCurrentSerialEventTarget(), __func__,
|
||||
[](nsTArray<nsString>&& aSuggestions) {
|
||||
return mozilla::SuggestionsPromise::CreateAndResolve(
|
||||
std::move(aSuggestions), __func__);
|
||||
},
|
||||
[](mozilla::ipc::ResponseRejectReason&& aReason) {
|
||||
return mozilla::SuggestionsPromise::CreateAndReject(
|
||||
NS_ERROR_NOT_AVAILABLE, __func__);
|
||||
});
|
||||
}
|
||||
|
||||
if (!mSpellCheckingEngine) {
|
||||
return mozilla::SuggestionsPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
|
||||
__func__);
|
||||
}
|
||||
|
||||
bool correct;
|
||||
nsresult rv = mSpellCheckingEngine->Check(aWord, &correct);
|
||||
if (NS_FAILED(rv)) {
|
||||
return mozilla::SuggestionsPromise::CreateAndReject(rv, __func__);
|
||||
}
|
||||
nsTArray<nsString> suggestions;
|
||||
if (!correct) {
|
||||
rv = mSpellCheckingEngine->Suggest(aWord, suggestions);
|
||||
if (NS_FAILED(rv)) {
|
||||
return mozilla::SuggestionsPromise::CreateAndReject(rv, __func__);
|
||||
}
|
||||
if (suggestions.Length() > aMaxCount) {
|
||||
suggestions.TruncateLength(aMaxCount);
|
||||
}
|
||||
}
|
||||
return mozilla::SuggestionsPromise::CreateAndResolve(std::move(suggestions),
|
||||
__func__);
|
||||
}
|
||||
|
||||
nsresult mozSpellChecker::Replace(const nsAString& aOldWord,
|
||||
const nsAString& aNewWord,
|
||||
bool aAllOccurrences) {
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace mozilla {
|
|||
class RemoteSpellcheckEngineChild;
|
||||
class TextServicesDocument;
|
||||
typedef MozPromise<CopyableTArray<bool>, nsresult, false> CheckWordPromise;
|
||||
typedef MozPromise<CopyableTArray<nsString>, nsresult, false>
|
||||
SuggestionsPromise;
|
||||
} // namespace mozilla
|
||||
|
||||
class mozSpellChecker final {
|
||||
|
@ -74,6 +76,12 @@ class mozSpellChecker final {
|
|||
RefPtr<mozilla::CheckWordPromise> CheckWords(
|
||||
const nsTArray<nsString>& aWords);
|
||||
|
||||
/*
|
||||
* Checks if a word is misspelled, then get suggestion words if existed.
|
||||
*/
|
||||
RefPtr<mozilla::SuggestionsPromise> Suggest(const nsAString& aWord,
|
||||
uint32_t aMaxCount);
|
||||
|
||||
/**
|
||||
* Replaces the old word with the specified new word.
|
||||
* @param aOldWord is the word to be replaced.
|
||||
|
|
Загрузка…
Ссылка в новой задаче