Bug 1352882 - Part 3. Cache nsIDocumentEncoder into TextEditor. r?masayuki draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Wed, 12 Apr 2017 15:34:33 +0900
changeset 561821 7d0e7c2c49c69bb5ef0630081f7b3d45a5119c77
parent 561820 02356927a18ffee80859ad67e1603ffd5fd93c8b
child 624100 198c8a609bcae638cf4cdfb4f0943a504643e0bf
push id53876
push userm_kato@ga2.so-net.ne.jp
push dateThu, 13 Apr 2017 07:39:56 +0000
reviewersmasayuki
bugs1352882
milestone55.0a1
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
editor/libeditor/TextEditor.cpp
editor/libeditor/TextEditor.h
--- 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;