LCOV - code coverage report
Current view: top level - dom/html - nsHTMLDocument.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 285 1667 17.1 %
Date: 2017-07-14 16:53:18 Functions: 32 139 23.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsHTMLDocument.h"
       8             : 
       9             : #include "nsIContentPolicy.h"
      10             : #include "mozilla/DebugOnly.h"
      11             : #include "mozilla/dom/HTMLAllCollection.h"
      12             : #include "nsCOMPtr.h"
      13             : #include "nsGlobalWindow.h"
      14             : #include "nsXPIDLString.h"
      15             : #include "nsPrintfCString.h"
      16             : #include "nsReadableUtils.h"
      17             : #include "nsUnicharUtils.h"
      18             : #include "nsIHTMLContentSink.h"
      19             : #include "nsIXMLContentSink.h"
      20             : #include "nsHTMLParts.h"
      21             : #include "nsHTMLStyleSheet.h"
      22             : #include "nsGkAtoms.h"
      23             : #include "nsIPresShell.h"
      24             : #include "nsPresContext.h"
      25             : #include "nsIDOMNode.h" // for Find
      26             : #include "nsIDOMNodeList.h"
      27             : #include "nsIDOMElement.h"
      28             : #include "nsPIDOMWindow.h"
      29             : #include "nsDOMString.h"
      30             : #include "nsIStreamListener.h"
      31             : #include "nsIURI.h"
      32             : #include "nsIIOService.h"
      33             : #include "nsNetUtil.h"
      34             : #include "nsIPrivateBrowsingChannel.h"
      35             : #include "nsIContentViewerContainer.h"
      36             : #include "nsIContentViewer.h"
      37             : #include "nsDocShell.h"
      38             : #include "nsDocShellLoadTypes.h"
      39             : #include "nsIWebNavigation.h"
      40             : #include "nsIBaseWindow.h"
      41             : #include "nsIWebShellServices.h"
      42             : #include "nsIScriptContext.h"
      43             : #include "nsIXPConnect.h"
      44             : #include "nsContentList.h"
      45             : #include "nsError.h"
      46             : #include "nsIPrincipal.h"
      47             : #include "nsJSPrincipals.h"
      48             : #include "nsIScriptSecurityManager.h"
      49             : #include "nsAttrName.h"
      50             : #include "nsNodeUtils.h"
      51             : 
      52             : #include "nsNetCID.h"
      53             : #include "nsICookieService.h"
      54             : 
      55             : #include "nsIServiceManager.h"
      56             : #include "nsIConsoleService.h"
      57             : #include "nsIComponentManager.h"
      58             : #include "nsParserCIID.h"
      59             : #include "nsIDOMHTMLElement.h"
      60             : #include "nsIDOMHTMLHeadElement.h"
      61             : #include "nsNameSpaceManager.h"
      62             : #include "nsGenericHTMLElement.h"
      63             : #include "mozilla/css/Loader.h"
      64             : #include "nsIHttpChannel.h"
      65             : #include "nsIFile.h"
      66             : #include "nsFrameSelection.h"
      67             : #include "nsISelectionPrivate.h"//for toStringwithformat code
      68             : 
      69             : #include "nsContentUtils.h"
      70             : #include "nsJSUtils.h"
      71             : #include "nsIDocumentInlines.h"
      72             : #include "nsIDocumentEncoder.h" //for outputting selection
      73             : #include "nsICachingChannel.h"
      74             : #include "nsIContentViewer.h"
      75             : #include "nsIWyciwygChannel.h"
      76             : #include "nsIScriptElement.h"
      77             : #include "nsIScriptError.h"
      78             : #include "nsIMutableArray.h"
      79             : #include "nsArrayUtils.h"
      80             : #include "nsIEffectiveTLDService.h"
      81             : 
      82             : //AHMED 12-2
      83             : #include "nsBidiUtils.h"
      84             : 
      85             : #include "mozilla/dom/FallbackEncoding.h"
      86             : #include "mozilla/Encoding.h"
      87             : #include "mozilla/LoadInfo.h"
      88             : #include "nsIEditingSession.h"
      89             : #include "nsIEditor.h"
      90             : #include "nsNodeInfoManager.h"
      91             : #include "nsIPlaintextEditor.h"
      92             : #include "nsIHTMLEditor.h"
      93             : #include "nsIEditorStyleSheets.h"
      94             : #include "nsIInlineSpellChecker.h"
      95             : #include "nsRange.h"
      96             : #include "mozAutoDocUpdate.h"
      97             : #include "nsCCUncollectableMarker.h"
      98             : #include "nsHtml5Module.h"
      99             : #include "mozilla/dom/Element.h"
     100             : #include "mozilla/Preferences.h"
     101             : #include "nsMimeTypes.h"
     102             : #include "nsIRequest.h"
     103             : #include "nsHtml5TreeOpExecutor.h"
     104             : #include "nsHtml5Parser.h"
     105             : #include "nsSandboxFlags.h"
     106             : #include "nsIImageDocument.h"
     107             : #include "mozilla/dom/HTMLBodyElement.h"
     108             : #include "mozilla/dom/HTMLDocumentBinding.h"
     109             : #include "nsCharsetSource.h"
     110             : #include "nsIStringBundle.h"
     111             : #include "nsDOMClassInfo.h"
     112             : #include "nsFocusManager.h"
     113             : #include "nsIFrame.h"
     114             : #include "nsIContent.h"
     115             : #include "nsLayoutStylesheetCache.h"
     116             : #include "mozilla/StyleSheet.h"
     117             : #include "mozilla/StyleSheetInlines.h"
     118             : #include "mozilla/Unused.h"
     119             : 
     120             : using namespace mozilla;
     121             : using namespace mozilla::dom;
     122             : 
     123             : #define NS_MAX_DOCUMENT_WRITE_DEPTH 20
     124             : 
     125             : #include "prtime.h"
     126             : 
     127             : //#define DEBUG_charset
     128             : 
     129             : static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
     130             : 
     131             : uint32_t       nsHTMLDocument::gWyciwygSessionCnt = 0;
     132             : 
     133             : // this function will return false if the command is not recognized
     134             : // inCommandID will be converted as necessary for internal operations
     135             : // inParam will be converted as necessary for internal operations
     136             : // outParam will be Empty if no parameter is needed or if returning a boolean
     137             : // outIsBoolean will determine whether to send param as a boolean or string
     138             : // outBooleanParam will not be set unless outIsBoolean
     139             : static bool ConvertToMidasInternalCommand(const nsAString & inCommandID,
     140             :                                             const nsAString & inParam,
     141             :                                             nsACString& outCommandID,
     142             :                                             nsACString& outParam,
     143             :                                             bool& isBoolean,
     144             :                                             bool& boolValue);
     145             : 
     146             : static bool ConvertToMidasInternalCommand(const nsAString & inCommandID,
     147             :                                             nsACString& outCommandID);
     148             : 
     149             : // ==================================================================
     150             : // =
     151             : // ==================================================================
     152             : 
     153             : static bool
     154           1 : IsAsciiCompatible(const Encoding* aEncoding)
     155             : {
     156           1 :   return aEncoding->IsAsciiCompatible() || aEncoding == ISO_2022_JP_ENCODING;
     157             : }
     158             : 
     159             : nsresult
     160           7 : NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
     161             : {
     162          14 :   RefPtr<nsHTMLDocument> doc = new nsHTMLDocument();
     163             : 
     164           7 :   nsresult rv = doc->Init();
     165             : 
     166           7 :   if (NS_FAILED(rv)) {
     167           0 :     *aInstancePtrResult = nullptr;
     168           0 :     return rv;
     169             :   }
     170             : 
     171           7 :   doc->SetLoadedAsData(aLoadedAsData);
     172           7 :   doc.forget(aInstancePtrResult);
     173             : 
     174           7 :   return NS_OK;
     175             : }
     176             : 
     177           7 : nsHTMLDocument::nsHTMLDocument()
     178             :   : nsDocument("text/html")
     179             :   , mNumForms(0)
     180             :   , mWriteLevel(0)
     181             :   , mLoadFlags(0)
     182             :   , mTooDeepWriteRecursion(false)
     183             :   , mDisableDocWrite(false)
     184             :   , mWarnedWidthHeight(false)
     185             :   , mContentEditableCount(0)
     186             :   , mEditingState(EditingState::eOff)
     187             :   , mDisableCookieAccess(false)
     188           7 :   , mPendingMaybeEditingStateChanged(false)
     189             : {
     190           7 :   mType = eHTML;
     191           7 :   mDefaultElementType = kNameSpaceID_XHTML;
     192           7 :   mCompatMode = eCompatibility_NavQuirks;
     193           7 : }
     194             : 
     195           0 : nsHTMLDocument::~nsHTMLDocument()
     196             : {
     197           0 : }
     198             : 
     199          14 : NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHTMLDocument, nsDocument,
     200             :                                    mAll,
     201             :                                    mImages,
     202             :                                    mApplets,
     203             :                                    mEmbeds,
     204             :                                    mLinks,
     205             :                                    mAnchors,
     206             :                                    mScripts,
     207             :                                    mForms,
     208             :                                    mFormControls,
     209             :                                    mWyciwygChannel,
     210             :                                    mMidasCommandManager)
     211             : 
     212        2547 : NS_IMPL_ADDREF_INHERITED(nsHTMLDocument, nsDocument)
     213        2459 : NS_IMPL_RELEASE_INHERITED(nsHTMLDocument, nsDocument)
     214             : 
     215             : // QueryInterface implementation for nsHTMLDocument
     216        1660 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLDocument)
     217        1571 :   NS_INTERFACE_TABLE_INHERITED(nsHTMLDocument, nsIHTMLDocument,
     218             :                                nsIDOMHTMLDocument)
     219        1571 : NS_INTERFACE_TABLE_TAIL_INHERITING(nsDocument)
     220             : 
     221             : JSObject*
     222           7 : nsHTMLDocument::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     223             : {
     224           7 :   return HTMLDocumentBinding::Wrap(aCx, this, aGivenProto);
     225             : }
     226             : 
     227             : nsresult
     228           7 : nsHTMLDocument::Init()
     229             : {
     230           7 :   nsresult rv = nsDocument::Init();
     231           7 :   NS_ENSURE_SUCCESS(rv, rv);
     232             : 
     233             :   // Now reset the compatibility mode of the CSSLoader
     234             :   // to match our compat mode.
     235           7 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
     236             : 
     237           7 :   return NS_OK;
     238             : }
     239             : 
     240             : 
     241             : void
     242           3 : nsHTMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
     243             : {
     244           3 :   nsDocument::Reset(aChannel, aLoadGroup);
     245             : 
     246           3 :   if (aChannel) {
     247           3 :     aChannel->GetLoadFlags(&mLoadFlags);
     248             :   }
     249           3 : }
     250             : 
     251             : void
     252           7 : nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
     253             :                            nsIPrincipal* aPrincipal)
     254             : {
     255           7 :   mLoadFlags = nsIRequest::LOAD_NORMAL;
     256             : 
     257           7 :   nsDocument::ResetToURI(aURI, aLoadGroup, aPrincipal);
     258             : 
     259           7 :   mImages = nullptr;
     260           7 :   mApplets = nullptr;
     261           7 :   mEmbeds = nullptr;
     262           7 :   mLinks = nullptr;
     263           7 :   mAnchors = nullptr;
     264           7 :   mScripts = nullptr;
     265             : 
     266           7 :   mForms = nullptr;
     267             : 
     268           7 :   NS_ASSERTION(!mWyciwygChannel,
     269             :                "nsHTMLDocument::Reset() - Wyciwyg Channel  still exists!");
     270             : 
     271           7 :   mWyciwygChannel = nullptr;
     272             : 
     273             :   // Make the content type default to "text/html", we are a HTML
     274             :   // document, after all. Once we start getting data, this may be
     275             :   // changed.
     276           7 :   SetContentTypeInternal(nsDependentCString("text/html"));
     277           7 : }
     278             : 
     279             : void
     280           3 : nsHTMLDocument::TryHintCharset(nsIContentViewer* aCv,
     281             :                                int32_t& aCharsetSource,
     282             :                                NotNull<const Encoding*>& aEncoding)
     283             : {
     284           3 :   if (aCv) {
     285             :     int32_t requestCharsetSource;
     286           3 :     nsresult rv = aCv->GetHintCharacterSetSource(&requestCharsetSource);
     287             : 
     288           3 :     if(NS_SUCCEEDED(rv) && kCharsetUninitialized != requestCharsetSource) {
     289           0 :       auto requestCharset = aCv->GetHintCharset();
     290           0 :       aCv->SetHintCharacterSetSource((int32_t)(kCharsetUninitialized));
     291             : 
     292           0 :       if (requestCharsetSource <= aCharsetSource)
     293           0 :         return;
     294             : 
     295           0 :       if (requestCharset && IsAsciiCompatible(requestCharset)) {
     296           0 :         aCharsetSource = requestCharsetSource;
     297           0 :         aEncoding = WrapNotNull(requestCharset);
     298             :       }
     299           0 :       return;
     300             :     }
     301             :   }
     302           3 :   return;
     303             : }
     304             : 
     305             : 
     306             : void
     307           3 : nsHTMLDocument::TryUserForcedCharset(nsIContentViewer* aCv,
     308             :                                      nsIDocShell*  aDocShell,
     309             :                                      int32_t& aCharsetSource,
     310             :                                      NotNull<const Encoding*>& aEncoding)
     311             : {
     312           3 :   if(kCharsetFromUserForced <= aCharsetSource)
     313           0 :     return;
     314             : 
     315             :   // mCharacterSet not updated yet for channel, so check aEncoding, too.
     316           3 :   if (WillIgnoreCharsetOverride() || !IsAsciiCompatible(aEncoding)) {
     317           2 :     return;
     318             :   }
     319             : 
     320           1 :   const Encoding* forceCharsetFromDocShell = nullptr;
     321           1 :   if (aCv) {
     322             :     // XXX mailnews-only
     323           1 :     forceCharsetFromDocShell = aCv->GetForceCharset();
     324             :   }
     325             : 
     326           1 :   if(forceCharsetFromDocShell &&
     327           0 :      IsAsciiCompatible(forceCharsetFromDocShell)) {
     328           0 :     aEncoding = WrapNotNull(forceCharsetFromDocShell);
     329           0 :     aCharsetSource = kCharsetFromUserForced;
     330           0 :     return;
     331             :   }
     332             : 
     333           1 :   if (aDocShell) {
     334             :     // This is the Character Encoding menu code path in Firefox
     335           1 :     auto encoding = nsDocShell::Cast(aDocShell)->GetForcedCharset();
     336             : 
     337           1 :     if (encoding) {
     338           0 :       if (!IsAsciiCompatible(encoding)) {
     339           0 :         return;
     340             :       }
     341           0 :       aEncoding = WrapNotNull(encoding);
     342           0 :       aCharsetSource = kCharsetFromUserForced;
     343           0 :       aDocShell->SetForcedCharset(NS_LITERAL_CSTRING(""));
     344             :     }
     345             :   }
     346             : }
     347             : 
     348             : void
     349           0 : nsHTMLDocument::TryCacheCharset(nsICachingChannel* aCachingChannel,
     350             :                                 int32_t& aCharsetSource,
     351             :                                 NotNull<const Encoding*>& aEncoding)
     352             : {
     353             :   nsresult rv;
     354             : 
     355           0 :   if (kCharsetFromCache <= aCharsetSource) {
     356           0 :     return;
     357             :   }
     358             : 
     359           0 :   nsCString cachedCharset;
     360           0 :   rv = aCachingChannel->GetCacheTokenCachedCharset(cachedCharset);
     361           0 :   if (NS_FAILED(rv) || cachedCharset.IsEmpty()) {
     362           0 :     return;
     363             :   }
     364             :   // The replacement encoding is not ASCII-compatible.
     365           0 :   if (cachedCharset.EqualsLiteral("replacement")) {
     366           0 :     return;
     367             :   }
     368             :   // The canonical names changed, so the cache may have an old name.
     369           0 :   const Encoding* encoding = Encoding::ForLabel(cachedCharset);
     370           0 :   if (!encoding) {
     371           0 :     return;
     372             :   }
     373             :   // Check IsAsciiCompatible() even in the cache case, because the value
     374             :   // might be stale and in the case of a stale charset that is not a rough
     375             :   // ASCII superset, the parser has no way to recover.
     376           0 :   if (!encoding->IsAsciiCompatible() && encoding != ISO_2022_JP_ENCODING) {
     377           0 :     return;
     378             :   }
     379           0 :   aEncoding = WrapNotNull(encoding);
     380           0 :   aCharsetSource = kCharsetFromCache;
     381             : }
     382             : 
     383             : void
     384           3 : nsHTMLDocument::TryParentCharset(nsIDocShell*  aDocShell,
     385             :                                  int32_t& aCharsetSource,
     386             :                                  NotNull<const Encoding*>& aEncoding)
     387             : {
     388           3 :   if (!aDocShell) {
     389           3 :     return;
     390             :   }
     391           3 :   if (aCharsetSource >= kCharsetFromParentForced) {
     392           0 :     return;
     393             :   }
     394             : 
     395             :   int32_t parentSource;
     396             :   const Encoding* parentCharset;
     397           3 :   nsCOMPtr<nsIPrincipal> parentPrincipal;
     398           3 :   aDocShell->GetParentCharset(parentCharset,
     399             :                               &parentSource,
     400           6 :                               getter_AddRefs(parentPrincipal));
     401           3 :   if (!parentCharset) {
     402           3 :     return;
     403             :   }
     404           0 :   if (kCharsetFromParentForced == parentSource ||
     405           0 :       kCharsetFromUserForced == parentSource) {
     406           0 :     if (WillIgnoreCharsetOverride() ||
     407           0 :         !IsAsciiCompatible(aEncoding) || // if channel said UTF-16
     408           0 :         !IsAsciiCompatible(parentCharset)) {
     409           0 :       return;
     410             :     }
     411           0 :     aEncoding = WrapNotNull(parentCharset);
     412           0 :     aCharsetSource = kCharsetFromParentForced;
     413           0 :     return;
     414             :   }
     415             : 
     416           0 :   if (aCharsetSource >= kCharsetFromParentFrame) {
     417           0 :     return;
     418             :   }
     419             : 
     420           0 :   if (kCharsetFromCache <= parentSource) {
     421             :     // Make sure that's OK
     422           0 :     if (!NodePrincipal()->Equals(parentPrincipal) ||
     423           0 :         !IsAsciiCompatible(parentCharset)) {
     424           0 :       return;
     425             :     }
     426             : 
     427           0 :     aEncoding = WrapNotNull(parentCharset);
     428           0 :     aCharsetSource = kCharsetFromParentFrame;
     429             :   }
     430             : }
     431             : 
     432             : void
     433           3 : nsHTMLDocument::TryTLD(int32_t& aCharsetSource,
     434             :                        NotNull<const Encoding*>& aEncoding)
     435             : {
     436           3 :   if (aCharsetSource >= kCharsetFromTopLevelDomain) {
     437           4 :     return;
     438             :   }
     439           2 :   if (!FallbackEncoding::sGuessFallbackFromTopLevelDomain) {
     440           0 :     return;
     441             :   }
     442           2 :   if (!mDocumentURI) {
     443           0 :     return;
     444             :   }
     445           2 :   nsAutoCString host;
     446           2 :   mDocumentURI->GetAsciiHost(host);
     447           2 :   if (host.IsEmpty()) {
     448           0 :     return;
     449             :   }
     450             :   // First let's see if the host is DNS-absolute and ends with a dot and
     451             :   // get rid of that one.
     452           2 :   if (host.Last() == '.') {
     453           0 :     host.SetLength(host.Length() - 1);
     454           0 :     if (host.IsEmpty()) {
     455           0 :       return;
     456             :     }
     457             :   }
     458             :   // If we still have a dot, the host is weird, so let's continue only
     459             :   // if we have something other than a dot now.
     460           2 :   if (host.Last() == '.') {
     461           0 :     return;
     462             :   }
     463           2 :   int32_t index = host.RFindChar('.');
     464           2 :   if (index == kNotFound) {
     465             :     // We have an intranet host, Gecko-internal URL or an IPv6 address.
     466           2 :     return;
     467             :   }
     468             :   // Since the string didn't end with a dot and we found a dot,
     469             :   // there is at least one character between the dot and the end of
     470             :   // the string, so taking the substring below is safe.
     471           0 :   nsAutoCString tld;
     472           0 :   ToLowerCase(Substring(host, index + 1, host.Length() - (index + 1)), tld);
     473             :   // Reject generic TLDs and country TLDs that need more research
     474           0 :   if (!FallbackEncoding::IsParticipatingTopLevelDomain(tld)) {
     475           0 :     return;
     476             :   }
     477             :   // Check if we have an IPv4 address
     478           0 :   bool seenNonDigit = false;
     479           0 :   for (size_t i = 0; i < tld.Length(); ++i) {
     480           0 :     char c = tld.CharAt(i);
     481           0 :     if (c < '0' || c > '9') {
     482           0 :       seenNonDigit = true;
     483           0 :       break;
     484             :     }
     485             :   }
     486           0 :   if (!seenNonDigit) {
     487           0 :     return;
     488             :   }
     489           0 :   aCharsetSource = kCharsetFromTopLevelDomain;
     490           0 :   aEncoding = FallbackEncoding::FromTopLevelDomain(tld);
     491             : }
     492             : 
     493             : void
     494           3 : nsHTMLDocument::TryFallback(int32_t& aCharsetSource,
     495             :                             NotNull<const Encoding*>& aEncoding)
     496             : {
     497           3 :   if (kCharsetFromFallback <= aCharsetSource)
     498           1 :     return;
     499             : 
     500           2 :   aCharsetSource = kCharsetFromFallback;
     501           2 :   aEncoding = FallbackEncoding::FromLocale();
     502             : }
     503             : 
     504             : void
     505           9 : nsHTMLDocument::SetDocumentCharacterSet(NotNull<const Encoding*> aEncoding)
     506             : {
     507           9 :   nsDocument::SetDocumentCharacterSet(aEncoding);
     508             :   // Make sure to stash this charset on our channel as needed if it's a wyciwyg
     509             :   // channel.
     510          18 :   nsCOMPtr<nsIWyciwygChannel> wyciwygChannel = do_QueryInterface(mChannel);
     511           9 :   if (wyciwygChannel) {
     512           0 :     nsAutoCString charset;
     513           0 :     aEncoding->Name(charset);
     514           0 :     wyciwygChannel->SetCharsetAndSource(GetDocumentCharacterSetSource(),
     515           0 :                                         charset);
     516             :   }
     517           9 : }
     518             : 
     519             : nsresult
     520           3 : nsHTMLDocument::StartDocumentLoad(const char* aCommand,
     521             :                                   nsIChannel* aChannel,
     522             :                                   nsILoadGroup* aLoadGroup,
     523             :                                   nsISupports* aContainer,
     524             :                                   nsIStreamListener **aDocListener,
     525             :                                   bool aReset,
     526             :                                   nsIContentSink* aSink)
     527             : {
     528           3 :   if (!aCommand) {
     529           0 :     MOZ_ASSERT(false, "Command is mandatory");
     530             :     return NS_ERROR_INVALID_POINTER;
     531             :   }
     532           3 :   if (aSink) {
     533           0 :     MOZ_ASSERT(false, "Got a sink override. Should not happen for HTML doc.");
     534             :     return NS_ERROR_INVALID_ARG;
     535             :   }
     536           3 :   if (mType != eHTML) {
     537           0 :     MOZ_ASSERT(mType == eXHTML);
     538           0 :     MOZ_ASSERT(false, "Must not set HTML doc to XHTML mode before load start.");
     539             :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     540             :   }
     541             : 
     542           6 :   nsAutoCString contentType;
     543           3 :   aChannel->GetContentType(contentType);
     544             : 
     545           3 :   bool view = !strcmp(aCommand, "view") ||
     546           3 :               !strcmp(aCommand, "external-resource");
     547           3 :   bool viewSource = !strcmp(aCommand, "view-source");
     548           3 :   bool asData = !strcmp(aCommand, kLoadAsData);
     549           3 :   if (!(view || viewSource || asData)) {
     550           0 :     MOZ_ASSERT(false, "Bad parser command");
     551             :     return NS_ERROR_INVALID_ARG;
     552             :   }
     553             : 
     554           3 :   bool html = contentType.EqualsLiteral(TEXT_HTML);
     555           3 :   bool xhtml = !html && (contentType.EqualsLiteral(APPLICATION_XHTML_XML) || contentType.EqualsLiteral(APPLICATION_WAPXHTML_XML));
     556           3 :   bool plainText = !html && !xhtml && nsContentUtils::IsPlainTextType(contentType);
     557           3 :   if (!(html || xhtml || plainText || viewSource)) {
     558           0 :     MOZ_ASSERT(false, "Channel with bad content type.");
     559             :     return NS_ERROR_INVALID_ARG;
     560             :   }
     561             : 
     562           3 :   bool forceUtf8 = plainText &&
     563           3 :     nsContentUtils::IsUtf8OnlyPlainTextType(contentType);
     564             : 
     565           3 :   bool loadAsHtml5 = true;
     566             : 
     567           3 :   if (!viewSource && xhtml) {
     568             :       // We're parsing XHTML as XML, remember that.
     569           0 :       mType = eXHTML;
     570           0 :       mCompatMode = eCompatibility_FullStandards;
     571           0 :       loadAsHtml5 = false;
     572             :   }
     573             : 
     574             :   // TODO: Proper about:blank treatment is bug 543435
     575           3 :   if (loadAsHtml5 && view) {
     576             :     // mDocumentURI hasn't been set, yet, so get the URI from the channel
     577           6 :     nsCOMPtr<nsIURI> uri;
     578           3 :     aChannel->GetOriginalURI(getter_AddRefs(uri));
     579             :     // Adapted from nsDocShell:
     580             :     // GetSpec can be expensive for some URIs, so check the scheme first.
     581           3 :     bool isAbout = false;
     582           3 :     if (uri && NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)) && isAbout) {
     583           1 :       if (uri->GetSpecOrDefault().EqualsLiteral("about:blank")) {
     584           1 :         loadAsHtml5 = false;
     585             :       }
     586             :     }
     587             :   }
     588             : 
     589           3 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
     590             : 
     591           3 :   nsresult rv = nsDocument::StartDocumentLoad(aCommand,
     592             :                                               aChannel, aLoadGroup,
     593             :                                               aContainer,
     594           3 :                                               aDocListener, aReset);
     595           3 :   if (NS_FAILED(rv)) {
     596           0 :     return rv;
     597             :   }
     598             : 
     599             :   // Store the security info for future use with wyciwyg channels.
     600           3 :   aChannel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
     601             : 
     602           6 :   nsCOMPtr<nsIURI> uri;
     603           3 :   rv = aChannel->GetURI(getter_AddRefs(uri));
     604           3 :   if (NS_FAILED(rv)) {
     605           0 :     return rv;
     606             :   }
     607             : 
     608           6 :   nsCOMPtr<nsICachingChannel> cachingChan = do_QueryInterface(aChannel);
     609             : 
     610           3 :   if (loadAsHtml5) {
     611           2 :     mParser = nsHtml5Module::NewHtml5Parser();
     612           2 :     if (plainText) {
     613           0 :       if (viewSource) {
     614           0 :         mParser->MarkAsNotScriptCreated("view-source-plain");
     615             :       } else {
     616           0 :         mParser->MarkAsNotScriptCreated("plain-text");
     617             :       }
     618           2 :     } else if (viewSource && !html) {
     619           0 :       mParser->MarkAsNotScriptCreated("view-source-xml");
     620             :     } else {
     621           2 :       mParser->MarkAsNotScriptCreated(aCommand);
     622             :     }
     623             :   } else {
     624           1 :     mParser = do_CreateInstance(kCParserCID, &rv);
     625           1 :     NS_ENSURE_SUCCESS(rv, rv);
     626             :   }
     627             : 
     628             :   // Look for the parent document.  Note that at this point we don't have our
     629             :   // content viewer set up yet, and therefore do not have a useful
     630             :   // mParentDocument.
     631             : 
     632             :   // in this block of code, if we get an error result, we return it
     633             :   // but if we get a null pointer, that's perfectly legal for parent
     634             :   // and parentContentViewer
     635           6 :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
     636           6 :   nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
     637           3 :   if (docShell) {
     638           3 :     docShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
     639             :   }
     640             : 
     641           6 :   nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
     642           6 :   nsCOMPtr<nsIContentViewer> parentContentViewer;
     643           3 :   if (parent) {
     644           1 :     rv = parent->GetContentViewer(getter_AddRefs(parentContentViewer));
     645           1 :     NS_ENSURE_SUCCESS(rv, rv);
     646             :   }
     647             : 
     648           6 :   nsCOMPtr<nsIContentViewer> cv;
     649           3 :   if (docShell) {
     650           3 :     docShell->GetContentViewer(getter_AddRefs(cv));
     651             :   }
     652           3 :   if (!cv) {
     653           1 :     cv = parentContentViewer.forget();
     654             :   }
     655             : 
     656           6 :   nsAutoCString urlSpec;
     657           3 :   uri->GetSpec(urlSpec);
     658             : #ifdef DEBUG_charset
     659             :   printf("Determining charset for %s\n", urlSpec.get());
     660             : #endif
     661             : 
     662             :   // These are the charset source and charset for our document
     663             :   int32_t charsetSource;
     664           3 :   auto encoding = UTF_8_ENCODING;
     665             : 
     666             :   // These are the charset source and charset for the parser.  This can differ
     667             :   // from that for the document if the channel is a wyciwyg channel.
     668             :   int32_t parserCharsetSource;
     669           3 :   auto parserCharset = UTF_8_ENCODING;
     670             : 
     671           6 :   nsCOMPtr<nsIWyciwygChannel> wyciwygChannel;
     672             : 
     673             :   // For error reporting and referrer policy setting
     674           3 :   nsHtml5TreeOpExecutor* executor = nullptr;
     675           3 :   if (loadAsHtml5) {
     676           2 :     executor = static_cast<nsHtml5TreeOpExecutor*> (mParser->GetContentSink());
     677           2 :     if (mReferrerPolicySet) {
     678             :       // CSP may have set the referrer policy, so a speculative parser should
     679             :       // start with the new referrer policy.
     680           0 :       executor->SetSpeculationReferrerPolicy(static_cast<ReferrerPolicy>(mReferrerPolicy));
     681             :     }
     682             :   }
     683             : 
     684           3 :   if (forceUtf8) {
     685           0 :     charsetSource = kCharsetFromUtf8OnlyMime;
     686           0 :     parserCharsetSource = charsetSource;
     687           3 :   } else if (!IsHTMLDocument() || !docShell) { // no docshell for text/html XHR
     688           0 :     charsetSource = IsHTMLDocument() ? kCharsetFromFallback
     689             :                                      : kCharsetFromDocTypeDefault;
     690           0 :     TryChannelCharset(aChannel, charsetSource, encoding, executor);
     691           0 :     parserCharset = encoding;
     692           0 :     parserCharsetSource = charsetSource;
     693             :   } else {
     694           3 :     NS_ASSERTION(docShell, "Unexpected null value");
     695             : 
     696           3 :     charsetSource = kCharsetUninitialized;
     697           3 :     wyciwygChannel = do_QueryInterface(aChannel);
     698             : 
     699             :     // The following will try to get the character encoding from various
     700             :     // sources. Each Try* function will return early if the source is already
     701             :     // at least as large as any of the sources it might look at.  Some of
     702             :     // these functions (like TryHintCharset and TryParentCharset) can set
     703             :     // charsetSource to various values depending on where the charset they
     704             :     // end up finding originally comes from.
     705             : 
     706             :     // Don't actually get the charset from the channel if this is a
     707             :     // wyciwyg channel; it'll always be UTF-16
     708           3 :     if (!wyciwygChannel) {
     709             :       // Otherwise, try the channel's charset (e.g., charset from HTTP
     710             :       // "Content-Type" header) first. This way, we get to reject overrides in
     711             :       // TryParentCharset and TryUserForcedCharset if the channel said UTF-16.
     712             :       // This is to avoid socially engineered XSS by adding user-supplied
     713             :       // content to a UTF-16 site such that the byte have a dangerous
     714             :       // interpretation as ASCII and the user can be lured to using the
     715             :       // charset menu.
     716           3 :       TryChannelCharset(aChannel, charsetSource, encoding, executor);
     717             :     }
     718             : 
     719           3 :     TryUserForcedCharset(cv, docShell, charsetSource, encoding);
     720             : 
     721           3 :     TryHintCharset(cv, charsetSource, encoding); // XXX mailnews-only
     722           3 :     TryParentCharset(docShell, charsetSource, encoding);
     723             : 
     724           3 :     if (cachingChan && !urlSpec.IsEmpty()) {
     725           0 :       TryCacheCharset(cachingChan, charsetSource, encoding);
     726             :     }
     727             : 
     728           3 :     TryTLD(charsetSource, encoding);
     729           3 :     TryFallback(charsetSource, encoding);
     730             : 
     731           3 :     if (wyciwygChannel) {
     732             :       // We know for sure that the parser needs to be using UTF16.
     733           0 :       parserCharset = UTF_16LE_ENCODING;
     734           0 :       parserCharsetSource = charsetSource < kCharsetFromChannel ?
     735             :         kCharsetFromChannel : charsetSource;
     736             : 
     737           0 :       nsAutoCString cachedCharset;
     738             :       int32_t cachedSource;
     739           0 :       rv = wyciwygChannel->GetCharsetAndSource(&cachedSource, cachedCharset);
     740           0 :       if (NS_SUCCEEDED(rv)) {
     741           0 :         if (cachedSource > charsetSource) {
     742           0 :           auto cachedEncoding = Encoding::ForLabel(cachedCharset);
     743           0 :           if (!cachedEncoding && cachedCharset.EqualsLiteral("replacement")) {
     744           0 :             cachedEncoding = REPLACEMENT_ENCODING;
     745             :           }
     746           0 :           if (cachedEncoding) {
     747           0 :             charsetSource = cachedSource;
     748           0 :             encoding = WrapNotNull(cachedEncoding);
     749             :           }
     750             :         }
     751             :       } else {
     752             :         // Don't propagate this error.
     753           0 :         rv = NS_OK;
     754             :       }
     755             :     } else {
     756           3 :       parserCharset = encoding;
     757           3 :       parserCharsetSource = charsetSource;
     758             :     }
     759             :   }
     760             : 
     761           3 :   SetDocumentCharacterSetSource(charsetSource);
     762           3 :   SetDocumentCharacterSet(encoding);
     763             : 
     764           3 :   if (cachingChan) {
     765           0 :     NS_ASSERTION(encoding == parserCharset,
     766             :                  "How did those end up different here?  wyciwyg channels are "
     767             :                  "not nsICachingChannel");
     768           0 :     nsAutoCString charset;
     769           0 :     encoding->Name(charset);
     770           0 :     rv = cachingChan->SetCacheTokenCachedCharset(charset);
     771           0 :     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "cannot SetMetaDataElement");
     772           0 :     rv = NS_OK; // don't propagate error
     773             :   }
     774             : 
     775             :   // Set the parser as the stream listener for the document loader...
     776           3 :   rv = NS_OK;
     777           6 :   nsCOMPtr<nsIStreamListener> listener = mParser->GetStreamListener();
     778           3 :   listener.forget(aDocListener);
     779             : 
     780             : #ifdef DEBUG_charset
     781             :   printf(" charset = %s source %d\n",
     782             :          charset.get(), charsetSource);
     783             : #endif
     784           3 :   mParser->SetDocumentCharset(parserCharset, parserCharsetSource);
     785           3 :   mParser->SetCommand(aCommand);
     786             : 
     787           3 :   if (!IsHTMLDocument()) {
     788           0 :     MOZ_ASSERT(!loadAsHtml5);
     789           0 :     nsCOMPtr<nsIXMLContentSink> xmlsink;
     790           0 :     NS_NewXMLContentSink(getter_AddRefs(xmlsink), this, uri,
     791           0 :                          docShell, aChannel);
     792           0 :     mParser->SetContentSink(xmlsink);
     793             :   } else {
     794           3 :     if (loadAsHtml5) {
     795           2 :       nsHtml5Module::Initialize(mParser, this, uri, docShell, aChannel);
     796             :     } else {
     797             :       // about:blank *only*
     798           2 :       nsCOMPtr<nsIHTMLContentSink> htmlsink;
     799           2 :       NS_NewHTMLContentSink(getter_AddRefs(htmlsink), this, uri,
     800           2 :                             docShell, aChannel);
     801           1 :       mParser->SetContentSink(htmlsink);
     802             :     }
     803             :   }
     804             : 
     805           3 :   if (plainText && !nsContentUtils::IsChildOfSameType(this) &&
     806           0 :       Preferences::GetBool("plain_text.wrap_long_lines")) {
     807           0 :     nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
     808           0 :     NS_ASSERTION(NS_SUCCEEDED(rv) && bundleService, "The bundle service could not be loaded");
     809           0 :     nsCOMPtr<nsIStringBundle> bundle;
     810           0 :     rv = bundleService->CreateBundle("chrome://global/locale/browser.properties",
     811           0 :                                      getter_AddRefs(bundle));
     812           0 :     NS_ASSERTION(NS_SUCCEEDED(rv) && bundle, "chrome://global/locale/browser.properties could not be loaded");
     813           0 :     nsXPIDLString title;
     814           0 :     if (bundle) {
     815           0 :       bundle->GetStringFromName(u"plainText.wordWrap", getter_Copies(title));
     816             :     }
     817           0 :     SetSelectedStyleSheetSet(title);
     818             :   }
     819             : 
     820             :   // parser the content of the URI
     821           3 :   mParser->Parse(uri, nullptr, (void *)this);
     822             : 
     823           3 :   return rv;
     824             : }
     825             : 
     826             : void
     827           4 : nsHTMLDocument::StopDocumentLoad()
     828             : {
     829           4 :   BlockOnload();
     830             : 
     831             :   // Remove the wyciwyg channel request from the document load group
     832             :   // that we added in Open() if Open() was called on this doc.
     833           4 :   RemoveWyciwygChannel();
     834           4 :   NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::StopDocumentLoad(): "
     835             :                "nsIWyciwygChannel could not be removed!");
     836             : 
     837           4 :   nsDocument::StopDocumentLoad();
     838           4 :   UnblockOnload(false);
     839           4 :   return;
     840             : }
     841             : 
     842             : void
     843           3 : nsHTMLDocument::BeginLoad()
     844             : {
     845           3 :   if (IsEditingOn()) {
     846             :     // Reset() blows away all event listeners in the document, and our
     847             :     // editor relies heavily on those. Midas is turned on, to make it
     848             :     // work, re-initialize it to give it a chance to add its event
     849             :     // listeners again.
     850             : 
     851           0 :     TurnEditingOff();
     852           0 :     EditingStateChanged();
     853             :   }
     854           3 :   nsDocument::BeginLoad();
     855           3 : }
     856             : 
     857             : void
     858           3 : nsHTMLDocument::EndLoad()
     859             : {
     860             :   bool turnOnEditing =
     861           3 :     mParser && (HasFlag(NODE_IS_EDITABLE) || mContentEditableCount > 0);
     862             :   // Note: nsDocument::EndLoad nulls out mParser.
     863           3 :   nsDocument::EndLoad();
     864           3 :   if (turnOnEditing) {
     865           0 :     EditingStateChanged();
     866             :   }
     867           3 : }
     868             : 
     869             : void
     870           3 : nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode)
     871             : {
     872           3 :   NS_ASSERTION(IsHTMLDocument() || aMode == eCompatibility_FullStandards,
     873             :                "Bad compat mode for XHTML document!");
     874             : 
     875           3 :   mCompatMode = aMode;
     876           3 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
     877           6 :   nsCOMPtr<nsIPresShell> shell = GetShell();
     878           3 :   if (shell) {
     879           2 :     nsPresContext *pc = shell->GetPresContext();
     880           2 :     if (pc) {
     881           2 :       pc->CompatibilityModeChanged();
     882             :     }
     883             :   }
     884           3 : }
     885             : 
     886             : //
     887             : // nsIDOMHTMLDocument interface implementation
     888             : //
     889             : already_AddRefed<nsIURI>
     890           0 : nsHTMLDocument::GetDomainURI()
     891             : {
     892           0 :   nsIPrincipal* principal = NodePrincipal();
     893             : 
     894           0 :   nsCOMPtr<nsIURI> uri;
     895           0 :   principal->GetDomain(getter_AddRefs(uri));
     896           0 :   if (uri) {
     897           0 :     return uri.forget();
     898             :   }
     899             : 
     900           0 :   principal->GetURI(getter_AddRefs(uri));
     901           0 :   return uri.forget();
     902             : }
     903             : 
     904             : 
     905             : NS_IMETHODIMP
     906           0 : nsHTMLDocument::GetDomain(nsAString& aDomain)
     907             : {
     908           0 :   nsCOMPtr<nsIURI> uri = GetDomainURI();
     909             : 
     910           0 :   if (!uri) {
     911           0 :     SetDOMStringToNull(aDomain);
     912           0 :     return NS_OK;
     913             :   }
     914             : 
     915           0 :   nsAutoCString hostName;
     916           0 :   nsresult rv = nsContentUtils::GetHostOrIPv6WithBrackets(uri, hostName);
     917           0 :   if (NS_SUCCEEDED(rv)) {
     918           0 :     CopyUTF8toUTF16(hostName, aDomain);
     919             :   } else {
     920             :     // If we can't get the host from the URI (e.g. about:, javascript:,
     921             :     // etc), just return an null string.
     922           0 :     SetDOMStringToNull(aDomain);
     923             :   }
     924           0 :   return NS_OK;
     925             : }
     926             : 
     927             : already_AddRefed<nsIURI>
     928           0 : nsHTMLDocument::CreateInheritingURIForHost(const nsACString& aHostString)
     929             : {
     930           0 :   if (aHostString.IsEmpty()) {
     931           0 :     return nullptr;
     932             :   }
     933             : 
     934             :   // Create new URI
     935           0 :   nsCOMPtr<nsIURI> uri = GetDomainURI();
     936           0 :   if (!uri) {
     937           0 :     return nullptr;
     938             :   }
     939             : 
     940           0 :   nsCOMPtr<nsIURI> newURI;
     941           0 :   nsresult rv = uri->Clone(getter_AddRefs(newURI));
     942           0 :   if (NS_FAILED(rv)) {
     943           0 :     return nullptr;
     944             :   }
     945             : 
     946           0 :   rv = newURI->SetUserPass(EmptyCString());
     947           0 :   if (NS_FAILED(rv)) {
     948           0 :     return nullptr;
     949             :   }
     950             : 
     951             :   // We use SetHostAndPort because we want to reset the port number if needed.
     952           0 :   rv = newURI->SetHostAndPort(aHostString);
     953           0 :   if (NS_FAILED(rv)) {
     954           0 :     return nullptr;
     955             :   }
     956             : 
     957           0 :   return newURI.forget();
     958             : }
     959             : 
     960             : already_AddRefed<nsIURI>
     961           0 : nsHTMLDocument::RegistrableDomainSuffixOfInternal(const nsAString& aNewDomain,
     962             :                                                   nsIURI* aOrigHost)
     963             : {
     964           0 :   if (NS_WARN_IF(!aOrigHost)) {
     965           0 :     return nullptr;
     966             :   }
     967             : 
     968           0 :   nsCOMPtr<nsIURI> newURI = CreateInheritingURIForHost(NS_ConvertUTF16toUTF8(aNewDomain));
     969           0 :   if (!newURI) {
     970             :     // Error: failed to parse input domain
     971           0 :     return nullptr;
     972             :   }
     973             : 
     974             :   // Check new domain - must be a superdomain of the current host
     975             :   // For example, a page from foo.bar.com may set domain to bar.com,
     976             :   // but not to ar.com, baz.com, or fi.foo.bar.com.
     977           0 :   nsAutoCString current;
     978           0 :   nsAutoCString domain;
     979           0 :   if (NS_FAILED(aOrigHost->GetAsciiHost(current))) {
     980           0 :     current.Truncate();
     981             :   }
     982           0 :   if (NS_FAILED(newURI->GetAsciiHost(domain))) {
     983           0 :     domain.Truncate();
     984             :   }
     985             : 
     986           0 :   bool ok = current.Equals(domain);
     987           0 :   if (current.Length() > domain.Length() &&
     988           0 :       StringEndsWith(current, domain) &&
     989           0 :       current.CharAt(current.Length() - domain.Length() - 1) == '.') {
     990             :     // We're golden if the new domain is the current page's base domain or a
     991             :     // subdomain of it.
     992             :     nsCOMPtr<nsIEffectiveTLDService> tldService =
     993           0 :       do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
     994           0 :     if (!tldService) {
     995           0 :       return nullptr;
     996             :     }
     997             : 
     998           0 :     nsAutoCString currentBaseDomain;
     999           0 :     ok = NS_SUCCEEDED(tldService->GetBaseDomain(aOrigHost, 0, currentBaseDomain));
    1000           0 :     NS_ASSERTION(StringEndsWith(domain, currentBaseDomain) ==
    1001             :                  (domain.Length() >= currentBaseDomain.Length()),
    1002             :                  "uh-oh!  slight optimization wasn't valid somehow!");
    1003           0 :     ok = ok && domain.Length() >= currentBaseDomain.Length();
    1004             :   }
    1005             : 
    1006           0 :   if (!ok) {
    1007             :     // Error: illegal domain
    1008           0 :     return nullptr;
    1009             :   }
    1010             : 
    1011           0 :   return CreateInheritingURIForHost(domain);
    1012             : }
    1013             : 
    1014             : bool
    1015           0 : nsHTMLDocument::IsRegistrableDomainSuffixOfOrEqualTo(const nsAString& aHostSuffixString,
    1016             :                                                      const nsACString& aOrigHost)
    1017             : {
    1018             :   // https://html.spec.whatwg.org/multipage/browsers.html#is-a-registrable-domain-suffix-of-or-is-equal-to
    1019           0 :   if (aHostSuffixString.IsEmpty()) {
    1020           0 :     return false;
    1021             :   }
    1022             : 
    1023           0 :   nsCOMPtr<nsIURI> origURI = CreateInheritingURIForHost(aOrigHost);
    1024           0 :   if (!origURI) {
    1025             :     // Error: failed to parse input domain
    1026           0 :     return false;
    1027             :   }
    1028             : 
    1029           0 :   nsCOMPtr<nsIURI> newURI = RegistrableDomainSuffixOfInternal(aHostSuffixString, origURI);
    1030           0 :   if (!newURI) {
    1031             :     // Error: illegal domain
    1032           0 :     return false;
    1033             :   }
    1034           0 :   return true;
    1035             : }
    1036             : 
    1037             : 
    1038             : NS_IMETHODIMP
    1039           0 : nsHTMLDocument::SetDomain(const nsAString& aDomain)
    1040             : {
    1041           0 :   ErrorResult rv;
    1042           0 :   SetDomain(aDomain, rv);
    1043           0 :   return rv.StealNSResult();
    1044             : }
    1045             : 
    1046             : void
    1047           0 : nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv)
    1048             : {
    1049           0 :   if (mSandboxFlags & SANDBOXED_DOMAIN) {
    1050             :     // We're sandboxed; disallow setting domain
    1051           0 :     rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    1052           0 :     return;
    1053             :   }
    1054             : 
    1055           0 :   if (aDomain.IsEmpty()) {
    1056           0 :     rv.Throw(NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN);
    1057           0 :     return;
    1058             :   }
    1059             : 
    1060           0 :   nsCOMPtr<nsIURI> uri = GetDomainURI();
    1061           0 :   if (!uri) {
    1062           0 :     rv.Throw(NS_ERROR_FAILURE);
    1063           0 :     return;
    1064             :   }
    1065             : 
    1066             :   // Check new domain - must be a superdomain of the current host
    1067             :   // For example, a page from foo.bar.com may set domain to bar.com,
    1068             :   // but not to ar.com, baz.com, or fi.foo.bar.com.
    1069             : 
    1070           0 :   nsCOMPtr<nsIURI> newURI = RegistrableDomainSuffixOfInternal(aDomain, uri);
    1071           0 :   if (!newURI) {
    1072             :     // Error: illegal domain
    1073           0 :     rv.Throw(NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN);
    1074           0 :     return;
    1075             :   }
    1076             : 
    1077           0 :   NS_TryToSetImmutable(newURI);
    1078           0 :   rv = NodePrincipal()->SetDomain(newURI);
    1079             : }
    1080             : 
    1081             : nsGenericHTMLElement*
    1082           6 : nsHTMLDocument::GetBody()
    1083             : {
    1084           6 :   Element* html = GetHtmlElement();
    1085           6 :   if (!html) {
    1086           0 :     return nullptr;
    1087             :   }
    1088             : 
    1089          12 :   for (nsIContent* child = html->GetFirstChild();
    1090          12 :        child;
    1091           6 :        child = child->GetNextSibling()) {
    1092          18 :     if (child->IsHTMLElement(nsGkAtoms::body) ||
    1093           6 :         child->IsHTMLElement(nsGkAtoms::frameset)) {
    1094           6 :       return static_cast<nsGenericHTMLElement*>(child);
    1095             :     }
    1096             :   }
    1097             : 
    1098           0 :   return nullptr;
    1099             : }
    1100             : 
    1101             : NS_IMETHODIMP
    1102           4 : nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
    1103             : {
    1104           4 :   *aBody = nullptr;
    1105             : 
    1106           4 :   nsIContent *body = GetBody();
    1107             : 
    1108           4 :   return body ? CallQueryInterface(body, aBody) : NS_OK;
    1109             : }
    1110             : 
    1111             : NS_IMETHODIMP
    1112           0 : nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody)
    1113             : {
    1114           0 :   nsCOMPtr<nsIContent> newBody = do_QueryInterface(aBody);
    1115           0 :   MOZ_ASSERT(!newBody || newBody->IsHTMLElement(),
    1116             :              "How could we be an nsIContent but not actually HTML here?");
    1117           0 :   ErrorResult rv;
    1118           0 :   SetBody(static_cast<nsGenericHTMLElement*>(newBody.get()), rv);
    1119           0 :   return rv.StealNSResult();
    1120             : }
    1121             : 
    1122             : void
    1123           0 : nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
    1124             : {
    1125           0 :   nsCOMPtr<Element> root = GetRootElement();
    1126             : 
    1127             :   // The body element must be either a body tag or a frameset tag. And we must
    1128             :   // have a html root tag, otherwise GetBody will not return the newly set
    1129             :   // body.
    1130           0 :   if (!newBody ||
    1131           0 :       !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) ||
    1132           0 :       !root || !root->IsHTMLElement() ||
    1133           0 :       !root->IsHTMLElement(nsGkAtoms::html)) {
    1134           0 :     rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
    1135           0 :     return;
    1136             :   }
    1137             : 
    1138             :   // Use DOM methods so that we pass through the appropriate security checks.
    1139           0 :   nsCOMPtr<Element> currentBody = GetBodyElement();
    1140           0 :   if (currentBody) {
    1141           0 :     root->ReplaceChild(*newBody, *currentBody, rv);
    1142             :   } else {
    1143           0 :     root->AppendChild(*newBody, rv);
    1144             :   }
    1145             : }
    1146             : 
    1147             : NS_IMETHODIMP
    1148           0 : nsHTMLDocument::GetHead(nsIDOMHTMLHeadElement** aHead)
    1149             : {
    1150           0 :   *aHead = nullptr;
    1151             : 
    1152           0 :   Element* head = GetHeadElement();
    1153             : 
    1154           0 :   return head ? CallQueryInterface(head, aHead) : NS_OK;
    1155             : }
    1156             : 
    1157             : NS_IMETHODIMP
    1158           0 : nsHTMLDocument::GetImages(nsIDOMHTMLCollection** aImages)
    1159             : {
    1160           0 :   NS_ADDREF(*aImages = Images());
    1161           0 :   return NS_OK;
    1162             : }
    1163             : 
    1164             : nsIHTMLCollection*
    1165           0 : nsHTMLDocument::Images()
    1166             : {
    1167           0 :   if (!mImages) {
    1168           0 :     mImages = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::img, nsGkAtoms::img);
    1169             :   }
    1170           0 :   return mImages;
    1171             : }
    1172             : 
    1173             : NS_IMETHODIMP
    1174           0 : nsHTMLDocument::GetApplets(nsIDOMHTMLCollection** aApplets)
    1175             : {
    1176           0 :   NS_ADDREF(*aApplets = Applets());
    1177           0 :   return NS_OK;
    1178             : }
    1179             : 
    1180             : nsIHTMLCollection*
    1181           0 : nsHTMLDocument::Applets()
    1182             : {
    1183           0 :   if (!mApplets) {
    1184           0 :     mApplets = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::applet, nsGkAtoms::applet);
    1185             :   }
    1186           0 :   return mApplets;
    1187             : }
    1188             : 
    1189             : bool
    1190           0 : nsHTMLDocument::MatchLinks(Element* aElement, int32_t aNamespaceID,
    1191             :                            nsIAtom* aAtom, void* aData)
    1192             : {
    1193           0 :   nsIDocument* doc = aElement->GetUncomposedDoc();
    1194             : 
    1195           0 :   if (doc) {
    1196           0 :     NS_ASSERTION(aElement->IsInUncomposedDoc(),
    1197             :                  "This method should never be called on content nodes that "
    1198             :                  "are not in a document!");
    1199             : #ifdef DEBUG
    1200             :     {
    1201             :       nsCOMPtr<nsIHTMLDocument> htmldoc =
    1202           0 :         do_QueryInterface(aElement->GetUncomposedDoc());
    1203           0 :       NS_ASSERTION(htmldoc,
    1204             :                    "Huh, how did this happen? This should only be used with "
    1205             :                    "HTML documents!");
    1206             :     }
    1207             : #endif
    1208             : 
    1209           0 :     mozilla::dom::NodeInfo *ni = aElement->NodeInfo();
    1210             : 
    1211           0 :     nsIAtom *localName = ni->NameAtom();
    1212           0 :     if (ni->NamespaceID() == kNameSpaceID_XHTML &&
    1213           0 :         (localName == nsGkAtoms::a || localName == nsGkAtoms::area)) {
    1214           0 :       return aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
    1215             :     }
    1216             :   }
    1217             : 
    1218           0 :   return false;
    1219             : }
    1220             : 
    1221             : NS_IMETHODIMP
    1222           0 : nsHTMLDocument::GetLinks(nsIDOMHTMLCollection** aLinks)
    1223             : {
    1224           0 :   NS_ADDREF(*aLinks = Links());
    1225           0 :   return NS_OK;
    1226             : }
    1227             : 
    1228             : nsIHTMLCollection*
    1229           0 : nsHTMLDocument::Links()
    1230             : {
    1231           0 :   if (!mLinks) {
    1232           0 :     mLinks = new nsContentList(this, MatchLinks, nullptr, nullptr);
    1233             :   }
    1234           0 :   return mLinks;
    1235             : }
    1236             : 
    1237             : bool
    1238           0 : nsHTMLDocument::MatchAnchors(Element* aElement, int32_t aNamespaceID,
    1239             :                              nsIAtom* aAtom, void* aData)
    1240             : {
    1241           0 :   NS_ASSERTION(aElement->IsInUncomposedDoc(),
    1242             :                "This method should never be called on content nodes that "
    1243             :                "are not in a document!");
    1244             : #ifdef DEBUG
    1245             :   {
    1246             :     nsCOMPtr<nsIHTMLDocument> htmldoc =
    1247           0 :       do_QueryInterface(aElement->GetUncomposedDoc());
    1248           0 :     NS_ASSERTION(htmldoc,
    1249             :                  "Huh, how did this happen? This should only be used with "
    1250             :                  "HTML documents!");
    1251             :   }
    1252             : #endif
    1253             : 
    1254           0 :   if (aElement->IsHTMLElement(nsGkAtoms::a)) {
    1255           0 :     return aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::name);
    1256             :   }
    1257             : 
    1258           0 :   return false;
    1259             : }
    1260             : 
    1261             : NS_IMETHODIMP
    1262           0 : nsHTMLDocument::GetAnchors(nsIDOMHTMLCollection** aAnchors)
    1263             : {
    1264           0 :   NS_ADDREF(*aAnchors = Anchors());
    1265           0 :   return NS_OK;
    1266             : }
    1267             : 
    1268             : nsIHTMLCollection*
    1269           0 : nsHTMLDocument::Anchors()
    1270             : {
    1271           0 :   if (!mAnchors) {
    1272           0 :     mAnchors = new nsContentList(this, MatchAnchors, nullptr, nullptr);
    1273             :   }
    1274           0 :   return mAnchors;
    1275             : }
    1276             : 
    1277             : NS_IMETHODIMP
    1278           0 : nsHTMLDocument::GetScripts(nsIDOMHTMLCollection** aScripts)
    1279             : {
    1280           0 :   NS_ADDREF(*aScripts = Scripts());
    1281           0 :   return NS_OK;
    1282             : }
    1283             : 
    1284             : nsIHTMLCollection*
    1285           0 : nsHTMLDocument::Scripts()
    1286             : {
    1287           0 :   if (!mScripts) {
    1288           0 :     mScripts = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::script, nsGkAtoms::script);
    1289             :   }
    1290           0 :   return mScripts;
    1291             : }
    1292             : 
    1293             : NS_IMETHODIMP
    1294           0 : nsHTMLDocument::GetCookie(nsAString& aCookie)
    1295             : {
    1296           0 :   ErrorResult rv;
    1297           0 :   GetCookie(aCookie, rv);
    1298           0 :   return rv.StealNSResult();
    1299             : }
    1300             : 
    1301             : already_AddRefed<nsIChannel>
    1302           0 : nsHTMLDocument::CreateDummyChannelForCookies(nsIURI* aCodebaseURI)
    1303             : {
    1304             :   // The cookie service reads the privacy status of the channel we pass to it in
    1305             :   // order to determine which cookie database to query.  In some cases we don't
    1306             :   // have a proper channel to hand it to the cookie service though.  This
    1307             :   // function creates a dummy channel that is not used to load anything, for the
    1308             :   // sole purpose of handing it to the cookie service.  DO NOT USE THIS CHANNEL
    1309             :   // FOR ANY OTHER PURPOSE.
    1310           0 :   MOZ_ASSERT(!mChannel);
    1311             : 
    1312             :   // The following channel is never openend, so it does not matter what
    1313             :   // securityFlags we pass; let's follow the principle of least privilege.
    1314           0 :   nsCOMPtr<nsIChannel> channel;
    1315           0 :   NS_NewChannel(getter_AddRefs(channel), aCodebaseURI, this,
    1316             :                 nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
    1317           0 :                 nsIContentPolicy::TYPE_INVALID);
    1318             :   nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel =
    1319           0 :     do_QueryInterface(channel);
    1320           0 :   nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
    1321           0 :   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
    1322           0 :   if (!pbChannel || !loadContext) {
    1323           0 :     return nullptr;
    1324             :   }
    1325           0 :   pbChannel->SetPrivate(loadContext->UsePrivateBrowsing());
    1326           0 :   return channel.forget();
    1327             : }
    1328             : 
    1329             : void
    1330           0 : nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv)
    1331             : {
    1332           0 :   aCookie.Truncate(); // clear current cookie in case service fails;
    1333             :                       // no cookie isn't an error condition.
    1334             : 
    1335           0 :   if (mDisableCookieAccess) {
    1336           0 :     return;
    1337             :   }
    1338             : 
    1339             :   // If the document's sandboxed origin flag is set, access to read cookies
    1340             :   // is prohibited.
    1341           0 :   if (mSandboxFlags & SANDBOXED_ORIGIN) {
    1342           0 :     rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    1343           0 :     return;
    1344             :   }
    1345             : 
    1346             :   // not having a cookie service isn't an error
    1347           0 :   nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
    1348           0 :   if (service) {
    1349             :     // Get a URI from the document principal. We use the original
    1350             :     // codebase in case the codebase was changed by SetDomain
    1351           0 :     nsCOMPtr<nsIURI> codebaseURI;
    1352           0 :     NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
    1353             : 
    1354           0 :     if (!codebaseURI) {
    1355             :       // Document's principal is not a codebase (may be system), so
    1356             :       // can't set cookies
    1357             : 
    1358           0 :       return;
    1359             :     }
    1360             : 
    1361           0 :     nsCOMPtr<nsIChannel> channel(mChannel);
    1362           0 :     if (!channel) {
    1363           0 :       channel = CreateDummyChannelForCookies(codebaseURI);
    1364           0 :       if (!channel) {
    1365           0 :         return;
    1366             :       }
    1367             :     }
    1368             : 
    1369           0 :     nsXPIDLCString cookie;
    1370           0 :     service->GetCookieString(codebaseURI, channel, getter_Copies(cookie));
    1371             :     // CopyUTF8toUTF16 doesn't handle error
    1372             :     // because it assumes that the input is valid.
    1373           0 :     UTF_8_ENCODING->DecodeWithoutBOMHandling(cookie, aCookie);
    1374             :   }
    1375             : }
    1376             : 
    1377             : NS_IMETHODIMP
    1378           0 : nsHTMLDocument::SetCookie(const nsAString& aCookie)
    1379             : {
    1380           0 :   ErrorResult rv;
    1381           0 :   SetCookie(aCookie, rv);
    1382           0 :   return rv.StealNSResult();
    1383             : }
    1384             : 
    1385             : void
    1386           0 : nsHTMLDocument::SetCookie(const nsAString& aCookie, ErrorResult& rv)
    1387             : {
    1388           0 :   if (mDisableCookieAccess) {
    1389           0 :     return;
    1390             :   }
    1391             : 
    1392             :   // If the document's sandboxed origin flag is set, access to write cookies
    1393             :   // is prohibited.
    1394           0 :   if (mSandboxFlags & SANDBOXED_ORIGIN) {
    1395           0 :     rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    1396           0 :     return;
    1397             :   }
    1398             : 
    1399             :   // not having a cookie service isn't an error
    1400           0 :   nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
    1401           0 :   if (service && mDocumentURI) {
    1402             :     // The for getting the URI matches nsNavigator::GetCookieEnabled
    1403           0 :     nsCOMPtr<nsIURI> codebaseURI;
    1404           0 :     NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
    1405             : 
    1406           0 :     if (!codebaseURI) {
    1407             :       // Document's principal is not a codebase (may be system), so
    1408             :       // can't set cookies
    1409             : 
    1410           0 :       return;
    1411             :     }
    1412             : 
    1413           0 :     nsCOMPtr<nsIChannel> channel(mChannel);
    1414           0 :     if (!channel) {
    1415           0 :       channel = CreateDummyChannelForCookies(codebaseURI);
    1416           0 :       if (!channel) {
    1417           0 :         return;
    1418             :       }
    1419             :     }
    1420             : 
    1421           0 :     NS_ConvertUTF16toUTF8 cookie(aCookie);
    1422           0 :     service->SetCookieString(codebaseURI, nullptr, cookie.get(), channel);
    1423             :   }
    1424             : }
    1425             : 
    1426             : NS_IMETHODIMP
    1427           0 : nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
    1428             :                      const nsAString& aReplaceOrName,
    1429             :                      const nsAString& aFeatures,
    1430             :                      JSContext* cx, uint8_t aOptionalArgCount,
    1431             :                      nsISupports** aReturn)
    1432             : {
    1433             :   // When called with 3 or more arguments, document.open() calls window.open().
    1434           0 :   if (aOptionalArgCount > 2) {
    1435           0 :     ErrorResult rv;
    1436           0 :     *aReturn = Open(cx, aContentTypeOrUrl, aReplaceOrName, aFeatures,
    1437           0 :                     false, rv).take();
    1438           0 :     return rv.StealNSResult();
    1439             :   }
    1440             : 
    1441           0 :   nsString type;
    1442           0 :   if (aOptionalArgCount > 0) {
    1443           0 :     type = aContentTypeOrUrl;
    1444             :   } else {
    1445           0 :     type.AssignLiteral("text/html");
    1446             :   }
    1447           0 :   nsString replace;
    1448           0 :   if (aOptionalArgCount > 1) {
    1449           0 :     replace = aReplaceOrName;
    1450             :   }
    1451           0 :   ErrorResult rv;
    1452           0 :   *aReturn = Open(cx, type, replace, rv).take();
    1453           0 :   return rv.StealNSResult();
    1454             : }
    1455             : 
    1456             : already_AddRefed<nsPIDOMWindowOuter>
    1457           0 : nsHTMLDocument::Open(JSContext* /* unused */,
    1458             :                      const nsAString& aURL,
    1459             :                      const nsAString& aName,
    1460             :                      const nsAString& aFeatures,
    1461             :                      bool aReplace,
    1462             :                      ErrorResult& rv)
    1463             : {
    1464           0 :   NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
    1465             :                "XOW should have caught this!");
    1466             : 
    1467           0 :   nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow();
    1468           0 :   if (!window) {
    1469           0 :     rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    1470           0 :     return nullptr;
    1471             :   }
    1472             :   nsCOMPtr<nsPIDOMWindowOuter> outer =
    1473           0 :     nsPIDOMWindowOuter::GetFromCurrentInner(window);
    1474           0 :   if (!outer) {
    1475           0 :     rv.Throw(NS_ERROR_NOT_INITIALIZED);
    1476           0 :     return nullptr;
    1477             :   }
    1478           0 :   RefPtr<nsGlobalWindow> win = nsGlobalWindow::Cast(outer);
    1479           0 :   nsCOMPtr<nsPIDOMWindowOuter> newWindow;
    1480             :   // XXXbz We ignore aReplace for now.
    1481           0 :   rv = win->OpenJS(aURL, aName, aFeatures, getter_AddRefs(newWindow));
    1482           0 :   return newWindow.forget();
    1483             : }
    1484             : 
    1485             : already_AddRefed<nsIDocument>
    1486           0 : nsHTMLDocument::Open(JSContext* cx,
    1487             :                      const nsAString& aType,
    1488             :                      const nsAString& aReplace,
    1489             :                      ErrorResult& rv)
    1490             : {
    1491             :   // Implements the "When called with two arguments (or fewer)" steps here:
    1492             :   // https://html.spec.whatwg.org/multipage/webappapis.html#opening-the-input-stream
    1493             : 
    1494           0 :   NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
    1495             :                "XOW should have caught this!");
    1496           0 :   if (!IsHTMLDocument() || mDisableDocWrite) {
    1497             :     // No calling document.open() on XHTML
    1498           0 :     rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    1499           0 :     return nullptr;
    1500             :   }
    1501             : 
    1502           0 :   nsAutoCString contentType;
    1503           0 :   contentType.AssignLiteral("text/html");
    1504             : 
    1505           0 :   nsAutoString type;
    1506           0 :   nsContentUtils::ASCIIToLower(aType, type);
    1507           0 :   nsAutoCString actualType, dummy;
    1508           0 :   NS_ParseRequestContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
    1509           0 :   if (!actualType.EqualsLiteral("text/html") &&
    1510           0 :       !type.EqualsLiteral("replace")) {
    1511           0 :     contentType.AssignLiteral("text/plain");
    1512             :   }
    1513             : 
    1514             :   // If we already have a parser we ignore the document.open call.
    1515           0 :   if (mParser || mParserAborted) {
    1516             :     // The WHATWG spec says: "If the document has an active parser that isn't
    1517             :     // a script-created parser, and the insertion point associated with that
    1518             :     // parser's input stream is not undefined (that is, it does point to
    1519             :     // somewhere in the input stream), then the method does nothing. Abort
    1520             :     // these steps and return the Document object on which the method was
    1521             :     // invoked."
    1522             :     // Note that aborting a parser leaves the parser "active" with its
    1523             :     // insertion point "not undefined". We track this using mParserAborted,
    1524             :     // because aborting a parser nulls out mParser.
    1525           0 :     nsCOMPtr<nsIDocument> ret = this;
    1526           0 :     return ret.forget();
    1527             :   }
    1528             : 
    1529             :   // No calling document.open() without a script global object
    1530           0 :   if (!mScriptGlobalObject) {
    1531           0 :     nsCOMPtr<nsIDocument> ret = this;
    1532           0 :     return ret.forget();
    1533             :   }
    1534             : 
    1535           0 :   nsPIDOMWindowOuter* outer = GetWindow();
    1536           0 :   if (!outer || (GetInnerWindow() != outer->GetCurrentInnerWindow())) {
    1537           0 :     nsCOMPtr<nsIDocument> ret = this;
    1538           0 :     return ret.forget();
    1539             :   }
    1540             : 
    1541             :   // check whether we're in the middle of unload.  If so, ignore this call.
    1542           0 :   nsCOMPtr<nsIDocShell> shell(mDocumentContainer);
    1543           0 :   if (!shell) {
    1544             :     // We won't be able to create a parser anyway.
    1545           0 :     nsCOMPtr<nsIDocument> ret = this;
    1546           0 :     return ret.forget();
    1547             :   }
    1548             : 
    1549             :   bool inUnload;
    1550           0 :   shell->GetIsInUnload(&inUnload);
    1551           0 :   if (inUnload) {
    1552           0 :     nsCOMPtr<nsIDocument> ret = this;
    1553           0 :     return ret.forget();
    1554             :   }
    1555             : 
    1556             :   // Note: We want to use GetEntryDocument here because this document
    1557             :   // should inherit the security information of the document that's opening us,
    1558             :   // (since if it's secure, then it's presumably trusted).
    1559           0 :   nsCOMPtr<nsIDocument> callerDoc = GetEntryDocument();
    1560           0 :   if (!callerDoc) {
    1561             :     // If we're called from C++ or in some other way without an originating
    1562             :     // document we can't do a document.open w/o changing the principal of the
    1563             :     // document to something like about:blank (as that's the only sane thing to
    1564             :     // do when we don't know the origin of this call), and since we can't
    1565             :     // change the principals of a document for security reasons we'll have to
    1566             :     // refuse to go ahead with this call.
    1567             : 
    1568           0 :     rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    1569           0 :     return nullptr;
    1570             :   }
    1571             : 
    1572             :   // Grab a reference to the calling documents security info (if any)
    1573             :   // and URIs as they may be lost in the call to Reset().
    1574           0 :   nsCOMPtr<nsISupports> securityInfo = callerDoc->GetSecurityInfo();
    1575           0 :   nsCOMPtr<nsIURI> uri = callerDoc->GetDocumentURI();
    1576           0 :   nsCOMPtr<nsIURI> baseURI = callerDoc->GetBaseURI();
    1577           0 :   nsCOMPtr<nsIPrincipal> callerPrincipal = callerDoc->NodePrincipal();
    1578           0 :   nsCOMPtr<nsIChannel> callerChannel = callerDoc->GetChannel();
    1579             : 
    1580             :   // We're called from script. Make sure the script is from the same
    1581             :   // origin, not just that the caller can access the document. This is
    1582             :   // needed to keep document principals from ever changing, which is
    1583             :   // needed because of the way we use our XOW code, and is a sane
    1584             :   // thing to do anyways.
    1585             : 
    1586           0 :   bool equals = false;
    1587           0 :   if (NS_FAILED(callerPrincipal->Equals(NodePrincipal(), &equals)) ||
    1588           0 :       !equals) {
    1589             : 
    1590             : #ifdef DEBUG
    1591           0 :     nsCOMPtr<nsIURI> callerDocURI = callerDoc->GetDocumentURI();
    1592           0 :     nsCOMPtr<nsIURI> thisURI = nsIDocument::GetDocumentURI();
    1593           0 :     printf("nsHTMLDocument::Open callerDoc %s this %s\n",
    1594           0 :            callerDocURI ? callerDocURI->GetSpecOrDefault().get() : "",
    1595           0 :            thisURI ? thisURI->GetSpecOrDefault().get() : "");
    1596             : #endif
    1597             : 
    1598           0 :     rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    1599           0 :     return nullptr;
    1600             :   }
    1601             : 
    1602             :   // Stop current loads targeted at the window this document is in.
    1603           0 :   if (mScriptGlobalObject) {
    1604           0 :     nsCOMPtr<nsIContentViewer> cv;
    1605           0 :     shell->GetContentViewer(getter_AddRefs(cv));
    1606             : 
    1607           0 :     if (cv) {
    1608             :       bool okToUnload;
    1609           0 :       if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) && !okToUnload) {
    1610             :         // We don't want to unload, so stop here, but don't throw an
    1611             :         // exception.
    1612           0 :         nsCOMPtr<nsIDocument> ret = this;
    1613           0 :         return ret.forget();
    1614             :       }
    1615             :     }
    1616             : 
    1617           0 :     nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(shell));
    1618           0 :     webnav->Stop(nsIWebNavigation::STOP_NETWORK);
    1619             : 
    1620             :     // The Stop call may have cancelled the onload blocker request or prevented
    1621             :     // it from getting added, so we need to make sure it gets added to the
    1622             :     // document again otherwise the document could have a non-zero onload block
    1623             :     // count without the onload blocker request being in the loadgroup.
    1624           0 :     EnsureOnloadBlocker();
    1625             :   }
    1626             : 
    1627             :   // The open occurred after the document finished loading.
    1628             :   // So we reset the document and then reinitialize it.
    1629           0 :   nsCOMPtr<nsIChannel> channel;
    1630           0 :   nsCOMPtr<nsILoadGroup> group = do_QueryReferent(mDocumentLoadGroup);
    1631           0 :   rv = NS_NewChannel(getter_AddRefs(channel),
    1632             :                      uri,
    1633             :                      callerDoc,
    1634             :                      nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
    1635             :                      nsIContentPolicy::TYPE_OTHER,
    1636           0 :                      group);
    1637             : 
    1638           0 :   if (rv.Failed()) {
    1639           0 :     return nullptr;
    1640             :   }
    1641             : 
    1642           0 :   if (callerChannel) {
    1643             :     nsLoadFlags callerLoadFlags;
    1644           0 :     rv = callerChannel->GetLoadFlags(&callerLoadFlags);
    1645           0 :     if (rv.Failed()) {
    1646           0 :       return nullptr;
    1647             :     }
    1648             : 
    1649             :     nsLoadFlags loadFlags;
    1650           0 :     rv = channel->GetLoadFlags(&loadFlags);
    1651           0 :     if (rv.Failed()) {
    1652           0 :       return nullptr;
    1653             :     }
    1654             : 
    1655           0 :     loadFlags |= callerLoadFlags & nsIRequest::INHIBIT_PERSISTENT_CACHING;
    1656             : 
    1657           0 :     rv = channel->SetLoadFlags(loadFlags);
    1658           0 :     if (rv.Failed()) {
    1659           0 :       return nullptr;
    1660             :     }
    1661             : 
    1662             :     // If the user has allowed mixed content on the rootDoc, then we should propogate it
    1663             :     // down to the new document channel.
    1664           0 :     bool rootHasSecureConnection = false;
    1665           0 :     bool allowMixedContent = false;
    1666           0 :     bool isDocShellRoot = false;
    1667           0 :     nsresult rvalue = shell->GetAllowMixedContentAndConnectionData(&rootHasSecureConnection, &allowMixedContent, &isDocShellRoot);
    1668           0 :     if (NS_SUCCEEDED(rvalue) && allowMixedContent && isDocShellRoot) {
    1669           0 :        shell->SetMixedContentChannel(channel);
    1670             :     }
    1671             :   }
    1672             : 
    1673             :   // Before we reset the doc notify the globalwindow of the change,
    1674             :   // but only if we still have a window (i.e. our window object the
    1675             :   // current inner window in our outer window).
    1676             : 
    1677             :   // Hold onto ourselves on the offchance that we're down to one ref
    1678           0 :   nsCOMPtr<nsIDocument> kungFuDeathGrip = this;
    1679             : 
    1680           0 :   if (nsPIDOMWindowInner *window = GetInnerWindow()) {
    1681             :     // Remember the old scope in case the call to SetNewDocument changes it.
    1682           0 :     nsCOMPtr<nsIScriptGlobalObject> oldScope(do_QueryReferent(mScopeObject));
    1683             : 
    1684             : #ifdef DEBUG
    1685           0 :     bool willReparent = mWillReparent;
    1686           0 :     mWillReparent = true;
    1687             : 
    1688             :     nsDocument* templateContentsOwner =
    1689           0 :       static_cast<nsDocument*>(mTemplateContentsOwner.get());
    1690             : 
    1691           0 :     if (templateContentsOwner) {
    1692           0 :       templateContentsOwner->mWillReparent = true;
    1693             :     }
    1694             : #endif
    1695             : 
    1696             :     // Per spec, we pass false here so that a new Window is created.
    1697           0 :     rv = window->SetNewDocument(this, nullptr,
    1698           0 :                                 /* aForceReuseInnerWindow */ false);
    1699           0 :     if (rv.Failed()) {
    1700           0 :       return nullptr;
    1701             :     }
    1702             : 
    1703             : #ifdef DEBUG
    1704           0 :     if (templateContentsOwner) {
    1705           0 :       templateContentsOwner->mWillReparent = willReparent;
    1706             :     }
    1707             : 
    1708           0 :     mWillReparent = willReparent;
    1709             : #endif
    1710             : 
    1711             :     // Now make sure we're not flagged as the initial document anymore, now
    1712             :     // that we've had stuff done to us.  From now on, if anyone tries to
    1713             :     // document.open() us, they get a new inner window.
    1714           0 :     SetIsInitialDocument(false);
    1715             : 
    1716           0 :     nsCOMPtr<nsIScriptGlobalObject> newScope(do_QueryReferent(mScopeObject));
    1717           0 :     JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
    1718           0 :     if (oldScope && newScope != oldScope && wrapper) {
    1719           0 :       JSAutoCompartment ac(cx, wrapper);
    1720           0 :       rv = mozilla::dom::ReparentWrapper(cx, wrapper);
    1721           0 :       if (rv.Failed()) {
    1722           0 :         return nullptr;
    1723             :       }
    1724             : 
    1725             :       // Also reparent the template contents owner document
    1726             :       // because its global is set to the same as this document.
    1727           0 :       if (mTemplateContentsOwner) {
    1728             :         JS::Rooted<JSObject*> contentsOwnerWrapper(cx,
    1729           0 :           mTemplateContentsOwner->GetWrapper());
    1730           0 :         if (contentsOwnerWrapper) {
    1731           0 :           rv = mozilla::dom::ReparentWrapper(cx, contentsOwnerWrapper);
    1732           0 :           if (rv.Failed()) {
    1733           0 :             return nullptr;
    1734             :           }
    1735             :         }
    1736             :       }
    1737             :     }
    1738             :   }
    1739             : 
    1740           0 :   mDidDocumentOpen = true;
    1741             : 
    1742             :   // Call Reset(), this will now do the full reset
    1743           0 :   Reset(channel, group);
    1744           0 :   if (baseURI) {
    1745           0 :     mDocumentBaseURI = baseURI;
    1746             :   }
    1747             : 
    1748             :   // Store the security info of the caller now that we're done
    1749             :   // resetting the document.
    1750           0 :   mSecurityInfo = securityInfo;
    1751             : 
    1752           0 :   mParserAborted = false;
    1753           0 :   mParser = nsHtml5Module::NewHtml5Parser();
    1754           0 :   nsHtml5Module::Initialize(mParser, this, uri, shell, channel);
    1755           0 :   if (mReferrerPolicySet) {
    1756             :     // CSP may have set the referrer policy, so a speculative parser should
    1757             :     // start with the new referrer policy.
    1758           0 :     nsHtml5TreeOpExecutor* executor = nullptr;
    1759           0 :     executor = static_cast<nsHtml5TreeOpExecutor*> (mParser->GetContentSink());
    1760           0 :     if (executor && mReferrerPolicySet) {
    1761           0 :       executor->SetSpeculationReferrerPolicy(static_cast<ReferrerPolicy>(mReferrerPolicy));
    1762             :     }
    1763             :   }
    1764             : 
    1765             :   // This will be propagated to the parser when someone actually calls write()
    1766           0 :   SetContentTypeInternal(contentType);
    1767             : 
    1768             :   // Prepare the docshell and the document viewer for the impending
    1769             :   // out of band document.write()
    1770           0 :   shell->PrepareForNewContentModel();
    1771             : 
    1772             :   // Now check whether we were opened with a "replace" argument.  If
    1773             :   // so, we need to tell the docshell to not create a new history
    1774             :   // entry for this load. Otherwise, make sure that we're doing a normal load,
    1775             :   // not whatever type of load was previously done on this docshell.
    1776           0 :   shell->SetLoadType(aReplace.LowerCaseEqualsLiteral("replace") ?
    1777           0 :                        LOAD_NORMAL_REPLACE : LOAD_NORMAL);
    1778             : 
    1779           0 :   nsCOMPtr<nsIContentViewer> cv;
    1780           0 :   shell->GetContentViewer(getter_AddRefs(cv));
    1781           0 :   if (cv) {
    1782           0 :     cv->LoadStart(this);
    1783             :   }
    1784             : 
    1785             :   // Add a wyciwyg channel request into the document load group
    1786           0 :   NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Open(): wyciwyg "
    1787             :                "channel already exists!");
    1788             : 
    1789             :   // In case the editor is listening and will see the new channel
    1790             :   // being added, make sure mWriteLevel is non-zero so that the editor
    1791             :   // knows that document.open/write/close() is being called on this
    1792             :   // document.
    1793           0 :   ++mWriteLevel;
    1794             : 
    1795           0 :   CreateAndAddWyciwygChannel();
    1796             : 
    1797           0 :   --mWriteLevel;
    1798             : 
    1799           0 :   SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
    1800             : 
    1801             :   // After changing everything around, make sure that the principal on the
    1802             :   // document's compartment exactly matches NodePrincipal().
    1803           0 :   DebugOnly<JSObject*> wrapper = GetWrapperPreserveColor();
    1804           0 :   MOZ_ASSERT_IF(wrapper,
    1805             :                 JS_GetCompartmentPrincipals(js::GetObjectCompartment(wrapper)) ==
    1806             :                 nsJSPrincipals::get(NodePrincipal()));
    1807             : 
    1808           0 :   return kungFuDeathGrip.forget();
    1809             : }
    1810             : 
    1811             : NS_IMETHODIMP
    1812           0 : nsHTMLDocument::Clear()
    1813             : {
    1814             :   // This method has been deprecated
    1815           0 :   return NS_OK;
    1816             : }
    1817             : 
    1818             : NS_IMETHODIMP
    1819           0 : nsHTMLDocument::Close()
    1820             : {
    1821           0 :   ErrorResult rv;
    1822           0 :   Close(rv);
    1823           0 :   return rv.StealNSResult();
    1824             : }
    1825             : 
    1826             : void
    1827           0 : nsHTMLDocument::Close(ErrorResult& rv)
    1828             : {
    1829           0 :   if (!IsHTMLDocument()) {
    1830             :     // No calling document.close() on XHTML!
    1831             : 
    1832           0 :     rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    1833           0 :     return;
    1834             :   }
    1835             : 
    1836           0 :   if (!mParser || !mParser->IsScriptCreated()) {
    1837           0 :     return;
    1838             :   }
    1839             : 
    1840           0 :   ++mWriteLevel;
    1841           0 :   rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
    1842           0 :     EmptyString(), nullptr, GetContentTypeInternal(), true);
    1843           0 :   --mWriteLevel;
    1844             : 
    1845             :   // Even if that Parse() call failed, do the rest of this method
    1846             : 
    1847             :   // XXX Make sure that all the document.written content is
    1848             :   // reflowed.  We should remove this call once we change
    1849             :   // nsHTMLDocument::OpenCommon() so that it completely destroys the
    1850             :   // earlier document's content and frame hierarchy.  Right now, it
    1851             :   // re-uses the earlier document's root content object and
    1852             :   // corresponding frame objects.  These re-used frame objects think
    1853             :   // that they have already been reflowed, so they drop initial
    1854             :   // reflows.  For certain cases of document.written content, like a
    1855             :   // frameset document, the dropping of the initial reflow means
    1856             :   // that we end up in document.close() without appended any reflow
    1857             :   // commands to the reflow queue and, consequently, without adding
    1858             :   // the dummy layout request to the load group.  Since the dummy
    1859             :   // layout request is not added to the load group, the onload
    1860             :   // handler of the frameset fires before the frames get reflowed
    1861             :   // and loaded.  That is the long explanation for why we need this
    1862             :   // one line of code here!
    1863             :   // XXXbz as far as I can tell this may not be needed anymore; all
    1864             :   // the testcases in bug 57636 pass without this line...  Leaving
    1865             :   // it be for now, though.  In any case, there's no reason to do
    1866             :   // this if we have no presshell, since in that case none of the
    1867             :   // above about reusing frames applies.
    1868             :   //
    1869             :   // XXXhsivonen keeping this around for bug 577508 / 253951 still :-(
    1870           0 :   if (GetShell()) {
    1871           0 :     FlushPendingNotifications(FlushType::Layout);
    1872             :   }
    1873             : 
    1874             :   // Removing the wyciwygChannel here is wrong when document.close() is
    1875             :   // called from within the document itself. However, legacy requires the
    1876             :   // channel to be removed here. Otherwise, the load event never fires.
    1877           0 :   NS_ASSERTION(mWyciwygChannel, "nsHTMLDocument::Close(): Trying to remove "
    1878             :                "nonexistent wyciwyg channel!");
    1879           0 :   RemoveWyciwygChannel();
    1880           0 :   NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Close(): "
    1881             :                "nsIWyciwygChannel could not be removed!");
    1882             : }
    1883             : 
    1884             : void
    1885           0 : nsHTMLDocument::WriteCommon(JSContext *cx,
    1886             :                             const Sequence<nsString>& aText,
    1887             :                             bool aNewlineTerminate,
    1888             :                             mozilla::ErrorResult& rv)
    1889             : {
    1890             :   // Fast path the common case
    1891           0 :   if (aText.Length() == 1) {
    1892           0 :     rv = WriteCommon(cx, aText[0], aNewlineTerminate);
    1893             :   } else {
    1894             :     // XXXbz it would be nice if we could pass all the strings to the parser
    1895             :     // without having to do all this copying and then ask it to start
    1896             :     // parsing....
    1897           0 :     nsString text;
    1898           0 :     for (uint32_t i = 0; i < aText.Length(); ++i) {
    1899           0 :       text.Append(aText[i]);
    1900             :     }
    1901           0 :     rv = WriteCommon(cx, text, aNewlineTerminate);
    1902             :   }
    1903           0 : }
    1904             : 
    1905             : nsresult
    1906           0 : nsHTMLDocument::WriteCommon(JSContext *cx,
    1907             :                             const nsAString& aText,
    1908             :                             bool aNewlineTerminate)
    1909             : {
    1910           0 :   mTooDeepWriteRecursion =
    1911           0 :     (mWriteLevel > NS_MAX_DOCUMENT_WRITE_DEPTH || mTooDeepWriteRecursion);
    1912           0 :   NS_ENSURE_STATE(!mTooDeepWriteRecursion);
    1913             : 
    1914           0 :   if (!IsHTMLDocument() || mDisableDocWrite) {
    1915             :     // No calling document.write*() on XHTML!
    1916             : 
    1917           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    1918             :   }
    1919             : 
    1920           0 :   if (mParserAborted) {
    1921             :     // Hixie says aborting the parser doesn't undefine the insertion point.
    1922             :     // However, since we null out mParser in that case, we track the
    1923             :     // theoretically defined insertion point using mParserAborted.
    1924           0 :     return NS_OK;
    1925             :   }
    1926             : 
    1927           0 :   nsresult rv = NS_OK;
    1928             : 
    1929           0 :   void *key = GenerateParserKey();
    1930           0 :   if (mParser && !mParser->IsInsertionPointDefined()) {
    1931           0 :     if (mExternalScriptsBeingEvaluated) {
    1932             :       // Instead of implying a call to document.open(), ignore the call.
    1933           0 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    1934           0 :                                       NS_LITERAL_CSTRING("DOM Events"), this,
    1935             :                                       nsContentUtils::eDOM_PROPERTIES,
    1936             :                                       "DocumentWriteIgnored",
    1937             :                                       nullptr, 0,
    1938           0 :                                       mDocumentURI);
    1939           0 :       return NS_OK;
    1940             :     }
    1941           0 :     mParser->Terminate();
    1942           0 :     NS_ASSERTION(!mParser, "mParser should have been null'd out");
    1943             :   }
    1944             : 
    1945           0 :   if (!mParser) {
    1946           0 :     if (mExternalScriptsBeingEvaluated) {
    1947             :       // Instead of implying a call to document.open(), ignore the call.
    1948           0 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    1949           0 :                                       NS_LITERAL_CSTRING("DOM Events"), this,
    1950             :                                       nsContentUtils::eDOM_PROPERTIES,
    1951             :                                       "DocumentWriteIgnored",
    1952             :                                       nullptr, 0,
    1953           0 :                                       mDocumentURI);
    1954           0 :       return NS_OK;
    1955             :     }
    1956           0 :     nsCOMPtr<nsISupports> ignored;
    1957           0 :     rv = Open(NS_LITERAL_STRING("text/html"), EmptyString(), EmptyString(), cx,
    1958           0 :               1, getter_AddRefs(ignored));
    1959             : 
    1960             :     // If Open() fails, or if it didn't create a parser (as it won't
    1961             :     // if the user chose to not discard the current document through
    1962             :     // onbeforeunload), don't write anything.
    1963           0 :     if (NS_FAILED(rv) || !mParser) {
    1964           0 :       return rv;
    1965             :     }
    1966           0 :     MOZ_ASSERT(!JS_IsExceptionPending(cx),
    1967             :                "Open() succeeded but JS exception is pending");
    1968             :   }
    1969             : 
    1970           0 :   static NS_NAMED_LITERAL_STRING(new_line, "\n");
    1971             : 
    1972             :   // Save the data in cache if the write isn't from within the doc
    1973           0 :   if (mWyciwygChannel && !key) {
    1974           0 :     if (!aText.IsEmpty()) {
    1975           0 :       mWyciwygChannel->WriteToCacheEntry(aText);
    1976             :     }
    1977             : 
    1978           0 :     if (aNewlineTerminate) {
    1979           0 :       mWyciwygChannel->WriteToCacheEntry(new_line);
    1980             :     }
    1981             :   }
    1982             : 
    1983           0 :   ++mWriteLevel;
    1984             : 
    1985             :   // This could be done with less code, but for performance reasons it
    1986             :   // makes sense to have the code for two separate Parse() calls here
    1987             :   // since the concatenation of strings costs more than we like. And
    1988             :   // why pay that price when we don't need to?
    1989           0 :   if (aNewlineTerminate) {
    1990           0 :     rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
    1991           0 :       aText + new_line, key, GetContentTypeInternal(), false);
    1992             :   } else {
    1993           0 :     rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
    1994           0 :       aText, key, GetContentTypeInternal(), false);
    1995             :   }
    1996             : 
    1997           0 :   --mWriteLevel;
    1998             : 
    1999           0 :   mTooDeepWriteRecursion = (mWriteLevel != 0 && mTooDeepWriteRecursion);
    2000             : 
    2001           0 :   return rv;
    2002             : }
    2003             : 
    2004             : NS_IMETHODIMP
    2005           0 : nsHTMLDocument::Write(const nsAString& aText, JSContext *cx)
    2006             : {
    2007           0 :   return WriteCommon(cx, aText, false);
    2008             : }
    2009             : 
    2010             : void
    2011           0 : nsHTMLDocument::Write(JSContext* cx, const Sequence<nsString>& aText,
    2012             :                       ErrorResult& rv)
    2013             : {
    2014           0 :   WriteCommon(cx, aText, false, rv);
    2015           0 : }
    2016             : 
    2017             : NS_IMETHODIMP
    2018           0 : nsHTMLDocument::Writeln(const nsAString& aText, JSContext *cx)
    2019             : {
    2020           0 :   return WriteCommon(cx, aText, true);
    2021             : }
    2022             : 
    2023             : void
    2024           0 : nsHTMLDocument::Writeln(JSContext* cx, const Sequence<nsString>& aText,
    2025             :                         ErrorResult& rv)
    2026             : {
    2027           0 :   WriteCommon(cx, aText, true, rv);
    2028           0 : }
    2029             : 
    2030             : bool
    2031           0 : nsHTMLDocument::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
    2032             :                                    nsIAtom* aAtom, void* aData)
    2033             : {
    2034           0 :   NS_PRECONDITION(aElement, "Must have element to work with!");
    2035           0 :   nsString* elementName = static_cast<nsString*>(aData);
    2036             :   return
    2037           0 :     aElement->GetNameSpaceID() == kNameSpaceID_XHTML &&
    2038           0 :     aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
    2039           0 :                           *elementName, eCaseMatters);
    2040             : }
    2041             : 
    2042             : /* static */
    2043             : void*
    2044           0 : nsHTMLDocument::UseExistingNameString(nsINode* aRootNode, const nsString* aName)
    2045             : {
    2046           0 :   return const_cast<nsString*>(aName);
    2047             : }
    2048             : 
    2049             : NS_IMETHODIMP
    2050           0 : nsHTMLDocument::GetElementsByName(const nsAString& aElementName,
    2051             :                                   nsIDOMNodeList** aReturn)
    2052             : {
    2053           0 :   *aReturn = GetElementsByName(aElementName).take();
    2054           0 :   return NS_OK;
    2055             : }
    2056             : 
    2057             : void
    2058           0 : nsHTMLDocument::AddedForm()
    2059             : {
    2060           0 :   ++mNumForms;
    2061           0 : }
    2062             : 
    2063             : void
    2064           0 : nsHTMLDocument::RemovedForm()
    2065             : {
    2066           0 :   --mNumForms;
    2067           0 : }
    2068             : 
    2069             : int32_t
    2070           0 : nsHTMLDocument::GetNumFormsSynchronous()
    2071             : {
    2072           0 :   return mNumForms;
    2073             : }
    2074             : 
    2075             : NS_IMETHODIMP
    2076           0 : nsHTMLDocument::GetAlinkColor(nsAString& aAlinkColor)
    2077             : {
    2078           0 :   aAlinkColor.Truncate();
    2079             : 
    2080           0 :   HTMLBodyElement* body = GetBodyElement();
    2081           0 :   if (body) {
    2082           0 :     body->GetALink(aAlinkColor);
    2083             :   }
    2084             : 
    2085           0 :   return NS_OK;
    2086             : }
    2087             : 
    2088             : NS_IMETHODIMP
    2089           0 : nsHTMLDocument::SetAlinkColor(const nsAString& aAlinkColor)
    2090             : {
    2091           0 :   HTMLBodyElement* body = GetBodyElement();
    2092           0 :   if (body) {
    2093           0 :     body->SetALink(aAlinkColor);
    2094             :   }
    2095             : 
    2096           0 :   return NS_OK;
    2097             : }
    2098             : 
    2099             : NS_IMETHODIMP
    2100           0 : nsHTMLDocument::GetLinkColor(nsAString& aLinkColor)
    2101             : {
    2102           0 :   aLinkColor.Truncate();
    2103             : 
    2104           0 :   HTMLBodyElement* body = GetBodyElement();
    2105           0 :   if (body) {
    2106           0 :     body->GetLink(aLinkColor);
    2107             :   }
    2108             : 
    2109           0 :   return NS_OK;
    2110             : }
    2111             : 
    2112             : NS_IMETHODIMP
    2113           0 : nsHTMLDocument::SetLinkColor(const nsAString& aLinkColor)
    2114             : {
    2115           0 :   HTMLBodyElement* body = GetBodyElement();
    2116           0 :   if (body) {
    2117           0 :     body->SetLink(aLinkColor);
    2118             :   }
    2119             : 
    2120           0 :   return NS_OK;
    2121             : }
    2122             : 
    2123             : NS_IMETHODIMP
    2124           0 : nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor)
    2125             : {
    2126           0 :   aVlinkColor.Truncate();
    2127             : 
    2128           0 :   HTMLBodyElement* body = GetBodyElement();
    2129           0 :   if (body) {
    2130           0 :     body->GetVLink(aVlinkColor);
    2131             :   }
    2132             : 
    2133           0 :   return NS_OK;
    2134             : }
    2135             : 
    2136             : NS_IMETHODIMP
    2137           0 : nsHTMLDocument::SetVlinkColor(const nsAString& aVlinkColor)
    2138             : {
    2139           0 :   HTMLBodyElement* body = GetBodyElement();
    2140           0 :   if (body) {
    2141           0 :     body->SetVLink(aVlinkColor);
    2142             :   }
    2143             : 
    2144           0 :   return NS_OK;
    2145             : }
    2146             : 
    2147             : NS_IMETHODIMP
    2148           0 : nsHTMLDocument::GetBgColor(nsAString& aBgColor)
    2149             : {
    2150           0 :   aBgColor.Truncate();
    2151             : 
    2152           0 :   HTMLBodyElement* body = GetBodyElement();
    2153           0 :   if (body) {
    2154           0 :     body->GetBgColor(aBgColor);
    2155             :   }
    2156             : 
    2157           0 :   return NS_OK;
    2158             : }
    2159             : 
    2160             : NS_IMETHODIMP
    2161           0 : nsHTMLDocument::SetBgColor(const nsAString& aBgColor)
    2162             : {
    2163           0 :   HTMLBodyElement* body = GetBodyElement();
    2164           0 :   if (body) {
    2165           0 :     body->SetBgColor(aBgColor);
    2166             :   }
    2167             : 
    2168           0 :   return NS_OK;
    2169             : }
    2170             : 
    2171             : NS_IMETHODIMP
    2172           0 : nsHTMLDocument::GetFgColor(nsAString& aFgColor)
    2173             : {
    2174           0 :   aFgColor.Truncate();
    2175             : 
    2176           0 :   HTMLBodyElement* body = GetBodyElement();
    2177           0 :   if (body) {
    2178           0 :     body->GetText(aFgColor);
    2179             :   }
    2180             : 
    2181           0 :   return NS_OK;
    2182             : }
    2183             : 
    2184             : NS_IMETHODIMP
    2185           0 : nsHTMLDocument::SetFgColor(const nsAString& aFgColor)
    2186             : {
    2187           0 :   HTMLBodyElement* body = GetBodyElement();
    2188           0 :   if (body) {
    2189           0 :     body->SetText(aFgColor);
    2190             :   }
    2191             : 
    2192           0 :   return NS_OK;
    2193             : }
    2194             : 
    2195             : 
    2196             : NS_IMETHODIMP
    2197           0 : nsHTMLDocument::GetEmbeds(nsIDOMHTMLCollection** aEmbeds)
    2198             : {
    2199           0 :   NS_ADDREF(*aEmbeds = Embeds());
    2200           0 :   return NS_OK;
    2201             : }
    2202             : 
    2203             : nsIHTMLCollection*
    2204           0 : nsHTMLDocument::Embeds()
    2205             : {
    2206           0 :   if (!mEmbeds) {
    2207           0 :     mEmbeds = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::embed, nsGkAtoms::embed);
    2208             :   }
    2209           0 :   return mEmbeds;
    2210             : }
    2211             : 
    2212             : NS_IMETHODIMP
    2213           0 : nsHTMLDocument::GetSelection(nsISelection** aReturn)
    2214             : {
    2215           0 :   ErrorResult rv;
    2216           0 :   NS_IF_ADDREF(*aReturn = GetSelection(rv));
    2217           0 :   return rv.StealNSResult();
    2218             : }
    2219             : 
    2220             : Selection*
    2221           0 : nsHTMLDocument::GetSelection(ErrorResult& aRv)
    2222             : {
    2223           0 :   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
    2224           0 :   if (!window) {
    2225           0 :     return nullptr;
    2226             :   }
    2227             : 
    2228           0 :   NS_ASSERTION(window->IsInnerWindow(), "Should have inner window here!");
    2229           0 :   if (!window->IsCurrentInnerWindow()) {
    2230           0 :     return nullptr;
    2231             :   }
    2232             : 
    2233           0 :   return nsGlobalWindow::Cast(window)->GetSelection(aRv);
    2234             : }
    2235             : 
    2236             : NS_IMETHODIMP
    2237           0 : nsHTMLDocument::CaptureEvents()
    2238             : {
    2239           0 :   WarnOnceAbout(nsIDocument::eUseOfCaptureEvents);
    2240           0 :   return NS_OK;
    2241             : }
    2242             : 
    2243             : NS_IMETHODIMP
    2244           0 : nsHTMLDocument::ReleaseEvents()
    2245             : {
    2246           0 :   WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);
    2247           0 :   return NS_OK;
    2248             : }
    2249             : 
    2250             : // Mapped to document.embeds for NS4 compatibility
    2251             : NS_IMETHODIMP
    2252           0 : nsHTMLDocument::GetPlugins(nsIDOMHTMLCollection** aPlugins)
    2253             : {
    2254           0 :   *aPlugins = nullptr;
    2255             : 
    2256           0 :   return GetEmbeds(aPlugins);
    2257             : }
    2258             : 
    2259             : nsIHTMLCollection*
    2260           0 : nsHTMLDocument::Plugins()
    2261             : {
    2262           0 :   return Embeds();
    2263             : }
    2264             : 
    2265             : nsISupports*
    2266          25 : nsHTMLDocument::ResolveName(const nsAString& aName, nsWrapperCache **aCache)
    2267             : {
    2268          25 :   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aName);
    2269          25 :   if (!entry) {
    2270          25 :     *aCache = nullptr;
    2271          25 :     return nullptr;
    2272             :   }
    2273             : 
    2274           0 :   nsBaseContentList *list = entry->GetNameContentList();
    2275           0 :   uint32_t length = list ? list->Length() : 0;
    2276             : 
    2277           0 :   if (length > 0) {
    2278           0 :     if (length == 1) {
    2279             :       // Only one element in the list, return the element instead of returning
    2280             :       // the list.
    2281           0 :       nsIContent *node = list->Item(0);
    2282           0 :       *aCache = node;
    2283           0 :       return node;
    2284             :     }
    2285             : 
    2286             :     // The list contains more than one element, return the whole list.
    2287           0 :     *aCache = list;
    2288           0 :     return list;
    2289             :   }
    2290             : 
    2291             :   // No named items were found, see if there's one registerd by id for aName.
    2292           0 :   Element *e = entry->GetIdElement();
    2293             : 
    2294           0 :   if (e && nsGenericHTMLElement::ShouldExposeIdAsHTMLDocumentProperty(e)) {
    2295           0 :     *aCache = e;
    2296           0 :     return e;
    2297             :   }
    2298             : 
    2299           0 :   *aCache = nullptr;
    2300           0 :   return nullptr;
    2301             : }
    2302             : 
    2303             : void
    2304           6 : nsHTMLDocument::NamedGetter(JSContext* cx, const nsAString& aName, bool& aFound,
    2305             :                             JS::MutableHandle<JSObject*> aRetval,
    2306             :                             ErrorResult& rv)
    2307             : {
    2308             :   nsWrapperCache* cache;
    2309           6 :   nsISupports* supp = ResolveName(aName, &cache);
    2310           6 :   if (!supp) {
    2311           6 :     aFound = false;
    2312           6 :     aRetval.set(nullptr);
    2313          12 :     return;
    2314             :   }
    2315             : 
    2316           0 :   JS::Rooted<JS::Value> val(cx);
    2317           0 :   if (!dom::WrapObject(cx, supp, cache, nullptr, &val)) {
    2318           0 :     rv.Throw(NS_ERROR_OUT_OF_MEMORY);
    2319           0 :     return;
    2320             :   }
    2321           0 :   aFound = true;
    2322           0 :   aRetval.set(&val.toObject());
    2323             : }
    2324             : 
    2325             : void
    2326           0 : nsHTMLDocument::GetSupportedNames(nsTArray<nsString>& aNames)
    2327             : {
    2328           0 :   for (auto iter = mIdentifierMap.Iter(); !iter.Done(); iter.Next()) {
    2329           0 :     nsIdentifierMapEntry* entry = iter.Get();
    2330           0 :     if (entry->HasNameElement() ||
    2331           0 :         entry->HasIdElementExposedAsHTMLDocumentProperty()) {
    2332           0 :       aNames.AppendElement(entry->GetKeyAsString());
    2333             :     }
    2334             :   }
    2335           0 : }
    2336             : 
    2337             : //----------------------------
    2338             : 
    2339             : // forms related stuff
    2340             : 
    2341             : NS_IMETHODIMP
    2342           0 : nsHTMLDocument::GetForms(nsIDOMHTMLCollection** aForms)
    2343             : {
    2344           0 :   NS_ADDREF(*aForms = nsHTMLDocument::GetForms());
    2345           0 :   return NS_OK;
    2346             : }
    2347             : 
    2348             : nsContentList*
    2349           0 : nsHTMLDocument::GetForms()
    2350             : {
    2351           0 :   if (!mForms) {
    2352           0 :     mForms = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::form, nsGkAtoms::form);
    2353             :   }
    2354             : 
    2355           0 :   return mForms;
    2356             : }
    2357             : 
    2358           0 : static bool MatchFormControls(Element* aElement, int32_t aNamespaceID,
    2359             :                               nsIAtom* aAtom, void* aData)
    2360             : {
    2361           0 :   return aElement->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL);
    2362             : }
    2363             : 
    2364             : nsContentList*
    2365           0 : nsHTMLDocument::GetFormControls()
    2366             : {
    2367           0 :   if (!mFormControls) {
    2368           0 :     mFormControls = new nsContentList(this, MatchFormControls, nullptr, nullptr);
    2369             :   }
    2370             : 
    2371           0 :   return mFormControls;
    2372             : }
    2373             : 
    2374             : nsresult
    2375           0 : nsHTMLDocument::CreateAndAddWyciwygChannel(void)
    2376             : {
    2377           0 :   nsresult rv = NS_OK;
    2378           0 :   nsAutoCString url, originalSpec;
    2379             : 
    2380           0 :   mDocumentURI->GetSpec(originalSpec);
    2381             : 
    2382             :   // Generate the wyciwyg url
    2383           0 :   url = NS_LITERAL_CSTRING("wyciwyg://")
    2384           0 :       + nsPrintfCString("%d", gWyciwygSessionCnt++)
    2385           0 :       + NS_LITERAL_CSTRING("/")
    2386           0 :       + originalSpec;
    2387             : 
    2388           0 :   nsCOMPtr<nsIURI> wcwgURI;
    2389           0 :   NS_NewURI(getter_AddRefs(wcwgURI), url);
    2390             : 
    2391             :   // Create the nsIWyciwygChannel to store out-of-band
    2392             :   // document.write() script to cache
    2393           0 :   nsCOMPtr<nsIChannel> channel;
    2394             :   // Create a wyciwyg Channel
    2395           0 :   rv = NS_NewChannel(getter_AddRefs(channel),
    2396             :                      wcwgURI,
    2397             :                      NodePrincipal(),
    2398             :                      nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
    2399           0 :                      nsIContentPolicy::TYPE_OTHER);
    2400           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2401           0 :   nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
    2402           0 :   NS_ENSURE_STATE(loadInfo);
    2403           0 :   loadInfo->SetPrincipalToInherit(NodePrincipal());
    2404             : 
    2405             : 
    2406           0 :   mWyciwygChannel = do_QueryInterface(channel);
    2407             : 
    2408           0 :   mWyciwygChannel->SetSecurityInfo(mSecurityInfo);
    2409             : 
    2410             :   // Note: we want to treat this like a "previous document" hint so that,
    2411             :   // e.g. a <meta> tag in the document.write content can override it.
    2412           0 :   SetDocumentCharacterSetSource(kCharsetFromHintPrevDoc);
    2413           0 :   nsAutoCString charset;
    2414           0 :   GetDocumentCharacterSet()->Name(charset);
    2415           0 :   mWyciwygChannel->SetCharsetAndSource(kCharsetFromHintPrevDoc, charset);
    2416             : 
    2417             :   // Inherit load flags from the original document's channel
    2418           0 :   channel->SetLoadFlags(mLoadFlags);
    2419             : 
    2420           0 :   nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    2421             : 
    2422             :   // Use the Parent document's loadgroup to trigger load notifications
    2423           0 :   if (loadGroup && channel) {
    2424           0 :     rv = channel->SetLoadGroup(loadGroup);
    2425           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2426             : 
    2427           0 :     nsLoadFlags loadFlags = 0;
    2428           0 :     channel->GetLoadFlags(&loadFlags);
    2429           0 :     loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
    2430           0 :     channel->SetLoadFlags(loadFlags);
    2431             : 
    2432           0 :     channel->SetOriginalURI(wcwgURI);
    2433             : 
    2434           0 :     rv = loadGroup->AddRequest(mWyciwygChannel, nullptr);
    2435           0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to add request to load group.");
    2436             :   }
    2437             : 
    2438           0 :   return rv;
    2439             : }
    2440             : 
    2441             : nsresult
    2442           4 : nsHTMLDocument::RemoveWyciwygChannel(void)
    2443             : {
    2444           8 :   nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    2445             : 
    2446             :   // note there can be a write request without a load group if
    2447             :   // this is a synchronously constructed about:blank document
    2448           4 :   if (loadGroup && mWyciwygChannel) {
    2449           0 :     mWyciwygChannel->CloseCacheEntry(NS_OK);
    2450           0 :     loadGroup->RemoveRequest(mWyciwygChannel, nullptr, NS_OK);
    2451             :   }
    2452             : 
    2453           4 :   mWyciwygChannel = nullptr;
    2454             : 
    2455           8 :   return NS_OK;
    2456             : }
    2457             : 
    2458             : void *
    2459           0 : nsHTMLDocument::GenerateParserKey(void)
    2460             : {
    2461           0 :   if (!mScriptLoader) {
    2462             :     // If we don't have a script loader, then the parser probably isn't parsing
    2463             :     // anything anyway, so just return null.
    2464           0 :     return nullptr;
    2465             :   }
    2466             : 
    2467             :   // The script loader provides us with the currently executing script element,
    2468             :   // which is guaranteed to be unique per script.
    2469           0 :   nsIScriptElement* script = mScriptLoader->GetCurrentParserInsertedScript();
    2470           0 :   if (script && mParser && mParser->IsScriptCreated()) {
    2471           0 :     nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
    2472           0 :     if (creatorParser != mParser) {
    2473             :       // Make scripts that aren't inserted by the active parser of this document
    2474             :       // participate in the context of the script that document.open()ed
    2475             :       // this document.
    2476           0 :       return nullptr;
    2477             :     }
    2478             :   }
    2479           0 :   return script;
    2480             : }
    2481             : 
    2482             : NS_IMETHODIMP
    2483           0 : nsHTMLDocument::GetDesignMode(nsAString& aDesignMode)
    2484             : {
    2485           0 :   if (HasFlag(NODE_IS_EDITABLE)) {
    2486           0 :     aDesignMode.AssignLiteral("on");
    2487             :   }
    2488             :   else {
    2489           0 :     aDesignMode.AssignLiteral("off");
    2490             :   }
    2491           0 :   return NS_OK;
    2492             : }
    2493             : 
    2494             : void
    2495         132 : nsHTMLDocument::MaybeEditingStateChanged()
    2496             : {
    2497         510 :   if (!mPendingMaybeEditingStateChanged && mMayStartLayout &&
    2498         284 :       mUpdateNestLevel == 0 && (mContentEditableCount > 0) != IsEditingOn()) {
    2499           0 :     if (nsContentUtils::IsSafeToRunScript()) {
    2500           0 :       EditingStateChanged();
    2501           0 :     } else if (!mInDestructor) {
    2502           0 :       nsContentUtils::AddScriptRunner(
    2503           0 :         NewRunnableMethod("nsHTMLDocument::MaybeEditingStateChanged",
    2504             :                           this,
    2505           0 :                           &nsHTMLDocument::MaybeEditingStateChanged));
    2506             :     }
    2507             :   }
    2508         132 : }
    2509             : 
    2510             : void
    2511         129 : nsHTMLDocument::EndUpdate(nsUpdateType aUpdateType)
    2512             : {
    2513         129 :   const bool reset = !mPendingMaybeEditingStateChanged;
    2514         129 :   mPendingMaybeEditingStateChanged = true;
    2515         129 :   nsDocument::EndUpdate(aUpdateType);
    2516         129 :   if (reset) {
    2517         129 :     mPendingMaybeEditingStateChanged = false;
    2518             :   }
    2519         129 :   MaybeEditingStateChanged();
    2520         129 : }
    2521             : 
    2522             : void
    2523           3 : nsHTMLDocument::SetMayStartLayout(bool aMayStartLayout)
    2524             : {
    2525           3 :   nsIDocument::SetMayStartLayout(aMayStartLayout);
    2526             : 
    2527           3 :   MaybeEditingStateChanged();
    2528           3 : }
    2529             : 
    2530             : 
    2531             : 
    2532             : // Helper class, used below in ChangeContentEditableCount().
    2533           0 : class DeferredContentEditableCountChangeEvent : public Runnable
    2534             : {
    2535             : public:
    2536           0 :   DeferredContentEditableCountChangeEvent(nsHTMLDocument* aDoc,
    2537             :                                           nsIContent* aElement)
    2538           0 :     : mozilla::Runnable("DeferredContentEditableCountChangeEvent")
    2539             :     , mDoc(aDoc)
    2540           0 :     , mElement(aElement)
    2541             :   {
    2542           0 :   }
    2543             : 
    2544           0 :   NS_IMETHOD Run() override {
    2545           0 :     if (mElement && mElement->OwnerDoc() == mDoc) {
    2546           0 :       mDoc->DeferredContentEditableCountChange(mElement);
    2547             :     }
    2548           0 :     return NS_OK;
    2549             :   }
    2550             : 
    2551             : private:
    2552             :   RefPtr<nsHTMLDocument> mDoc;
    2553             :   nsCOMPtr<nsIContent> mElement;
    2554             : };
    2555             : 
    2556             : nsresult
    2557           0 : nsHTMLDocument::ChangeContentEditableCount(nsIContent *aElement,
    2558             :                                            int32_t aChange)
    2559             : {
    2560           0 :   NS_ASSERTION(int32_t(mContentEditableCount) + aChange >= 0,
    2561             :                "Trying to decrement too much.");
    2562             : 
    2563           0 :   mContentEditableCount += aChange;
    2564             : 
    2565             :   nsContentUtils::AddScriptRunner(
    2566           0 :     new DeferredContentEditableCountChangeEvent(this, aElement));
    2567             : 
    2568           0 :   return NS_OK;
    2569             : }
    2570             : 
    2571             : void
    2572           0 : nsHTMLDocument::DeferredContentEditableCountChange(nsIContent *aElement)
    2573             : {
    2574           0 :   if (mParser ||
    2575           0 :       (mUpdateNestLevel > 0 && (mContentEditableCount > 0) != IsEditingOn())) {
    2576           0 :     return;
    2577             :   }
    2578             : 
    2579           0 :   EditingState oldState = mEditingState;
    2580             : 
    2581           0 :   nsresult rv = EditingStateChanged();
    2582           0 :   NS_ENSURE_SUCCESS_VOID(rv);
    2583             : 
    2584           0 :   if (oldState == mEditingState && mEditingState == eContentEditable) {
    2585             :     // We just changed the contentEditable state of a node, we need to reset
    2586             :     // the spellchecking state of that node.
    2587           0 :     nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
    2588           0 :     if (node) {
    2589           0 :       nsPIDOMWindowOuter *window = GetWindow();
    2590           0 :       if (!window)
    2591           0 :         return;
    2592             : 
    2593           0 :       nsIDocShell *docshell = window->GetDocShell();
    2594           0 :       if (!docshell)
    2595           0 :         return;
    2596             : 
    2597           0 :       nsCOMPtr<nsIEditor> editor;
    2598           0 :       docshell->GetEditor(getter_AddRefs(editor));
    2599           0 :       if (editor) {
    2600           0 :         RefPtr<nsRange> range = new nsRange(aElement);
    2601           0 :         rv = range->SelectNode(node);
    2602           0 :         if (NS_FAILED(rv)) {
    2603             :           // The node might be detached from the document at this point,
    2604             :           // which would cause this call to fail.  In this case, we can
    2605             :           // safely ignore the contenteditable count change.
    2606           0 :           return;
    2607             :         }
    2608             : 
    2609           0 :         nsCOMPtr<nsIInlineSpellChecker> spellChecker;
    2610           0 :         rv = editor->GetInlineSpellChecker(false,
    2611           0 :                                            getter_AddRefs(spellChecker));
    2612           0 :         NS_ENSURE_SUCCESS_VOID(rv);
    2613             : 
    2614           0 :         if (spellChecker) {
    2615           0 :           rv = spellChecker->SpellCheckRange(range);
    2616             :         }
    2617             :       }
    2618             :     }
    2619             :   }
    2620             : }
    2621             : 
    2622             : HTMLAllCollection*
    2623           0 : nsHTMLDocument::All()
    2624             : {
    2625           0 :   if (!mAll) {
    2626           0 :     mAll = new HTMLAllCollection(this);
    2627             :   }
    2628           0 :   return mAll;
    2629             : }
    2630             : 
    2631             : static void
    2632           0 : NotifyEditableStateChange(nsINode *aNode, nsIDocument *aDocument)
    2633             : {
    2634           0 :   for (nsIContent* child = aNode->GetFirstChild();
    2635           0 :        child;
    2636           0 :        child = child->GetNextSibling()) {
    2637           0 :     if (child->IsElement()) {
    2638           0 :       child->AsElement()->UpdateState(true);
    2639             :     }
    2640           0 :     NotifyEditableStateChange(child, aDocument);
    2641             :   }
    2642           0 : }
    2643             : 
    2644             : void
    2645           0 : nsHTMLDocument::TearingDownEditor(nsIEditor *aEditor)
    2646             : {
    2647           0 :   if (IsEditingOn()) {
    2648           0 :     EditingState oldState = mEditingState;
    2649           0 :     mEditingState = eTearingDown;
    2650             : 
    2651           0 :     nsCOMPtr<nsIPresShell> presShell = GetShell();
    2652           0 :     if (!presShell)
    2653           0 :       return;
    2654             : 
    2655           0 :     nsTArray<RefPtr<StyleSheet>> agentSheets;
    2656           0 :     presShell->GetAgentStyleSheets(agentSheets);
    2657             : 
    2658           0 :     auto cache = nsLayoutStylesheetCache::For(GetStyleBackendType());
    2659             : 
    2660           0 :     agentSheets.RemoveElement(cache->ContentEditableSheet());
    2661           0 :     if (oldState == eDesignMode)
    2662           0 :       agentSheets.RemoveElement(cache->DesignModeSheet());
    2663             : 
    2664           0 :     presShell->SetAgentStyleSheets(agentSheets);
    2665             : 
    2666           0 :     presShell->RestyleForCSSRuleChanges();
    2667             :   }
    2668             : }
    2669             : 
    2670             : nsresult
    2671           0 : nsHTMLDocument::TurnEditingOff()
    2672             : {
    2673           0 :   NS_ASSERTION(mEditingState != eOff, "Editing is already off.");
    2674             : 
    2675           0 :   nsPIDOMWindowOuter *window = GetWindow();
    2676           0 :   if (!window)
    2677           0 :     return NS_ERROR_FAILURE;
    2678             : 
    2679           0 :   nsIDocShell *docshell = window->GetDocShell();
    2680           0 :   if (!docshell)
    2681           0 :     return NS_ERROR_FAILURE;
    2682             : 
    2683           0 :   nsCOMPtr<nsIEditingSession> editSession;
    2684           0 :   nsresult rv = docshell->GetEditingSession(getter_AddRefs(editSession));
    2685           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2686             : 
    2687             :   // turn editing off
    2688           0 :   rv = editSession->TearDownEditorOnWindow(window);
    2689           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2690             : 
    2691           0 :   mEditingState = eOff;
    2692             : 
    2693           0 :   return NS_OK;
    2694             : }
    2695             : 
    2696           0 : static bool HasPresShell(nsPIDOMWindowOuter *aWindow)
    2697             : {
    2698           0 :   nsIDocShell *docShell = aWindow->GetDocShell();
    2699           0 :   if (!docShell)
    2700           0 :     return false;
    2701           0 :   return docShell->GetPresShell() != nullptr;
    2702             : }
    2703             : 
    2704             : nsresult
    2705           0 : nsHTMLDocument::SetEditingState(EditingState aState)
    2706             : {
    2707           0 :   mEditingState = aState;
    2708           0 :   return NS_OK;
    2709             : }
    2710             : 
    2711             : nsresult
    2712           0 : nsHTMLDocument::EditingStateChanged()
    2713             : {
    2714           0 :   if (mRemovedFromDocShell) {
    2715           0 :     return NS_OK;
    2716             :   }
    2717             : 
    2718           0 :   if (mEditingState == eSettingUp || mEditingState == eTearingDown) {
    2719             :     // XXX We shouldn't recurse
    2720           0 :     return NS_OK;
    2721             :   }
    2722             : 
    2723           0 :   bool designMode = HasFlag(NODE_IS_EDITABLE);
    2724           0 :   EditingState newState = designMode ? eDesignMode :
    2725           0 :                           (mContentEditableCount > 0 ? eContentEditable : eOff);
    2726           0 :   if (mEditingState == newState) {
    2727             :     // No changes in editing mode.
    2728           0 :     return NS_OK;
    2729             :   }
    2730             : 
    2731           0 :   if (newState == eOff) {
    2732             :     // Editing is being turned off.
    2733           0 :     nsAutoScriptBlocker scriptBlocker;
    2734           0 :     NotifyEditableStateChange(this, this);
    2735           0 :     return TurnEditingOff();
    2736             :   }
    2737             : 
    2738             :   // Flush out style changes on our _parent_ document, if any, so that
    2739             :   // our check for a presshell won't get stale information.
    2740           0 :   if (mParentDocument) {
    2741           0 :     mParentDocument->FlushPendingNotifications(FlushType::Style);
    2742             :   }
    2743             : 
    2744             :   // get editing session, make sure this is a strong reference so the
    2745             :   // window can't get deleted during the rest of this call.
    2746           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
    2747           0 :   if (!window)
    2748           0 :     return NS_ERROR_FAILURE;
    2749             : 
    2750           0 :   nsIDocShell *docshell = window->GetDocShell();
    2751           0 :   if (!docshell)
    2752           0 :     return NS_ERROR_FAILURE;
    2753             : 
    2754           0 :   nsCOMPtr<nsIEditingSession> editSession;
    2755           0 :   nsresult rv = docshell->GetEditingSession(getter_AddRefs(editSession));
    2756           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2757             : 
    2758           0 :   nsCOMPtr<nsIEditor> existingEditor;
    2759           0 :   editSession->GetEditorForWindow(window, getter_AddRefs(existingEditor));
    2760           0 :   if (existingEditor) {
    2761             :     // We might already have an editor if it was set up for mail, let's see
    2762             :     // if this is actually the case.
    2763             : #ifdef DEBUG
    2764           0 :     nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(existingEditor);
    2765           0 :     MOZ_ASSERT(htmlEditor, "If we have an editor, it must be an HTML editor");
    2766             : #endif
    2767           0 :     uint32_t flags = 0;
    2768           0 :     existingEditor->GetFlags(&flags);
    2769           0 :     if (flags & nsIPlaintextEditor::eEditorMailMask) {
    2770             :       // We already have a mail editor, then we should not attempt to create
    2771             :       // another one.
    2772           0 :       return NS_OK;
    2773             :     }
    2774             :   }
    2775             : 
    2776           0 :   if (!HasPresShell(window)) {
    2777             :     // We should not make the window editable or setup its editor.
    2778             :     // It's probably style=display:none.
    2779           0 :     return NS_OK;
    2780             :   }
    2781             : 
    2782           0 :   bool makeWindowEditable = mEditingState == eOff;
    2783           0 :   bool updateState = false;
    2784           0 :   bool spellRecheckAll = false;
    2785           0 :   bool putOffToRemoveScriptBlockerUntilModifyingEditingState = false;
    2786           0 :   nsCOMPtr<nsIEditor> editor;
    2787             : 
    2788             :   {
    2789           0 :     EditingState oldState = mEditingState;
    2790           0 :     nsAutoEditingState push(this, eSettingUp);
    2791             : 
    2792           0 :     nsCOMPtr<nsIPresShell> presShell = GetShell();
    2793           0 :     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
    2794             : 
    2795             :     // Before making this window editable, we need to modify UA style sheet
    2796             :     // because new style may change whether focused element will be focusable
    2797             :     // or not.
    2798           0 :     nsTArray<RefPtr<StyleSheet>> agentSheets;
    2799           0 :     rv = presShell->GetAgentStyleSheets(agentSheets);
    2800           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2801             : 
    2802           0 :     auto cache = nsLayoutStylesheetCache::For(GetStyleBackendType());
    2803             : 
    2804           0 :     StyleSheet* contentEditableSheet = cache->ContentEditableSheet();
    2805             : 
    2806           0 :     if (!agentSheets.Contains(contentEditableSheet)) {
    2807           0 :       agentSheets.AppendElement(contentEditableSheet);
    2808             :     }
    2809             : 
    2810             :     // Should we update the editable state of all the nodes in the document? We
    2811             :     // need to do this when the designMode value changes, as that overrides
    2812             :     // specific states on the elements.
    2813           0 :     if (designMode) {
    2814             :       // designMode is being turned on (overrides contentEditable).
    2815           0 :       StyleSheet* designModeSheet = cache->DesignModeSheet();
    2816           0 :       if (!agentSheets.Contains(designModeSheet)) {
    2817           0 :         agentSheets.AppendElement(designModeSheet);
    2818             :       }
    2819             : 
    2820           0 :       updateState = true;
    2821           0 :       spellRecheckAll = oldState == eContentEditable;
    2822             :     }
    2823           0 :     else if (oldState == eDesignMode) {
    2824             :       // designMode is being turned off (contentEditable is still on).
    2825           0 :       agentSheets.RemoveElement(cache->DesignModeSheet());
    2826           0 :       updateState = true;
    2827             :     }
    2828             : 
    2829           0 :     rv = presShell->SetAgentStyleSheets(agentSheets);
    2830           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2831             : 
    2832           0 :     presShell->RestyleForCSSRuleChanges();
    2833             : 
    2834             :     // Adjust focused element with new style but blur event shouldn't be fired
    2835             :     // until mEditingState is modified with newState.
    2836           0 :     nsAutoScriptBlocker scriptBlocker;
    2837           0 :     if (designMode) {
    2838           0 :       nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
    2839             :       nsIContent* focusedContent =
    2840           0 :         nsFocusManager::GetFocusedDescendant(window, false,
    2841           0 :                                              getter_AddRefs(focusedWindow));
    2842           0 :       if (focusedContent) {
    2843           0 :         nsIFrame* focusedFrame = focusedContent->GetPrimaryFrame();
    2844           0 :         bool clearFocus = focusedFrame ? !focusedFrame->IsFocusable() :
    2845           0 :                                          !focusedContent->IsFocusable();
    2846           0 :         if (clearFocus) {
    2847           0 :           nsFocusManager* fm = nsFocusManager::GetFocusManager();
    2848           0 :           if (fm) {
    2849           0 :             fm->ClearFocus(window);
    2850             :             // If we need to dispatch blur event, we should put off after
    2851             :             // modifying mEditingState since blur event handler may change
    2852             :             // designMode state again.
    2853           0 :             putOffToRemoveScriptBlockerUntilModifyingEditingState = true;
    2854             :           }
    2855             :         }
    2856             :       }
    2857             :     }
    2858             : 
    2859           0 :     if (makeWindowEditable) {
    2860             :       // Editing is being turned on (through designMode or contentEditable)
    2861             :       // Turn on editor.
    2862             :       // XXX This can cause flushing which can change the editing state, so make
    2863             :       //     sure to avoid recursing.
    2864           0 :       rv = editSession->MakeWindowEditable(window, "html", false, false,
    2865           0 :                                            true);
    2866           0 :       NS_ENSURE_SUCCESS(rv, rv);
    2867             :     }
    2868             : 
    2869             :     // XXX Need to call TearDownEditorOnWindow for all failures.
    2870           0 :     docshell->GetEditor(getter_AddRefs(editor));
    2871           0 :     if (!editor)
    2872           0 :       return NS_ERROR_FAILURE;
    2873             : 
    2874             :     // If we're entering the design mode, put the selection at the beginning of
    2875             :     // the document for compatibility reasons.
    2876           0 :     if (designMode && oldState == eOff) {
    2877           0 :       editor->BeginningOfDocument();
    2878             :     }
    2879             : 
    2880           0 :     if (putOffToRemoveScriptBlockerUntilModifyingEditingState) {
    2881           0 :       nsContentUtils::AddScriptBlocker();
    2882             :     }
    2883             :   }
    2884             : 
    2885           0 :   mEditingState = newState;
    2886           0 :   if (putOffToRemoveScriptBlockerUntilModifyingEditingState) {
    2887           0 :     nsContentUtils::RemoveScriptBlocker();
    2888             :     // If mEditingState is overwritten by another call and already disabled
    2889             :     // the editing, we shouldn't keep making window editable.
    2890           0 :     if (mEditingState == eOff) {
    2891           0 :       return NS_OK;
    2892             :     }
    2893             :   }
    2894             : 
    2895           0 :   if (makeWindowEditable) {
    2896             :     // Set the editor to not insert br's on return when in p
    2897             :     // elements by default.
    2898             :     // XXX Do we only want to do this for designMode?
    2899             :     // Note that it doesn't matter what CallerType we pass, because the callee
    2900             :     // doesn't use it for this command.  Play it safe and pass the more
    2901             :     // restricted one.
    2902           0 :     ErrorResult errorResult;
    2903           0 :     Unused << ExecCommand(NS_LITERAL_STRING("insertBrOnReturn"), false,
    2904           0 :                           NS_LITERAL_STRING("false"),
    2905             :                           // Principal doesn't matter here, because the
    2906             :                           // insertBrOnReturn command doesn't use it.   Still
    2907             :                           // it's too bad we can't easily grab a nullprincipal
    2908             :                           // from somewhere without allocating one..
    2909           0 :                           *NodePrincipal(),
    2910           0 :                           errorResult);
    2911             : 
    2912           0 :     if (errorResult.Failed()) {
    2913             :       // Editor setup failed. Editing is not on after all.
    2914             :       // XXX Should we reset the editable flag on nodes?
    2915           0 :       editSession->TearDownEditorOnWindow(window);
    2916           0 :       mEditingState = eOff;
    2917             : 
    2918           0 :       return errorResult.StealNSResult();
    2919             :     }
    2920             :   }
    2921             : 
    2922           0 :   if (updateState) {
    2923           0 :     nsAutoScriptBlocker scriptBlocker;
    2924           0 :     NotifyEditableStateChange(this, this);
    2925             :   }
    2926             : 
    2927             :   // Resync the editor's spellcheck state.
    2928           0 :   if (spellRecheckAll) {
    2929           0 :     nsCOMPtr<nsISelectionController> selcon;
    2930           0 :     nsresult rv = editor->GetSelectionController(getter_AddRefs(selcon));
    2931           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2932             : 
    2933           0 :     nsCOMPtr<nsISelection> spellCheckSelection;
    2934           0 :     rv = selcon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
    2935           0 :                               getter_AddRefs(spellCheckSelection));
    2936           0 :     if (NS_SUCCEEDED(rv)) {
    2937           0 :       spellCheckSelection->RemoveAllRanges();
    2938             :     }
    2939             :   }
    2940           0 :   editor->SyncRealTimeSpell();
    2941             : 
    2942           0 :   return NS_OK;
    2943             : }
    2944             : 
    2945             : NS_IMETHODIMP
    2946           0 : nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode)
    2947             : {
    2948           0 :   ErrorResult rv;
    2949           0 :   SetDesignMode(aDesignMode, nsContentUtils::GetCurrentJSContext()
    2950           0 :                                ? Some(nsContentUtils::SubjectPrincipal())
    2951           0 :                                : Nothing(), rv);
    2952           0 :   return rv.StealNSResult();
    2953             : }
    2954             : 
    2955             : void
    2956           0 : nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
    2957             :                               nsIPrincipal& aSubjectPrincipal,
    2958             :                               ErrorResult& rv)
    2959             : {
    2960           0 :   SetDesignMode(aDesignMode, Some(&aSubjectPrincipal), rv);
    2961           0 : }
    2962             : 
    2963             : void
    2964           0 : nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
    2965             :                               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
    2966             :                               ErrorResult& rv)
    2967             : {
    2968           0 :   if (aSubjectPrincipal.isSome() &&
    2969           0 :       !aSubjectPrincipal.value()->Subsumes(NodePrincipal())) {
    2970           0 :     rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
    2971           0 :     return;
    2972             :   }
    2973           0 :   bool editableMode = HasFlag(NODE_IS_EDITABLE);
    2974           0 :   if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
    2975           0 :     SetEditableFlag(!editableMode);
    2976             : 
    2977           0 :     rv = EditingStateChanged();
    2978             :   }
    2979             : }
    2980             : 
    2981             : nsresult
    2982           0 : nsHTMLDocument::GetMidasCommandManager(nsICommandManager** aCmdMgr)
    2983             : {
    2984             :   // initialize return value
    2985           0 :   NS_ENSURE_ARG_POINTER(aCmdMgr);
    2986             : 
    2987             :   // check if we have it cached
    2988           0 :   if (mMidasCommandManager) {
    2989           0 :     NS_ADDREF(*aCmdMgr = mMidasCommandManager);
    2990           0 :     return NS_OK;
    2991             :   }
    2992             : 
    2993           0 :   *aCmdMgr = nullptr;
    2994             : 
    2995           0 :   nsPIDOMWindowOuter *window = GetWindow();
    2996           0 :   if (!window)
    2997           0 :     return NS_ERROR_FAILURE;
    2998             : 
    2999           0 :   nsIDocShell *docshell = window->GetDocShell();
    3000           0 :   if (!docshell)
    3001           0 :     return NS_ERROR_FAILURE;
    3002             : 
    3003           0 :   mMidasCommandManager = docshell->GetCommandManager();
    3004           0 :   if (!mMidasCommandManager)
    3005           0 :     return NS_ERROR_FAILURE;
    3006             : 
    3007           0 :   NS_ADDREF(*aCmdMgr = mMidasCommandManager);
    3008             : 
    3009           0 :   return NS_OK;
    3010             : }
    3011             : 
    3012             : 
    3013             : struct MidasCommand {
    3014             :   const char*  incomingCommandString;
    3015             :   const char*  internalCommandString;
    3016             :   const char*  internalParamString;
    3017             :   bool useNewParam;
    3018             :   bool convertToBoolean;
    3019             : };
    3020             : 
    3021             : static const struct MidasCommand gMidasCommandTable[] = {
    3022             :   { "bold",          "cmd_bold",            "", true,  false },
    3023             :   { "italic",        "cmd_italic",          "", true,  false },
    3024             :   { "underline",     "cmd_underline",       "", true,  false },
    3025             :   { "strikethrough", "cmd_strikethrough",   "", true,  false },
    3026             :   { "subscript",     "cmd_subscript",       "", true,  false },
    3027             :   { "superscript",   "cmd_superscript",     "", true,  false },
    3028             :   { "cut",           "cmd_cut",             "", true,  false },
    3029             :   { "copy",          "cmd_copy",            "", true,  false },
    3030             :   { "paste",         "cmd_paste",           "", true,  false },
    3031             :   { "delete",        "cmd_deleteCharBackward", "", true,  false },
    3032             :   { "forwarddelete", "cmd_deleteCharForward", "", true,  false },
    3033             :   { "selectall",     "cmd_selectAll",       "", true,  false },
    3034             :   { "undo",          "cmd_undo",            "", true,  false },
    3035             :   { "redo",          "cmd_redo",            "", true,  false },
    3036             :   { "indent",        "cmd_indent",          "", true,  false },
    3037             :   { "outdent",       "cmd_outdent",         "", true,  false },
    3038             :   { "backcolor",     "cmd_highlight",       "", false, false },
    3039             :   { "forecolor",     "cmd_fontColor",       "", false, false },
    3040             :   { "hilitecolor",   "cmd_highlight",       "", false, false },
    3041             :   { "fontname",      "cmd_fontFace",        "", false, false },
    3042             :   { "fontsize",      "cmd_fontSize",        "", false, false },
    3043             :   { "increasefontsize", "cmd_increaseFont", "", false, false },
    3044             :   { "decreasefontsize", "cmd_decreaseFont", "", false, false },
    3045             :   { "inserthorizontalrule", "cmd_insertHR", "", true,  false },
    3046             :   { "createlink",    "cmd_insertLinkNoUI",  "", false, false },
    3047             :   { "insertimage",   "cmd_insertImageNoUI", "", false, false },
    3048             :   { "inserthtml",    "cmd_insertHTML",      "", false, false },
    3049             :   { "inserttext",    "cmd_insertText",      "", false, false },
    3050             :   { "gethtml",       "cmd_getContents",     "", false, false },
    3051             :   { "justifyleft",   "cmd_align",       "left", true,  false },
    3052             :   { "justifyright",  "cmd_align",      "right", true,  false },
    3053             :   { "justifycenter", "cmd_align",     "center", true,  false },
    3054             :   { "justifyfull",   "cmd_align",    "justify", true,  false },
    3055             :   { "removeformat",  "cmd_removeStyles",    "", true,  false },
    3056             :   { "unlink",        "cmd_removeLinks",     "", true,  false },
    3057             :   { "insertorderedlist",   "cmd_ol",        "", true,  false },
    3058             :   { "insertunorderedlist", "cmd_ul",        "", true,  false },
    3059             :   { "insertparagraph", "cmd_insertParagraph", "", true,  false },
    3060             :   { "insertlinebreak", "cmd_insertLineBreak", "", true,  false },
    3061             :   { "formatblock",   "cmd_paragraphState",  "", false, false },
    3062             :   { "heading",       "cmd_paragraphState",  "", false, false },
    3063             :   { "styleWithCSS",  "cmd_setDocumentUseCSS", "", false, true },
    3064             :   { "contentReadOnly", "cmd_setDocumentReadOnly", "", false, true },
    3065             :   { "insertBrOnReturn", "cmd_insertBrOnReturn", "", false, true },
    3066             :   { "defaultParagraphSeparator", "cmd_defaultParagraphSeparator", "", false, false },
    3067             :   { "enableObjectResizing", "cmd_enableObjectResizing", "", false, true },
    3068             :   { "enableInlineTableEditing", "cmd_enableInlineTableEditing", "", false, true },
    3069             : #if 0
    3070             : // no editor support to remove alignments right now
    3071             :   { "justifynone",   "cmd_align",           "", true,  false },
    3072             : 
    3073             : // the following will need special review before being turned on
    3074             :   { "saveas",        "cmd_saveAs",          "", true,  false },
    3075             :   { "print",         "cmd_print",           "", true,  false },
    3076             : #endif
    3077             :   { nullptr, nullptr, nullptr, false, false }
    3078             : };
    3079             : 
    3080             : #define MidasCommandCount ((sizeof(gMidasCommandTable) / sizeof(struct MidasCommand)) - 1)
    3081             : 
    3082             : static const char* const gBlocks[] = {
    3083             :   "ADDRESS",
    3084             :   "BLOCKQUOTE",
    3085             :   "DD",
    3086             :   "DIV",
    3087             :   "DL",
    3088             :   "DT",
    3089             :   "H1",
    3090             :   "H2",
    3091             :   "H3",
    3092             :   "H4",
    3093             :   "H5",
    3094             :   "H6",
    3095             :   "P",
    3096             :   "PRE"
    3097             : };
    3098             : 
    3099             : static bool
    3100           0 : ConvertToMidasInternalCommandInner(const nsAString& inCommandID,
    3101             :                                    const nsAString& inParam,
    3102             :                                    nsACString& outCommandID,
    3103             :                                    nsACString& outParam,
    3104             :                                    bool& outIsBoolean,
    3105             :                                    bool& outBooleanValue,
    3106             :                                    bool aIgnoreParams)
    3107             : {
    3108           0 :   NS_ConvertUTF16toUTF8 convertedCommandID(inCommandID);
    3109             : 
    3110             :   // Hack to support old boolean commands that were backwards (see bug 301490).
    3111           0 :   bool invertBool = false;
    3112           0 :   if (convertedCommandID.LowerCaseEqualsLiteral("usecss")) {
    3113           0 :     convertedCommandID.AssignLiteral("styleWithCSS");
    3114           0 :     invertBool = true;
    3115           0 :   } else if (convertedCommandID.LowerCaseEqualsLiteral("readonly")) {
    3116           0 :     convertedCommandID.AssignLiteral("contentReadOnly");
    3117           0 :     invertBool = true;
    3118             :   }
    3119             : 
    3120             :   uint32_t i;
    3121           0 :   bool found = false;
    3122           0 :   for (i = 0; i < MidasCommandCount; ++i) {
    3123           0 :     if (convertedCommandID.Equals(gMidasCommandTable[i].incomingCommandString,
    3124           0 :                                   nsCaseInsensitiveCStringComparator())) {
    3125           0 :       found = true;
    3126           0 :       break;
    3127             :     }
    3128             :   }
    3129             : 
    3130           0 :   if (!found) {
    3131             :     // reset results if the command is not found in our table
    3132           0 :     outCommandID.SetLength(0);
    3133           0 :     outParam.SetLength(0);
    3134           0 :     outIsBoolean = false;
    3135           0 :     return false;
    3136             :   }
    3137             : 
    3138             :   // set outCommandID (what we use internally)
    3139           0 :   outCommandID.Assign(gMidasCommandTable[i].internalCommandString);
    3140             : 
    3141             :   // set outParam & outIsBoolean based on flags from the table
    3142           0 :   outIsBoolean = gMidasCommandTable[i].convertToBoolean;
    3143             : 
    3144           0 :   if (aIgnoreParams) {
    3145             :     // No further work to do
    3146           0 :     return true;
    3147             :   }
    3148             : 
    3149           0 :   if (gMidasCommandTable[i].useNewParam) {
    3150             :     // Just have to copy it, no checking
    3151           0 :     outParam.Assign(gMidasCommandTable[i].internalParamString);
    3152           0 :     return true;
    3153             :   }
    3154             : 
    3155             :   // handle checking of param passed in
    3156           0 :   if (outIsBoolean) {
    3157             :     // If this is a boolean value and it's not explicitly false (e.g. no value)
    3158             :     // we default to "true". For old backwards commands we invert the check (see
    3159             :     // bug 301490).
    3160           0 :     if (invertBool) {
    3161           0 :       outBooleanValue = inParam.LowerCaseEqualsLiteral("false");
    3162             :     } else {
    3163           0 :       outBooleanValue = !inParam.LowerCaseEqualsLiteral("false");
    3164             :     }
    3165           0 :     outParam.Truncate();
    3166             : 
    3167           0 :     return true;
    3168             :   }
    3169             : 
    3170             :   // String parameter -- see if we need to convert it (necessary for
    3171             :   // cmd_paragraphState and cmd_fontSize)
    3172           0 :   if (outCommandID.EqualsLiteral("cmd_paragraphState")) {
    3173           0 :     const char16_t* start = inParam.BeginReading();
    3174           0 :     const char16_t* end = inParam.EndReading();
    3175           0 :     if (start != end && *start == '<' && *(end - 1) == '>') {
    3176           0 :       ++start;
    3177           0 :       --end;
    3178             :     }
    3179             : 
    3180           0 :     NS_ConvertUTF16toUTF8 convertedParam(Substring(start, end));
    3181             :     uint32_t j;
    3182           0 :     for (j = 0; j < ArrayLength(gBlocks); ++j) {
    3183           0 :       if (convertedParam.Equals(gBlocks[j],
    3184           0 :                                 nsCaseInsensitiveCStringComparator())) {
    3185           0 :         outParam.Assign(gBlocks[j]);
    3186           0 :         break;
    3187             :       }
    3188             :     }
    3189             : 
    3190           0 :     if (j == ArrayLength(gBlocks)) {
    3191           0 :       outParam.Truncate();
    3192             :     }
    3193           0 :   } else if (outCommandID.EqualsLiteral("cmd_fontSize")) {
    3194             :     // Per editing spec as of April 23, 2012, we need to reject the value if
    3195             :     // it's not a valid floating-point number surrounded by optional whitespace.
    3196             :     // Otherwise, we parse it as a legacy font size.  For now, we just parse as
    3197             :     // a legacy font size regardless (matching WebKit) -- bug 747879.
    3198           0 :     outParam.Truncate();
    3199           0 :     int32_t size = nsContentUtils::ParseLegacyFontSize(inParam);
    3200           0 :     if (size) {
    3201           0 :       outParam.AppendInt(size);
    3202             :     }
    3203             :   } else {
    3204           0 :     CopyUTF16toUTF8(inParam, outParam);
    3205             :   }
    3206             : 
    3207           0 :   return true;
    3208             : }
    3209             : 
    3210             : static bool
    3211           0 : ConvertToMidasInternalCommand(const nsAString & inCommandID,
    3212             :                               const nsAString & inParam,
    3213             :                               nsACString& outCommandID,
    3214             :                               nsACString& outParam,
    3215             :                               bool& outIsBoolean,
    3216             :                               bool& outBooleanValue)
    3217             : {
    3218             :   return ConvertToMidasInternalCommandInner(inCommandID, inParam, outCommandID,
    3219             :                                             outParam, outIsBoolean,
    3220           0 :                                             outBooleanValue, false);
    3221             : }
    3222             : 
    3223             : static bool
    3224           0 : ConvertToMidasInternalCommand(const nsAString & inCommandID,
    3225             :                               nsACString& outCommandID)
    3226             : {
    3227           0 :   nsAutoCString dummyCString;
    3228           0 :   nsAutoString dummyString;
    3229             :   bool dummyBool;
    3230             :   return ConvertToMidasInternalCommandInner(inCommandID, dummyString,
    3231             :                                             outCommandID, dummyCString,
    3232           0 :                                             dummyBool, dummyBool, true);
    3233             : }
    3234             : 
    3235             : bool
    3236           0 : nsHTMLDocument::ExecCommand(const nsAString& commandID,
    3237             :                             bool doShowUI,
    3238             :                             const nsAString& value,
    3239             :                             nsIPrincipal& aSubjectPrincipal,
    3240             :                             ErrorResult& rv)
    3241             : {
    3242             :   //  for optional parameters see dom/src/base/nsHistory.cpp: HistoryImpl::Go()
    3243             :   //  this might add some ugly JS dependencies?
    3244             : 
    3245           0 :   nsAutoCString cmdToDispatch, paramStr;
    3246             :   bool isBool, boolVal;
    3247           0 :   if (!ConvertToMidasInternalCommand(commandID, value,
    3248             :                                      cmdToDispatch, paramStr,
    3249             :                                      isBool, boolVal)) {
    3250           0 :     return false;
    3251             :   }
    3252             : 
    3253           0 :   bool isCutCopy = (commandID.LowerCaseEqualsLiteral("cut") ||
    3254           0 :                     commandID.LowerCaseEqualsLiteral("copy"));
    3255             : 
    3256             :   // if editing is not on, bail
    3257           0 :   if (!isCutCopy && !IsEditingOnAfterFlush()) {
    3258           0 :     return false;
    3259             :   }
    3260             : 
    3261             :   // if they are requesting UI from us, let's fail since we have no UI
    3262           0 :   if (doShowUI) {
    3263           0 :     return false;
    3264             :   }
    3265             : 
    3266             :   // special case for cut & copy
    3267             :   // cut & copy are allowed in non editable documents
    3268           0 :   if (isCutCopy) {
    3269           0 :     if (!nsContentUtils::IsCutCopyAllowed(&aSubjectPrincipal)) {
    3270             :       // We have rejected the event due to it not being performed in an
    3271             :       // input-driven context therefore, we report the error to the console.
    3272           0 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    3273           0 :                                       NS_LITERAL_CSTRING("DOM"), this,
    3274             :                                       nsContentUtils::eDOM_PROPERTIES,
    3275           0 :                                       "ExecCommandCutCopyDeniedNotInputDriven");
    3276           0 :       return false;
    3277             :     }
    3278             : 
    3279             :     // For cut & copy commands, we need the behaviour from nsWindowRoot::GetControllers
    3280             :     // which is to look at the focused element, and defer to a focused textbox's controller
    3281             :     // The code past taken by other commands in ExecCommand always uses the window directly,
    3282             :     // rather than deferring to the textbox, which is desireable for most editor commands,
    3283             :     // but not 'cut' and 'copy' (as those should allow copying out of embedded editors).
    3284             :     // This behaviour is invoked if we call DoCommand directly on the docShell.
    3285           0 :     nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
    3286           0 :     if (docShell) {
    3287           0 :       nsresult res = docShell->DoCommand(cmdToDispatch.get());
    3288           0 :       return NS_SUCCEEDED(res);
    3289             :     }
    3290           0 :     return false;
    3291             :   }
    3292             : 
    3293           0 :   if (commandID.LowerCaseEqualsLiteral("gethtml")) {
    3294           0 :     rv.Throw(NS_ERROR_FAILURE);
    3295           0 :     return false;
    3296             :   }
    3297             : 
    3298           0 :   bool restricted = commandID.LowerCaseEqualsLiteral("paste");
    3299           0 :   if (restricted && !nsContentUtils::PrincipalHasPermission(&aSubjectPrincipal,
    3300           0 :                                                             NS_LITERAL_STRING("clipboardRead"))) {
    3301           0 :     return false;
    3302             :   }
    3303             : 
    3304             :   // get command manager and dispatch command to our window if it's acceptable
    3305           0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3306           0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3307           0 :   if (!cmdMgr) {
    3308           0 :     rv.Throw(NS_ERROR_FAILURE);
    3309           0 :     return false;
    3310             :   }
    3311             : 
    3312           0 :   nsPIDOMWindowOuter* window = GetWindow();
    3313           0 :   if (!window) {
    3314           0 :     rv.Throw(NS_ERROR_FAILURE);
    3315           0 :     return false;
    3316             :   }
    3317             : 
    3318           0 :   if ((cmdToDispatch.EqualsLiteral("cmd_fontSize") ||
    3319           0 :        cmdToDispatch.EqualsLiteral("cmd_insertImageNoUI") ||
    3320           0 :        cmdToDispatch.EqualsLiteral("cmd_insertLinkNoUI") ||
    3321           0 :        cmdToDispatch.EqualsLiteral("cmd_paragraphState")) &&
    3322           0 :       paramStr.IsEmpty()) {
    3323             :     // Invalid value, return false
    3324           0 :     return false;
    3325             :   }
    3326             : 
    3327           0 :   if (cmdToDispatch.EqualsLiteral("cmd_defaultParagraphSeparator") &&
    3328           0 :       !paramStr.LowerCaseEqualsLiteral("div") &&
    3329           0 :       !paramStr.LowerCaseEqualsLiteral("p") &&
    3330           0 :       !paramStr.LowerCaseEqualsLiteral("br")) {
    3331             :     // Invalid value
    3332           0 :     return false;
    3333             :   }
    3334             : 
    3335             :   // Return false for disabled commands (bug 760052)
    3336           0 :   bool enabled = false;
    3337           0 :   cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &enabled);
    3338           0 :   if (!enabled) {
    3339           0 :     return false;
    3340             :   }
    3341             : 
    3342           0 :   if (!isBool && paramStr.IsEmpty()) {
    3343           0 :     rv = cmdMgr->DoCommand(cmdToDispatch.get(), nullptr, window);
    3344             :   } else {
    3345             :     // we have a command that requires a parameter, create params
    3346           0 :     nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3347           0 :                                             NS_COMMAND_PARAMS_CONTRACTID);
    3348           0 :     if (!cmdParams) {
    3349           0 :       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
    3350           0 :       return false;
    3351             :     }
    3352             : 
    3353           0 :     if (isBool) {
    3354           0 :       rv = cmdParams->SetBooleanValue("state_attribute", boolVal);
    3355           0 :     } else if (cmdToDispatch.EqualsLiteral("cmd_fontFace")) {
    3356           0 :       rv = cmdParams->SetStringValue("state_attribute", value);
    3357           0 :     } else if (cmdToDispatch.EqualsLiteral("cmd_insertHTML") ||
    3358           0 :                cmdToDispatch.EqualsLiteral("cmd_insertText")) {
    3359           0 :       rv = cmdParams->SetStringValue("state_data", value);
    3360             :     } else {
    3361           0 :       rv = cmdParams->SetCStringValue("state_attribute", paramStr.get());
    3362             :     }
    3363           0 :     if (rv.Failed()) {
    3364           0 :       return false;
    3365             :     }
    3366           0 :     rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window);
    3367             :   }
    3368             : 
    3369           0 :   return !rv.Failed();
    3370             : }
    3371             : 
    3372             : bool
    3373           0 : nsHTMLDocument::QueryCommandEnabled(const nsAString& commandID,
    3374             :                                     nsIPrincipal& aSubjectPrincipal,
    3375             :                                     ErrorResult& rv)
    3376             : {
    3377           0 :   nsAutoCString cmdToDispatch;
    3378           0 :   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
    3379           0 :     return false;
    3380             :   }
    3381             : 
    3382             :   // cut & copy are always allowed
    3383           0 :   bool isCutCopy = commandID.LowerCaseEqualsLiteral("cut") ||
    3384           0 :                    commandID.LowerCaseEqualsLiteral("copy");
    3385           0 :   if (isCutCopy) {
    3386           0 :     return nsContentUtils::IsCutCopyAllowed(&aSubjectPrincipal);
    3387             :   }
    3388             : 
    3389             :   // Report false for restricted commands
    3390           0 :   bool restricted = commandID.LowerCaseEqualsLiteral("paste");
    3391           0 :   if (restricted && !nsContentUtils::IsSystemPrincipal(&aSubjectPrincipal)) {
    3392           0 :     return false;
    3393             :   }
    3394             : 
    3395             :   // if editing is not on, bail
    3396           0 :   if (!IsEditingOnAfterFlush()) {
    3397           0 :     return false;
    3398             :   }
    3399             : 
    3400             :   // get command manager and dispatch command to our window if it's acceptable
    3401           0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3402           0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3403           0 :   if (!cmdMgr) {
    3404           0 :     rv.Throw(NS_ERROR_FAILURE);
    3405           0 :     return false;
    3406             :   }
    3407             : 
    3408           0 :   nsPIDOMWindowOuter* window = GetWindow();
    3409           0 :   if (!window) {
    3410           0 :     rv.Throw(NS_ERROR_FAILURE);
    3411           0 :     return false;
    3412             :   }
    3413             : 
    3414             :   bool retval;
    3415           0 :   rv = cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &retval);
    3416           0 :   return retval;
    3417             : }
    3418             : 
    3419             : NS_IMETHODIMP
    3420           0 : nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID,
    3421             :                                      bool *_retval)
    3422             : {
    3423           0 :   ErrorResult rv;
    3424           0 :   *_retval = QueryCommandIndeterm(commandID, rv);
    3425           0 :   return rv.StealNSResult();
    3426             : }
    3427             : 
    3428             : bool
    3429           0 : nsHTMLDocument::QueryCommandIndeterm(const nsAString& commandID, ErrorResult& rv)
    3430             : {
    3431           0 :   nsAutoCString cmdToDispatch;
    3432           0 :   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
    3433           0 :     return false;
    3434             :   }
    3435             : 
    3436             :   // if editing is not on, bail
    3437           0 :   if (!IsEditingOnAfterFlush()) {
    3438           0 :     return false;
    3439             :   }
    3440             : 
    3441             :   // get command manager and dispatch command to our window if it's acceptable
    3442           0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3443           0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3444           0 :   if (!cmdMgr) {
    3445           0 :     rv.Throw(NS_ERROR_FAILURE);
    3446           0 :     return false;
    3447             :   }
    3448             : 
    3449           0 :   nsPIDOMWindowOuter* window = GetWindow();
    3450           0 :   if (!window) {
    3451           0 :     rv.Throw(NS_ERROR_FAILURE);
    3452           0 :     return false;
    3453             :   }
    3454             : 
    3455             :   nsresult res;
    3456           0 :   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3457           0 :                                            NS_COMMAND_PARAMS_CONTRACTID, &res);
    3458           0 :   if (NS_FAILED(res)) {
    3459           0 :     rv.Throw(res);
    3460           0 :     return false;
    3461             :   }
    3462             : 
    3463           0 :   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
    3464           0 :   if (rv.Failed()) {
    3465           0 :     return false;
    3466             :   }
    3467             : 
    3468             :   // If command does not have a state_mixed value, this call fails and sets
    3469             :   // retval to false.  This is fine -- we want to return false in that case
    3470             :   // anyway (bug 738385), so we just don't throw regardless.
    3471           0 :   bool retval = false;
    3472           0 :   cmdParams->GetBooleanValue("state_mixed", &retval);
    3473           0 :   return retval;
    3474             : }
    3475             : 
    3476             : NS_IMETHODIMP
    3477           0 : nsHTMLDocument::QueryCommandState(const nsAString & commandID, bool *_retval)
    3478             : {
    3479           0 :   ErrorResult rv;
    3480           0 :   *_retval = QueryCommandState(commandID, rv);
    3481           0 :   return rv.StealNSResult();
    3482             : }
    3483             : 
    3484             : bool
    3485           0 : nsHTMLDocument::QueryCommandState(const nsAString& commandID, ErrorResult& rv)
    3486             : {
    3487           0 :   nsAutoCString cmdToDispatch, paramToCheck;
    3488             :   bool dummy, dummy2;
    3489           0 :   if (!ConvertToMidasInternalCommand(commandID, commandID,
    3490             :                                      cmdToDispatch, paramToCheck,
    3491             :                                      dummy, dummy2)) {
    3492           0 :     return false;
    3493             :   }
    3494             : 
    3495             :   // if editing is not on, bail
    3496           0 :   if (!IsEditingOnAfterFlush()) {
    3497           0 :     return false;
    3498             :   }
    3499             : 
    3500             :   // get command manager and dispatch command to our window if it's acceptable
    3501           0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3502           0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3503           0 :   if (!cmdMgr) {
    3504           0 :     rv.Throw(NS_ERROR_FAILURE);
    3505           0 :     return false;
    3506             :   }
    3507             : 
    3508           0 :   nsPIDOMWindowOuter* window = GetWindow();
    3509           0 :   if (!window) {
    3510           0 :     rv.Throw(NS_ERROR_FAILURE);
    3511           0 :     return false;
    3512             :   }
    3513             : 
    3514           0 :   if (commandID.LowerCaseEqualsLiteral("usecss")) {
    3515             :     // Per spec, state is supported for styleWithCSS but not useCSS, so we just
    3516             :     // return false always.
    3517           0 :     return false;
    3518             :   }
    3519             : 
    3520           0 :   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3521           0 :                                            NS_COMMAND_PARAMS_CONTRACTID);
    3522           0 :   if (!cmdParams) {
    3523           0 :     rv.Throw(NS_ERROR_OUT_OF_MEMORY);
    3524           0 :     return false;
    3525             :   }
    3526             : 
    3527           0 :   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
    3528           0 :   if (rv.Failed()) {
    3529           0 :     return false;
    3530             :   }
    3531             : 
    3532             :   // handle alignment as a special case (possibly other commands too?)
    3533             :   // Alignment is special because the external api is individual
    3534             :   // commands but internally we use cmd_align with different
    3535             :   // parameters.  When getting the state of this command, we need to
    3536             :   // return the boolean for this particular alignment rather than the
    3537             :   // string of 'which alignment is this?'
    3538           0 :   if (cmdToDispatch.EqualsLiteral("cmd_align")) {
    3539           0 :     char * actualAlignmentType = nullptr;
    3540           0 :     rv = cmdParams->GetCStringValue("state_attribute", &actualAlignmentType);
    3541           0 :     bool retval = false;
    3542           0 :     if (!rv.Failed() && actualAlignmentType && actualAlignmentType[0]) {
    3543           0 :       retval = paramToCheck.Equals(actualAlignmentType);
    3544             :     }
    3545           0 :     if (actualAlignmentType) {
    3546           0 :       free(actualAlignmentType);
    3547             :     }
    3548           0 :     return retval;
    3549             :   }
    3550             : 
    3551             :   // If command does not have a state_all value, this call fails and sets
    3552             :   // retval to false.  This is fine -- we want to return false in that case
    3553             :   // anyway (bug 738385), so we just succeed and return false regardless.
    3554           0 :   bool retval = false;
    3555           0 :   cmdParams->GetBooleanValue("state_all", &retval);
    3556           0 :   return retval;
    3557             : }
    3558             : 
    3559             : bool
    3560           0 : nsHTMLDocument::QueryCommandSupported(const nsAString& commandID,
    3561             :                                       CallerType aCallerType)
    3562             : {
    3563             :   // Gecko technically supports all the clipboard commands including
    3564             :   // cut/copy/paste, but non-privileged content will be unable to call
    3565             :   // paste, and depending on the pref "dom.allow_cut_copy", cut and copy
    3566             :   // may also be disallowed to be called from non-privileged content.
    3567             :   // For that reason, we report the support status of corresponding
    3568             :   // command accordingly.
    3569           0 :   if (aCallerType != CallerType::System) {
    3570           0 :     if (commandID.LowerCaseEqualsLiteral("paste")) {
    3571           0 :       return false;
    3572             :     }
    3573           0 :     if (nsContentUtils::IsCutCopyRestricted()) {
    3574             :       // XXXbz should we worry about correctly reporting "true" in the
    3575             :       // "restricted, but we're an addon with clipboardWrite permissions" case?
    3576             :       // See also nsContentUtils::IsCutCopyAllowed.
    3577           0 :       if (commandID.LowerCaseEqualsLiteral("cut") ||
    3578           0 :           commandID.LowerCaseEqualsLiteral("copy")) {
    3579           0 :         return false;
    3580             :       }
    3581             :     }
    3582             :   }
    3583             : 
    3584             :   // commandID is supported if it can be converted to a Midas command
    3585           0 :   nsAutoCString cmdToDispatch;
    3586           0 :   return ConvertToMidasInternalCommand(commandID, cmdToDispatch);
    3587             : }
    3588             : 
    3589             : NS_IMETHODIMP
    3590           0 : nsHTMLDocument::QueryCommandValue(const nsAString & commandID,
    3591             :                                   nsAString &_retval)
    3592             : {
    3593           0 :   ErrorResult rv;
    3594           0 :   QueryCommandValue(commandID, _retval, rv);
    3595           0 :   return rv.StealNSResult();
    3596             : }
    3597             : 
    3598             : void
    3599           0 : nsHTMLDocument::QueryCommandValue(const nsAString& commandID,
    3600             :                                   nsAString& aValue,
    3601             :                                   ErrorResult& rv)
    3602             : {
    3603           0 :   aValue.Truncate();
    3604             : 
    3605           0 :   nsAutoCString cmdToDispatch, paramStr;
    3606           0 :   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
    3607             :     // Return empty string
    3608           0 :     return;
    3609             :   }
    3610             : 
    3611             :   // if editing is not on, bail
    3612           0 :   if (!IsEditingOnAfterFlush()) {
    3613           0 :     return;
    3614             :   }
    3615             : 
    3616             :   // get command manager and dispatch command to our window if it's acceptable
    3617           0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3618           0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3619           0 :   if (!cmdMgr) {
    3620           0 :     rv.Throw(NS_ERROR_FAILURE);
    3621           0 :     return;
    3622             :   }
    3623             : 
    3624           0 :   nsPIDOMWindowOuter* window = GetWindow();
    3625           0 :   if (!window) {
    3626           0 :     rv.Throw(NS_ERROR_FAILURE);
    3627           0 :     return;
    3628             :   }
    3629             : 
    3630             :   // create params
    3631           0 :   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3632           0 :                                            NS_COMMAND_PARAMS_CONTRACTID);
    3633           0 :   if (!cmdParams) {
    3634           0 :     rv.Throw(NS_ERROR_OUT_OF_MEMORY);
    3635           0 :     return;
    3636             :   }
    3637             : 
    3638             :   // this is a special command since we are calling DoCommand rather than
    3639             :   // GetCommandState like the other commands
    3640           0 :   if (cmdToDispatch.EqualsLiteral("cmd_getContents")) {
    3641           0 :     rv = cmdParams->SetBooleanValue("selection_only", true);
    3642           0 :     if (rv.Failed()) {
    3643           0 :       return;
    3644             :     }
    3645           0 :     rv = cmdParams->SetCStringValue("format", "text/html");
    3646           0 :     if (rv.Failed()) {
    3647           0 :       return;
    3648             :     }
    3649           0 :     rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window);
    3650           0 :     if (rv.Failed()) {
    3651           0 :       return;
    3652             :     }
    3653           0 :     rv = cmdParams->GetStringValue("result", aValue);
    3654           0 :     return;
    3655             :   }
    3656             : 
    3657           0 :   rv = cmdParams->SetCStringValue("state_attribute", paramStr.get());
    3658           0 :   if (rv.Failed()) {
    3659           0 :     return;
    3660             :   }
    3661             : 
    3662           0 :   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
    3663           0 :   if (rv.Failed()) {
    3664           0 :     return;
    3665             :   }
    3666             : 
    3667             :   // If command does not have a state_attribute value, this call fails, and
    3668             :   // aValue will wind up being the empty string.  This is fine -- we want to
    3669             :   // return "" in that case anyway (bug 738385), so we just return NS_OK
    3670             :   // regardless.
    3671           0 :   nsXPIDLCString cStringResult;
    3672           0 :   cmdParams->GetCStringValue("state_attribute",
    3673           0 :                              getter_Copies(cStringResult));
    3674           0 :   CopyUTF8toUTF16(cStringResult, aValue);
    3675             : }
    3676             : 
    3677             : nsresult
    3678           0 : nsHTMLDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
    3679             :                       bool aPreallocateChildren) const
    3680             : {
    3681           0 :   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
    3682             :                "Can't import this document into another document!");
    3683             : 
    3684           0 :   RefPtr<nsHTMLDocument> clone = new nsHTMLDocument();
    3685           0 :   nsresult rv = CloneDocHelper(clone.get(), aPreallocateChildren);
    3686           0 :   NS_ENSURE_SUCCESS(rv, rv);
    3687             : 
    3688             :   // State from nsHTMLDocument
    3689           0 :   clone->mLoadFlags = mLoadFlags;
    3690             : 
    3691           0 :   return CallQueryInterface(clone.get(), aResult);
    3692             : }
    3693             : 
    3694             : bool
    3695           0 : nsHTMLDocument::IsEditingOnAfterFlush()
    3696             : {
    3697           0 :   nsIDocument* doc = GetParentDocument();
    3698           0 :   if (doc) {
    3699             :     // Make sure frames are up to date, since that can affect whether
    3700             :     // we're editable.
    3701           0 :     doc->FlushPendingNotifications(FlushType::Frames);
    3702             :   }
    3703             : 
    3704           0 :   return IsEditingOn();
    3705             : }
    3706             : 
    3707             : void
    3708           8 : nsHTMLDocument::RemovedFromDocShell()
    3709             : {
    3710           8 :   mEditingState = eOff;
    3711           8 :   nsDocument::RemovedFromDocShell();
    3712           8 : }
    3713             : 
    3714             : /* virtual */ void
    3715           0 : nsHTMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
    3716             : {
    3717           0 :   nsDocument::DocAddSizeOfExcludingThis(aWindowSizes);
    3718             : 
    3719             :   // Measurement of the following members may be added later if DMD finds it is
    3720             :   // worthwhile:
    3721             :   // - mImages
    3722             :   // - mApplets
    3723             :   // - mEmbeds
    3724             :   // - mLinks
    3725             :   // - mAnchors
    3726             :   // - mScripts
    3727             :   // - mForms
    3728             :   // - mFormControls
    3729             :   // - mWyciwygChannel
    3730             :   // - mMidasCommandManager
    3731           0 : }
    3732             : 
    3733             : bool
    3734           8 : nsHTMLDocument::WillIgnoreCharsetOverride()
    3735             : {
    3736           8 :   if (mType != eHTML) {
    3737           0 :     MOZ_ASSERT(mType == eXHTML);
    3738           0 :     return true;
    3739             :   }
    3740           8 :   if (mCharacterSetSource >= kCharsetFromByteOrderMark) {
    3741           0 :     return true;
    3742             :   }
    3743           8 :   if (!mCharacterSet->IsAsciiCompatible() &&
    3744           0 :       mCharacterSet != ISO_2022_JP_ENCODING) {
    3745           0 :     return true;
    3746             :   }
    3747          16 :   nsCOMPtr<nsIWyciwygChannel> wyciwyg = do_QueryInterface(mChannel);
    3748           8 :   if (wyciwyg) {
    3749           0 :     return true;
    3750             :   }
    3751           8 :   nsIURI* uri = GetOriginalURI();
    3752           8 :   if (uri) {
    3753           8 :     bool schemeIs = false;
    3754           8 :     uri->SchemeIs("about", &schemeIs);
    3755           8 :     if (schemeIs) {
    3756           9 :       return true;
    3757             :     }
    3758             :     bool isResource;
    3759             :     nsresult rv = NS_URIChainHasFlags(uri,
    3760             :                                       nsIProtocolHandler::URI_IS_UI_RESOURCE,
    3761           4 :                                       &isResource);
    3762           4 :     if (NS_FAILED(rv) || isResource) {
    3763           1 :       return true;
    3764             :     }
    3765             :   }
    3766           3 :   return false;
    3767             : }

Generated by: LCOV version 1.13