Merge inbound to mozilla-central. a=merge

This commit is contained in:
shindli 2019-01-17 18:13:41 +02:00
Родитель de59370b24 91431779d9
Коммит a2bd3a1afa
13 изменённых файлов: 218 добавлений и 59 удалений

Просмотреть файл

@ -137,7 +137,7 @@
<!-- Clear Site Data Button -->
<vbox hidden="true"
id="identity-popup-clear-sitedata-footer"
class="panel-footer identity-popup-footer">
class="panel-footer">
<button id="identity-popup-clear-sitedata-button"
label="&identity.clearSiteData;"
oncommand="gIdentityHandler.clearSiteData(event); gIdentityHandler.recordClick('clear_sitedata');"/>
@ -226,7 +226,7 @@
oncommand="gIdentityHandler.enableMixedContentProtection()"/>
</vbox>
<vbox id="identity-popup-more-info-footer" class="panel-footer identity-popup-footer">
<vbox id="identity-popup-more-info-footer" class="panel-footer">
<!-- More Security Information -->
<button id="identity-popup-more-info"
label="&identity.moreInfoLinkText2;"
@ -246,7 +246,7 @@
<image/>
<label>&contentBlocking.trackersView.strictInfo.label;</label>
</hbox>
<vbox class="panel-footer identity-popup-footer">
<vbox class="panel-footer">
<button id="identity-popup-trackersView-settings-button"
label="&contentBlocking.manageSettings.label;"
accesskey="&contentBlocking.manageSettings.accesskey;"
@ -261,7 +261,7 @@
descriptionheightworkaround="true">
<vbox id="identity-popup-cookiesView-list" class="identity-popup-content-blocking-list">
</vbox>
<vbox class="panel-footer identity-popup-footer">
<vbox class="panel-footer">
<button id="identity-popup-cookiesView-settings-button"
label="&contentBlocking.manageSettings.label;"
accesskey="&contentBlocking.manageSettings.accesskey;"
@ -289,7 +289,7 @@
</vbox>
</vbox>
<vbox id="identity-popup-breakageReportView-footer"
class="panel-footer identity-popup-footer">
class="panel-footer">
<button id="identity-popup-breakageReportView-cancel"
label="&contentBlocking.breakageReportView.cancel.label;"
oncommand="ContentBlocking.backToMainView();"/>

Просмотреть файл

