LCOV - code coverage report
Current view: top level - dom/webbrowserpersist - WebBrowserPersistLocalDocument.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 765 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 58 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "WebBrowserPersistLocalDocument.h"
       7             : #include "WebBrowserPersistDocumentParent.h"
       8             : 
       9             : #include "mozilla/dom/HTMLInputElement.h"
      10             : #include "mozilla/dom/HTMLSharedElement.h"
      11             : #include "mozilla/dom/HTMLSharedObjectElement.h"
      12             : #include "mozilla/dom/TabParent.h"
      13             : #include "nsComponentManagerUtils.h"
      14             : #include "nsContentUtils.h"
      15             : #include "nsContentCID.h"
      16             : #include "nsCycleCollectionParticipant.h"
      17             : #include "nsFrameLoader.h"
      18             : #include "nsIComponentRegistrar.h"
      19             : #include "nsIContent.h"
      20             : #include "nsIDOMAttr.h"
      21             : #include "nsIDOMComment.h"
      22             : #include "nsIDOMDocument.h"
      23             : #include "nsIDOMHTMLAnchorElement.h"
      24             : #include "nsIDOMHTMLAppletElement.h"
      25             : #include "nsIDOMHTMLAreaElement.h"
      26             : #include "nsIDOMHTMLBaseElement.h"
      27             : #include "nsIDOMHTMLCollection.h"
      28             : #include "nsIDOMHTMLDocument.h"
      29             : #include "nsIDOMHTMLEmbedElement.h"
      30             : #include "nsIDOMHTMLFrameElement.h"
      31             : #include "nsIDOMHTMLIFrameElement.h"
      32             : #include "nsIDOMHTMLImageElement.h"
      33             : #include "nsIDOMHTMLInputElement.h"
      34             : #include "nsIDOMHTMLLinkElement.h"
      35             : #include "nsIDOMHTMLMediaElement.h"
      36             : #include "nsIDOMHTMLObjectElement.h"
      37             : #include "nsIDOMHTMLOptionElement.h"
      38             : #include "nsIDOMHTMLScriptElement.h"
      39             : #include "nsIDOMHTMLSourceElement.h"
      40             : #include "nsIDOMHTMLTextAreaElement.h"
      41             : #include "nsIDOMMozNamedAttrMap.h"
      42             : #include "nsIDOMNode.h"
      43             : #include "nsIDOMNodeFilter.h"
      44             : #include "nsIDOMNodeList.h"
      45             : #include "nsIDOMProcessingInstruction.h"
      46             : #include "nsIDOMTreeWalker.h"
      47             : #include "nsIDOMWindowUtils.h"
      48             : #include "nsIDocShell.h"
      49             : #include "nsIDocument.h"
      50             : #include "nsIDocumentEncoder.h"
      51             : #include "nsILoadContext.h"
      52             : #include "nsIProtocolHandler.h"
      53             : #include "nsISHEntry.h"
      54             : #include "nsISupportsPrimitives.h"
      55             : #include "nsITabParent.h"
      56             : #include "nsIWebBrowserPersist.h"
      57             : #include "nsIWebNavigation.h"
      58             : #include "nsIWebPageDescriptor.h"
      59             : #include "nsNetUtil.h"
      60             : 
      61             : namespace mozilla {
      62             : 
      63           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(WebBrowserPersistLocalDocument)
      64           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(WebBrowserPersistLocalDocument)
      65             : 
      66           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebBrowserPersistLocalDocument)
      67           0 :   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersistDocument)
      68           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      69           0 : NS_INTERFACE_MAP_END
      70             : 
      71           0 : NS_IMPL_CYCLE_COLLECTION(WebBrowserPersistLocalDocument, mDocument)
      72             : 
      73             : 
      74           0 : WebBrowserPersistLocalDocument::WebBrowserPersistLocalDocument(nsIDocument* aDocument)
      75             : : mDocument(aDocument)
      76           0 : , mPersistFlags(0)
      77             : {
      78           0 :     MOZ_ASSERT(mDocument);
      79           0 : }
      80             : 
      81             : WebBrowserPersistLocalDocument::~WebBrowserPersistLocalDocument() = default;
      82             : 
      83             : NS_IMETHODIMP
      84           0 : WebBrowserPersistLocalDocument::SetPersistFlags(uint32_t aFlags)
      85             : {
      86           0 :     mPersistFlags = aFlags;
      87           0 :     return NS_OK;
      88             : }
      89             : 
      90             : NS_IMETHODIMP
      91           0 : WebBrowserPersistLocalDocument::GetPersistFlags(uint32_t* aFlags)
      92             : {
      93           0 :     *aFlags = mPersistFlags;
      94           0 :     return NS_OK;
      95             : }
      96             : 
      97             : NS_IMETHODIMP
      98           0 : WebBrowserPersistLocalDocument::GetIsPrivate(bool* aIsPrivate)
      99             : {
     100           0 :     nsCOMPtr<nsILoadContext> privacyContext = mDocument->GetLoadContext();
     101           0 :     *aIsPrivate = privacyContext && privacyContext->UsePrivateBrowsing();
     102           0 :     return NS_OK;
     103             : }
     104             : 
     105             : NS_IMETHODIMP
     106           0 : WebBrowserPersistLocalDocument::GetDocumentURI(nsACString& aURISpec)
     107             : {
     108           0 :     nsCOMPtr<nsIURI> uri = mDocument->GetDocumentURI();
     109           0 :     if (!uri) {
     110           0 :         return NS_ERROR_UNEXPECTED;
     111             :     }
     112           0 :     return uri->GetSpec(aURISpec);
     113             : }
     114             : 
     115             : NS_IMETHODIMP
     116           0 : WebBrowserPersistLocalDocument::GetBaseURI(nsACString& aURISpec)
     117             : {
     118           0 :     nsCOMPtr<nsIURI> uri = GetBaseURI();
     119           0 :     if (!uri) {
     120           0 :         return NS_ERROR_UNEXPECTED;
     121             :     }
     122           0 :     return uri->GetSpec(aURISpec);
     123             : }
     124             : 
     125             : NS_IMETHODIMP
     126           0 : WebBrowserPersistLocalDocument::GetContentType(nsACString& aContentType)
     127             : {
     128           0 :     nsAutoString utf16Type;
     129             :     nsresult rv;
     130             : 
     131           0 :     rv = mDocument->GetContentType(utf16Type);
     132           0 :     NS_ENSURE_SUCCESS(rv, rv);
     133           0 :     aContentType = NS_ConvertUTF16toUTF8(utf16Type);
     134           0 :     return NS_OK;
     135             : }
     136             : 
     137             : NS_IMETHODIMP
     138           0 : WebBrowserPersistLocalDocument::GetCharacterSet(nsACString& aCharSet)
     139             : {
     140           0 :     GetCharacterSet()->Name(aCharSet);
     141           0 :     return NS_OK;
     142             : }
     143             : 
     144             : NS_IMETHODIMP
     145           0 : WebBrowserPersistLocalDocument::GetTitle(nsAString& aTitle)
     146             : {
     147           0 :     nsAutoString titleBuffer;
     148           0 :     mDocument->GetTitle(titleBuffer);
     149           0 :     aTitle = titleBuffer;
     150           0 :     return NS_OK;
     151             : }
     152             : 
     153             : NS_IMETHODIMP
     154           0 : WebBrowserPersistLocalDocument::GetReferrer(nsAString& aReferrer)
     155             : {
     156           0 :     mDocument->GetReferrer(aReferrer);
     157           0 :     return NS_OK;
     158             : }
     159             : 
     160             : NS_IMETHODIMP
     161           0 : WebBrowserPersistLocalDocument::GetContentDisposition(nsAString& aCD)
     162             : {
     163           0 :     nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetDefaultView();
     164           0 :     if (NS_WARN_IF(!window)) {
     165           0 :         aCD.SetIsVoid(true);
     166           0 :         return NS_OK;
     167             :     }
     168           0 :     nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
     169           0 :     if (NS_WARN_IF(!utils)) {
     170           0 :         aCD.SetIsVoid(true);
     171           0 :         return NS_OK;
     172             :     }
     173           0 :     nsresult rv = utils->GetDocumentMetadata(
     174           0 :         NS_LITERAL_STRING("content-disposition"), aCD);
     175           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     176           0 :         aCD.SetIsVoid(true);
     177             :     }
     178           0 :     return NS_OK;
     179             : }
     180             : 
     181             : NS_IMETHODIMP
     182           0 : WebBrowserPersistLocalDocument::GetCacheKey(uint32_t* aKey)
     183             : {
     184           0 :     nsCOMPtr<nsISHEntry> history = GetHistory();
     185           0 :     if (!history) {
     186           0 :         *aKey = 0;
     187           0 :         return NS_OK;
     188             :     }
     189           0 :     nsCOMPtr<nsISupports> abstractKey;
     190           0 :     nsresult rv = history->GetCacheKey(getter_AddRefs(abstractKey));
     191           0 :     if (NS_WARN_IF(NS_FAILED(rv)) || !abstractKey) {
     192           0 :         *aKey = 0;
     193           0 :         return NS_OK;
     194             :     }
     195           0 :     nsCOMPtr<nsISupportsPRUint32> u32 = do_QueryInterface(abstractKey);
     196           0 :     if (NS_WARN_IF(!u32)) {
     197           0 :         *aKey = 0;
     198           0 :         return NS_OK;
     199             :     }
     200           0 :     return u32->GetData(aKey);
     201             : }
     202             : 
     203             : NS_IMETHODIMP
     204           0 : WebBrowserPersistLocalDocument::GetPostData(nsIInputStream** aStream)
     205             : {
     206           0 :     nsCOMPtr<nsISHEntry> history = GetHistory();
     207           0 :     if (!history) {
     208           0 :         *aStream = nullptr;
     209           0 :         return NS_OK;
     210             :     }
     211           0 :     return history->GetPostData(aStream);
     212             : }
     213             : 
     214             : already_AddRefed<nsISHEntry>
     215           0 : WebBrowserPersistLocalDocument::GetHistory()
     216             : {
     217           0 :     nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetDefaultView();
     218           0 :     if (NS_WARN_IF(!window)) {
     219           0 :         return nullptr;
     220             :     }
     221           0 :     nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(window);
     222           0 :     if (NS_WARN_IF(!webNav)) {
     223           0 :         return nullptr;
     224             :     }
     225           0 :     nsCOMPtr<nsIWebPageDescriptor> desc = do_QueryInterface(webNav);
     226           0 :     if (NS_WARN_IF(!desc)) {
     227           0 :         return nullptr;
     228             :     }
     229           0 :     nsCOMPtr<nsISupports> curDesc;
     230           0 :     nsresult rv = desc->GetCurrentDescriptor(getter_AddRefs(curDesc));
     231             :     // This can fail if, e.g., the document is a Print Preview.
     232           0 :     if (NS_FAILED(rv) || NS_WARN_IF(!curDesc)) {
     233           0 :         return nullptr;
     234             :     }
     235           0 :     nsCOMPtr<nsISHEntry> history = do_QueryInterface(curDesc);
     236           0 :     return history.forget();
     237             : }
     238             : 
     239             : NotNull<const Encoding*>
     240           0 : WebBrowserPersistLocalDocument::GetCharacterSet() const
     241             : {
     242           0 :     return mDocument->GetDocumentCharacterSet();
     243             : }
     244             : 
     245             : uint32_t
     246           0 : WebBrowserPersistLocalDocument::GetPersistFlags() const
     247             : {
     248           0 :     return mPersistFlags;
     249             : }
     250             : 
     251             : 
     252             : already_AddRefed<nsIURI>
     253           0 : WebBrowserPersistLocalDocument::GetBaseURI() const
     254             : {
     255           0 :     return mDocument->GetBaseURI();
     256             : }
     257             : 
     258             : namespace {
     259             : 
     260             : // Helper class for ReadResources().
     261             : class ResourceReader final : public nsIWebBrowserPersistDocumentReceiver {
     262             : public:
     263             :     ResourceReader(WebBrowserPersistLocalDocument* aParent,
     264             :                    nsIWebBrowserPersistResourceVisitor* aVisitor);
     265             :     nsresult OnWalkDOMNode(nsIDOMNode* aNode);
     266             : 
     267             :     // This is called both to indicate the end of the document walk
     268             :     // and when a subdocument is (maybe asynchronously) sent to the
     269             :     // visitor.  The call to EndVisit needs to happen after both of
     270             :     // those have finished.
     271             :     void DocumentDone(nsresult aStatus);
     272             : 
     273             :     NS_DECL_NSIWEBBROWSERPERSISTDOCUMENTRECEIVER
     274             :     NS_DECL_ISUPPORTS
     275             : 
     276             : private:
     277             :     RefPtr<WebBrowserPersistLocalDocument> mParent;
     278             :     nsCOMPtr<nsIWebBrowserPersistResourceVisitor> mVisitor;
     279             :     nsCOMPtr<nsIURI> mCurrentBaseURI;
     280             :     uint32_t mPersistFlags;
     281             : 
     282             :     // The number of DocumentDone calls after which EndVisit will be
     283             :     // called on the visitor.  Counts the main document if it's still
     284             :     // being walked and any outstanding asynchronous subdocument
     285             :     // StartPersistence calls.
     286             :     size_t mOutstandingDocuments;
     287             :     // Collects the status parameters to DocumentDone calls.
     288             :     nsresult mEndStatus;
     289             : 
     290             :     nsresult OnWalkURI(const nsACString& aURISpec);
     291             :     nsresult OnWalkURI(nsIURI* aURI);
     292             :     nsresult OnWalkAttribute(nsIDOMNode* aNode,
     293             :                              const char* aAttribute,
     294             :                              const char* aNamespaceURI = "");
     295             :     nsresult OnWalkSubframe(nsIDOMNode* aNode);
     296             : 
     297             :     ~ResourceReader();
     298             : 
     299             :     using IWBP = nsIWebBrowserPersist;
     300             : };
     301             : 
     302           0 : NS_IMPL_ISUPPORTS(ResourceReader, nsIWebBrowserPersistDocumentReceiver)
     303             : 
     304           0 : ResourceReader::ResourceReader(WebBrowserPersistLocalDocument* aParent,
     305           0 :                                nsIWebBrowserPersistResourceVisitor* aVisitor)
     306             : : mParent(aParent)
     307             : , mVisitor(aVisitor)
     308           0 : , mCurrentBaseURI(aParent->GetBaseURI())
     309           0 : , mPersistFlags(aParent->GetPersistFlags())
     310             : , mOutstandingDocuments(1)
     311           0 : , mEndStatus(NS_OK)
     312             : {
     313           0 :     MOZ_ASSERT(mCurrentBaseURI);
     314           0 : }
     315             : 
     316           0 : ResourceReader::~ResourceReader()
     317             : {
     318           0 :     MOZ_ASSERT(mOutstandingDocuments == 0);
     319           0 : }
     320             : 
     321             : void
     322           0 : ResourceReader::DocumentDone(nsresult aStatus)
     323             : {
     324           0 :     MOZ_ASSERT(mOutstandingDocuments > 0);
     325           0 :     if (NS_SUCCEEDED(mEndStatus)) {
     326           0 :         mEndStatus = aStatus;
     327             :     }
     328           0 :     if (--mOutstandingDocuments == 0) {
     329           0 :         mVisitor->EndVisit(mParent, mEndStatus);
     330             :     }
     331           0 : }
     332             : 
     333             : nsresult
     334           0 : ResourceReader::OnWalkSubframe(nsIDOMNode* aNode)
     335             : {
     336           0 :     nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aNode);
     337           0 :     NS_ENSURE_STATE(loaderOwner);
     338           0 :     RefPtr<nsFrameLoader> loader = loaderOwner->GetFrameLoader();
     339           0 :     NS_ENSURE_STATE(loader);
     340             : 
     341           0 :     ++mOutstandingDocuments;
     342             :     // Pass in 0 as the outer window ID so that we start
     343             :     // persisting the root of this subframe, and not some other
     344             :     // subframe child of this subframe.
     345           0 :     nsresult rv = loader->StartPersistence(0, this);
     346           0 :     if (NS_FAILED(rv)) {
     347           0 :         if (rv == NS_ERROR_NO_CONTENT) {
     348             :             // Just ignore frames with no content document.
     349           0 :             rv = NS_OK;
     350             :         }
     351             :         // StartPersistence won't eventually call this if it failed,
     352             :         // so this does so (to keep mOutstandingDocuments correct).
     353           0 :         DocumentDone(rv);
     354             :     }
     355           0 :     return rv;
     356             : }
     357             : 
     358             : NS_IMETHODIMP
     359           0 : ResourceReader::OnDocumentReady(nsIWebBrowserPersistDocument* aDocument)
     360             : {
     361           0 :     mVisitor->VisitDocument(mParent, aDocument);
     362           0 :     DocumentDone(NS_OK);
     363           0 :     return NS_OK;
     364             : }
     365             : 
     366             : NS_IMETHODIMP
     367           0 : ResourceReader::OnError(nsresult aFailure)
     368             : {
     369           0 :     DocumentDone(aFailure);
     370           0 :     return NS_OK;
     371             : }
     372             : 
     373             : nsresult
     374           0 : ResourceReader::OnWalkURI(nsIURI* aURI)
     375             : {
     376             :     // Test if this URI should be persisted. By default
     377             :     // we should assume the URI  is persistable.
     378             :     bool doNotPersistURI;
     379             :     nsresult rv = NS_URIChainHasFlags(aURI,
     380             :                                       nsIProtocolHandler::URI_NON_PERSISTABLE,
     381           0 :                                       &doNotPersistURI);
     382           0 :     if (NS_SUCCEEDED(rv) && doNotPersistURI) {
     383           0 :         return NS_OK;
     384             :     }
     385             : 
     386           0 :     nsAutoCString stringURI;
     387           0 :     rv = aURI->GetSpec(stringURI);
     388           0 :     NS_ENSURE_SUCCESS(rv, rv);
     389           0 :     return mVisitor->VisitResource(mParent, stringURI);
     390             : }
     391             : 
     392             : nsresult
     393           0 : ResourceReader::OnWalkURI(const nsACString& aURISpec)
     394             : {
     395             :     nsresult rv;
     396           0 :     nsCOMPtr<nsIURI> uri;
     397             : 
     398           0 :     rv = NS_NewURI(getter_AddRefs(uri),
     399             :                    aURISpec,
     400             :                    mParent->GetCharacterSet(),
     401           0 :                    mCurrentBaseURI);
     402           0 :     NS_ENSURE_SUCCESS(rv, rv);
     403           0 :     return OnWalkURI(uri);
     404             : }
     405             : 
     406             : static nsresult
     407           0 : ExtractAttribute(nsIDOMNode* aNode,
     408             :                  const char* aAttribute,
     409             :                  const char* aNamespaceURI,
     410             :                  nsCString&  aValue)
     411             : {
     412           0 :     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
     413           0 :     MOZ_ASSERT(element);
     414             : 
     415             :     // Find the named URI attribute on the (element) node and store
     416             :     // a reference to the URI that maps onto a local file name
     417             : 
     418           0 :     nsCOMPtr<nsIDOMMozNamedAttrMap> attrMap;
     419           0 :     nsresult rv = element->GetAttributes(getter_AddRefs(attrMap));
     420           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
     421             : 
     422           0 :     NS_ConvertASCIItoUTF16 namespaceURI(aNamespaceURI);
     423           0 :     NS_ConvertASCIItoUTF16 attribute(aAttribute);
     424           0 :     nsCOMPtr<nsIDOMAttr> attr;
     425           0 :     rv = attrMap->GetNamedItemNS(namespaceURI, attribute, getter_AddRefs(attr));
     426           0 :     NS_ENSURE_SUCCESS(rv, rv);
     427           0 :     if (attr) {
     428           0 :         nsAutoString value;
     429           0 :         rv = attr->GetValue(value);
     430           0 :         NS_ENSURE_SUCCESS(rv, rv);
     431           0 :         aValue = NS_ConvertUTF16toUTF8(value);
     432             :     } else {
     433           0 :         aValue.Truncate();
     434             :     }
     435           0 :     return NS_OK;
     436             : }
     437             : 
     438             : nsresult
     439           0 : ResourceReader::OnWalkAttribute(nsIDOMNode* aNode,
     440             :                                 const char* aAttribute,
     441             :                                 const char* aNamespaceURI)
     442             : {
     443           0 :     nsAutoCString uriSpec;
     444           0 :     nsresult rv = ExtractAttribute(aNode, aAttribute, aNamespaceURI, uriSpec);
     445           0 :     NS_ENSURE_SUCCESS(rv, rv);
     446           0 :     if (uriSpec.IsEmpty()) {
     447           0 :         return NS_OK;
     448             :     }
     449           0 :     return OnWalkURI(uriSpec);
     450             : }
     451             : 
     452             : static nsresult
     453           0 : GetXMLStyleSheetLink(nsIDOMProcessingInstruction *aPI, nsAString &aHref)
     454             : {
     455             :     nsresult rv;
     456           0 :     nsAutoString data;
     457           0 :     rv = aPI->GetData(data);
     458           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
     459             : 
     460           0 :     nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::href, aHref);
     461           0 :     return NS_OK;
     462             : }
     463             : 
     464             : nsresult
     465           0 : ResourceReader::OnWalkDOMNode(nsIDOMNode* aNode)
     466             : {
     467             :     nsresult rv;
     468             : 
     469             :     // Fixup xml-stylesheet processing instructions
     470           0 :     nsCOMPtr<nsIDOMProcessingInstruction> nodeAsPI = do_QueryInterface(aNode);
     471           0 :     if (nodeAsPI) {
     472           0 :         nsAutoString target;
     473           0 :         rv = nodeAsPI->GetTarget(target);
     474           0 :         NS_ENSURE_SUCCESS(rv, rv);
     475           0 :         if (target.EqualsLiteral("xml-stylesheet")) {
     476           0 :             nsAutoString href;
     477           0 :             GetXMLStyleSheetLink(nodeAsPI, href);
     478           0 :             if (!href.IsEmpty()) {
     479           0 :                 return OnWalkURI(NS_ConvertUTF16toUTF8(href));
     480             :             }
     481             :         }
     482           0 :         return NS_OK;
     483             :     }
     484             : 
     485           0 :     nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
     486           0 :     if (!content) {
     487           0 :         return NS_OK;
     488             :     }
     489             : 
     490             :     // Test the node to see if it's an image, frame, iframe, css, js
     491           0 :     nsCOMPtr<nsIDOMHTMLImageElement> nodeAsImage = do_QueryInterface(aNode);
     492           0 :     if (nodeAsImage) {
     493           0 :         return OnWalkAttribute(aNode, "src");
     494             :     }
     495             : 
     496           0 :     if (content->IsSVGElement(nsGkAtoms::img)) {
     497           0 :         return OnWalkAttribute(aNode, "href", "http://www.w3.org/1999/xlink");
     498             :     }
     499             : 
     500           0 :     nsCOMPtr<nsIDOMHTMLMediaElement> nodeAsMedia = do_QueryInterface(aNode);
     501           0 :     if (nodeAsMedia) {
     502           0 :         return OnWalkAttribute(aNode, "src");
     503             :     }
     504           0 :     nsCOMPtr<nsIDOMHTMLSourceElement> nodeAsSource = do_QueryInterface(aNode);
     505           0 :     if (nodeAsSource) {
     506           0 :         return OnWalkAttribute(aNode, "src");
     507             :     }
     508             : 
     509           0 :     if (content->IsHTMLElement(nsGkAtoms::body)) {
     510           0 :         return OnWalkAttribute(aNode, "background");
     511             :     }
     512             : 
     513           0 :     if (content->IsHTMLElement(nsGkAtoms::table)) {
     514           0 :         return OnWalkAttribute(aNode, "background");
     515             :     }
     516             : 
     517           0 :     if (content->IsHTMLElement(nsGkAtoms::tr)) {
     518           0 :         return OnWalkAttribute(aNode, "background");
     519             :     }
     520             : 
     521           0 :     if (content->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
     522           0 :         return OnWalkAttribute(aNode, "background");
     523             :     }
     524             : 
     525           0 :     nsCOMPtr<nsIDOMHTMLScriptElement> nodeAsScript = do_QueryInterface(aNode);
     526           0 :     if (nodeAsScript) {
     527           0 :         return OnWalkAttribute(aNode, "src");
     528             :     }
     529             : 
     530           0 :     if (content->IsSVGElement(nsGkAtoms::script)) {
     531           0 :         return OnWalkAttribute(aNode, "href", "http://www.w3.org/1999/xlink");
     532             :     }
     533             : 
     534           0 :     nsCOMPtr<nsIDOMHTMLEmbedElement> nodeAsEmbed = do_QueryInterface(aNode);
     535           0 :     if (nodeAsEmbed) {
     536           0 :         return OnWalkAttribute(aNode, "src");
     537             :     }
     538             : 
     539           0 :     nsCOMPtr<nsIDOMHTMLObjectElement> nodeAsObject = do_QueryInterface(aNode);
     540           0 :     if (nodeAsObject) {
     541           0 :         return OnWalkAttribute(aNode, "data");
     542             :     }
     543             : 
     544           0 :     nsCOMPtr<nsIDOMHTMLAppletElement> nodeAsApplet = do_QueryInterface(aNode);
     545           0 :     if (nodeAsApplet) {
     546             :         // For an applet, relative URIs are resolved relative to the
     547             :         // codebase (which is resolved relative to the base URI).
     548           0 :         nsCOMPtr<nsIURI> oldBase = mCurrentBaseURI;
     549           0 :         nsAutoString codebase;
     550           0 :         rv = nodeAsApplet->GetCodeBase(codebase);
     551           0 :         NS_ENSURE_SUCCESS(rv, rv);
     552           0 :         if (!codebase.IsEmpty()) {
     553           0 :             nsCOMPtr<nsIURI> baseURI;
     554           0 :             rv = NS_NewURI(getter_AddRefs(baseURI), codebase,
     555           0 :                            mParent->GetCharacterSet(), mCurrentBaseURI);
     556           0 :             NS_ENSURE_SUCCESS(rv, rv);
     557           0 :             if (baseURI) {
     558           0 :                 mCurrentBaseURI = baseURI;
     559             :                 // Must restore this before returning (or ENSURE'ing).
     560             :             }
     561             :         }
     562             : 
     563             :         // We only store 'code' locally if there is no 'archive',
     564             :         // otherwise we assume the archive file(s) contains it (bug 430283).
     565           0 :         nsAutoCString archiveAttr;
     566           0 :         rv = ExtractAttribute(aNode, "archive", "", archiveAttr);
     567           0 :         if (NS_SUCCEEDED(rv)) {
     568           0 :             if (!archiveAttr.IsEmpty()) {
     569           0 :                 rv = OnWalkURI(archiveAttr);
     570             :             } else {
     571           0 :                 rv = OnWalkAttribute(aNode, "core");
     572             :             }
     573             :         }
     574             : 
     575             :         // restore the base URI we really want to have
     576           0 :         mCurrentBaseURI = oldBase;
     577           0 :         return rv;
     578             :     }
     579             : 
     580           0 :     nsCOMPtr<nsIDOMHTMLLinkElement> nodeAsLink = do_QueryInterface(aNode);
     581           0 :     if (nodeAsLink) {
     582             :         // Test if the link has a rel value indicating it to be a stylesheet
     583           0 :         nsAutoString linkRel;
     584           0 :         if (NS_SUCCEEDED(nodeAsLink->GetRel(linkRel)) && !linkRel.IsEmpty()) {
     585           0 :             nsReadingIterator<char16_t> start;
     586           0 :             nsReadingIterator<char16_t> end;
     587           0 :             nsReadingIterator<char16_t> current;
     588             : 
     589           0 :             linkRel.BeginReading(start);
     590           0 :             linkRel.EndReading(end);
     591             : 
     592             :             // Walk through space delimited string looking for "stylesheet"
     593           0 :             for (current = start; current != end; ++current) {
     594             :                 // Ignore whitespace
     595           0 :                 if (nsCRT::IsAsciiSpace(*current)) {
     596           0 :                     continue;
     597             :                 }
     598             : 
     599             :                 // Grab the next space delimited word
     600           0 :                 nsReadingIterator<char16_t> startWord = current;
     601           0 :                 do {
     602           0 :                     ++current;
     603           0 :                 } while (current != end && !nsCRT::IsAsciiSpace(*current));
     604             : 
     605             :                 // Store the link for fix up if it says "stylesheet"
     606           0 :                 if (Substring(startWord, current)
     607             :                         .LowerCaseEqualsLiteral("stylesheet")) {
     608           0 :                     OnWalkAttribute(aNode, "href");
     609           0 :                     return NS_OK;
     610             :                 }
     611           0 :                 if (current == end) {
     612           0 :                     break;
     613             :                 }
     614             :             }
     615             :         }
     616           0 :         return NS_OK;
     617             :     }
     618             : 
     619           0 :     nsCOMPtr<nsIDOMHTMLFrameElement> nodeAsFrame = do_QueryInterface(aNode);
     620           0 :     if (nodeAsFrame) {
     621           0 :         return OnWalkSubframe(aNode);
     622             :     }
     623             : 
     624           0 :     nsCOMPtr<nsIDOMHTMLIFrameElement> nodeAsIFrame = do_QueryInterface(aNode);
     625           0 :     if (nodeAsIFrame && !(mPersistFlags &
     626           0 :                           IWBP::PERSIST_FLAGS_IGNORE_IFRAMES)) {
     627           0 :         return OnWalkSubframe(aNode);
     628             :     }
     629             : 
     630           0 :     nsCOMPtr<nsIDOMHTMLInputElement> nodeAsInput = do_QueryInterface(aNode);
     631           0 :     if (nodeAsInput) {
     632           0 :         return OnWalkAttribute(aNode, "src");
     633             :     }
     634             : 
     635           0 :     return NS_OK;
     636             : }
     637             : 
     638             : // Helper class for node rewriting in writeContent().
     639             : class PersistNodeFixup final : public nsIDocumentEncoderNodeFixup {
     640             : public:
     641             :     PersistNodeFixup(WebBrowserPersistLocalDocument* aParent,
     642             :                      nsIWebBrowserPersistURIMap* aMap,
     643             :                      nsIURI* aTargetURI);
     644             : 
     645             :     NS_DECL_ISUPPORTS
     646             :     NS_DECL_NSIDOCUMENTENCODERNODEFIXUP
     647             : private:
     648           0 :     virtual ~PersistNodeFixup() = default;
     649             :     RefPtr<WebBrowserPersistLocalDocument> mParent;
     650             :     nsClassHashtable<nsCStringHashKey, nsCString> mMap;
     651             :     nsCOMPtr<nsIURI> mCurrentBaseURI;
     652             :     nsCOMPtr<nsIURI> mTargetBaseURI;
     653             : 
     654           0 :     bool IsFlagSet(uint32_t aFlag) const {
     655           0 :         return mParent->GetPersistFlags() & aFlag;
     656             :     }
     657             : 
     658             :     nsresult GetNodeToFixup(nsIDOMNode* aNodeIn, nsIDOMNode** aNodeOut);
     659             :     nsresult FixupURI(nsAString& aURI);
     660             :     nsresult FixupAttribute(nsIDOMNode* aNode,
     661             :                             const char* aAttribute,
     662             :                             const char* aNamespaceURI = "");
     663             :     nsresult FixupAnchor(nsIDOMNode* aNode);
     664             :     nsresult FixupXMLStyleSheetLink(nsIDOMProcessingInstruction* aPI,
     665             :                                     const nsAString& aHref);
     666             : 
     667             :     using IWBP = nsIWebBrowserPersist;
     668             : };
     669             : 
     670           0 : NS_IMPL_ISUPPORTS(PersistNodeFixup, nsIDocumentEncoderNodeFixup)
     671             : 
     672           0 : PersistNodeFixup::PersistNodeFixup(WebBrowserPersistLocalDocument* aParent,
     673             :                                    nsIWebBrowserPersistURIMap* aMap,
     674           0 :                                    nsIURI* aTargetURI)
     675             : : mParent(aParent)
     676           0 : , mCurrentBaseURI(aParent->GetBaseURI())
     677           0 : , mTargetBaseURI(aTargetURI)
     678             : {
     679           0 :     if (aMap) {
     680             :         uint32_t mapSize;
     681           0 :         nsresult rv = aMap->GetNumMappedURIs(&mapSize);
     682           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
     683           0 :         NS_ENSURE_SUCCESS_VOID(rv);
     684           0 :         for (uint32_t i = 0; i < mapSize; ++i) {
     685           0 :             nsAutoCString urlFrom;
     686           0 :             auto* urlTo = new nsCString();
     687             : 
     688           0 :             rv = aMap->GetURIMapping(i, urlFrom, *urlTo);
     689           0 :             MOZ_ASSERT(NS_SUCCEEDED(rv));
     690           0 :             if (NS_SUCCEEDED(rv)) {
     691           0 :                 mMap.Put(urlFrom, urlTo);
     692             :             }
     693             :         }
     694             :     }
     695             : }
     696             : 
     697             : nsresult
     698           0 : PersistNodeFixup::GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut)
     699             : {
     700             :     // Avoid mixups in FixupNode that could leak objects; this goes
     701             :     // against the usual out parameter convention, but it's a private
     702             :     // method so shouldn't be a problem.
     703           0 :     MOZ_ASSERT(!*aNodeOut);
     704             : 
     705           0 :     if (!IsFlagSet(IWBP::PERSIST_FLAGS_FIXUP_ORIGINAL_DOM)) {
     706           0 :         nsresult rv = aNodeIn->CloneNode(false, 1, aNodeOut);
     707           0 :         NS_ENSURE_SUCCESS(rv, rv);
     708             :     } else {
     709           0 :         NS_ADDREF(*aNodeOut = aNodeIn);
     710             :     }
     711           0 :     return NS_OK;
     712             : }
     713             : 
     714             : nsresult
     715           0 : PersistNodeFixup::FixupURI(nsAString &aURI)
     716             : {
     717             :     // get the current location of the file (absolutized)
     718           0 :     nsCOMPtr<nsIURI> uri;
     719           0 :     nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI,
     720           0 :                             mParent->GetCharacterSet(), mCurrentBaseURI);
     721           0 :     NS_ENSURE_SUCCESS(rv, rv);
     722           0 :     nsAutoCString spec;
     723           0 :     rv = uri->GetSpec(spec);
     724           0 :     NS_ENSURE_SUCCESS(rv, rv);
     725             : 
     726           0 :     const nsCString* replacement = mMap.Get(spec);
     727           0 :     if (!replacement) {
     728             :         // Note that most callers ignore this "failure".
     729           0 :         return NS_ERROR_FAILURE;
     730             :     }
     731           0 :     if (!replacement->IsEmpty()) {
     732           0 :         aURI = NS_ConvertUTF8toUTF16(*replacement);
     733             :     }
     734           0 :     return NS_OK;
     735             : }
     736             : 
     737             : nsresult
     738           0 : PersistNodeFixup::FixupAttribute(nsIDOMNode* aNode,
     739             :                                  const char* aAttribute,
     740             :                                  const char* aNamespaceURI)
     741             : {
     742           0 :     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
     743           0 :     MOZ_ASSERT(element);
     744             : 
     745           0 :     nsCOMPtr<nsIDOMMozNamedAttrMap> attrMap;
     746           0 :     nsresult rv = element->GetAttributes(getter_AddRefs(attrMap));
     747           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
     748             : 
     749           0 :     NS_ConvertASCIItoUTF16 attribute(aAttribute);
     750           0 :     NS_ConvertASCIItoUTF16 namespaceURI(aNamespaceURI);
     751           0 :     nsCOMPtr<nsIDOMAttr> attr;
     752           0 :     rv = attrMap->GetNamedItemNS(namespaceURI, attribute, getter_AddRefs(attr));
     753           0 :     if (attr) {
     754           0 :         nsString uri;
     755           0 :         attr->GetValue(uri);
     756           0 :         rv = FixupURI(uri);
     757           0 :         if (NS_SUCCEEDED(rv)) {
     758           0 :             attr->SetValue(uri);
     759             :         }
     760             :     }
     761             : 
     762           0 :     return rv;
     763             : }
     764             : 
     765             : nsresult
     766           0 : PersistNodeFixup::FixupAnchor(nsIDOMNode *aNode)
     767             : {
     768           0 :     if (IsFlagSet(IWBP::PERSIST_FLAGS_DONT_FIXUP_LINKS)) {
     769           0 :         return NS_OK;
     770             :     }
     771             : 
     772           0 :     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
     773           0 :     MOZ_ASSERT(element);
     774             : 
     775           0 :     nsCOMPtr<nsIDOMMozNamedAttrMap> attrMap;
     776           0 :     nsresult rv = element->GetAttributes(getter_AddRefs(attrMap));
     777           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
     778             : 
     779             :     // Make all anchor links absolute so they point off onto the Internet
     780           0 :     nsString attribute(NS_LITERAL_STRING("href"));
     781           0 :     nsCOMPtr<nsIDOMAttr> attr;
     782           0 :     rv = attrMap->GetNamedItem(attribute, getter_AddRefs(attr));
     783           0 :     if (attr) {
     784           0 :         nsString oldValue;
     785           0 :         attr->GetValue(oldValue);
     786           0 :         NS_ConvertUTF16toUTF8 oldCValue(oldValue);
     787             : 
     788             :         // Skip empty values and self-referencing bookmarks
     789           0 :         if (oldCValue.IsEmpty() || oldCValue.CharAt(0) == '#') {
     790           0 :             return NS_OK;
     791             :         }
     792             : 
     793             :         // if saving file to same location, we don't need to do any fixup
     794             :         bool isEqual;
     795           0 :         if (mTargetBaseURI &&
     796           0 :             NS_SUCCEEDED(mCurrentBaseURI->Equals(mTargetBaseURI, &isEqual)) &&
     797             :             isEqual) {
     798           0 :             return NS_OK;
     799             :         }
     800             : 
     801           0 :         nsCOMPtr<nsIURI> relativeURI;
     802           0 :         relativeURI = IsFlagSet(IWBP::PERSIST_FLAGS_FIXUP_LINKS_TO_DESTINATION)
     803           0 :                       ? mTargetBaseURI : mCurrentBaseURI;
     804             :         // Make a new URI to replace the current one
     805           0 :         nsCOMPtr<nsIURI> newURI;
     806           0 :         rv = NS_NewURI(getter_AddRefs(newURI), oldCValue,
     807           0 :                        mParent->GetCharacterSet(), relativeURI);
     808           0 :         if (NS_SUCCEEDED(rv) && newURI) {
     809           0 :             newURI->SetUserPass(EmptyCString());
     810           0 :             nsAutoCString uriSpec;
     811           0 :             rv = newURI->GetSpec(uriSpec);
     812           0 :             NS_ENSURE_SUCCESS(rv, rv);
     813           0 :             attr->SetValue(NS_ConvertUTF8toUTF16(uriSpec));
     814             :         }
     815             :     }
     816             : 
     817           0 :     return NS_OK;
     818             : }
     819             : 
     820             : static void
     821           0 : AppendXMLAttr(const nsAString& key, const nsAString& aValue, nsAString& aBuffer)
     822             : {
     823           0 :     if (!aBuffer.IsEmpty()) {
     824           0 :         aBuffer.Append(' ');
     825             :     }
     826           0 :     aBuffer.Append(key);
     827           0 :     aBuffer.AppendLiteral(R"(=")");
     828           0 :     for (size_t i = 0; i < aValue.Length(); ++i) {
     829           0 :         switch (aValue[i]) {
     830             :             case '&':
     831           0 :                 aBuffer.AppendLiteral("&amp;");
     832           0 :                 break;
     833             :             case '<':
     834           0 :                 aBuffer.AppendLiteral("&lt;");
     835           0 :                 break;
     836             :             case '>':
     837           0 :                 aBuffer.AppendLiteral("&gt;");
     838           0 :                 break;
     839             :             case '"':
     840           0 :                 aBuffer.AppendLiteral("&quot;");
     841           0 :                 break;
     842             :             default:
     843           0 :                 aBuffer.Append(aValue[i]);
     844           0 :                 break;
     845             :         }
     846             :     }
     847           0 :     aBuffer.Append('"');
     848           0 : }
     849             : 
     850             : nsresult
     851           0 : PersistNodeFixup::FixupXMLStyleSheetLink(nsIDOMProcessingInstruction* aPI,
     852             :                                          const nsAString& aHref)
     853             : {
     854           0 :     NS_ENSURE_ARG_POINTER(aPI);
     855           0 :     nsresult rv = NS_OK;
     856             : 
     857           0 :     nsAutoString data;
     858           0 :     rv = aPI->GetData(data);
     859           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
     860             : 
     861           0 :     nsAutoString href;
     862             :     nsContentUtils::GetPseudoAttributeValue(data,
     863             :                                             nsGkAtoms::href,
     864           0 :                                             href);
     865             : 
     866             :     // Construct and set a new data value for the xml-stylesheet
     867           0 :     if (!aHref.IsEmpty() && !href.IsEmpty())
     868             :     {
     869           0 :         nsAutoString alternate;
     870           0 :         nsAutoString charset;
     871           0 :         nsAutoString title;
     872           0 :         nsAutoString type;
     873           0 :         nsAutoString media;
     874             : 
     875             :         nsContentUtils::GetPseudoAttributeValue(data,
     876             :                                                 nsGkAtoms::alternate,
     877           0 :                                                 alternate);
     878             :         nsContentUtils::GetPseudoAttributeValue(data,
     879             :                                                 nsGkAtoms::charset,
     880           0 :                                                 charset);
     881             :         nsContentUtils::GetPseudoAttributeValue(data,
     882             :                                                 nsGkAtoms::title,
     883           0 :                                                 title);
     884             :         nsContentUtils::GetPseudoAttributeValue(data,
     885             :                                                 nsGkAtoms::type,
     886           0 :                                                 type);
     887             :         nsContentUtils::GetPseudoAttributeValue(data,
     888             :                                                 nsGkAtoms::media,
     889           0 :                                                 media);
     890             : 
     891           0 :         nsAutoString newData;
     892           0 :         AppendXMLAttr(NS_LITERAL_STRING("href"), aHref, newData);
     893           0 :         if (!title.IsEmpty()) {
     894           0 :             AppendXMLAttr(NS_LITERAL_STRING("title"), title, newData);
     895             :         }
     896           0 :         if (!media.IsEmpty()) {
     897           0 :             AppendXMLAttr(NS_LITERAL_STRING("media"), media, newData);
     898             :         }
     899           0 :         if (!type.IsEmpty()) {
     900           0 :             AppendXMLAttr(NS_LITERAL_STRING("type"), type, newData);
     901             :         }
     902           0 :         if (!charset.IsEmpty()) {
     903           0 :             AppendXMLAttr(NS_LITERAL_STRING("charset"), charset, newData);
     904             :         }
     905           0 :         if (!alternate.IsEmpty()) {
     906           0 :             AppendXMLAttr(NS_LITERAL_STRING("alternate"), alternate, newData);
     907             :         }
     908           0 :         aPI->SetData(newData);
     909             :     }
     910             : 
     911           0 :     return rv;
     912             : }
     913             : 
     914             : NS_IMETHODIMP
     915           0 : PersistNodeFixup::FixupNode(nsIDOMNode *aNodeIn,
     916             :                             bool *aSerializeCloneKids,
     917             :                             nsIDOMNode **aNodeOut)
     918             : {
     919           0 :     *aNodeOut = nullptr;
     920           0 :     *aSerializeCloneKids = false;
     921             : 
     922             :     uint16_t type;
     923           0 :     nsresult rv = aNodeIn->GetNodeType(&type);
     924           0 :     NS_ENSURE_SUCCESS(rv, rv);
     925           0 :     if (type != nsIDOMNode::ELEMENT_NODE &&
     926           0 :         type != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
     927           0 :         return NS_OK;
     928             :     }
     929             : 
     930             :     // Fixup xml-stylesheet processing instructions
     931           0 :     nsCOMPtr<nsIDOMProcessingInstruction> nodeAsPI = do_QueryInterface(aNodeIn);
     932           0 :     if (nodeAsPI) {
     933           0 :         nsAutoString target;
     934           0 :         nodeAsPI->GetTarget(target);
     935           0 :         if (target.EqualsLiteral("xml-stylesheet"))
     936             :         {
     937           0 :             rv = GetNodeToFixup(aNodeIn, aNodeOut);
     938           0 :             if (NS_SUCCEEDED(rv) && *aNodeOut) {
     939             :                 nsCOMPtr<nsIDOMProcessingInstruction> outNode =
     940           0 :                     do_QueryInterface(*aNodeOut);
     941           0 :                 nsAutoString href;
     942           0 :                 GetXMLStyleSheetLink(nodeAsPI, href);
     943           0 :                 if (!href.IsEmpty()) {
     944           0 :                     FixupURI(href);
     945           0 :                     FixupXMLStyleSheetLink(outNode, href);
     946             :                 }
     947             :             }
     948             :         }
     949           0 :         return NS_OK;
     950             :     }
     951             : 
     952             :     // BASE elements are replaced by a comment so relative links are not hosed.
     953           0 :     if (!IsFlagSet(IWBP::PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS)) {
     954           0 :         nsCOMPtr<nsIDOMHTMLBaseElement> nodeAsBase = do_QueryInterface(aNodeIn);
     955           0 :         if (nodeAsBase) {
     956           0 :             nsCOMPtr<nsIDOMDocument> ownerDocument;
     957           0 :             auto* base = static_cast<dom::HTMLSharedElement*>(nodeAsBase.get());
     958           0 :             base->GetOwnerDocument(getter_AddRefs(ownerDocument));
     959           0 :             if (ownerDocument) {
     960           0 :                 nsAutoString href;
     961           0 :                 base->GetHref(href); // Doesn't matter if this fails
     962           0 :                 nsCOMPtr<nsIDOMComment> comment;
     963           0 :                 nsAutoString commentText;
     964           0 :                 commentText.AssignLiteral(" base ");
     965           0 :                 if (!href.IsEmpty()) {
     966           0 :                     commentText += NS_LITERAL_STRING("href=\"") + href
     967           0 :                                    + NS_LITERAL_STRING("\" ");
     968             :                 }
     969           0 :                 rv = ownerDocument->CreateComment(commentText,
     970           0 :                                                   getter_AddRefs(comment));
     971           0 :                 if (comment) {
     972           0 :                     return CallQueryInterface(comment, aNodeOut);
     973             :                 }
     974             :             }
     975           0 :             return NS_OK;
     976             :         }
     977             :     }
     978             : 
     979           0 :     nsCOMPtr<nsIContent> content = do_QueryInterface(aNodeIn);
     980           0 :     if (!content) {
     981           0 :         return NS_OK;
     982             :     }
     983             : 
     984             :     // Fix up href and file links in the elements
     985           0 :     nsCOMPtr<nsIDOMHTMLAnchorElement> nodeAsAnchor = do_QueryInterface(aNodeIn);
     986           0 :     if (nodeAsAnchor) {
     987           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
     988           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
     989           0 :             FixupAnchor(*aNodeOut);
     990             :         }
     991           0 :         return rv;
     992             :     }
     993             : 
     994           0 :     nsCOMPtr<nsIDOMHTMLAreaElement> nodeAsArea = do_QueryInterface(aNodeIn);
     995           0 :     if (nodeAsArea) {
     996           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
     997           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
     998           0 :             FixupAnchor(*aNodeOut);
     999             :         }
    1000           0 :         return rv;
    1001             :     }
    1002             : 
    1003           0 :     if (content->IsHTMLElement(nsGkAtoms::body)) {
    1004           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1005           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1006           0 :             FixupAttribute(*aNodeOut, "background");
    1007             :         }
    1008           0 :         return rv;
    1009             :     }
    1010             : 
    1011           0 :     if (content->IsHTMLElement(nsGkAtoms::table)) {
    1012           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1013           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1014           0 :             FixupAttribute(*aNodeOut, "background");
    1015             :         }
    1016           0 :         return rv;
    1017             :     }
    1018             : 
    1019           0 :     if (content->IsHTMLElement(nsGkAtoms::tr)) {
    1020           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1021           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1022           0 :             FixupAttribute(*aNodeOut, "background");
    1023             :         }
    1024           0 :         return rv;
    1025             :     }
    1026             : 
    1027           0 :     if (content->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
    1028           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1029           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1030           0 :             FixupAttribute(*aNodeOut, "background");
    1031             :         }
    1032           0 :         return rv;
    1033             :     }
    1034             : 
    1035           0 :     nsCOMPtr<nsIDOMHTMLImageElement> nodeAsImage = do_QueryInterface(aNodeIn);
    1036           0 :     if (nodeAsImage) {
    1037           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1038           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1039             :             // Disable image loads
    1040             :             nsCOMPtr<nsIImageLoadingContent> imgCon =
    1041           0 :                 do_QueryInterface(*aNodeOut);
    1042           0 :             if (imgCon) {
    1043           0 :                 imgCon->SetLoadingEnabled(false);
    1044             :             }
    1045           0 :             FixupAnchor(*aNodeOut);
    1046           0 :             FixupAttribute(*aNodeOut, "src");
    1047             :         }
    1048           0 :         return rv;
    1049             :     }
    1050             : 
    1051           0 :     nsCOMPtr<nsIDOMHTMLMediaElement> nodeAsMedia = do_QueryInterface(aNodeIn);
    1052           0 :     if (nodeAsMedia) {
    1053           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1054           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1055           0 :             FixupAttribute(*aNodeOut, "src");
    1056             :         }
    1057           0 :         return rv;
    1058             :     }
    1059             : 
    1060           0 :     nsCOMPtr<nsIDOMHTMLSourceElement> nodeAsSource = do_QueryInterface(aNodeIn);
    1061           0 :     if (nodeAsSource) {
    1062           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1063           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1064           0 :             FixupAttribute(*aNodeOut, "src");
    1065             :         }
    1066           0 :         return rv;
    1067             :     }
    1068             : 
    1069           0 :     if (content->IsSVGElement(nsGkAtoms::img)) {
    1070           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1071           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1072             :             // Disable image loads
    1073             :             nsCOMPtr<nsIImageLoadingContent> imgCon =
    1074           0 :                 do_QueryInterface(*aNodeOut);
    1075           0 :             if (imgCon)
    1076           0 :                 imgCon->SetLoadingEnabled(false);
    1077             : 
    1078             :             // FixupAnchor(*aNodeOut);  // XXXjwatt: is this line needed?
    1079           0 :             FixupAttribute(*aNodeOut, "href", "http://www.w3.org/1999/xlink");
    1080             :         }
    1081           0 :         return rv;
    1082             :     }
    1083             : 
    1084           0 :     nsCOMPtr<nsIDOMHTMLScriptElement> nodeAsScript = do_QueryInterface(aNodeIn);
    1085           0 :     if (nodeAsScript) {
    1086           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1087           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1088           0 :             FixupAttribute(*aNodeOut, "src");
    1089             :         }
    1090           0 :         return rv;
    1091             :     }
    1092             : 
    1093           0 :     if (content->IsSVGElement(nsGkAtoms::script)) {
    1094           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1095           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1096           0 :             FixupAttribute(*aNodeOut, "href", "http://www.w3.org/1999/xlink");
    1097             :         }
    1098           0 :         return rv;
    1099             :     }
    1100             : 
    1101           0 :         nsCOMPtr<nsIDOMHTMLEmbedElement> nodeAsEmbed = do_QueryInterface(aNodeIn);
    1102           0 :     if (nodeAsEmbed) {
    1103           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1104           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1105           0 :             FixupAttribute(*aNodeOut, "src");
    1106             :         }
    1107           0 :         return rv;
    1108             :     }
    1109             : 
    1110           0 :     nsCOMPtr<nsIDOMHTMLObjectElement> nodeAsObject = do_QueryInterface(aNodeIn);
    1111           0 :     if (nodeAsObject) {
    1112           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1113           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1114           0 :             FixupAttribute(*aNodeOut, "data");
    1115             :         }
    1116           0 :         return rv;
    1117             :     }
    1118             : 
    1119           0 :     nsCOMPtr<nsIDOMHTMLAppletElement> nodeAsApplet = do_QueryInterface(aNodeIn);
    1120           0 :     if (nodeAsApplet) {
    1121           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1122           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1123             :             nsCOMPtr<nsIDOMHTMLAppletElement> newApplet =
    1124           0 :                 do_QueryInterface(*aNodeOut);
    1125             :             // For an applet, relative URIs are resolved relative to the
    1126             :             // codebase (which is resolved relative to the base URI).
    1127           0 :             nsCOMPtr<nsIURI> oldBase = mCurrentBaseURI;
    1128           0 :             nsAutoString codebase;
    1129           0 :             nodeAsApplet->GetCodeBase(codebase);
    1130           0 :             if (!codebase.IsEmpty()) {
    1131           0 :                 nsCOMPtr<nsIURI> baseURI;
    1132           0 :                 NS_NewURI(getter_AddRefs(baseURI), codebase,
    1133           0 :                           mParent->GetCharacterSet(), mCurrentBaseURI);
    1134           0 :                 if (baseURI) {
    1135           0 :                     mCurrentBaseURI = baseURI;
    1136             :                 }
    1137             :             }
    1138             :             // Unset the codebase too, since we'll correctly relativize the
    1139             :             // code and archive paths.
    1140           0 :             IgnoredErrorResult ignored;
    1141           0 :             static_cast<dom::HTMLSharedObjectElement*>(newApplet.get())->
    1142           0 :               RemoveAttribute(NS_LITERAL_STRING("codebase"), ignored);
    1143           0 :             FixupAttribute(*aNodeOut, "code");
    1144           0 :             FixupAttribute(*aNodeOut, "archive");
    1145             :             // restore the base URI we really want to have
    1146           0 :             mCurrentBaseURI = oldBase;
    1147             :         }
    1148           0 :         return rv;
    1149             :     }
    1150             : 
    1151           0 :     nsCOMPtr<nsIDOMHTMLLinkElement> nodeAsLink = do_QueryInterface(aNodeIn);
    1152           0 :     if (nodeAsLink) {
    1153           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1154           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1155             :             // First see if the link represents linked content
    1156           0 :             rv = FixupAttribute(*aNodeOut, "href");
    1157           0 :             if (NS_FAILED(rv)) {
    1158             :                 // Perhaps this link is actually an anchor to related content
    1159           0 :                 FixupAnchor(*aNodeOut);
    1160             :             }
    1161             :             // TODO if "type" attribute == "text/css"
    1162             :             //        fixup stylesheet
    1163             :         }
    1164           0 :         return rv;
    1165             :     }
    1166             : 
    1167           0 :     nsCOMPtr<nsIDOMHTMLFrameElement> nodeAsFrame = do_QueryInterface(aNodeIn);
    1168           0 :     if (nodeAsFrame) {
    1169           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1170           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1171           0 :             FixupAttribute(*aNodeOut, "src");
    1172             :         }
    1173           0 :         return rv;
    1174             :     }
    1175             : 
    1176           0 :     nsCOMPtr<nsIDOMHTMLIFrameElement> nodeAsIFrame = do_QueryInterface(aNodeIn);
    1177           0 :     if (nodeAsIFrame) {
    1178           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1179           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1180           0 :             FixupAttribute(*aNodeOut, "src");
    1181             :         }
    1182           0 :         return rv;
    1183             :     }
    1184             : 
    1185             :     RefPtr<dom::HTMLInputElement> nodeAsInput =
    1186           0 :         dom::HTMLInputElement::FromContentOrNull(content);
    1187           0 :     if (nodeAsInput) {
    1188           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1189           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1190             :             // Disable image loads
    1191             :             nsCOMPtr<nsIImageLoadingContent> imgCon =
    1192           0 :                 do_QueryInterface(*aNodeOut);
    1193           0 :             if (imgCon) {
    1194           0 :                 imgCon->SetLoadingEnabled(false);
    1195             :             }
    1196             : 
    1197           0 :             FixupAttribute(*aNodeOut, "src");
    1198             : 
    1199           0 :             nsAutoString valueStr;
    1200           0 :             NS_NAMED_LITERAL_STRING(valueAttr, "value");
    1201             :             // Update element node attributes with user-entered form state
    1202           0 :             nsCOMPtr<nsIContent> content = do_QueryInterface(*aNodeOut);
    1203             :             RefPtr<dom::HTMLInputElement> outElt =
    1204           0 :               dom::HTMLInputElement::FromContentOrNull(content);
    1205           0 :             nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(*aNodeOut);
    1206           0 :             switch (formControl->ControlType()) {
    1207             :                 case NS_FORM_INPUT_EMAIL:
    1208             :                 case NS_FORM_INPUT_SEARCH:
    1209             :                 case NS_FORM_INPUT_TEXT:
    1210             :                 case NS_FORM_INPUT_TEL:
    1211             :                 case NS_FORM_INPUT_URL:
    1212             :                 case NS_FORM_INPUT_NUMBER:
    1213             :                 case NS_FORM_INPUT_RANGE:
    1214             :                 case NS_FORM_INPUT_DATE:
    1215             :                 case NS_FORM_INPUT_TIME:
    1216             :                 case NS_FORM_INPUT_COLOR:
    1217           0 :                     nodeAsInput->GetValue(valueStr, dom::CallerType::System);
    1218             :                     // Avoid superfluous value="" serialization
    1219           0 :                     if (valueStr.IsEmpty()) {
    1220           0 :                       IgnoredErrorResult ignored;
    1221           0 :                       outElt->RemoveAttribute(valueAttr, ignored);
    1222             :                     } else {
    1223           0 :                       outElt->SetAttribute(valueAttr, valueStr);
    1224             :                     }
    1225           0 :                     break;
    1226             :                 case NS_FORM_INPUT_CHECKBOX:
    1227             :                 case NS_FORM_INPUT_RADIO:
    1228             :                     {
    1229           0 :                         bool checked = nodeAsInput->Checked();
    1230           0 :                         outElt->SetDefaultChecked(checked);
    1231             :                     }
    1232           0 :                     break;
    1233             :                 default:
    1234           0 :                     break;
    1235             :             }
    1236             :         }
    1237           0 :         return rv;
    1238             :     }
    1239             : 
    1240           0 :     nsCOMPtr<nsIDOMHTMLTextAreaElement> nodeAsTextArea = do_QueryInterface(aNodeIn);
    1241           0 :     if (nodeAsTextArea) {
    1242           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1243           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1244             :             // Tell the document encoder to serialize the text child we create below
    1245           0 :             *aSerializeCloneKids = true;
    1246             : 
    1247           0 :             nsAutoString valueStr;
    1248           0 :             nodeAsTextArea->GetValue(valueStr);
    1249             : 
    1250           0 :             (*aNodeOut)->SetTextContent(valueStr);
    1251             :         }
    1252           0 :         return rv;
    1253             :     }
    1254             : 
    1255           0 :     nsCOMPtr<nsIDOMHTMLOptionElement> nodeAsOption = do_QueryInterface(aNodeIn);
    1256           0 :     if (nodeAsOption) {
    1257           0 :         rv = GetNodeToFixup(aNodeIn, aNodeOut);
    1258           0 :         if (NS_SUCCEEDED(rv) && *aNodeOut) {
    1259           0 :             nsCOMPtr<nsIDOMHTMLOptionElement> outElt = do_QueryInterface(*aNodeOut);
    1260             :             bool selected;
    1261           0 :             nodeAsOption->GetSelected(&selected);
    1262           0 :             outElt->SetDefaultSelected(selected);
    1263             :         }
    1264           0 :         return rv;
    1265             :     }
    1266             : 
    1267           0 :     return NS_OK;
    1268             : }
    1269             : 
    1270             : } // unnamed namespace
    1271             : 
    1272             : NS_IMETHODIMP
    1273           0 : WebBrowserPersistLocalDocument::ReadResources(nsIWebBrowserPersistResourceVisitor* aVisitor)
    1274             : {
    1275           0 :     nsresult rv = NS_OK;
    1276           0 :     nsCOMPtr<nsIWebBrowserPersistResourceVisitor> visitor = aVisitor;
    1277             : 
    1278           0 :     nsCOMPtr<nsIDOMNode> docAsNode = do_QueryInterface(mDocument);
    1279           0 :     NS_ENSURE_TRUE(docAsNode, NS_ERROR_FAILURE);
    1280             : 
    1281           0 :     nsCOMPtr<nsIDOMTreeWalker> walker;
    1282           0 :     nsCOMPtr<nsIDOMDocument> oldStyleDoc = do_QueryInterface(mDocument);
    1283           0 :     MOZ_ASSERT(oldStyleDoc);
    1284           0 :     rv = oldStyleDoc->CreateTreeWalker(docAsNode,
    1285             :             nsIDOMNodeFilter::SHOW_ELEMENT |
    1286             :             nsIDOMNodeFilter::SHOW_DOCUMENT |
    1287             :             nsIDOMNodeFilter::SHOW_PROCESSING_INSTRUCTION,
    1288           0 :             nullptr, 1, getter_AddRefs(walker));
    1289           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1290           0 :     MOZ_ASSERT(walker);
    1291             : 
    1292           0 :     RefPtr<ResourceReader> reader = new ResourceReader(this, aVisitor);
    1293           0 :     nsCOMPtr<nsIDOMNode> currentNode;
    1294           0 :     walker->GetCurrentNode(getter_AddRefs(currentNode));
    1295           0 :     while (currentNode) {
    1296           0 :         rv = reader->OnWalkDOMNode(currentNode);
    1297           0 :         if (NS_WARN_IF(NS_FAILED(rv))) {
    1298           0 :             break;
    1299             :         }
    1300           0 :         rv = walker->NextNode(getter_AddRefs(currentNode));
    1301           0 :         if (NS_WARN_IF(NS_FAILED(rv))) {
    1302           0 :             break;
    1303             :         }
    1304             :     }
    1305           0 :     reader->DocumentDone(rv);
    1306             :     // If NS_FAILED(rv), it was / will be reported by an EndVisit call
    1307             :     // via DocumentDone.  This method must return a failure if and
    1308             :     // only if visitor won't be invoked.
    1309           0 :     return NS_OK;
    1310             : }
    1311             : 
    1312             : static uint32_t
    1313           0 : ConvertEncoderFlags(uint32_t aEncoderFlags)
    1314             : {
    1315           0 :     uint32_t encoderFlags = 0;
    1316             : 
    1317           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_SELECTION_ONLY)
    1318           0 :         encoderFlags |= nsIDocumentEncoder::OutputSelectionOnly;
    1319           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_FORMATTED)
    1320           0 :         encoderFlags |= nsIDocumentEncoder::OutputFormatted;
    1321           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_RAW)
    1322           0 :         encoderFlags |= nsIDocumentEncoder::OutputRaw;
    1323           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_BODY_ONLY)
    1324           0 :         encoderFlags |= nsIDocumentEncoder::OutputBodyOnly;
    1325           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_PREFORMATTED)
    1326           0 :         encoderFlags |= nsIDocumentEncoder::OutputPreformatted;
    1327           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_WRAP)
    1328           0 :         encoderFlags |= nsIDocumentEncoder::OutputWrap;
    1329           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_FORMAT_FLOWED)
    1330           0 :         encoderFlags |= nsIDocumentEncoder::OutputFormatFlowed;
    1331           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_ABSOLUTE_LINKS)
    1332           0 :         encoderFlags |= nsIDocumentEncoder::OutputAbsoluteLinks;
    1333           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_ENCODE_BASIC_ENTITIES)
    1334           0 :         encoderFlags |= nsIDocumentEncoder::OutputEncodeBasicEntities;
    1335           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES)
    1336           0 :         encoderFlags |= nsIDocumentEncoder::OutputEncodeLatin1Entities;
    1337           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_ENCODE_HTML_ENTITIES)
    1338           0 :         encoderFlags |= nsIDocumentEncoder::OutputEncodeHTMLEntities;
    1339           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_ENCODE_W3C_ENTITIES)
    1340           0 :         encoderFlags |= nsIDocumentEncoder::OutputEncodeW3CEntities;
    1341           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_CR_LINEBREAKS)
    1342           0 :         encoderFlags |= nsIDocumentEncoder::OutputCRLineBreak;
    1343           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_LF_LINEBREAKS)
    1344           0 :         encoderFlags |= nsIDocumentEncoder::OutputLFLineBreak;
    1345           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_NOSCRIPT_CONTENT)
    1346           0 :         encoderFlags |= nsIDocumentEncoder::OutputNoScriptContent;
    1347           0 :     if (aEncoderFlags & nsIWebBrowserPersist::ENCODE_FLAGS_NOFRAMES_CONTENT)
    1348           0 :         encoderFlags |= nsIDocumentEncoder::OutputNoFramesContent;
    1349             : 
    1350           0 :     return encoderFlags;
    1351             : }
    1352             : 
    1353             : static bool
    1354           0 : ContentTypeEncoderExists(const nsACString& aType)
    1355             : {
    1356           0 :     nsAutoCString contractID(NS_DOC_ENCODER_CONTRACTID_BASE);
    1357           0 :     contractID.Append(aType);
    1358             : 
    1359           0 :     nsCOMPtr<nsIComponentRegistrar> registrar;
    1360           0 :     nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
    1361           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    1362           0 :     if (NS_SUCCEEDED(rv) && registrar) {
    1363             :         bool result;
    1364           0 :         rv = registrar->IsContractIDRegistered(contractID.get(), &result);
    1365           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
    1366           0 :         return NS_SUCCEEDED(rv) && result;
    1367             :     }
    1368           0 :     return false;
    1369             : }
    1370             : 
    1371             : void
    1372           0 : WebBrowserPersistLocalDocument::DecideContentType(nsACString& aContentType)
    1373             : {
    1374           0 :     if (aContentType.IsEmpty()) {
    1375           0 :         if (NS_WARN_IF(NS_FAILED(GetContentType(aContentType)))) {
    1376           0 :             aContentType.Truncate();
    1377             :         }
    1378             :     }
    1379           0 :     if (!aContentType.IsEmpty() &&
    1380           0 :         !ContentTypeEncoderExists(aContentType)) {
    1381           0 :         aContentType.Truncate();
    1382             :     }
    1383           0 :     if (aContentType.IsEmpty()) {
    1384           0 :         aContentType.AssignLiteral("text/html");
    1385             :     }
    1386           0 : }
    1387             : 
    1388             : nsresult
    1389           0 : WebBrowserPersistLocalDocument::GetDocEncoder(const nsACString& aContentType,
    1390             :                                               uint32_t aEncoderFlags,
    1391             :                                               nsIDocumentEncoder** aEncoder)
    1392             : {
    1393             :     nsresult rv;
    1394           0 :     nsAutoCString contractID(NS_DOC_ENCODER_CONTRACTID_BASE);
    1395           0 :     contractID.Append(aContentType);
    1396             :     nsCOMPtr<nsIDocumentEncoder> encoder =
    1397           0 :         do_CreateInstance(contractID.get(), &rv);
    1398           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1399             : 
    1400           0 :     rv = encoder->NativeInit(mDocument,
    1401           0 :                              NS_ConvertASCIItoUTF16(aContentType),
    1402           0 :                              ConvertEncoderFlags(aEncoderFlags));
    1403           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1404             : 
    1405           0 :     nsAutoCString charSet;
    1406           0 :     rv = GetCharacterSet(charSet);
    1407           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1408           0 :     rv = encoder->SetCharset(charSet);
    1409           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1410             : 
    1411           0 :     encoder.forget(aEncoder);
    1412           0 :     return NS_OK;
    1413             : }
    1414             : 
    1415             : 
    1416             : NS_IMETHODIMP
    1417           0 : WebBrowserPersistLocalDocument::WriteContent(
    1418             :     nsIOutputStream* aStream,
    1419             :     nsIWebBrowserPersistURIMap* aMap,
    1420             :     const nsACString& aRequestedContentType,
    1421             :     uint32_t aEncoderFlags,
    1422             :     uint32_t aWrapColumn,
    1423             :     nsIWebBrowserPersistWriteCompletion* aCompletion)
    1424             : {
    1425           0 :     NS_ENSURE_ARG_POINTER(aStream);
    1426           0 :     NS_ENSURE_ARG_POINTER(aCompletion);
    1427           0 :     nsAutoCString contentType(aRequestedContentType);
    1428           0 :     DecideContentType(contentType);
    1429             : 
    1430           0 :     nsCOMPtr<nsIDocumentEncoder> encoder;
    1431           0 :     nsresult rv = GetDocEncoder(contentType, aEncoderFlags,
    1432           0 :                                 getter_AddRefs(encoder));
    1433           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1434             : 
    1435           0 :     if (aWrapColumn != 0 && (aEncoderFlags
    1436           0 :                              & nsIWebBrowserPersist::ENCODE_FLAGS_WRAP)) {
    1437           0 :         encoder->SetWrapColumn(aWrapColumn);
    1438             :     }
    1439             : 
    1440           0 :     nsCOMPtr<nsIURI> targetURI;
    1441           0 :     if (aMap) {
    1442           0 :         nsAutoCString targetURISpec;
    1443           0 :         rv = aMap->GetTargetBaseURI(targetURISpec);
    1444           0 :         if (NS_SUCCEEDED(rv) && !targetURISpec.IsEmpty()) {
    1445           0 :             rv = NS_NewURI(getter_AddRefs(targetURI), targetURISpec,
    1446           0 :                            /* charset: */ nullptr, /* base: */ nullptr);
    1447           0 :             NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
    1448           0 :         } else if (mPersistFlags & nsIWebBrowserPersist::PERSIST_FLAGS_FIXUP_LINKS_TO_DESTINATION) {
    1449           0 :             return NS_ERROR_UNEXPECTED;
    1450             :         }
    1451             :     }
    1452           0 :     rv = encoder->SetNodeFixup(new PersistNodeFixup(this, aMap, targetURI));
    1453           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1454             : 
    1455           0 :     rv = encoder->EncodeToStream(aStream);
    1456           0 :     aCompletion->OnFinish(this, aStream, contentType, rv);
    1457           0 :     return NS_OK;
    1458             : }
    1459             : 
    1460             : } // namespace mozilla

Generated by: LCOV version 1.13