Bug 1352882 - Part 3. Cache nsIDocumentEncoder into TextEditor. r?masayuki
All editor code gets nsIDocumentEncoder from TextEditor::GetAndInitDocEncoder(), so we can have a cache into TextEditor, then return cached object.
MozReview-Commit-ID: IEoOvz7BG7T
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -101,20 +101,22 @@ TextEditor::~TextEditor()
}
NS_IMPL_CYCLE_COLLECTION_CLASS(TextEditor)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TextEditor, EditorBase)
if (tmp->mRules)
tmp->mRules->DetachEditor();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRules)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedDocumentEncoder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TextEditor, EditorBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRules)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedDocumentEncoder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(TextEditor, EditorBase)
NS_IMPL_RELEASE_INHERITED(TextEditor, EditorBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextEditor)
NS_INTERFACE_MAP_ENTRY(nsIPlaintextEditor)
NS_INTERFACE_MAP_ENTRY(nsIEditorMailSupport)
@@ -1164,67 +1166,85 @@ NS_IMETHODIMP
TextEditor::CanDelete(bool* aCanDelete)
{
NS_ENSURE_ARG_POINTER(aCanDelete);
*aCanDelete = IsModifiable() && CanCutOrCopy(ePasswordFieldAllowed);
return NS_OK;
}
// Shared between OutputToString and OutputToStream
-nsresult
+already_AddRefed<nsIDocumentEncoder>
TextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
uint32_t aFlags,
- const nsACString& aCharset,
- nsIDocumentEncoder** encoder)
+ const nsACString& aCharset)
{
- nsresult rv = NS_OK;
-
- nsAutoCString formatType(NS_DOC_ENCODER_CONTRACTID_BASE);
- LossyAppendUTF16toASCII(aFormatType, formatType);
- nsCOMPtr<nsIDocumentEncoder> docEncoder (do_CreateInstance(formatType.get(), &rv));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIDocumentEncoder> docEncoder;
+ if (!mCachedDocumentEncoder ||
+ !mCachedDocumentEncoderType.Equals(aFormatType)) {
+ nsAutoCString formatType(NS_DOC_ENCODER_CONTRACTID_BASE);
+ LossyAppendUTF16toASCII(aFormatType, formatType);
+ docEncoder = do_CreateInstance(formatType.get());
+ if (NS_WARN_IF(!docEncoder)) {
+ return nullptr;
+ }
+ mCachedDocumentEncoder = docEncoder;
+ mCachedDocumentEncoderType = aFormatType;
+ } else {
+ docEncoder = mCachedDocumentEncoder;
+ }
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryReferent(mDocWeak);
NS_ASSERTION(domDoc, "Need a document");
- rv = docEncoder->Init(domDoc, aFormatType, aFlags);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ docEncoder->Init(domDoc, aFormatType,
+ aFlags | nsIDocumentEncoder::ReleaseDocumentAfterOutput);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
if (!aCharset.IsEmpty() && !aCharset.EqualsLiteral("null")) {
docEncoder->SetCharset(aCharset);
}
int32_t wc;
(void) GetWrapWidth(&wc);
if (wc >= 0) {
(void) docEncoder->SetWrapColumn(wc);
}
// Set the selection, if appropriate.
// We do this either if the OutputSelectionOnly flag is set,
// in which case we use our existing selection ...
if (aFlags & nsIDocumentEncoder::OutputSelectionOnly) {
RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
+ if (NS_WARN_IF(!selection)) {
+ return nullptr;
+ }
rv = docEncoder->SetSelection(selection);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ 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();
- NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
+ if (NS_WARN_IF(!rootElement)) {
+ return nullptr;
+ }
if (!rootElement->IsHTMLElement(nsGkAtoms::body)) {
rv = docEncoder->SetNativeContainerNode(rootElement);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
}
}
- docEncoder.forget(encoder);
- return NS_OK;
+ return docEncoder.forget();
}
NS_IMETHODIMP
TextEditor::OutputToString(const nsAString& aFormatType,
uint32_t aFlags,
nsAString& aOutputString)
{
@@ -1249,19 +1269,22 @@ TextEditor::OutputToString(const nsAStri
}
nsAutoCString charsetStr;
rv = GetDocumentCharacterSet(charsetStr);
if (NS_FAILED(rv) || charsetStr.IsEmpty()) {
charsetStr.AssignLiteral("ISO-8859-1");
}
- nsCOMPtr<nsIDocumentEncoder> encoder;
- rv = GetAndInitDocEncoder(aFormatType, aFlags, charsetStr, getter_AddRefs(encoder));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIDocumentEncoder> encoder =
+ GetAndInitDocEncoder(aFormatType, aFlags, charsetStr);
+ if (NS_WARN_IF(!encoder)) {
+ return NS_ERROR_FAILURE;
+ }
+
return encoder->EncodeToString(aOutputString);
}
NS_IMETHODIMP
TextEditor::OutputToStream(nsIOutputStream* aOutputStream,
const nsAString& aFormatType,
const nsACString& aCharset,
uint32_t aFlags)
@@ -1276,21 +1299,21 @@ TextEditor::OutputToStream(nsIOutputStre
rv = GetDocumentIsEmpty(&docEmpty);
NS_ENSURE_SUCCESS(rv, rv);
if (docEmpty) {
return NS_OK; // Output nothing.
}
}
- nsCOMPtr<nsIDocumentEncoder> encoder;
- rv = GetAndInitDocEncoder(aFormatType, aFlags, aCharset,
- getter_AddRefs(encoder));
-
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIDocumentEncoder> encoder =
+ GetAndInitDocEncoder(aFormatType, aFlags, aCharset);
+ if (NS_WARN_IF(!encoder)) {
+ return NS_ERROR_FAILURE;
+ }
return encoder->EncodeToStream(aOutputStream);
}
NS_IMETHODIMP
TextEditor::InsertTextWithQuotations(const nsAString& aStringToInsert)
{
return InsertText(aStringToInsert);
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -179,20 +179,20 @@ public:
protected:
virtual ~TextEditor();
NS_IMETHOD InitRules();
void BeginEditorInit();
nsresult EndEditorInit();
- nsresult GetAndInitDocEncoder(const nsAString& aFormatType,
- uint32_t aFlags,
- const nsACString& aCharset,
- nsIDocumentEncoder** encoder);
+ already_AddRefed<nsIDocumentEncoder> GetAndInitDocEncoder(
+ const nsAString& aFormatType,
+ uint32_t aFlags,
+ const nsACString& aCharset);
NS_IMETHOD CreateBR(nsIDOMNode* aNode, int32_t aOffset,
nsCOMPtr<nsIDOMNode>* outBRNode,
EDirection aSelect = eNone);
already_AddRefed<Element> CreateBRImpl(nsCOMPtr<nsINode>* aInOutParent,
int32_t* aInOutOffset,
EDirection aSelect);
nsresult CreateBRImpl(nsCOMPtr<nsIDOMNode>* aInOutParent,
@@ -227,16 +227,18 @@ protected:
int32_t aSelectionType,
bool* aActionTaken = nullptr);
bool UpdateMetaCharset(nsIDocument& aDocument,
const nsACString& aCharacterSet);
protected:
nsCOMPtr<nsIEditRules> mRules;
+ nsCOMPtr<nsIDocumentEncoder> mCachedDocumentEncoder;
+ nsString mCachedDocumentEncoderType;
int32_t mWrapColumn;
int32_t mMaxTextLength;
int32_t mInitTriggerCounter;
int32_t mNewlineHandling;
int32_t mCaretStyle;
friend class AutoEditInitRulesTrigger;
friend class HTMLEditRules;