@ -441,6 +441,16 @@ EditorSpellCheck::CheckCurrentWordNoSuggest(const nsAString& aSuggestedWord,
return mSpellChecker->CheckWord(aSuggestedWord, aIsMisspelled, nullptr);
}
RefPtr<CheckWordPromise> EditorSpellCheck::CheckCurrentWordsNoSuggest(
const nsTArray<nsString>& aSuggestedWords) {
if (NS_WARN_IF(!mSpellChecker)) {
return CheckWordPromise::CreateAndReject(NS_ERROR_NOT_INITIALIZED,
__func__);
}
return mSpellChecker->CheckWords(aSuggestedWords);
}
NS_IMETHODIMP
EditorSpellCheck::ReplaceWord(const nsAString& aMisspelledWord,
const nsAString& aReplaceWord,

Просмотреть файл

@ -6,7 +6,8 @@
#ifndef mozilla_EditorSpellCheck_h
#define mozilla_EditorSpellCheck_h
#include "nsCOMPtr.h" // for nsCOMPtr
#include "mozilla/mozSpellChecker.h" // for mozilla::CheckWordPromise
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsCycleCollectionParticipant.h"
#include "nsIEditorSpellCheck.h" // for NS_DECL_NSIEDITORSPELLCHECK, etc
#include "nsISupportsImpl.h"
@ -42,6 +43,19 @@ class EditorSpellCheck final : public nsIEditorSpellCheck {
mozSpellChecker* GetSpellChecker();
/**
* Like CheckCurrentWord, checks the word you give it, returning true via
* promise if it's misspelled.
* This is faster than CheckCurrentWord because it does not compute
* any suggestions.
*
* Watch out: this does not clear any suggestions left over from previous
* calls to CheckCurrentWord, so there may be suggestions, but they will be
* invalid.
*/
RefPtr<mozilla::CheckWordPromise> CheckCurrentWordsNoSuggest(
const nsTArray<nsString>& aSuggestedWords);
protected:
virtual ~EditorSpellCheck();

Просмотреть файл

@ -13,6 +13,7 @@ parent:
async __delete__();
sync Check(nsString aWord) returns (bool aIsMisspelled);
async CheckAsync(nsString[] aWord) returns (bool[] aIsMisspelled);
sync CheckAndSuggest(nsString aWord) returns (bool aIsMisspelled, nsString[] aSuggestions);

Просмотреть файл

@ -45,6 +45,23 @@ mozilla::ipc::IPCResult RemoteSpellcheckEngineParent::RecvCheck(
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteSpellcheckEngineParent::RecvCheckAsync(
nsTArray<nsString>&& aWords, CheckAsyncResolver&& aResolve) {
nsTArray<bool> misspells;
misspells.SetCapacity(aWords.Length());
for (auto& word : aWords) {
bool misspelled;
nsresult rv = mSpellChecker->CheckWord(word, &misspelled, nullptr);
// If CheckWord failed, we can't tell whether the word is correctly spelled
if (NS_FAILED(rv)) {
misspelled = false;
}
misspells.AppendElement(misspelled);
}
aResolve(std::move(misspells));
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteSpellcheckEngineParent::RecvCheckAndSuggest(
const nsString& aWord, bool* aIsMisspelled,
InfallibleTArray<nsString>* aSuggestions) {

Просмотреть файл

@ -30,6 +30,9 @@ class RemoteSpellcheckEngineParent : public PRemoteSpellcheckEngineParent {
virtual mozilla::ipc::IPCResult RecvCheck(const nsString& aWord,
bool* aIsMisspelled) override;
virtual mozilla::ipc::IPCResult RecvCheckAsync(
nsTArray<nsString>&& aWord, CheckAsyncResolver&& aResolve) override;
virtual mozilla::ipc::IPCResult RecvCheckAndSuggest(
const nsString& aWord, bool* aIsMisspelled,
InfallibleTArray<nsString>* aSuggestions) override;

Просмотреть файл

@ -68,6 +68,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::ipc;
// Set to spew messages to the console about what is happening.
//#define DEBUG_INLINESPELL
@ -81,6 +82,9 @@ using namespace mozilla::dom;
// be too short to a low-end machine.
#define INLINESPELL_MINIMUM_WORDS_BEFORE_TIMEOUT 5
// The maximum number of words to check word via IPC.
#define INLINESPELL_MAXIMUM_CHUNKED_WORDS_PER_TASK 25
// These notifications are broadcast when spell check starts and ends. STARTED
// must always be followed by ENDED.
#define INLINESPELL_STARTED_TOPIC "inlineSpellChecker-spellCheck-started"
@ -92,7 +96,7 @@ static const PRTime kMaxSpellCheckTimeInUsec =
INLINESPELL_CHECK_TIMEOUT * PR_USEC_PER_MSEC;
mozInlineSpellStatus::mozInlineSpellStatus(mozInlineSpellChecker* aSpellChecker)
: mSpellChecker(aSpellChecker), mWordCount(0) {}
: mSpellChecker(aSpellChecker) {}
// mozInlineSpellStatus::InitForEditorChange
//
@ -520,7 +524,6 @@ mozInlineSpellChecker::mozInlineSpellChecker()
if (prefs)
prefs->GetIntPref(kMaxSpellCheckSelectionSize,
&mMaxNumWordsInSpellSelection);
mMaxMisspellingsPerCheck = mMaxNumWordsInSpellSelection * 3 / 4;
}
mozInlineSpellChecker::~mozInlineSpellChecker() {}
@ -1195,8 +1198,6 @@ nsresult mozInlineSpellChecker::DoSpellCheckSelection(
MOZ_ASSERT(
doneChecking,
"We gave the spellchecker one word, but it didn't finish checking?!?!");
status->mWordCount = 0;
}
return NS_OK;
@ -1238,12 +1239,18 @@ nsresult mozInlineSpellChecker::DoSpellCheck(
const UniquePtr<mozInlineSpellStatus>& aStatus, bool* aDoneChecking) {
*aDoneChecking = true;
NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
if (NS_WARN_IF(!mSpellCheck)) {
return NS_ERROR_NOT_INITIALIZED;
}
if (SpellCheckSelectionIsFull()) {
return NS_OK;
}
// get the editor for ShouldSpellCheckNode, this may fail in reasonable
// circumstances since the editor could have gone away
RefPtr<TextEditor> textEditor = mTextEditor;
if (!textEditor) {
if (!textEditor || textEditor->Destroyed()) {
return NS_ERROR_FAILURE;
}
@ -1291,25 +1298,34 @@ nsresult mozInlineSpellChecker::DoSpellCheck(
int32_t wordsChecked = 0;
PRTime beginTime = PR_Now();
nsTArray<nsString> words;
nsTArray<NodeOffsetRange> checkRanges;
nsAutoString wordText;
NodeOffsetRange wordNodeOffsetRange;
bool dontCheckWord;
// XXX Spellchecker API isn't async on chrome process.
static const size_t requestChunkSize =
XRE_IsContentProcess() ? INLINESPELL_MAXIMUM_CHUNKED_WORDS_PER_TASK : 1;
while (NS_SUCCEEDED(aWordUtil.GetNextWord(wordText, &wordNodeOffsetRange,
&dontCheckWord)) &&
!wordNodeOffsetRange.Empty()) {
// get the range for the current word.
nsINode* beginNode = wordNodeOffsetRange.Begin().mNode;
nsINode* endNode = wordNodeOffsetRange.End().mNode;
int32_t beginOffset = wordNodeOffsetRange.Begin().mOffset;
int32_t endOffset = wordNodeOffsetRange.End().mOffset;
nsINode* beginNode = wordNodeOffsetRange.Begin().Node();
nsINode* endNode = wordNodeOffsetRange.End().Node();
int32_t beginOffset = wordNodeOffsetRange.Begin().Offset();
int32_t endOffset = wordNodeOffsetRange.End().Offset();
// see if we've done enough words in this round and run out of time.
if (wordsChecked >= INLINESPELL_MINIMUM_WORDS_BEFORE_TIMEOUT &&
PR_Now() > PRTime(beginTime + kMaxSpellCheckTimeInUsec)) {
// stop checking, our time limit has been exceeded.
#ifdef DEBUG_INLINESPELL
printf("We have run out of the time, schedule next round.");
printf("We have run out of the time, schedule next round.\n");
#endif
CheckCurrentWordsNoSuggest(aSpellCheckSelection, words, checkRanges);
words.Clear();
checkRanges.Clear();
// move the range to encompass the stuff that needs checking.
nsresult rv = aStatus->mRange->SetStart(beginNode, beginOffset);
if (NS_FAILED(rv)) {
@ -1366,39 +1382,31 @@ nsresult mozInlineSpellChecker::DoSpellCheck(
}
// check spelling and add to selection if misspelled
bool isMisspelled;
mozInlineSpellWordUtil::NormalizeWord(wordText);
nsresult rv =
mSpellCheck->CheckCurrentWordNoSuggest(wordText, &isMisspelled);
if (NS_FAILED(rv)) continue;
words.AppendElement(wordText);
checkRanges.AppendElement(wordNodeOffsetRange);
wordsChecked++;
if (isMisspelled) {
// misspelled words count extra toward the max
RefPtr<nsRange> wordRange;
// If we somehow can't make a range for this word, just ignore it.
if (NS_SUCCEEDED(aWordUtil.MakeRange(wordNodeOffsetRange.Begin(),
wordNodeOffsetRange.End(),
getter_AddRefs(wordRange)))) {
AddRange(aSpellCheckSelection, wordRange);
aStatus->mWordCount++;
if (aStatus->mWordCount >= mMaxMisspellingsPerCheck ||
SpellCheckSelectionIsFull()) {
break;
}
}
if (words.Length() >= requestChunkSize) {
CheckCurrentWordsNoSuggest(aSpellCheckSelection, words, checkRanges);
words.Clear();
checkRanges.Clear();
}
}
CheckCurrentWordsNoSuggest(aSpellCheckSelection, words, checkRanges);
return NS_OK;
}
// An RAII helper that calls ChangeNumPendingSpellChecks on destruction.
class AutoChangeNumPendingSpellChecks {
class MOZ_RAII AutoChangeNumPendingSpellChecks final {
public:
AutoChangeNumPendingSpellChecks(mozInlineSpellChecker* aSpellChecker,
int32_t aDelta)
: mSpellChecker(aSpellChecker), mDelta(aDelta) {}
explicit AutoChangeNumPendingSpellChecks(mozInlineSpellChecker* aSpellChecker,
int32_t aDelta
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mSpellChecker(aSpellChecker), mDelta(aDelta) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoChangeNumPendingSpellChecks() {
mSpellChecker->ChangeNumPendingSpellChecks(mDelta);
@ -1407,8 +1415,68 @@ class AutoChangeNumPendingSpellChecks {
private:
RefPtr<mozInlineSpellChecker> mSpellChecker;
int32_t mDelta;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
void mozInlineSpellChecker::CheckCurrentWordsNoSuggest(
Selection* aSpellCheckSelection, const nsTArray<nsString>& aWords,
const nsTArray<NodeOffsetRange>& aRanges) {
if (aWords.IsEmpty()) {
return;
}
ChangeNumPendingSpellChecks(1);
RefPtr<mozInlineSpellChecker> self = this;
RefPtr<Selection> spellCheckerSelection = aSpellCheckSelection;
uint32_t token = mDisabledAsyncToken;
mSpellCheck->CheckCurrentWordsNoSuggest(aWords)->Then(
GetMainThreadSerialEventTarget(), __func__,
[self, spellCheckerSelection, aRanges,
token](const nsTArray<bool>& aIsMisspelled) {
if (token != self->mDisabledAsyncToken) {
// This result is never used
return;
}
if (!self->mTextEditor || self->mTextEditor->Destroyed()) {
return;
}
AutoChangeNumPendingSpellChecks pendingChecks(self, -1);
if (self->SpellCheckSelectionIsFull()) {
return;
}
for (size_t i = 0; i < aIsMisspelled.Length(); i++) {
if (!aIsMisspelled[i]) {
continue;
}
RefPtr<nsRange> wordRange =
mozInlineSpellWordUtil::MakeRange(aRanges[i]);
// If we somehow can't make a range for this word, just ignore
// it.
if (wordRange) {
self->AddRange(spellCheckerSelection, wordRange);
}
}
},
[self, token](nsresult aRv) {
if (!self->mTextEditor || self->mTextEditor->Destroyed()) {
return;
}
if (token != self->mDisabledAsyncToken) {
// This result is never used
return;
}
self->ChangeNumPendingSpellChecks(-1);
});
}
// mozInlineSpellChecker::ResumeCheck
//
// Called by the resume event when it fires. We will try to pick up where

Просмотреть файл

@ -10,11 +10,11 @@
#include "nsIDOMEventListener.h"
#include "nsIEditorSpellCheck.h"
#include "nsIInlineSpellChecker.h"
#include "mozInlineSpellWordUtil.h"
#include "nsRange.h"
#include "nsWeakReference.h"
class InitEditorSpellCheckCallback;
class mozInlineSpellWordUtil;
class mozInlineSpellChecker;
class mozInlineSpellResume;
class UpdateCurrentDictionaryCallback;
@ -52,11 +52,6 @@ class mozInlineSpellStatus {
RefPtr<mozInlineSpellChecker> mSpellChecker;
// The total number of words checked in this sequence, using this tally tells
// us when to stop. This count is preserved as we continue checking in new
// messages.
int32_t mWordCount;
// what happened?
enum Operation {
eOpChange, // for SpellCheckAfterEditorChange except
@ -139,13 +134,6 @@ class mozInlineSpellChecker final : public nsIInlineSpellChecker,
int32_t mNumWordsInSpellSelection;
int32_t mMaxNumWordsInSpellSelection;
// How many misspellings we can add at once. This is often less than the max
// total number of misspellings. When you have a large textarea prepopulated
// with text with many misspellings, we can hit this limit. By making it
// lower than the total number of misspelled words, new text typed by the
// user can also have spellchecking in it.
int32_t mMaxMisspellingsPerCheck;
// we need to keep track of the current text position in the document
// so we can spell check the old word when the user clicks around the
// document.
@ -282,6 +270,10 @@ class mozInlineSpellChecker final : public nsIInlineSpellChecker,
void StartToListenToEditSubActions() { mIsListeningToEditSubActions = true; }
void EndListeningToEditSubActions() { mIsListeningToEditSubActions = false; }
void CheckCurrentWordsNoSuggest(mozilla::dom::Selection* aSpellCheckSelection,
const nsTArray<nsString>& aWords,
const nsTArray<NodeOffsetRange>& aRanges);
};
#endif // #ifndef mozilla_mozInlineSpellChecker_h

Просмотреть файл

@ -330,6 +330,19 @@ nsresult mozInlineSpellWordUtil::MakeRange(NodeOffset aBegin, NodeOffset aEnd,
return NS_OK;
}
// static
already_AddRefed<nsRange> mozInlineSpellWordUtil::MakeRange(
const NodeOffsetRange& aRange) {
RefPtr<nsRange> range = new nsRange(aRange.Begin().Node());
nsresult rv =
range->SetStartAndEnd(aRange.Begin().Node(), aRange.Begin().Offset(),
aRange.End().Node(), aRange.End().Offset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
return range.forget();
}
/*********** Word Splitting ************/
// classifies a given character in the DOM word

Просмотреть файл

@ -22,10 +22,10 @@ class TextEditor;
} // namespace mozilla
struct NodeOffset {
nsINode* mNode;
nsCOMPtr<nsINode> mNode;
int32_t mOffset;
NodeOffset() : mNode(nullptr), mOffset(0) {}
NodeOffset() : mOffset(0) {}
NodeOffset(nsINode* aNode, int32_t aOffset)
: mNode(aNode), mOffset(aOffset) {}
@ -34,6 +34,9 @@ struct NodeOffset {
}
bool operator!=(const NodeOffset& aOther) const { return !(*this == aOther); }
nsINode* Node() const { return mNode.get(); }
int32_t Offset() const { return mOffset; }
};
class NodeOffsetRange {
@ -47,11 +50,11 @@ class NodeOffsetRange {
NodeOffsetRange(NodeOffset b, NodeOffset e)
: mBegin(b), mEnd(e), mEmpty(false) {}
NodeOffset Begin() { return mBegin; }
NodeOffset Begin() const { return mBegin; }
NodeOffset End() { return mEnd; }
NodeOffset End() const { return mEnd; }
bool Empty() { return mEmpty; }
bool Empty() const { return mEmpty; }
};
/**
@ -104,6 +107,7 @@ class MOZ_STACK_CLASS mozInlineSpellWordUtil {
// Convenience functions, object must be initialized
nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd, nsRange** aRange);
static already_AddRefed<nsRange> MakeRange(const NodeOffsetRange& aRange);
// Moves to the the next word in the range, and retrieves it's text and range.
// An empty word and a nullptr range are returned when we are done checking.

Просмотреть файл

@ -116,6 +116,34 @@ nsresult mozSpellChecker::NextMisspelledWord(nsAString &aWord,
return NS_OK;
}
RefPtr<CheckWordPromise> mozSpellChecker::CheckWords(
const nsTArray<nsString> &aWords) {
if (XRE_IsContentProcess()) {
return mEngine->SendCheckAsync(aWords)->Then(
GetMainThreadSerialEventTarget(), __func__,
[](nsTArray<bool> &&aIsMisspelled) {
return CheckWordPromise::CreateAndResolve(std::move(aIsMisspelled),
__func__);
},
[](mozilla::ipc::ResponseRejectReason &&aReason) {
return CheckWordPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
__func__);
});
}
nsTArray<bool> misspells;
misspells.SetCapacity(aWords.Length());
for (auto &word : aWords) {
bool misspelled;
nsresult rv = CheckWord(word, &misspelled, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return CheckWordPromise::CreateAndReject(rv, __func__);
}
misspells.AppendElement(misspelled);
}
return CheckWordPromise::CreateAndResolve(std::move(misspells), __func__);
}
nsresult mozSpellChecker::CheckWord(const nsAString &aWord, bool *aIsMisspelled,
nsTArray<nsString> *aSuggestions) {
nsresult result;

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef mozSpellChecker_h__
#define mozSpellChecker_h__
#include "mozilla/MozPromise.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsString.h"
@ -20,6 +21,7 @@ class mozEnglishWordUtils;
namespace mozilla {
class RemoteSpellcheckEngineChild;
class TextServicesDocument;
typedef MozPromise<nsTArray<bool>, nsresult, false> CheckWordPromise;
} // namespace mozilla
class mozSpellChecker final {
@ -63,6 +65,13 @@ class mozSpellChecker final {
nsresult CheckWord(const nsAString& aWord, bool* aIsMisspelled,
nsTArray<nsString>* aSuggestions);
/**
* This is a flavor of CheckWord, is async version of CheckWord.
* @Param aWords is array of words to check
*/
RefPtr<mozilla::CheckWordPromise> CheckWords(
const nsTArray<nsString>& aWords);
/**
* Replaces the old word with the specified new word.
* @param aOldWord is the word to be replaced.

Просмотреть файл

@ -111,7 +111,7 @@ class FeatureHolder final {
class TableData {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TableData);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FeatureHolder::TableData);
explicit TableData(const nsACString& aTable) : mTable(aTable) {}