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

Generated by: LCOV version 1.13