зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1540037 - part 31: Move `TextEditor::GetAndIniitDocEncoder()` into `EditorBase` r=m_kato
It's a helper method of `TextEditor::ComputeValueInternal()` which is used by `TextEditor` and `HTMLEditor::Rewrap()`. So, before we move `ComputeValueInternal()`, we need to move this first. Depends on D116347 Differential Revision: https://phabricator.services.mozilla.com/D116348
This commit is contained in:
Родитель
d762ddd8ca
Коммит
11f319ab64
|
@ -94,6 +94,7 @@
|
|||
#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::dir
|
||||
#include "nsIClipboard.h" // for nsIClipboard
|
||||
#include "nsIContent.h" // for nsIContent
|
||||
#include "nsIDocumentEncoder.h" // for nsIDocumentEncoder
|
||||
#include "nsIDocumentStateListener.h" // for nsIDocumentStateListener
|
||||
#include "nsIEditActionListener.h" // for nsIEditActionListener
|
||||
#include "nsIEditorObserver.h" // for nsIEditorObserver
|
||||
|
@ -214,6 +215,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaceholderTransaction)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedDocumentEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
|
@ -239,6 +241,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlaceholderTransaction)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedDocumentEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase)
|
||||
|
@ -1408,6 +1411,77 @@ NS_IMETHODIMP EditorBase::SetDocumentCharacterSet(
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDocumentEncoder> EditorBase::GetAndInitDocEncoder(
|
||||
const nsAString& aFormatType, uint32_t aDocumentEncoderFlags,
|
||||
const nsACString& aCharset) const {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> docEncoder;
|
||||
if (!mCachedDocumentEncoder ||
|
||||
!mCachedDocumentEncoderType.Equals(aFormatType)) {
|
||||
nsAutoCString formatType;
|
||||
LossyAppendUTF16toASCII(aFormatType, formatType);
|
||||
docEncoder = do_createDocumentEncoder(PromiseFlatCString(formatType).get());
|
||||
if (NS_WARN_IF(!docEncoder)) {
|
||||
return nullptr;
|
||||
}
|
||||
mCachedDocumentEncoder = docEncoder;
|
||||
mCachedDocumentEncoderType = aFormatType;
|
||||
} else {
|
||||
docEncoder = mCachedDocumentEncoder;
|
||||
}
|
||||
|
||||
RefPtr<Document> doc = GetDocument();
|
||||
NS_ASSERTION(doc, "Need a document");
|
||||
|
||||
nsresult rv = docEncoder->NativeInit(
|
||||
doc, aFormatType,
|
||||
aDocumentEncoderFlags | nsIDocumentEncoder::RequiresReinitAfterOutput);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsIDocumentEncoder::NativeInit() failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aCharset.IsEmpty() && !aCharset.EqualsLiteral("null")) {
|
||||
DebugOnly<nsresult> rvIgnored = docEncoder->SetCharset(aCharset);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rvIgnored),
|
||||
"nsIDocumentEncoder::SetCharset() failed, but ignored");
|
||||
}
|
||||
|
||||
const int32_t wrapWidth = std::max(WrapWidth(), 0);
|
||||
DebugOnly<nsresult> rvIgnored = docEncoder->SetWrapColumn(wrapWidth);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rvIgnored),
|
||||
"nsIDocumentEncoder::SetWrapColumn() failed, but ignored");
|
||||
|
||||
// Set the selection, if appropriate.
|
||||
// We do this either if the OutputSelectionOnly flag is set,
|
||||
// in which case we use our existing selection ...
|
||||
if (aDocumentEncoderFlags & nsIDocumentEncoder::OutputSelectionOnly) {
|
||||
if (NS_FAILED(docEncoder->SetSelection(&SelectionRef()))) {
|
||||
NS_WARNING("nsIDocumentEncoder::SetSelection() failed");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
// ... or if the root element is not a body,
|
||||
// in which case we set the selection to encompass the root.
|
||||
else {
|
||||
Element* rootElement = GetRoot();
|
||||
if (NS_WARN_IF(!rootElement)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!rootElement->IsHTMLElement(nsGkAtoms::body)) {
|
||||
if (NS_FAILED(docEncoder->SetContainerNode(rootElement))) {
|
||||
NS_WARNING("nsIDocumentEncoder::SetContainerNode() failed");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return docEncoder.forget();
|
||||
}
|
||||
|
||||
bool EditorBase::AreClipboardCommandsUnconditionallyEnabled() const {
|
||||
Document* document = GetDocument();
|
||||
return document && document->AreClipboardCommandsUnconditionallyEnabled();
|
||||
|
|
|
@ -44,6 +44,7 @@ class mozInlineSpellChecker;
|
|||
class nsAtom;
|
||||
class nsCaret;
|
||||
class nsIContent;
|
||||
class nsIDocumentEncoder;
|
||||
class nsIDocumentStateListener;
|
||||
class nsIEditActionListener;
|
||||
class nsIEditorObserver;
|
||||
|
@ -2240,6 +2241,19 @@ class EditorBase : public nsIEditor,
|
|||
*/
|
||||
nsresult GetDocumentCharsetInternal(nsACString& aCharset) const;
|
||||
|
||||
/**
|
||||
* GetAndInitDocEncoder() returns a document encoder instance for aFormatType
|
||||
* after initializing it. The result may be cached for saving recreation
|
||||
* cost.
|
||||
*
|
||||
* @param aFormatType MIME type like "text/plain".
|
||||
* @param aDocumentEncoderFlags Flags of nsIDocumentEncoder.
|
||||
* @param aCharset Encoding of the document.
|
||||
*/
|
||||
already_AddRefed<nsIDocumentEncoder> GetAndInitDocEncoder(
|
||||
const nsAString& aFormatType, uint32_t aDocumentEncoderFlags,
|
||||
const nsACString& aCharset) const;
|
||||
|
||||
/**
|
||||
* SelectAllInternal() should be used instead of SelectAll() in editor
|
||||
* because SelectAll() creates AutoEditActionSetter but we should avoid
|
||||
|
@ -2726,6 +2740,12 @@ class EditorBase : public nsIEditor,
|
|||
|
||||
RefPtr<IMEContentObserver> mIMEContentObserver;
|
||||
|
||||
// These members cache last encoder and its type for the performance in
|
||||
// TextEditor::ComputeTextValue() which is the implementation of
|
||||
// `<input>.value` and `<textarea>.value`. See `GetAndInitDocEncoder()`.
|
||||
mutable nsCOMPtr<nsIDocumentEncoder> mCachedDocumentEncoder;
|
||||
mutable nsString mCachedDocumentEncoderType;
|
||||
|
||||
// Listens to all low level actions on the doc.
|
||||
// Edit action listener is currently used by highlighter of the findbar and
|
||||
// the spellchecker. So, we should reserve only 2 items.
|
||||
|
|
|
@ -95,12 +95,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TextEditor, EditorBase)
|
|||
if (tmp->mMaskTimer) {
|
||||
tmp->mMaskTimer->Cancel();
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedDocumentEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMaskTimer)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TextEditor, EditorBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedDocumentEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMaskTimer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -480,77 +478,6 @@ bool TextEditor::IsCopyToClipboardAllowedInternal() const {
|
|||
return mUnmaskedStart <= selectionStart && UnmaskedEnd() >= selectionEnd;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDocumentEncoder> TextEditor::GetAndInitDocEncoder(
|
||||
const nsAString& aFormatType, uint32_t aDocumentEncoderFlags,
|
||||
const nsACString& aCharset) const {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> docEncoder;
|
||||
if (!mCachedDocumentEncoder ||
|
||||
!mCachedDocumentEncoderType.Equals(aFormatType)) {
|
||||
nsAutoCString formatType;
|
||||
LossyAppendUTF16toASCII(aFormatType, formatType);
|
||||
docEncoder = do_createDocumentEncoder(PromiseFlatCString(formatType).get());
|
||||
if (NS_WARN_IF(!docEncoder)) {
|
||||
return nullptr;
|
||||
}
|
||||
mCachedDocumentEncoder = docEncoder;
|
||||
mCachedDocumentEncoderType = aFormatType;
|
||||
} else {
|
||||
docEncoder = mCachedDocumentEncoder;
|
||||
}
|
||||
|
||||
RefPtr<Document> doc = GetDocument();
|
||||
NS_ASSERTION(doc, "Need a document");
|
||||
|
||||
nsresult rv = docEncoder->NativeInit(
|
||||
doc, aFormatType,
|
||||
aDocumentEncoderFlags | nsIDocumentEncoder::RequiresReinitAfterOutput);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsIDocumentEncoder::NativeInit() failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aCharset.IsEmpty() && !aCharset.EqualsLiteral("null")) {
|
||||
DebugOnly<nsresult> rvIgnored = docEncoder->SetCharset(aCharset);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rvIgnored),
|
||||
"nsIDocumentEncoder::SetCharset() failed, but ignored");
|
||||
}
|
||||
|
||||
const int32_t wrapWidth = std::max(WrapWidth(), 0);
|
||||
DebugOnly<nsresult> rvIgnored = docEncoder->SetWrapColumn(wrapWidth);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rvIgnored),
|
||||
"nsIDocumentEncoder::SetWrapColumn() failed, but ignored");
|
||||
|
||||
// Set the selection, if appropriate.
|
||||
// We do this either if the OutputSelectionOnly flag is set,
|
||||
// in which case we use our existing selection ...
|
||||
if (aDocumentEncoderFlags & nsIDocumentEncoder::OutputSelectionOnly) {
|
||||
if (NS_FAILED(docEncoder->SetSelection(&SelectionRef()))) {
|
||||
NS_WARNING("nsIDocumentEncoder::SetSelection() failed");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
// ... or if the root element is not a body,
|
||||
// in which case we set the selection to encompass the root.
|
||||
else {
|
||||
dom::Element* rootElement = GetRoot();
|
||||
if (NS_WARN_IF(!rootElement)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!rootElement->IsHTMLElement(nsGkAtoms::body)) {
|
||||
if (NS_FAILED(docEncoder->SetContainerNode(rootElement))) {
|
||||
NS_WARNING("nsIDocumentEncoder::SetContainerNode() failed");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return docEncoder.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP TextEditor::OutputToString(const nsAString& aFormatType,
|
||||
uint32_t aDocumentEncoderFlags,
|
||||
nsAString& aOutputString) {
|
||||
|
@ -602,7 +529,7 @@ nsresult TextEditor::ComputeValueInternal(const nsAString& aFormatType,
|
|||
nsCOMPtr<nsIDocumentEncoder> encoder =
|
||||
GetAndInitDocEncoder(aFormatType, aDocumentEncoderFlags, charset);
|
||||
if (!encoder) {
|
||||
NS_WARNING("TextEditor::GetAndInitDocEncoder() failed");
|
||||
NS_WARNING("EditorBase::GetAndInitDocEncoder() failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -522,19 +522,6 @@ class TextEditor : public EditorBase, public nsITimerCallback, public nsINamed {
|
|||
*/
|
||||
bool IsSafeToInsertData(const Document* aSourceDoc) const;
|
||||
|
||||
/**
|
||||
* GetAndInitDocEncoder() returns a document encoder instance for aFormatType
|
||||
* after initializing it. The result may be cached for saving recreation
|
||||
* cost.
|
||||
*
|
||||
* @param aFormatType MIME type like "text/plain".
|
||||
* @param aDocumentEncoderFlags Flags of nsIDocumentEncoder.
|
||||
* @param aCharset Encoding of the document.
|
||||
*/
|
||||
already_AddRefed<nsIDocumentEncoder> GetAndInitDocEncoder(
|
||||
const nsAString& aFormatType, uint32_t aDocumentEncoderFlags,
|
||||
const nsACString& aCharset) const;
|
||||
|
||||
/**
|
||||
* ComputeValueInternal() computes string value of this editor for given
|
||||
* format. This may be too expensive if it's in hot path.
|
||||
|
@ -573,14 +560,10 @@ class TextEditor : public EditorBase, public nsITimerCallback, public nsINamed {
|
|||
bool aForceStartMasking);
|
||||
|
||||
protected:
|
||||
mutable nsCOMPtr<nsIDocumentEncoder> mCachedDocumentEncoder;
|
||||
|
||||
// Timer to mask unmasked characters automatically. Used only when it's
|
||||
// a password field.
|
||||
nsCOMPtr<nsITimer> mMaskTimer;
|
||||
|
||||
mutable nsString mCachedDocumentEncoderType;
|
||||
|
||||
int32_t mMaxTextLength;
|
||||
|
||||
// Unmasked character range. Used only when it's a password field.
|
||||
|
|
Загрузка…
Ссылка в новой задаче