LCOV - code coverage report
Current view: top level - dom/base - nsContentSink.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 90 694 13.0 %
Date: 2018-08-07 16:42:27 Functions: 0 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             : /*
       8             :  * Base class for the XML and HTML content sinks, which construct a
       9             :  * DOM based on information from the parser.
      10             :  */
      11             : 
      12             : #include "nsContentSink.h"
      13             : #include "nsIDocument.h"
      14             : #include "mozilla/css/Loader.h"
      15             : #include "mozilla/dom/SRILogHelper.h"
      16             : #include "nsStyleLinkElement.h"
      17             : #include "nsIDocShell.h"
      18             : #include "nsILoadContext.h"
      19             : #include "nsCPrefetchService.h"
      20             : #include "nsIURI.h"
      21             : #include "nsNetUtil.h"
      22             : #include "nsIMIMEHeaderParam.h"
      23             : #include "nsIProtocolHandler.h"
      24             : #include "nsIHttpChannel.h"
      25             : #include "nsIContent.h"
      26             : #include "nsIPresShell.h"
      27             : #include "nsPresContext.h"
      28             : #include "nsViewManager.h"
      29             : #include "nsAtom.h"
      30             : #include "nsGkAtoms.h"
      31             : #include "nsNetCID.h"
      32             : #include "nsIOfflineCacheUpdate.h"
      33             : #include "nsIApplicationCache.h"
      34             : #include "nsIApplicationCacheContainer.h"
      35             : #include "nsIApplicationCacheChannel.h"
      36             : #include "nsIScriptSecurityManager.h"
      37             : #include "nsICookieService.h"
      38             : #include "nsContentUtils.h"
      39             : #include "nsNodeInfoManager.h"
      40             : #include "nsIAppShell.h"
      41             : #include "nsIWidget.h"
      42             : #include "nsWidgetsCID.h"
      43             : #include "mozAutoDocUpdate.h"
      44             : #include "nsIWebNavigation.h"
      45             : #include "nsGenericHTMLElement.h"
      46             : #include "nsHTMLDNSPrefetch.h"
      47             : #include "nsIObserverService.h"
      48             : #include "mozilla/Preferences.h"
      49             : #include "mozilla/dom/ServiceWorkerDescriptor.h"
      50             : #include "mozilla/dom/ScriptLoader.h"
      51             : #include "nsParserConstants.h"
      52             : #include "nsSandboxFlags.h"
      53             : #include "Link.h"
      54             : #include "HTMLLinkElement.h"
      55             : 
      56             : using namespace mozilla;
      57             : using namespace mozilla::css;
      58             : using namespace mozilla::dom;
      59             : 
      60             : LazyLogModule gContentSinkLogModuleInfo("nscontentsink");
      61             : 
      62           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink)
      63           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink)
      64             : 
      65           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsContentSink)
      66           0 :   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
      67           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
      68           0 :   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
      69           0 :   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
      70           0 :   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
      71           0 :   NS_INTERFACE_MAP_ENTRY(nsINamed)
      72           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentObserver)
      73           0 : NS_INTERFACE_MAP_END
      74             : 
      75             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSink)
      76             : 
      77           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink)
      78           0 :   if (tmp->mDocument) {
      79           0 :     tmp->mDocument->RemoveObserver(tmp);
      80             :   }
      81           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
      82           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser)
      83           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
      84           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
      85           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
      86           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader)
      87           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      88           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsContentSink)
      89           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
      90           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser)
      91           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
      92           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
      93           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
      94           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader)
      95           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      96             : 
      97             : 
      98           0 : nsContentSink::nsContentSink()
      99             :   : mBackoffCount(0)
     100             :   , mLastNotificationTime(0)
     101             :   , mBeganUpdate(0)
     102             :   , mLayoutStarted(0)
     103             :   , mDynamicLowerValue(0)
     104             :   , mParsing(0)
     105             :   , mDroppedTimer(0)
     106             :   , mDeferredLayoutStart(0)
     107             :   , mDeferredFlushTags(0)
     108             :   , mIsDocumentObserver(0)
     109             :   , mRunsToCompletion(0)
     110             :   , mIsBlockingOnload(false)
     111             :   , mDeflectedCount(0)
     112             :   , mHasPendingEvent(false)
     113             :   , mCurrentParseEndTime(0)
     114             :   , mBeginLoadTime(0)
     115             :   , mLastSampledUserEventTime(0)
     116             :   , mInMonolithicContainer(0)
     117             :   , mInNotification(0)
     118             :   , mUpdatesInNotification(0)
     119           0 :   , mPendingSheetCount(0)
     120             : {
     121           0 :   NS_ASSERTION(!mLayoutStarted, "What?");
     122           0 :   NS_ASSERTION(!mDynamicLowerValue, "What?");
     123           0 :   NS_ASSERTION(!mParsing, "What?");
     124           0 :   NS_ASSERTION(mLastSampledUserEventTime == 0, "What?");
     125           0 :   NS_ASSERTION(mDeflectedCount == 0, "What?");
     126           0 :   NS_ASSERTION(!mDroppedTimer, "What?");
     127           0 :   NS_ASSERTION(mInMonolithicContainer == 0, "What?");
     128           0 :   NS_ASSERTION(mInNotification == 0, "What?");
     129           0 :   NS_ASSERTION(!mDeferredLayoutStart, "What?");
     130           0 : }
     131             : 
     132           0 : nsContentSink::~nsContentSink()
     133             : {
     134           0 :   if (mDocument) {
     135             :     // Remove ourselves just to be safe, though we really should have
     136             :     // been removed in DidBuildModel if everything worked right.
     137           0 :     mDocument->RemoveObserver(this);
     138             :   }
     139           0 : }
     140             : 
     141             : bool    nsContentSink::sNotifyOnTimer;
     142             : int32_t nsContentSink::sBackoffCount;
     143             : int32_t nsContentSink::sNotificationInterval;
     144             : int32_t nsContentSink::sInteractiveDeflectCount;
     145             : int32_t nsContentSink::sPerfDeflectCount;
     146             : int32_t nsContentSink::sPendingEventMode;
     147             : int32_t nsContentSink::sEventProbeRate;
     148             : int32_t nsContentSink::sInteractiveParseTime;
     149             : int32_t nsContentSink::sPerfParseTime;
     150             : int32_t nsContentSink::sInteractiveTime;
     151             : int32_t nsContentSink::sInitialPerfTime;
     152             : int32_t nsContentSink::sEnablePerfMode;
     153             : 
     154             : void
     155           0 : nsContentSink::InitializeStatics()
     156             : {
     157             :   Preferences::AddBoolVarCache(&sNotifyOnTimer,
     158           0 :                                "content.notify.ontimer", true);
     159             :   // -1 means never.
     160             :   Preferences::AddIntVarCache(&sBackoffCount,
     161           0 :                               "content.notify.backoffcount", -1);
     162             :   // The gNotificationInterval has a dramatic effect on how long it
     163             :   // takes to initially display content for slow connections.
     164             :   // The current value provides good
     165             :   // incremental display of content without causing an increase
     166             :   // in page load time. If this value is set below 1/10 of second
     167             :   // it starts to impact page load performance.
     168             :   // see bugzilla bug 72138 for more info.
     169             :   Preferences::AddIntVarCache(&sNotificationInterval,
     170           0 :                               "content.notify.interval", 120000);
     171             :   Preferences::AddIntVarCache(&sInteractiveDeflectCount,
     172           0 :                               "content.sink.interactive_deflect_count", 0);
     173             :   Preferences::AddIntVarCache(&sPerfDeflectCount,
     174           0 :                               "content.sink.perf_deflect_count", 200);
     175             :   Preferences::AddIntVarCache(&sPendingEventMode,
     176           0 :                               "content.sink.pending_event_mode", 1);
     177             :   Preferences::AddIntVarCache(&sEventProbeRate,
     178           0 :                               "content.sink.event_probe_rate", 1);
     179             :   Preferences::AddIntVarCache(&sInteractiveParseTime,
     180           0 :                               "content.sink.interactive_parse_time", 3000);
     181             :   Preferences::AddIntVarCache(&sPerfParseTime,
     182           0 :                               "content.sink.perf_parse_time", 360000);
     183             :   Preferences::AddIntVarCache(&sInteractiveTime,
     184           0 :                               "content.sink.interactive_time", 750000);
     185             :   Preferences::AddIntVarCache(&sInitialPerfTime,
     186           0 :                               "content.sink.initial_perf_time", 2000000);
     187             :   Preferences::AddIntVarCache(&sEnablePerfMode,
     188           0 :                               "content.sink.enable_perf_mode", 0);
     189           0 : }
     190             : 
     191             : nsresult
     192           0 : nsContentSink::Init(nsIDocument* aDoc,
     193             :                     nsIURI* aURI,
     194             :                     nsISupports* aContainer,
     195             :                     nsIChannel* aChannel)
     196             : {
     197           0 :   MOZ_ASSERT(aDoc, "null ptr");
     198           0 :   MOZ_ASSERT(aURI, "null ptr");
     199             : 
     200           0 :   if (!aDoc || !aURI) {
     201             :     return NS_ERROR_NULL_POINTER;
     202             :   }
     203             : 
     204           0 :   mDocument = aDoc;
     205             : 
     206           0 :   mDocumentURI = aURI;
     207           0 :   mDocShell = do_QueryInterface(aContainer);
     208           0 :   mScriptLoader = mDocument->ScriptLoader();
     209             : 
     210           0 :   if (!mRunsToCompletion) {
     211           0 :     if (mDocShell) {
     212           0 :       uint32_t loadType = 0;
     213           0 :       mDocShell->GetLoadType(&loadType);
     214           0 :       mDocument->SetChangeScrollPosWhenScrollingToRef(
     215           0 :         (loadType & nsIDocShell::LOAD_CMD_HISTORY) == 0);
     216             :     }
     217             : 
     218           0 :     ProcessHTTPHeaders(aChannel);
     219             :   }
     220             : 
     221           0 :   mCSSLoader = aDoc->CSSLoader();
     222             : 
     223           0 :   mNodeInfoManager = aDoc->NodeInfoManager();
     224             : 
     225           0 :   mBackoffCount = sBackoffCount;
     226             : 
     227           0 :   if (sEnablePerfMode != 0) {
     228           0 :     mDynamicLowerValue = sEnablePerfMode == 1;
     229           0 :     FavorPerformanceHint(!mDynamicLowerValue, 0);
     230             :   }
     231             : 
     232             :   return NS_OK;
     233             : }
     234             : 
     235             : NS_IMETHODIMP
     236           0 : nsContentSink::StyleSheetLoaded(StyleSheet* aSheet,
     237             :                                 bool aWasDeferred,
     238             :                                 nsresult aStatus)
     239             : {
     240           0 :   MOZ_ASSERT(!mRunsToCompletion, "How come a fragment parser observed sheets?");
     241           0 :   if (!aWasDeferred) {
     242           0 :     MOZ_ASSERT(mPendingSheetCount > 0, "How'd that happen?");
     243           0 :     --mPendingSheetCount;
     244             : 
     245           0 :     if (mPendingSheetCount == 0 &&
     246           0 :         (mDeferredLayoutStart || mDeferredFlushTags)) {
     247           0 :       if (mDeferredFlushTags) {
     248           0 :         FlushTags();
     249             :       }
     250           0 :       if (mDeferredLayoutStart) {
     251             :         // We might not have really started layout, since this sheet was still
     252             :         // loading.  Do it now.  Probably doesn't matter whether we do this
     253             :         // before or after we unblock scripts, but before feels saner.  Note
     254             :         // that if mDeferredLayoutStart is true, that means any subclass
     255             :         // StartLayout() stuff that needs to happen has already happened, so we
     256             :         // don't need to worry about it.
     257           0 :         StartLayout(false);
     258             :       }
     259             : 
     260             :       // Go ahead and try to scroll to our ref if we have one
     261           0 :       ScrollToRef();
     262             :     }
     263             : 
     264           0 :     mScriptLoader->RemoveParserBlockingScriptExecutionBlocker();
     265             :   }
     266             : 
     267           0 :   return NS_OK;
     268             : }
     269             : 
     270             : nsresult
     271           0 : nsContentSink::ProcessHTTPHeaders(nsIChannel* aChannel)
     272             : {
     273           0 :   nsCOMPtr<nsIHttpChannel> httpchannel(do_QueryInterface(aChannel));
     274             : 
     275           0 :   if (!httpchannel) {
     276             :     return NS_OK;
     277             :   }
     278             : 
     279             :   // Note that the only header we care about is the "link" header, since we
     280             :   // have all the infrastructure for kicking off stylesheet loads.
     281             : 
     282           0 :   nsAutoCString linkHeader;
     283             : 
     284           0 :   nsresult rv = httpchannel->GetResponseHeader(NS_LITERAL_CSTRING("link"),
     285           0 :                                                linkHeader);
     286           0 :   if (NS_SUCCEEDED(rv) && !linkHeader.IsEmpty()) {
     287           0 :     mDocument->SetHeaderData(nsGkAtoms::link,
     288           0 :                              NS_ConvertASCIItoUTF16(linkHeader));
     289             : 
     290           0 :     NS_ASSERTION(!mProcessLinkHeaderEvent.get(),
     291             :                  "Already dispatched an event?");
     292             : 
     293             :     mProcessLinkHeaderEvent =
     294           0 :       NewNonOwningRunnableMethod("nsContentSink::DoProcessLinkHeader",
     295             :                                  this,
     296           0 :                                  &nsContentSink::DoProcessLinkHeader);
     297           0 :     rv = NS_DispatchToCurrentThread(mProcessLinkHeaderEvent.get());
     298           0 :     if (NS_FAILED(rv)) {
     299           0 :       mProcessLinkHeaderEvent.Forget();
     300             :     }
     301             :   }
     302             : 
     303           0 :   return NS_OK;
     304             : }
     305             : 
     306             : nsresult
     307           0 : nsContentSink::ProcessHeaderData(nsAtom* aHeader, const nsAString& aValue,
     308             :                                  nsIContent* aContent)
     309             : {
     310           0 :   nsresult rv = NS_OK;
     311             :   // necko doesn't process headers coming in from the parser
     312             : 
     313           0 :   mDocument->SetHeaderData(aHeader, aValue);
     314             : 
     315           0 :   if (aHeader == nsGkAtoms::setcookie) {
     316             :     // Note: Necko already handles cookies set via the channel.  We can't just
     317             :     // call SetCookie on the channel because we want to do some security checks
     318             :     // here.
     319             :     nsCOMPtr<nsICookieService> cookieServ =
     320           0 :       do_GetService(NS_COOKIESERVICE_CONTRACTID, &rv);
     321           0 :     if (NS_FAILED(rv)) {
     322           0 :       return rv;
     323             :     }
     324             : 
     325             :     // Get a URI from the document principal
     326             : 
     327             :     // We use the original codebase in case the codebase was changed
     328             :     // by SetDomain
     329             : 
     330             :     // Note that a non-codebase principal (eg the system principal) will return
     331             :     // a null URI.
     332           0 :     nsCOMPtr<nsIURI> codebaseURI;
     333           0 :     rv = mDocument->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
     334           0 :     NS_ENSURE_TRUE(codebaseURI, rv);
     335             : 
     336           0 :     nsCOMPtr<nsIChannel> channel;
     337           0 :     if (mParser) {
     338           0 :       mParser->GetChannel(getter_AddRefs(channel));
     339             :     }
     340             : 
     341           0 :     rv = cookieServ->SetCookieString(codebaseURI,
     342             :                                      nullptr,
     343           0 :                                      NS_ConvertUTF16toUTF8(aValue).get(),
     344           0 :                                      channel);
     345           0 :     if (NS_FAILED(rv)) {
     346           0 :       return rv;
     347             :     }
     348             :   }
     349             : 
     350           0 :   return rv;
     351             : }
     352             : 
     353             : 
     354             : void
     355           0 : nsContentSink::DoProcessLinkHeader()
     356             : {
     357           0 :   nsAutoString value;
     358           0 :   mDocument->GetHeaderData(nsGkAtoms::link, value);
     359           0 :   ProcessLinkHeader(value);
     360           0 : }
     361             : 
     362             : // check whether the Link header field applies to the context resource
     363             : // see <http://tools.ietf.org/html/rfc5988#section-5.2>
     364             : 
     365             : bool
     366           0 : nsContentSink::LinkContextIsOurDocument(const nsAString& aAnchor)
     367             : {
     368           0 :   if (aAnchor.IsEmpty()) {
     369             :     // anchor parameter not present or empty -> same document reference
     370             :     return true;
     371             :   }
     372             : 
     373           0 :   nsIURI* docUri = mDocument->GetDocumentURI();
     374             : 
     375             :   // the document URI might contain a fragment identifier ("#...')
     376             :   // we want to ignore that because it's invisible to the server
     377             :   // and just affects the local interpretation in the recipient
     378           0 :   nsCOMPtr<nsIURI> contextUri;
     379           0 :   nsresult rv = docUri->CloneIgnoringRef(getter_AddRefs(contextUri));
     380             : 
     381           0 :   if (NS_FAILED(rv)) {
     382             :     // copying failed
     383             :     return false;
     384             :   }
     385             : 
     386             :   // resolve anchor against context
     387           0 :   nsCOMPtr<nsIURI> resolvedUri;
     388           0 :   rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor,
     389           0 :       nullptr, contextUri);
     390             : 
     391           0 :   if (NS_FAILED(rv)) {
     392             :     // resolving failed
     393             :     return false;
     394             :   }
     395             : 
     396             :   bool same;
     397           0 :   rv = contextUri->Equals(resolvedUri, &same);
     398           0 :   if (NS_FAILED(rv)) {
     399             :     // comparison failed
     400             :     return false;
     401             :   }
     402             : 
     403           0 :   return same;
     404             : }
     405             : 
     406             : // Decode a parameter value using the encoding defined in RFC 5987 (in place)
     407             : //
     408             : //   charset  "'" [ language ] "'" value-chars
     409             : //
     410             : // returns true when decoding happened successfully (otherwise leaves
     411             : // passed value alone)
     412             : bool
     413           0 : nsContentSink::Decode5987Format(nsAString& aEncoded) {
     414             : 
     415             :   nsresult rv;
     416             :   nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
     417           0 :   do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
     418           0 :   if (NS_FAILED(rv))
     419             :     return false;
     420             : 
     421           0 :   nsAutoCString asciiValue;
     422             : 
     423           0 :   const char16_t* encstart = aEncoded.BeginReading();
     424           0 :   const char16_t* encend = aEncoded.EndReading();
     425             : 
     426             :   // create a plain ASCII string, aborting if we can't do that
     427             :   // converted form is always shorter than input
     428           0 :   while (encstart != encend) {
     429           0 :     if (*encstart > 0 && *encstart < 128) {
     430           0 :       asciiValue.Append((char)*encstart);
     431             :     } else {
     432             :       return false;
     433             :     }
     434           0 :     encstart++;
     435             :   }
     436             : 
     437           0 :   nsAutoString decoded;
     438           0 :   nsAutoCString language;
     439             : 
     440           0 :   rv = mimehdrpar->DecodeRFC5987Param(asciiValue, language, decoded);
     441           0 :   if (NS_FAILED(rv))
     442             :     return false;
     443             : 
     444           0 :   aEncoded = decoded;
     445           0 :   return true;
     446             : }
     447             : 
     448             : nsresult
     449           0 : nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
     450             : {
     451           0 :   nsresult rv = NS_OK;
     452             : 
     453             :   // keep track where we are within the header field
     454           0 :   bool seenParameters = false;
     455             : 
     456             :   // parse link content and call process style link
     457           0 :   nsAutoString href;
     458           0 :   nsAutoString rel;
     459           0 :   nsAutoString title;
     460           0 :   nsAutoString titleStar;
     461           0 :   nsAutoString type;
     462           0 :   nsAutoString media;
     463           0 :   nsAutoString anchor;
     464           0 :   nsAutoString crossOrigin;
     465           0 :   nsAutoString referrerPolicy;
     466           0 :   nsAutoString as;
     467             : 
     468           0 :   crossOrigin.SetIsVoid(true);
     469             : 
     470             :   // copy to work buffer
     471           0 :   nsAutoString stringList(aLinkData);
     472             : 
     473             :   // put an extra null at the end
     474           0 :   stringList.Append(kNullCh);
     475             : 
     476           0 :   char16_t* start = stringList.BeginWriting();
     477           0 :   char16_t* end   = start;
     478           0 :   char16_t* last  = start;
     479             :   char16_t  endCh;
     480             : 
     481           0 :   while (*start != kNullCh) {
     482             :     // skip leading space
     483           0 :     while ((*start != kNullCh) && nsCRT::IsAsciiSpace(*start)) {
     484           0 :       ++start;
     485             :     }
     486             : 
     487           0 :     end = start;
     488           0 :     last = end - 1;
     489             : 
     490           0 :     bool wasQuotedString = false;
     491             : 
     492             :     // look for semicolon or comma
     493           0 :     while (*end != kNullCh && *end != kSemicolon && *end != kComma) {
     494           0 :       char16_t ch = *end;
     495             : 
     496           0 :       if (ch == kQuote || ch == kLessThan) {
     497             :         // quoted string
     498             : 
     499           0 :         char16_t quote = ch;
     500           0 :         if (quote == kLessThan) {
     501           0 :           quote = kGreaterThan;
     502             :         }
     503             : 
     504           0 :         wasQuotedString = (ch == kQuote);
     505             : 
     506           0 :         char16_t* closeQuote = (end + 1);
     507             : 
     508             :         // seek closing quote
     509           0 :         while (*closeQuote != kNullCh && quote != *closeQuote) {
     510             :           // in quoted-string, "\" is an escape character
     511           0 :           if (wasQuotedString && *closeQuote == kBackSlash && *(closeQuote + 1) != kNullCh) {
     512           0 :             ++closeQuote;
     513             :           }
     514             : 
     515           0 :           ++closeQuote;
     516             :         }
     517             : 
     518           0 :         if (quote == *closeQuote) {
     519             :           // found closer
     520             : 
     521             :           // skip to close quote
     522           0 :           end = closeQuote;
     523             : 
     524           0 :           last = end - 1;
     525             : 
     526           0 :           ch = *(end + 1);
     527             : 
     528           0 :           if (ch != kNullCh && ch != kSemicolon && ch != kComma) {
     529             :             // end string here
     530           0 :             *(++end) = kNullCh;
     531             : 
     532           0 :             ch = *(end + 1);
     533             : 
     534             :             // keep going until semi or comma
     535           0 :             while (ch != kNullCh && ch != kSemicolon && ch != kComma) {
     536           0 :               ++end;
     537             : 
     538           0 :               ch = *(end + 1);
     539             :             }
     540             :           }
     541             :         }
     542             :       }
     543             : 
     544           0 :       ++end;
     545           0 :       ++last;
     546             :     }
     547             : 
     548           0 :     endCh = *end;
     549             : 
     550             :     // end string here
     551           0 :     *end = kNullCh;
     552             : 
     553           0 :     if (start < end) {
     554           0 :       if ((*start == kLessThan) && (*last == kGreaterThan)) {
     555           0 :         *last = kNullCh;
     556             : 
     557             :         // first instance of <...> wins
     558             :         // also, do not allow hrefs after the first param was seen
     559           0 :         if (href.IsEmpty() && !seenParameters) {
     560           0 :           href = (start + 1);
     561           0 :           href.StripWhitespace();
     562             :         }
     563             :       } else {
     564             :         char16_t* equals = start;
     565             :         seenParameters = true;
     566             : 
     567           0 :         while ((*equals != kNullCh) && (*equals != kEqual)) {
     568           0 :           equals++;
     569             :         }
     570             : 
     571           0 :         if (*equals != kNullCh) {
     572           0 :           *equals = kNullCh;
     573           0 :           nsAutoString  attr(start);
     574           0 :           attr.StripWhitespace();
     575             : 
     576           0 :           char16_t* value = ++equals;
     577           0 :           while (nsCRT::IsAsciiSpace(*value)) {
     578           0 :             value++;
     579             :           }
     580             : 
     581           0 :           if ((*value == kQuote) && (*value == *last)) {
     582           0 :             *last = kNullCh;
     583           0 :             value++;
     584             :           }
     585             : 
     586           0 :           if (wasQuotedString) {
     587             :             // unescape in-place
     588             :             char16_t* unescaped = value;
     589             :             char16_t *src = value;
     590             : 
     591           0 :             while (*src != kNullCh) {
     592           0 :               if (*src == kBackSlash && *(src + 1) != kNullCh) {
     593           0 :                 src++;
     594             :               }
     595           0 :               *unescaped++ = *src++;
     596             :             }
     597             : 
     598           0 :             *unescaped = kNullCh;
     599             :           }
     600             : 
     601           0 :           if (attr.LowerCaseEqualsLiteral("rel")) {
     602           0 :             if (rel.IsEmpty()) {
     603           0 :               rel = value;
     604           0 :               rel.CompressWhitespace();
     605             :             }
     606           0 :           } else if (attr.LowerCaseEqualsLiteral("title")) {
     607           0 :             if (title.IsEmpty()) {
     608           0 :               title = value;
     609           0 :               title.CompressWhitespace();
     610             :             }
     611           0 :           } else if (attr.LowerCaseEqualsLiteral("title*")) {
     612           0 :             if (titleStar.IsEmpty() && !wasQuotedString) {
     613             :               // RFC 5987 encoding; uses token format only, so skip if we get
     614             :               // here with a quoted-string
     615           0 :               nsAutoString tmp;
     616           0 :               tmp = value;
     617           0 :               if (Decode5987Format(tmp)) {
     618           0 :                 titleStar = tmp;
     619           0 :                 titleStar.CompressWhitespace();
     620             :               } else {
     621             :                 // header value did not parse, throw it away
     622           0 :                 titleStar.Truncate();
     623             :               }
     624             :             }
     625           0 :           } else if (attr.LowerCaseEqualsLiteral("type")) {
     626           0 :             if (type.IsEmpty()) {
     627           0 :               type = value;
     628           0 :               type.StripWhitespace();
     629             :             }
     630           0 :           } else if (attr.LowerCaseEqualsLiteral("media")) {
     631           0 :             if (media.IsEmpty()) {
     632           0 :               media = value;
     633             : 
     634             :               // The HTML5 spec is formulated in terms of the CSS3 spec,
     635             :               // which specifies that media queries are case insensitive.
     636           0 :               nsContentUtils::ASCIIToLower(media);
     637             :             }
     638           0 :           } else if (attr.LowerCaseEqualsLiteral("anchor")) {
     639           0 :             if (anchor.IsEmpty()) {
     640           0 :               anchor = value;
     641           0 :               anchor.StripWhitespace();
     642             :             }
     643           0 :           } else if (attr.LowerCaseEqualsLiteral("crossorigin")) {
     644           0 :             if (crossOrigin.IsVoid()) {
     645           0 :               crossOrigin.SetIsVoid(false);
     646           0 :               crossOrigin = value;
     647           0 :               crossOrigin.StripWhitespace();
     648             :             }
     649           0 :           } else if (attr.LowerCaseEqualsLiteral("as")) {
     650           0 :             if (as.IsEmpty()) {
     651           0 :               as = value;
     652           0 :               as.CompressWhitespace();
     653             :             }
     654           0 :           } else if (attr.LowerCaseEqualsLiteral("referrerpolicy")) {
     655             :             // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#referrer-policy-attribute
     656             :             // Specs says referrer policy attribute is an enumerated attribute,
     657             :             // case insensitive and includes the empty string
     658             :             // We will parse the value with AttributeReferrerPolicyFromString
     659             :             // later, which will handle parsing it as an enumerated attribute.
     660           0 :             if (referrerPolicy.IsEmpty()) {
     661             :               referrerPolicy = value;
     662             :             }
     663             :           }
     664             :         }
     665             :       }
     666             :     }
     667             : 
     668           0 :     if (endCh == kComma) {
     669             :       // hit a comma, process what we've got so far
     670             : 
     671           0 :       href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
     672           0 :       if (!href.IsEmpty() && !rel.IsEmpty()) {
     673           0 :         rv = ProcessLinkFromHeader(anchor, href, rel,
     674             :                                    // prefer RFC 5987 variant over non-I18zed version
     675           0 :                                    titleStar.IsEmpty() ? title : titleStar,
     676           0 :                                    type, media, crossOrigin, referrerPolicy, as);
     677             :       }
     678             : 
     679           0 :       href.Truncate();
     680           0 :       rel.Truncate();
     681           0 :       title.Truncate();
     682           0 :       type.Truncate();
     683           0 :       media.Truncate();
     684           0 :       anchor.Truncate();
     685           0 :       referrerPolicy.Truncate();
     686           0 :       crossOrigin.SetIsVoid(true);
     687           0 :       as.Truncate();
     688             : 
     689           0 :       seenParameters = false;
     690             :     }
     691             : 
     692           0 :     start = ++end;
     693             :   }
     694             : 
     695           0 :   href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
     696           0 :   if (!href.IsEmpty() && !rel.IsEmpty()) {
     697           0 :     rv = ProcessLinkFromHeader(anchor, href, rel,
     698             :                                // prefer RFC 5987 variant over non-I18zed version
     699           0 :                                titleStar.IsEmpty() ? title : titleStar,
     700           0 :                                type, media, crossOrigin, referrerPolicy, as);
     701             :   }
     702             : 
     703           0 :   return rv;
     704             : }
     705             : 
     706             : 
     707             : nsresult
     708           0 : nsContentSink::ProcessLinkFromHeader(const nsAString& aAnchor, const nsAString& aHref,
     709             :                                      const nsAString& aRel, const nsAString& aTitle,
     710             :                                      const nsAString& aType, const nsAString& aMedia,
     711             :                                      const nsAString& aCrossOrigin,
     712             :                                      const nsAString& aReferrerPolicy,
     713             :                                      const nsAString& aAs)
     714             : {
     715             :   uint32_t linkTypes =
     716           0 :     nsStyleLinkElement::ParseLinkTypes(aRel);
     717             : 
     718             :   // The link relation may apply to a different resource, specified
     719             :   // in the anchor parameter. For the link relations supported so far,
     720             :   // we simply abort if the link applies to a resource different to the
     721             :   // one we've loaded
     722           0 :   if (!LinkContextIsOurDocument(aAnchor)) {
     723             :     return NS_OK;
     724             :   }
     725             : 
     726           0 :   if (nsContentUtils::PrefetchPreloadEnabled(mDocShell)) {
     727             :     // prefetch href if relation is "next" or "prefetch"
     728           0 :     if ((linkTypes & nsStyleLinkElement::eNEXT) ||
     729           0 :         (linkTypes & nsStyleLinkElement::ePREFETCH) ||
     730             :         (linkTypes & nsStyleLinkElement::ePRELOAD)) {
     731           0 :       PrefetchPreloadHref(aHref, mDocument, linkTypes, aAs, aType, aMedia);
     732             :     }
     733             : 
     734           0 :     if (!aHref.IsEmpty() && (linkTypes & nsStyleLinkElement::eDNS_PREFETCH)) {
     735           0 :       PrefetchDNS(aHref);
     736             :     }
     737             : 
     738           0 :     if (!aHref.IsEmpty() && (linkTypes & nsStyleLinkElement::ePRECONNECT)) {
     739           0 :       Preconnect(aHref, aCrossOrigin);
     740             :     }
     741             :   }
     742             : 
     743             :   // is it a stylesheet link?
     744           0 :   if (!(linkTypes & nsStyleLinkElement::eSTYLESHEET)) {
     745             :     return NS_OK;
     746             :   }
     747             : 
     748           0 :   bool isAlternate = linkTypes & nsStyleLinkElement::eALTERNATE;
     749           0 :   return ProcessStyleLinkFromHeader(aHref, isAlternate, aTitle, aType,
     750           0 :                                     aMedia, aReferrerPolicy);
     751             : }
     752             : 
     753             : nsresult
     754           0 : nsContentSink::ProcessStyleLinkFromHeader(const nsAString& aHref,
     755             :                                           bool aAlternate,
     756             :                                           const nsAString& aTitle,
     757             :                                           const nsAString& aType,
     758             :                                           const nsAString& aMedia,
     759             :                                           const nsAString& aReferrerPolicy)
     760             : {
     761           0 :   if (aAlternate && aTitle.IsEmpty()) {
     762             :     // alternates must have title return without error, for now
     763             :     return NS_OK;
     764             :   }
     765             : 
     766           0 :   nsAutoString  mimeType;
     767           0 :   nsAutoString  params;
     768           0 :   nsContentUtils::SplitMimeType(aType, mimeType, params);
     769             : 
     770             :   // see bug 18817
     771           0 :   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
     772             :     // Unknown stylesheet language
     773             :     return NS_OK;
     774             :   }
     775             : 
     776           0 :   nsCOMPtr<nsIURI> url;
     777           0 :   nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr,
     778           0 :                           mDocument->GetDocBaseURI());
     779             : 
     780           0 :   if (NS_FAILED(rv)) {
     781             :     // The URI is bad, move along, don't propagate the error (for now)
     782             :     return NS_OK;
     783             :   }
     784             : 
     785             : 
     786             :   Loader::SheetInfo info {
     787           0 :     *mDocument,
     788             :     nullptr,
     789           0 :     url.forget(),
     790             :     nullptr,
     791             :     net::AttributeReferrerPolicyFromString(aReferrerPolicy),
     792             :     CORS_NONE,
     793             :     aTitle,
     794             :     aMedia,
     795             :     aAlternate ? Loader::HasAlternateRel::Yes : Loader::HasAlternateRel::No,
     796             :     Loader::IsInline::No,
     797           0 :   };
     798             : 
     799             :   auto loadResultOrErr =
     800           0 :     mCSSLoader->LoadStyleLink(info, mRunsToCompletion ? nullptr : this);
     801           0 :   if (loadResultOrErr.isErr()) {
     802           0 :     return loadResultOrErr.unwrapErr();
     803             :   }
     804             : 
     805           0 :   if (loadResultOrErr.unwrap().ShouldBlock() && !mRunsToCompletion) {
     806           0 :     ++mPendingSheetCount;
     807           0 :     mScriptLoader->AddParserBlockingScriptExecutionBlocker();
     808             :   }
     809             : 
     810             :   return NS_OK;
     811             : }
     812             : 
     813             : 
     814             : nsresult
     815           0 : nsContentSink::ProcessMETATag(nsIContent* aContent)
     816             : {
     817           0 :   NS_ASSERTION(aContent, "missing meta-element");
     818           0 :   MOZ_ASSERT(aContent->IsElement());
     819             : 
     820           0 :   Element* element = aContent->AsElement();
     821             : 
     822           0 :   nsresult rv = NS_OK;
     823             : 
     824             :   // set any HTTP-EQUIV data into document's header data as well as url
     825           0 :   nsAutoString header;
     826           0 :   element->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
     827           0 :   if (!header.IsEmpty()) {
     828             :     // Ignore META REFRESH when document is sandboxed from automatic features.
     829           0 :     nsContentUtils::ASCIIToLower(header);
     830           0 :     if (nsGkAtoms::refresh->Equals(header) &&
     831           0 :         (mDocument->GetSandboxFlags() & SANDBOXED_AUTOMATIC_FEATURES)) {
     832           0 :       return NS_OK;
     833             :     }
     834             : 
     835             :     // Don't allow setting cookies in <meta http-equiv> in cookie averse
     836             :     // documents.
     837           0 :     if (nsGkAtoms::setcookie->Equals(header) && mDocument->IsCookieAverse()) {
     838             :       return NS_OK;
     839             :     }
     840             : 
     841           0 :     nsAutoString result;
     842           0 :     element->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
     843           0 :     if (!result.IsEmpty()) {
     844           0 :       RefPtr<nsAtom> fieldAtom(NS_Atomize(header));
     845           0 :       rv = ProcessHeaderData(fieldAtom, result, element);
     846             :     }
     847             :   }
     848           0 :   NS_ENSURE_SUCCESS(rv, rv);
     849             : 
     850           0 :   if (element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
     851             :                            nsGkAtoms::handheldFriendly, eIgnoreCase)) {
     852           0 :     nsAutoString result;
     853           0 :     element->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
     854           0 :     if (!result.IsEmpty()) {
     855           0 :       nsContentUtils::ASCIIToLower(result);
     856           0 :       mDocument->SetHeaderData(nsGkAtoms::handheldFriendly, result);
     857             :     }
     858             :   }
     859             : 
     860             :   return rv;
     861             : }
     862             : 
     863             : 
     864             : void
     865           0 : nsContentSink::PrefetchPreloadHref(const nsAString &aHref,
     866             :                                    nsINode *aSource,
     867             :                                    uint32_t aLinkTypes,
     868             :                                    const nsAString& aAs,
     869             :                                    const nsAString& aType,
     870             :                                    const nsAString& aMedia)
     871             : {
     872           0 :   nsCOMPtr<nsIPrefetchService> prefetchService(do_GetService(NS_PREFETCHSERVICE_CONTRACTID));
     873           0 :   if (prefetchService) {
     874             :     // construct URI using document charset
     875           0 :     auto encoding = mDocument->GetDocumentCharacterSet();
     876           0 :     nsCOMPtr<nsIURI> uri;
     877           0 :     NS_NewURI(getter_AddRefs(uri), aHref, encoding,
     878           0 :               mDocument->GetDocBaseURI());
     879           0 :     if (uri) {
     880           0 :       if (aLinkTypes & nsStyleLinkElement::ePRELOAD) {
     881           0 :         nsAttrValue asAttr;
     882           0 :         Link::ParseAsValue(aAs, asAttr);
     883           0 :         nsContentPolicyType policyType = Link::AsValueToContentPolicy(asAttr);
     884             : 
     885           0 :         if (policyType == nsIContentPolicy::TYPE_INVALID) {
     886             :           // Ignore preload with a wrong or empty as attribute.
     887           0 :           return;
     888             :         }
     889             : 
     890           0 :         nsAutoString mimeType;
     891           0 :         nsAutoString notUsed;
     892           0 :         nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
     893           0 :         if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType,
     894             :                                                 aMedia,mDocument)) {
     895           0 :           policyType = nsIContentPolicy::TYPE_INVALID;
     896             :         }
     897             : 
     898           0 :         prefetchService->PreloadURI(uri, mDocumentURI, aSource, policyType);
     899             :       } else {
     900           0 :         prefetchService->PrefetchURI(uri, mDocumentURI, aSource,
     901           0 :                                      aLinkTypes & nsStyleLinkElement::ePREFETCH);
     902             :       }
     903             :     }
     904             :   }
     905             : }
     906             : 
     907             : void
     908           0 : nsContentSink::PrefetchDNS(const nsAString &aHref)
     909             : {
     910           0 :   nsAutoString hostname;
     911             : 
     912           0 :   if (StringBeginsWith(aHref, NS_LITERAL_STRING("//")))  {
     913           0 :     hostname = Substring(aHref, 2);
     914             :   }
     915             :   else {
     916           0 :     nsCOMPtr<nsIURI> uri;
     917           0 :     NS_NewURI(getter_AddRefs(uri), aHref);
     918           0 :     if (!uri) {
     919           0 :       return;
     920             :     }
     921             :     nsresult rv;
     922           0 :     bool isLocalResource = false;
     923           0 :     rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
     924           0 :                              &isLocalResource);
     925           0 :     if (NS_SUCCEEDED(rv) && !isLocalResource) {
     926           0 :       nsAutoCString host;
     927           0 :       uri->GetHost(host);
     928           0 :       CopyUTF8toUTF16(host, hostname);
     929             :     }
     930             :   }
     931             : 
     932           0 :   if (!hostname.IsEmpty() && nsHTMLDNSPrefetch::IsAllowed(mDocument)) {
     933           0 :     nsHTMLDNSPrefetch::PrefetchLow(hostname,
     934           0 :                                    mDocument->NodePrincipal()->OriginAttributesRef());
     935             :   }
     936             : }
     937             : 
     938             : void
     939           0 : nsContentSink::Preconnect(const nsAString& aHref, const nsAString& aCrossOrigin)
     940             : {
     941             :   // construct URI using document charset
     942           0 :   auto encoding = mDocument->GetDocumentCharacterSet();
     943           0 :   nsCOMPtr<nsIURI> uri;
     944           0 :   NS_NewURI(getter_AddRefs(uri), aHref, encoding,
     945           0 :             mDocument->GetDocBaseURI());
     946             : 
     947           0 :   if (uri && mDocument) {
     948           0 :     mDocument->MaybePreconnect(uri, dom::Element::StringToCORSMode(aCrossOrigin));
     949             :   }
     950           0 : }
     951             : 
     952             : nsresult
     953           0 : nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
     954             :                                  nsIURI *aManifestURI,
     955             :                                  bool aFetchedWithHTTPGetOrEquiv,
     956             :                                  CacheSelectionAction *aAction)
     957             : {
     958             :   nsresult rv;
     959             : 
     960           0 :   *aAction = CACHE_SELECTION_NONE;
     961             : 
     962             :   nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
     963           0 :     do_QueryInterface(mDocument);
     964           0 :   NS_ASSERTION(applicationCacheDocument,
     965             :                "mDocument must implement nsIApplicationCacheContainer.");
     966             : 
     967           0 :   if (aLoadApplicationCache) {
     968           0 :     nsCOMPtr<nsIURI> groupURI;
     969           0 :     rv = aLoadApplicationCache->GetManifestURI(getter_AddRefs(groupURI));
     970           0 :     NS_ENSURE_SUCCESS(rv, rv);
     971             : 
     972           0 :     bool equal = false;
     973           0 :     rv = groupURI->Equals(aManifestURI, &equal);
     974           0 :     NS_ENSURE_SUCCESS(rv, rv);
     975             : 
     976           0 :     if (!equal) {
     977             :       // This is a foreign entry, force a reload to avoid loading the foreign
     978             :       // entry. The entry will be marked as foreign to avoid loading it again.
     979             : 
     980           0 :       *aAction = CACHE_SELECTION_RELOAD;
     981             :     }
     982             :     else {
     983             :       // The http manifest attribute URI is equal to the manifest URI of
     984             :       // the cache the document was loaded from - associate the document with
     985             :       // that cache and invoke the cache update process.
     986             : #ifdef DEBUG
     987           0 :       nsAutoCString docURISpec, clientID;
     988           0 :       mDocumentURI->GetAsciiSpec(docURISpec);
     989           0 :       aLoadApplicationCache->GetClientID(clientID);
     990           0 :       SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
     991             :                  SINK_TRACE_CALLS,
     992             :                 ("Selection: assigning app cache %s to document %s",
     993             :                   clientID.get(), docURISpec.get()));
     994             : #endif
     995             : 
     996           0 :       rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
     997           0 :       NS_ENSURE_SUCCESS(rv, rv);
     998             : 
     999             :       // Document will be added as implicit entry to the cache as part of
    1000             :       // the update process.
    1001           0 :       *aAction = CACHE_SELECTION_UPDATE;
    1002             :     }
    1003             :   }
    1004             :   else {
    1005             :     // The document was not loaded from an application cache
    1006             :     // Here we know the manifest has the same origin as the
    1007             :     // document. There is call to CheckMayLoad() on it above.
    1008             : 
    1009           0 :     if (!aFetchedWithHTTPGetOrEquiv) {
    1010             :       // The document was not loaded using HTTP GET or equivalent
    1011             :       // method. The spec says to run the cache selection algorithm w/o
    1012             :       // the manifest specified.
    1013           0 :       *aAction = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
    1014             :     }
    1015             :     else {
    1016             :       // Always do an update in this case
    1017           0 :       *aAction = CACHE_SELECTION_UPDATE;
    1018             :     }
    1019             :   }
    1020             : 
    1021             :   return NS_OK;
    1022             : }
    1023             : 
    1024             : nsresult
    1025           0 : nsContentSink::SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
    1026             :                                            nsIURI **aManifestURI,
    1027             :                                            CacheSelectionAction *aAction)
    1028             : {
    1029           0 :   *aManifestURI = nullptr;
    1030           0 :   *aAction = CACHE_SELECTION_NONE;
    1031             : 
    1032             :   nsresult rv;
    1033             : 
    1034           0 :   if (aLoadApplicationCache) {
    1035             :     // The document was loaded from an application cache, use that
    1036             :     // application cache as the document's application cache.
    1037             :     nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
    1038           0 :       do_QueryInterface(mDocument);
    1039           0 :     NS_ASSERTION(applicationCacheDocument,
    1040             :                  "mDocument must implement nsIApplicationCacheContainer.");
    1041             : 
    1042             : #ifdef DEBUG
    1043           0 :     nsAutoCString docURISpec, clientID;
    1044           0 :     mDocumentURI->GetAsciiSpec(docURISpec);
    1045           0 :     aLoadApplicationCache->GetClientID(clientID);
    1046           0 :     SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
    1047             :                SINK_TRACE_CALLS,
    1048             :              ("Selection, no manifest: assigning app cache %s to document %s",
    1049             :                clientID.get(), docURISpec.get()));
    1050             : #endif
    1051             : 
    1052           0 :     rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
    1053           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1054             : 
    1055             :     // Return the uri and invoke the update process for the selected
    1056             :     // application cache.
    1057           0 :     rv = aLoadApplicationCache->GetManifestURI(aManifestURI);
    1058           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1059             : 
    1060           0 :     *aAction = CACHE_SELECTION_UPDATE;
    1061             :   }
    1062             : 
    1063             :   return NS_OK;
    1064             : }
    1065             : 
    1066             : void
    1067           0 : nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
    1068             : {
    1069             :   // Only check the manifest for root document nodes.
    1070           0 :   if (aElement != mDocument->GetRootElement()) {
    1071           0 :     return;
    1072             :   }
    1073             : 
    1074             :   // Don't bother processing offline manifest for documents
    1075             :   // without a docshell
    1076           0 :   if (!mDocShell) {
    1077             :     return;
    1078             :   }
    1079             : 
    1080             :   // Check for a manifest= attribute.
    1081           0 :   nsAutoString manifestSpec;
    1082           0 :   aElement->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
    1083           0 :   ProcessOfflineManifest(manifestSpec);
    1084             : }
    1085             : 
    1086             : void
    1087           0 : nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
    1088             : {
    1089             :   // Don't bother processing offline manifest for documents
    1090             :   // without a docshell
    1091           0 :   if (!mDocShell) {
    1092           0 :     return;
    1093             :   }
    1094             : 
    1095             :   // If this document has been interecepted, let's skip the processing of the
    1096             :   // manifest.
    1097           0 :   if (mDocument->GetController().isSome()) {
    1098             :     return;
    1099             :   }
    1100             : 
    1101             :   // If the docshell's in private browsing mode, we don't want to do any
    1102             :   // manifest processing.
    1103           0 :   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(mDocShell);
    1104           0 :   if (loadContext->UsePrivateBrowsing()) {
    1105           0 :     return;
    1106             :   }
    1107             : 
    1108             :   nsresult rv;
    1109             : 
    1110             :   // Grab the application cache the document was loaded from, if any.
    1111           0 :   nsCOMPtr<nsIApplicationCache> applicationCache;
    1112             : 
    1113             :   nsCOMPtr<nsIApplicationCacheChannel> applicationCacheChannel =
    1114           0 :     do_QueryInterface(mDocument->GetChannel());
    1115           0 :   if (applicationCacheChannel) {
    1116             :     bool loadedFromApplicationCache;
    1117           0 :     rv = applicationCacheChannel->GetLoadedFromApplicationCache(
    1118           0 :       &loadedFromApplicationCache);
    1119           0 :     if (NS_FAILED(rv)) {
    1120           0 :       return;
    1121             :     }
    1122             : 
    1123           0 :     if (loadedFromApplicationCache) {
    1124           0 :       rv = applicationCacheChannel->GetApplicationCache(
    1125           0 :         getter_AddRefs(applicationCache));
    1126           0 :       if (NS_FAILED(rv)) {
    1127             :         return;
    1128             :       }
    1129             :     }
    1130             :   }
    1131             : 
    1132           0 :   if (aManifestSpec.IsEmpty() && !applicationCache) {
    1133             :     // Not loaded from an application cache, and no manifest
    1134             :     // attribute.  Nothing to do here.
    1135             :     return;
    1136             :   }
    1137             : 
    1138           0 :   CacheSelectionAction action = CACHE_SELECTION_NONE;
    1139           0 :   nsCOMPtr<nsIURI> manifestURI;
    1140             : 
    1141           0 :   if (aManifestSpec.IsEmpty()) {
    1142           0 :     action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
    1143             :   }
    1144             :   else {
    1145           0 :     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
    1146             :                                               aManifestSpec, mDocument,
    1147           0 :                                               mDocumentURI);
    1148           0 :     if (!manifestURI) {
    1149           0 :       return;
    1150             :     }
    1151             : 
    1152             :     // Documents must list a manifest from the same origin
    1153           0 :     rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, true, false);
    1154           0 :     if (NS_FAILED(rv)) {
    1155           0 :       action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
    1156             :     }
    1157             :     else {
    1158             :       // Only continue if the document has permission to use offline APIs or
    1159             :       // when preferences indicate to permit it automatically.
    1160           0 :       if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal()) &&
    1161           0 :           !nsContentUtils::MaybeAllowOfflineAppByDefault(mDocument->NodePrincipal()) &&
    1162           0 :           !nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
    1163           0 :         return;
    1164             :       }
    1165             : 
    1166           0 :       bool fetchedWithHTTPGetOrEquiv = false;
    1167           0 :       nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mDocument->GetChannel()));
    1168           0 :       if (httpChannel) {
    1169           0 :         nsAutoCString method;
    1170           0 :         rv = httpChannel->GetRequestMethod(method);
    1171           0 :         if (NS_SUCCEEDED(rv))
    1172           0 :           fetchedWithHTTPGetOrEquiv = method.EqualsLiteral("GET");
    1173             :       }
    1174             : 
    1175           0 :       rv = SelectDocAppCache(applicationCache, manifestURI,
    1176           0 :                              fetchedWithHTTPGetOrEquiv, &action);
    1177           0 :       if (NS_FAILED(rv)) {
    1178           0 :         return;
    1179             :       }
    1180             :     }
    1181             :   }
    1182             : 
    1183           0 :   if (action == CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST) {
    1184           0 :     rv = SelectDocAppCacheNoManifest(applicationCache,
    1185           0 :                                      getter_AddRefs(manifestURI),
    1186           0 :                                      &action);
    1187           0 :     if (NS_FAILED(rv)) {
    1188             :       return;
    1189             :     }
    1190             :   }
    1191             : 
    1192           0 :   switch (action)
    1193             :   {
    1194             :   case CACHE_SELECTION_NONE:
    1195             :     break;
    1196             :   case CACHE_SELECTION_UPDATE: {
    1197             :     nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
    1198           0 :       do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
    1199             : 
    1200           0 :     if (updateService) {
    1201           0 :       updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI,
    1202           0 :                                             mDocument->NodePrincipal(), mDocument);
    1203             :     }
    1204             :     break;
    1205             :   }
    1206             :   case CACHE_SELECTION_RELOAD: {
    1207             :     // This situation occurs only for toplevel documents, see bottom
    1208             :     // of SelectDocAppCache method.
    1209             :     // The document has been loaded from a different offline cache group than
    1210             :     // the manifest it refers to, i.e. this is a foreign entry, mark it as such
    1211             :     // and force a reload to avoid loading it.  The next attempt will not
    1212             :     // choose it.
    1213             : 
    1214           0 :     applicationCacheChannel->MarkOfflineCacheEntryAsForeign();
    1215             : 
    1216           0 :     nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mDocShell);
    1217             : 
    1218           0 :     webNav->Stop(nsIWebNavigation::STOP_ALL);
    1219           0 :     webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
    1220             :     break;
    1221             :   }
    1222             :   default:
    1223           0 :     NS_ASSERTION(false,
    1224             :           "Cache selection algorithm didn't decide on proper action");
    1225             :     break;
    1226             :   }
    1227             : }
    1228             : 
    1229             : void
    1230           0 : nsContentSink::ScrollToRef()
    1231             : {
    1232           0 :   mDocument->ScrollToRef();
    1233           0 : }
    1234             : 
    1235             : void
    1236           0 : nsContentSink::StartLayout(bool aIgnorePendingSheets)
    1237             : {
    1238           0 :   AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("nsContentSink::StartLayout", LAYOUT,
    1239             :                                         mDocumentURI->GetSpecOrDefault());
    1240             : 
    1241          73 :   if (mLayoutStarted) {
    1242             :     // Nothing to do here
    1243           0 :     return;
    1244             :   }
    1245             : 
    1246          49 :   mDeferredLayoutStart = true;
    1247             : 
    1248          49 :   if (!aIgnorePendingSheets && WaitForPendingSheets()) {
    1249             :     // Bail out; we'll start layout when the sheets load
    1250             :     return;
    1251             :   }
    1252             : 
    1253          49 :   mDeferredLayoutStart = false;
    1254             : 
    1255             :   // Notify on all our content.  If none of our presshells have started layout
    1256             :   // yet it'll be a no-op except for updating our data structures, a la
    1257             :   // UpdateChildCounts() (because we don't want to double-notify on whatever we
    1258             :   // have right now).  If some of them _have_ started layout, we want to make
    1259             :   // sure to flush tags instead of just calling UpdateChildCounts() after we
    1260             :   // loop over the shells.
    1261           0 :   FlushTags();
    1262             : 
    1263           0 :   mLayoutStarted = true;
    1264           0 :   mLastNotificationTime = PR_Now();
    1265             : 
    1266          49 :   mDocument->SetMayStartLayout(true);
    1267         147 :   nsCOMPtr<nsIPresShell> shell = mDocument->GetShell();
    1268             :   // Make sure we don't call Initialize() for a shell that has
    1269             :   // already called it. This can happen when the layout frame for
    1270             :   // an iframe is constructed *between* the Embed() call for the
    1271             :   // docshell in the iframe, and the content sink's call to OpenBody().
    1272             :   // (Bug 153815)
    1273           1 :   if (shell && !shell->DidInitialize()) {
    1274          16 :     nsresult rv = shell->Initialize();
    1275          16 :     if (NS_FAILED(rv)) {
    1276           0 :       return;
    1277             :     }
    1278             :   }
    1279             : 
    1280             :   // If the document we are loading has a reference or it is a
    1281             :   // frameset document, disable the scroll bars on the views.
    1282             : 
    1283          98 :   mDocument->SetScrollToRef(mDocument->GetDocumentURI());
    1284             : }
    1285             : 
    1286             : void
    1287          60 : nsContentSink::NotifyAppend(nsIContent* aContainer, uint32_t aStartIndex)
    1288             : {
    1289         120 :   if (aContainer->GetUncomposedDoc() != mDocument) {
    1290             :     // aContainer is not actually in our document anymore.... Just bail out of
    1291             :     // here; notifying on our document for this append would be wrong.
    1292             :     return;
    1293             :   }
    1294             : 
    1295          60 :   mInNotification++;
    1296             : 
    1297             :   {
    1298             :     // Scope so we call EndUpdate before we decrease mInNotification
    1299           0 :     MOZ_AUTO_DOC_UPDATE(mDocument, !mBeganUpdate);
    1300          60 :     nsNodeUtils::ContentAppended(aContainer,
    1301         120 :                                  aContainer->GetChildAt_Deprecated(aStartIndex));
    1302           0 :     mLastNotificationTime = PR_Now();
    1303             :   }
    1304             : 
    1305          60 :   mInNotification--;
    1306             : }
    1307             : 
    1308             : NS_IMETHODIMP
    1309           0 : nsContentSink::Notify(nsITimer *timer)
    1310             : {
    1311           0 :   if (mParsing) {
    1312             :     // We shouldn't interfere with our normal DidProcessAToken logic
    1313           0 :     mDroppedTimer = true;
    1314           0 :     return NS_OK;
    1315             :   }
    1316             : 
    1317           0 :   if (WaitForPendingSheets()) {
    1318           0 :     mDeferredFlushTags = true;
    1319             :   } else {
    1320           0 :     FlushTags();
    1321             : 
    1322             :     // Now try and scroll to the reference
    1323             :     // XXX Should we scroll unconditionally for history loads??
    1324           0 :     ScrollToRef();
    1325             :   }
    1326             : 
    1327           0 :   mNotificationTimer = nullptr;
    1328           0 :   return NS_OK;
    1329             : }
    1330             : 
    1331             : bool
    1332           0 : nsContentSink::IsTimeToNotify()
    1333             : {
    1334       12190 :   if (!sNotifyOnTimer || !mLayoutStarted || !mBackoffCount ||
    1335        4428 :       mInMonolithicContainer) {
    1336             :     return false;
    1337             :   }
    1338             : 
    1339        4428 :   if (WaitForPendingSheets()) {
    1340           0 :     mDeferredFlushTags = true;
    1341           0 :     return false;
    1342             :   }
    1343             : 
    1344           0 :   PRTime now = PR_Now();
    1345             : 
    1346           0 :   int64_t interval = GetNotificationInterval();
    1347           0 :   int64_t diff = now - mLastNotificationTime;
    1348             : 
    1349        4428 :   if (diff > interval) {
    1350           0 :     mBackoffCount--;
    1351           0 :     return true;
    1352             :   }
    1353             : 
    1354             :   return false;
    1355             : }
    1356             : 
    1357             : nsresult
    1358          44 : nsContentSink::WillInterruptImpl()
    1359             : {
    1360          44 :   nsresult result = NS_OK;
    1361             : 
    1362          88 :   SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
    1363             :              SINK_TRACE_CALLS,
    1364             :              ("nsContentSink::WillInterrupt: this=%p", this));
    1365             : #ifndef SINK_NO_INCREMENTAL
    1366           0 :   if (WaitForPendingSheets()) {
    1367           0 :     mDeferredFlushTags = true;
    1368           0 :   } else if (sNotifyOnTimer && mLayoutStarted) {
    1369           0 :     if (mBackoffCount && !mInMonolithicContainer) {
    1370          24 :       int64_t now = PR_Now();
    1371          24 :       int64_t interval = GetNotificationInterval();
    1372           0 :       int64_t diff = now - mLastNotificationTime;
    1373             : 
    1374             :       // If it's already time for us to have a notification
    1375          24 :       if (diff > interval || mDroppedTimer) {
    1376           0 :         mBackoffCount--;
    1377           0 :         SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
    1378             :                    SINK_TRACE_REFLOW,
    1379             :                    ("nsContentSink::WillInterrupt: flushing tags since we've "
    1380             :                     "run out time; backoff count: %d", mBackoffCount));
    1381           0 :         result = FlushTags();
    1382           0 :         if (mDroppedTimer) {
    1383           0 :           ScrollToRef();
    1384           0 :           mDroppedTimer = false;
    1385             :         }
    1386          48 :       } else if (!mNotificationTimer) {
    1387          24 :         interval -= diff;
    1388           0 :         int32_t delay = interval;
    1389             : 
    1390             :         // Convert to milliseconds
    1391          24 :         delay /= PR_USEC_PER_MSEC;
    1392             : 
    1393           0 :         NS_NewTimerWithCallback(getter_AddRefs(mNotificationTimer),
    1394             :                                 this, delay,
    1395          24 :                                 nsITimer::TYPE_ONE_SHOT);
    1396          48 :         if (mNotificationTimer) {
    1397          48 :           SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
    1398             :                      SINK_TRACE_REFLOW,
    1399             :                      ("nsContentSink::WillInterrupt: setting up timer with "
    1400             :                       "delay %d", delay));
    1401             :         }
    1402             :       }
    1403             :     }
    1404             :   } else {
    1405          40 :     SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
    1406             :                SINK_TRACE_REFLOW,
    1407             :                ("nsContentSink::WillInterrupt: flushing tags "
    1408             :                 "unconditionally"));
    1409          20 :     result = FlushTags();
    1410             :   }
    1411             : #endif
    1412             : 
    1413          44 :   mParsing = false;
    1414             : 
    1415          44 :   return result;
    1416             : }
    1417             : 
    1418             : nsresult
    1419          89 : nsContentSink::WillResumeImpl()
    1420             : {
    1421         178 :   SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
    1422             :              SINK_TRACE_CALLS,
    1423             :              ("nsContentSink::WillResume: this=%p", this));
    1424             : 
    1425          89 :   mParsing = true;
    1426             : 
    1427          89 :   return NS_OK;
    1428             : }
    1429             : 
    1430             : nsresult
    1431       22303 : nsContentSink::DidProcessATokenImpl()
    1432             : {
    1433       44606 :   if (mRunsToCompletion || !mParser) {
    1434             :     return NS_OK;
    1435             :   }
    1436             : 
    1437             :   // Get the current user event time
    1438       44606 :   nsIPresShell *shell = mDocument->GetShell();
    1439       22303 :   if (!shell) {
    1440             :     // If there's no pres shell in the document, return early since
    1441             :     // we're not laying anything out here.
    1442             :     return NS_OK;
    1443             :   }
    1444             : 
    1445             :   // Increase before comparing to gEventProbeRate
    1446           0 :   ++mDeflectedCount;
    1447             : 
    1448             :   // Check if there's a pending event
    1449           1 :   if (sPendingEventMode != 0 && !mHasPendingEvent &&
    1450           0 :       (mDeflectedCount % sEventProbeRate) == 0) {
    1451           0 :     nsViewManager* vm = shell->GetViewManager();
    1452           0 :     NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
    1453           0 :     nsCOMPtr<nsIWidget> widget;
    1454           0 :     vm->GetRootWidget(getter_AddRefs(widget));
    1455           0 :     mHasPendingEvent = widget && widget->HasPendingInputEvent();
    1456             :   }
    1457             : 
    1458         202 :   if (mHasPendingEvent && sPendingEventMode == 2) {
    1459             :     return NS_ERROR_HTMLPARSER_INTERRUPTED;
    1460             :   }
    1461             : 
    1462             :   // Have we processed enough tokens to check time?
    1463         404 :   if (!mHasPendingEvent &&
    1464         404 :       mDeflectedCount < uint32_t(mDynamicLowerValue ? sInteractiveDeflectCount :
    1465         202 :                                                       sPerfDeflectCount)) {
    1466             :     return NS_OK;
    1467             :   }
    1468             : 
    1469           0 :   mDeflectedCount = 0;
    1470             : 
    1471             :   // Check if it's time to return to the main event loop
    1472           3 :   if (PR_IntervalToMicroseconds(PR_IntervalNow()) > mCurrentParseEndTime) {
    1473             :     return NS_ERROR_HTMLPARSER_INTERRUPTED;
    1474             :   }
    1475             : 
    1476           3 :   return NS_OK;
    1477             : }
    1478             : 
    1479             : //----------------------------------------------------------------------
    1480             : 
    1481             : void
    1482           0 : nsContentSink::FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay)
    1483             : {
    1484             :   static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
    1485           0 :   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
    1486           0 :   if (appShell)
    1487           0 :     appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay);
    1488           0 : }
    1489             : 
    1490             : void
    1491           0 : nsContentSink::BeginUpdate(nsIDocument* aDocument)
    1492             : {
    1493             :   // Remember nested updates from updates that we started.
    1494         313 :   if (mInNotification > 0 && mUpdatesInNotification < 2) {
    1495         165 :     ++mUpdatesInNotification;
    1496             :   }
    1497             : 
    1498             :   // If we're in a script and we didn't do the notification,
    1499             :   // something else in the script processing caused the
    1500             :   // notification to occur. Since this could result in frame
    1501             :   // creation, make sure we've flushed everything before we
    1502             :   // continue.
    1503             : 
    1504           0 :   if (!mInNotification++) {
    1505          80 :     FlushTags();
    1506             :   }
    1507           0 : }
    1508             : 
    1509             : void
    1510         313 : nsContentSink::EndUpdate(nsIDocument* aDocument)
    1511             : {
    1512             :   // If we're in a script and we didn't do the notification,
    1513             :   // something else in the script processing caused the
    1514             :   // notification to occur. Update our notion of how much
    1515             :   // has been flushed to include any new content if ending
    1516             :   // this update leaves us not inside a notification.
    1517           0 :   if (!--mInNotification) {
    1518          80 :     UpdateChildCounts();
    1519             :   }
    1520           0 : }
    1521             : 
    1522             : void
    1523           0 : nsContentSink::DidBuildModelImpl(bool aTerminated)
    1524             : {
    1525          98 :   if (mDocument) {
    1526           0 :     MOZ_ASSERT(aTerminated ||
    1527             :                mDocument->GetReadyStateEnum() ==
    1528             :                nsIDocument::READYSTATE_LOADING, "Bad readyState");
    1529           0 :     mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
    1530             :   }
    1531             : 
    1532          98 :   if (mScriptLoader) {
    1533           0 :     mScriptLoader->ParsingComplete(aTerminated);
    1534             :   }
    1535             : 
    1536          98 :   if (!mDocument->HaveFiredDOMTitleChange()) {
    1537          49 :     mDocument->NotifyPossibleTitleChange(false);
    1538             :   }
    1539             : 
    1540             :   // Cancel a timer if we had one out there
    1541          98 :   if (mNotificationTimer) {
    1542          48 :     SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
    1543             :                SINK_TRACE_REFLOW,
    1544             :                ("nsContentSink::DidBuildModel: canceling notification "
    1545             :                 "timeout"));
    1546           0 :     mNotificationTimer->Cancel();
    1547          24 :     mNotificationTimer = nullptr;
    1548             :   }
    1549           0 : }
    1550             : 
    1551             : void
    1552          49 : nsContentSink::DropParserAndPerfHint(void)
    1553             : {
    1554          98 :   if (!mParser) {
    1555             :     // Make sure we don't unblock unload too many times
    1556           0 :     return;
    1557             :   }
    1558             : 
    1559             :   // Ref. Bug 49115
    1560             :   // Do this hack to make sure that the parser
    1561             :   // doesn't get destroyed, accidently, before
    1562             :   // the circularity, between sink & parser, is
    1563             :   // actually broken.
    1564             :   // Drop our reference to the parser to get rid of a circular
    1565             :   // reference.
    1566         196 :   RefPtr<nsParserBase> kungFuDeathGrip(mParser.forget());
    1567             : 
    1568           0 :   if (mDynamicLowerValue) {
    1569             :     // Reset the performance hint which was set to FALSE
    1570             :     // when mDynamicLowerValue was set.
    1571           0 :     FavorPerformanceHint(true, 0);
    1572             :   }
    1573             : 
    1574             :   // Call UnblockOnload only if mRunsToComletion is false and if
    1575             :   // we have already started loading because it's possible that this function
    1576             :   // is called (i.e. the parser is terminated) before we start loading due to
    1577             :   // destroying the window inside unload event callbacks for the previous
    1578             :   // document.
    1579          49 :   if (!mRunsToCompletion && mIsBlockingOnload) {
    1580          49 :     mDocument->UnblockOnload(true);
    1581          49 :     mIsBlockingOnload = false;
    1582             :   }
    1583             : }
    1584             : 
    1585             : bool
    1586         102 : nsContentSink::IsScriptExecutingImpl()
    1587             : {
    1588         204 :   return !!mScriptLoader->GetCurrentScript();
    1589             : }
    1590             : 
    1591             : nsresult
    1592         102 : nsContentSink::WillParseImpl(void)
    1593             : {
    1594         204 :   if (mRunsToCompletion || !mDocument) {
    1595             :     return NS_OK;
    1596             :   }
    1597             : 
    1598         204 :   nsIPresShell *shell = mDocument->GetShell();
    1599         102 :   if (!shell) {
    1600             :     return NS_OK;
    1601             :   }
    1602             : 
    1603           0 :   uint32_t currentTime = PR_IntervalToMicroseconds(PR_IntervalNow());
    1604             : 
    1605          38 :   if (sEnablePerfMode == 0) {
    1606           0 :     nsViewManager* vm = shell->GetViewManager();
    1607          38 :     NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
    1608             :     uint32_t lastEventTime;
    1609           0 :     vm->GetLastUserEventTime(lastEventTime);
    1610             : 
    1611             :     bool newDynLower =
    1612          76 :       mDocument->IsInBackgroundWindow() ||
    1613           0 :       ((currentTime - mBeginLoadTime) > uint32_t(sInitialPerfTime) &&
    1614           0 :        (currentTime - lastEventTime) < uint32_t(sInteractiveTime));
    1615             : 
    1616          38 :     if (mDynamicLowerValue != newDynLower) {
    1617           0 :       FavorPerformanceHint(!newDynLower, 0);
    1618           0 :       mDynamicLowerValue = newDynLower;
    1619             :     }
    1620             :   }
    1621             : 
    1622           0 :   mDeflectedCount = 0;
    1623           0 :   mHasPendingEvent = false;
    1624             : 
    1625           0 :   mCurrentParseEndTime = currentTime +
    1626          38 :     (mDynamicLowerValue ? sInteractiveParseTime : sPerfParseTime);
    1627             : 
    1628          38 :   return NS_OK;
    1629             : }
    1630             : 
    1631             : void
    1632           0 : nsContentSink::WillBuildModelImpl()
    1633             : {
    1634          49 :   if (!mRunsToCompletion) {
    1635           0 :     mDocument->BlockOnload();
    1636          49 :     mIsBlockingOnload = true;
    1637             : 
    1638           0 :     mBeginLoadTime = PR_IntervalToMicroseconds(PR_IntervalNow());
    1639             :   }
    1640             : 
    1641           0 :   mDocument->ResetScrolledToRefAlready();
    1642             : 
    1643           0 :   if (mProcessLinkHeaderEvent.get()) {
    1644           0 :     mProcessLinkHeaderEvent.Revoke();
    1645             : 
    1646           0 :     DoProcessLinkHeader();
    1647             :   }
    1648          49 : }
    1649             : 
    1650             : /* static */
    1651             : void
    1652          51 : nsContentSink::NotifyDocElementCreated(nsIDocument* aDoc)
    1653             : {
    1654           0 :   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
    1655             : 
    1656             :   nsCOMPtr<nsIObserverService> observerService =
    1657           0 :     mozilla::services::GetObserverService();
    1658           0 :   if (observerService) {
    1659          51 :     observerService->
    1660          51 :       NotifyObservers(aDoc, "document-element-inserted",
    1661         102 :                       EmptyString().get());
    1662             :   }
    1663             : 
    1664             :   nsContentUtils::DispatchChromeEvent(aDoc, aDoc,
    1665          51 :                                       NS_LITERAL_STRING("DOMDocElementInserted"),
    1666         102 :                                       true, false);
    1667           0 : }
    1668             : 
    1669             : NS_IMETHODIMP
    1670           0 : nsContentSink::GetName(nsACString& aName)
    1671             : {
    1672             :   aName.AssignASCII("nsContentSink_timer");
    1673             :   return NS_OK;
    1674             : }

Generated by: LCOV version 1.13-14-ga5dd952