2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2006-03-30 12:03:04 +04:00
|
|
|
/*
|
|
|
|
* Base class for the XML and HTML content sinks, which construct a
|
|
|
|
* DOM based on information from the parser.
|
|
|
|
*/
|
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
#include "nsContentSink.h"
|
2018-12-17 04:27:58 +03:00
|
|
|
#include "mozilla/Components.h"
|
2019-03-29 18:12:47 +03:00
|
|
|
#include "mozilla/PresShell.h"
|
2020-03-10 02:36:39 +03:00
|
|
|
#include "mozilla/StaticPrefs_browser.h"
|
|
|
|
#include "mozilla/StaticPrefs_content.h"
|
2019-01-02 16:05:23 +03:00
|
|
|
#include "mozilla/dom/Document.h"
|
2020-05-21 06:07:16 +03:00
|
|
|
#include "mozilla/dom/LinkStyle.h"
|
2010-06-29 02:49:35 +04:00
|
|
|
#include "mozilla/css/Loader.h"
|
2020-05-21 06:07:16 +03:00
|
|
|
#include "mozilla/dom/MutationObservers.h"
|
2016-05-04 03:43:33 +03:00
|
|
|
#include "mozilla/dom/SRILogHelper.h"
|
2020-05-20 20:27:43 +03:00
|
|
|
#include "mozilla/StoragePrincipalHelper.h"
|
2003-10-05 11:29:50 +04:00
|
|
|
#include "nsIDocShell.h"
|
2012-05-24 19:31:54 +04:00
|
|
|
#include "nsILoadContext.h"
|
2018-12-17 04:27:58 +03:00
|
|
|
#include "nsIPrefetchService.h"
|
2003-10-05 11:29:50 +04:00
|
|
|
#include "nsIURI.h"
|
|
|
|
#include "nsNetUtil.h"
|
2015-07-07 05:17:00 +03:00
|
|
|
#include "nsIMIMEHeaderParam.h"
|
|
|
|
#include "nsIProtocolHandler.h"
|
2003-10-05 11:29:50 +04:00
|
|
|
#include "nsIHttpChannel.h"
|
2004-01-28 15:14:17 +03:00
|
|
|
#include "nsIContent.h"
|
2004-08-01 03:15:21 +04:00
|
|
|
#include "nsPresContext.h"
|
2013-01-05 07:12:24 +04:00
|
|
|
#include "nsViewManager.h"
|
2017-10-03 01:05:19 +03:00
|
|
|
#include "nsAtom.h"
|
2006-12-26 20:47:52 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2019-02-23 00:27:44 +03:00
|
|
|
#include "nsGlobalWindowInner.h"
|
2003-10-30 05:59:31 +03:00
|
|
|
#include "nsNetCID.h"
|
2003-10-05 11:29:50 +04:00
|
|
|
#include "nsICookieService.h"
|
2003-10-22 02:11:49 +04:00
|
|
|
#include "nsContentUtils.h"
|
2004-06-25 16:26:02 +04:00
|
|
|
#include "nsNodeInfoManager.h"
|
2007-01-31 00:21:06 +03:00
|
|
|
#include "nsIAppShell.h"
|
2009-04-02 01:59:02 +04:00
|
|
|
#include "nsIWidget.h"
|
2007-01-31 00:21:06 +03:00
|
|
|
#include "nsWidgetsCID.h"
|
2008-04-11 21:29:06 +04:00
|
|
|
#include "mozAutoDocUpdate.h"
|
2008-08-28 05:15:32 +04:00
|
|
|
#include "nsIWebNavigation.h"
|
2008-11-08 02:00:26 +03:00
|
|
|
#include "nsGenericHTMLElement.h"
|
2012-06-06 11:40:02 +04:00
|
|
|
#include "nsIObserverService.h"
|
2011-05-29 03:42:57 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
Bug 1691589 - Reduce reliance on GeckoProfiler.h when only labels (and maybe markers) are needed - r=necko-reviewers,geckoview-reviewers,sg,agi,florian
There are no code changes, only #include changes.
It was a fairly mechanical process: Search for all "AUTO_PROFILER_LABEL", and in each file, if only labels are used, convert "GeckoProfiler.h" into "ProfilerLabels.h" (or just add that last one where needed).
In some files, there were also some marker calls but no other profiler-related calls, in these cases "GeckoProfiler.h" was replaced with both "ProfilerLabels.h" and "ProfilerMarkers.h", which still helps in reducing the use of the all-encompassing "GeckoProfiler.h".
Differential Revision: https://phabricator.services.mozilla.com/D104588
2021-02-16 07:44:19 +03:00
|
|
|
#include "mozilla/ProfilerLabels.h"
|
2021-01-27 07:37:58 +03:00
|
|
|
#include "mozilla/dom/HTMLDNSPrefetch.h"
|
2017-12-20 18:53:18 +03:00
|
|
|
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
2017-05-08 09:24:22 +03:00
|
|
|
#include "mozilla/dom/ScriptLoader.h"
|
2011-08-01 11:48:24 +04:00
|
|
|
#include "nsParserConstants.h"
|
2015-04-29 09:28:17 +03:00
|
|
|
#include "nsSandboxFlags.h"
|
2017-07-10 16:05:56 +03:00
|
|
|
#include "Link.h"
|
2018-04-20 12:47:00 +03:00
|
|
|
#include "HTMLLinkElement.h"
|
2015-11-23 22:09:25 +03:00
|
|
|
using namespace mozilla;
|
2018-05-06 17:10:09 +03:00
|
|
|
using namespace mozilla::css;
|
2017-07-10 16:05:56 +03:00
|
|
|
using namespace mozilla::dom;
|
2015-11-23 22:09:25 +03:00
|
|
|
|
|
|
|
LazyLogModule gContentSinkLogModuleInfo("nscontentsink");
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2008-02-09 01:07:51 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink)
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsContentSink)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
2008-03-05 07:54:21 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
2017-02-14 02:45:23 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsINamed)
|
2012-01-20 15:16:27 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentObserver)
|
2008-02-09 01:07:51 +03:00
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
2013-08-02 05:29:05 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSink)
|
|
|
|
|
2008-03-05 07:54:21 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink)
|
|
|
|
if (tmp->mDocument) {
|
|
|
|
tmp->mDocument->RemoveObserver(tmp);
|
|
|
|
}
|
2012-11-15 11:32:40 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser)
|
2017-10-02 17:58:42 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
|
2015-08-20 00:49:36 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
|
2012-11-15 11:32:40 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader)
|
2020-02-25 22:44:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
|
2008-03-05 07:54:21 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsContentSink)
|
2012-11-15 11:32:40 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser)
|
2017-10-02 17:58:42 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
|
2015-08-20 00:49:36 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
|
2012-11-15 11:32:40 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader)
|
2008-03-05 07:54:21 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
nsContentSink::nsContentSink()
|
2016-10-25 09:18:03 +03:00
|
|
|
: mBackoffCount(0),
|
|
|
|
mLastNotificationTime(0),
|
|
|
|
mLayoutStarted(0),
|
|
|
|
mDynamicLowerValue(0),
|
|
|
|
mParsing(0),
|
|
|
|
mDroppedTimer(0),
|
|
|
|
mDeferredLayoutStart(0),
|
|
|
|
mDeferredFlushTags(0),
|
|
|
|
mIsDocumentObserver(0),
|
|
|
|
mRunsToCompletion(0),
|
2018-02-16 00:15:01 +03:00
|
|
|
mIsBlockingOnload(false),
|
2016-10-25 09:18:03 +03:00
|
|
|
mDeflectedCount(0),
|
|
|
|
mHasPendingEvent(false),
|
|
|
|
mCurrentParseEndTime(0),
|
|
|
|
mBeginLoadTime(0),
|
|
|
|
mLastSampledUserEventTime(0),
|
|
|
|
mInMonolithicContainer(0),
|
|
|
|
mInNotification(0),
|
|
|
|
mUpdatesInNotification(0),
|
|
|
|
mPendingSheetCount(0) {
|
2010-02-07 18:52:43 +03:00
|
|
|
NS_ASSERTION(!mLayoutStarted, "What?");
|
|
|
|
NS_ASSERTION(!mDynamicLowerValue, "What?");
|
|
|
|
NS_ASSERTION(!mParsing, "What?");
|
2007-02-02 05:12:48 +03:00
|
|
|
NS_ASSERTION(mLastSampledUserEventTime == 0, "What?");
|
|
|
|
NS_ASSERTION(mDeflectedCount == 0, "What?");
|
2010-02-07 18:52:43 +03:00
|
|
|
NS_ASSERTION(!mDroppedTimer, "What?");
|
2007-02-02 05:12:48 +03:00
|
|
|
NS_ASSERTION(mInMonolithicContainer == 0, "What?");
|
|
|
|
NS_ASSERTION(mInNotification == 0, "What?");
|
2010-02-07 18:52:43 +03:00
|
|
|
NS_ASSERTION(!mDeferredLayoutStart, "What?");
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsContentSink::~nsContentSink() {
|
2008-03-05 07:54:21 +03:00
|
|
|
if (mDocument) {
|
|
|
|
// Remove ourselves just to be safe, though we really should have
|
|
|
|
// been removed in DidBuildModel if everything worked right.
|
|
|
|
mDocument->RemoveObserver(this);
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
2010-04-27 13:57:32 +04:00
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
nsresult nsContentSink::Init(Document* aDoc, nsIURI* aURI,
|
2003-10-05 11:29:50 +04:00
|
|
|
nsISupports* aContainer, nsIChannel* aChannel) {
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aDoc, "null ptr");
|
|
|
|
MOZ_ASSERT(aURI, "null ptr");
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2004-01-10 02:54:21 +03:00
|
|
|
if (!aDoc || !aURI) {
|
2003-10-05 11:29:50 +04:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
mDocument = aDoc;
|
|
|
|
|
2004-01-10 02:54:21 +03:00
|
|
|
mDocumentURI = aURI;
|
2003-10-05 11:29:50 +04:00
|
|
|
mDocShell = do_QueryInterface(aContainer);
|
2011-05-04 10:35:14 +04:00
|
|
|
mScriptLoader = mDocument->ScriptLoader();
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2012-01-20 16:03:49 +04:00
|
|
|
if (!mRunsToCompletion) {
|
2011-05-04 10:35:14 +04:00
|
|
|
if (mDocShell) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t loadType = 0;
|
2011-05-04 10:35:14 +04:00
|
|
|
mDocShell->GetLoadType(&loadType);
|
|
|
|
mDocument->SetChangeScrollPosWhenScrollingToRef(
|
|
|
|
(loadType & nsIDocShell::LOAD_CMD_HISTORY) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ProcessHTTPHeaders(aChannel);
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2011-05-04 10:35:14 +04:00
|
|
|
mCSSLoader = aDoc->CSSLoader();
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2004-06-25 16:26:02 +04:00
|
|
|
mNodeInfoManager = aDoc->NodeInfoManager();
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2019-08-01 19:06:56 +03:00
|
|
|
mBackoffCount = StaticPrefs::content_notify_backoffcount();
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2019-08-01 19:09:11 +03:00
|
|
|
if (StaticPrefs::content_sink_enable_perf_mode() != 0) {
|
|
|
|
mDynamicLowerValue = StaticPrefs::content_sink_enable_perf_mode() == 1;
|
2015-04-13 19:02:27 +03:00
|
|
|
FavorPerformanceHint(!mDynamicLowerValue, 0);
|
2009-05-19 19:54:42 +04:00
|
|
|
}
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2004-06-25 16:26:02 +04:00
|
|
|
return NS_OK;
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-09-26 15:03:25 +03:00
|
|
|
nsContentSink::StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
|
2005-09-12 22:41:15 +04:00
|
|
|
nsresult aStatus) {
|
2018-04-24 20:17:33 +03:00
|
|
|
MOZ_ASSERT(!mRunsToCompletion, "How come a fragment parser observed sheets?");
|
2020-03-20 16:33:11 +03:00
|
|
|
if (aWasDeferred) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(mPendingSheetCount > 0, "How'd that happen?");
|
|
|
|
--mPendingSheetCount;
|
2007-04-21 02:59:18 +04:00
|
|
|
|
2020-03-20 16:33:11 +03:00
|
|
|
const bool loadedAllSheets = !mPendingSheetCount;
|
|
|
|
if (loadedAllSheets && (mDeferredLayoutStart || mDeferredFlushTags)) {
|
|
|
|
if (mDeferredFlushTags) {
|
|
|
|
FlushTags();
|
|
|
|
}
|
|
|
|
if (mDeferredLayoutStart) {
|
|
|
|
// We might not have really started layout, since this sheet was still
|
|
|
|
// loading. Do it now. Probably doesn't matter whether we do this
|
|
|
|
// before or after we unblock scripts, but before feels saner. Note
|
|
|
|
// that if mDeferredLayoutStart is true, that means any subclass
|
|
|
|
// StartLayout() stuff that needs to happen has already happened, so
|
|
|
|
// we don't need to worry about it.
|
|
|
|
StartLayout(false);
|
2007-04-21 02:59:18 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2020-03-20 16:33:11 +03:00
|
|
|
// Go ahead and try to scroll to our ref if we have one
|
|
|
|
ScrollToRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
mScriptLoader->RemoveParserBlockingScriptExecutionBlocker();
|
|
|
|
|
|
|
|
if (loadedAllSheets &&
|
|
|
|
mDocument->GetReadyStateEnum() >= Document::READYSTATE_INTERACTIVE) {
|
|
|
|
mScriptLoader->DeferCheckpointReached();
|
2007-04-21 02:59:18 +04:00
|
|
|
}
|
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsContentSink::ProcessHTTPHeaders(nsIChannel* aChannel) {
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpchannel(do_QueryInterface(aChannel));
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
if (!httpchannel) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-04-30 01:10:05 +04:00
|
|
|
|
2005-04-05 07:28:54 +04:00
|
|
|
// Note that the only header we care about is the "link" header, since we
|
|
|
|
// have all the infrastructure for kicking off stylesheet loads.
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString linkHeader;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2005-04-05 07:28:54 +04:00
|
|
|
nsresult rv = httpchannel->GetResponseHeader("link"_ns, linkHeader);
|
|
|
|
if (NS_SUCCEEDED(rv) && !linkHeader.IsEmpty()) {
|
2009-06-25 17:13:38 +04:00
|
|
|
mDocument->SetHeaderData(nsGkAtoms::link,
|
|
|
|
NS_ConvertASCIItoUTF16(linkHeader));
|
|
|
|
|
|
|
|
NS_ASSERTION(!mProcessLinkHeaderEvent.get(),
|
|
|
|
"Already dispatched an event?");
|
|
|
|
|
|
|
|
mProcessLinkHeaderEvent =
|
2017-06-12 22:34:10 +03:00
|
|
|
NewNonOwningRunnableMethod("nsContentSink::DoProcessLinkHeader", this,
|
|
|
|
&nsContentSink::DoProcessLinkHeader);
|
2009-06-25 17:13:38 +04:00
|
|
|
rv = NS_DispatchToCurrentThread(mProcessLinkHeaderEvent.get());
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
mProcessLinkHeaderEvent.Forget();
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-25 17:13:38 +04:00
|
|
|
void nsContentSink::DoProcessLinkHeader() {
|
|
|
|
nsAutoString value;
|
|
|
|
mDocument->GetHeaderData(nsGkAtoms::link, value);
|
2012-08-28 21:10:07 +04:00
|
|
|
ProcessLinkHeader(value);
|
2009-06-25 17:13:38 +04:00
|
|
|
}
|
|
|
|
|
2011-06-08 00:19:06 +04:00
|
|
|
// check whether the Link header field applies to the context resource
|
|
|
|
// see <http://tools.ietf.org/html/rfc5988#section-5.2>
|
|
|
|
|
2017-06-20 12:19:52 +03:00
|
|
|
bool nsContentSink::LinkContextIsOurDocument(const nsAString& aAnchor) {
|
2011-06-08 00:19:06 +04:00
|
|
|
if (aAnchor.IsEmpty()) {
|
|
|
|
// anchor parameter not present or empty -> same document reference
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2011-06-08 00:19:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIURI* docUri = mDocument->GetDocumentURI();
|
|
|
|
|
|
|
|
// the document URI might contain a fragment identifier ("#...')
|
|
|
|
// we want to ignore that because it's invisible to the server
|
|
|
|
// and just affects the local interpretation in the recipient
|
|
|
|
nsCOMPtr<nsIURI> contextUri;
|
2018-07-23 14:28:47 +03:00
|
|
|
nsresult rv = NS_GetURIWithoutRef(docUri, getter_AddRefs(contextUri));
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-06-08 00:19:06 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
// copying failed
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2011-06-08 00:19:06 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-06-08 00:19:06 +04:00
|
|
|
// resolve anchor against context
|
|
|
|
nsCOMPtr<nsIURI> resolvedUri;
|
|
|
|
rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri);
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-06-08 00:19:06 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
// resolving failed
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2011-06-08 00:19:06 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool same;
|
2011-06-08 00:19:06 +04:00
|
|
|
rv = contextUri->Equals(resolvedUri, &same);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
// comparison failed
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2011-06-08 00:19:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return same;
|
|
|
|
}
|
|
|
|
|
2012-05-21 17:31:00 +04:00
|
|
|
// Decode a parameter value using the encoding defined in RFC 5987 (in place)
|
|
|
|
//
|
|
|
|
// charset "'" [ language ] "'" value-chars
|
|
|
|
//
|
|
|
|
// returns true when decoding happened successfully (otherwise leaves
|
|
|
|
// passed value alone)
|
|
|
|
bool nsContentSink::Decode5987Format(nsAString& aEncoded) {
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
|
|
|
|
do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return false;
|
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString asciiValue;
|
2012-05-21 17:31:00 +04:00
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t* encstart = aEncoded.BeginReading();
|
|
|
|
const char16_t* encend = aEncoded.EndReading();
|
2012-05-21 17:31:00 +04:00
|
|
|
|
|
|
|
// create a plain ASCII string, aborting if we can't do that
|
|
|
|
// converted form is always shorter than input
|
|
|
|
while (encstart != encend) {
|
|
|
|
if (*encstart > 0 && *encstart < 128) {
|
|
|
|
asciiValue.Append((char)*encstart);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
encstart++;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString decoded;
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString language;
|
2012-05-21 17:31:00 +04:00
|
|
|
|
|
|
|
rv = mimehdrpar->DecodeRFC5987Param(asciiValue, language, decoded);
|
|
|
|
if (NS_FAILED(rv)) return false;
|
|
|
|
|
|
|
|
aEncoded = decoded;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-28 21:10:07 +04:00
|
|
|
nsresult nsContentSink::ProcessLinkHeader(const nsAString& aLinkData) {
|
2003-10-05 11:29:50 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
2011-08-04 10:56:25 +04:00
|
|
|
// keep track where we are within the header field
|
2011-09-29 10:19:26 +04:00
|
|
|
bool seenParameters = false;
|
2011-08-04 10:56:25 +04:00
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
// parse link content and call process style link
|
|
|
|
nsAutoString href;
|
|
|
|
nsAutoString rel;
|
|
|
|
nsAutoString title;
|
2012-05-21 17:31:00 +04:00
|
|
|
nsAutoString titleStar;
|
2020-05-18 20:33:57 +03:00
|
|
|
nsAutoString integrity;
|
|
|
|
nsAutoString srcset;
|
|
|
|
nsAutoString sizes;
|
2003-10-05 11:29:50 +04:00
|
|
|
nsAutoString type;
|
|
|
|
nsAutoString media;
|
2011-06-08 00:19:06 +04:00
|
|
|
nsAutoString anchor;
|
2015-06-20 00:11:42 +03:00
|
|
|
nsAutoString crossOrigin;
|
2017-08-15 07:05:00 +03:00
|
|
|
nsAutoString referrerPolicy;
|
2017-07-10 16:05:56 +03:00
|
|
|
nsAutoString as;
|
2015-06-20 00:11:42 +03:00
|
|
|
|
|
|
|
crossOrigin.SetIsVoid(true);
|
2003-10-05 11:29:50 +04:00
|
|
|
|
|
|
|
// copy to work buffer
|
|
|
|
nsAutoString stringList(aLinkData);
|
|
|
|
|
|
|
|
// put an extra null at the end
|
|
|
|
stringList.Append(kNullCh);
|
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
char16_t* start = stringList.BeginWriting();
|
|
|
|
char16_t* end = start;
|
|
|
|
char16_t* last = start;
|
|
|
|
char16_t endCh;
|
2003-10-05 11:29:50 +04:00
|
|
|
|
|
|
|
while (*start != kNullCh) {
|
|
|
|
// skip leading space
|
|
|
|
while ((*start != kNullCh) && nsCRT::IsAsciiSpace(*start)) {
|
|
|
|
++start;
|
|
|
|
}
|
|
|
|
|
|
|
|
end = start;
|
|
|
|
last = end - 1;
|
|
|
|
|
2012-05-21 17:31:00 +04:00
|
|
|
bool wasQuotedString = false;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
// look for semicolon or comma
|
2011-07-23 16:31:49 +04:00
|
|
|
while (*end != kNullCh && *end != kSemicolon && *end != kComma) {
|
2014-01-04 19:02:17 +04:00
|
|
|
char16_t ch = *end;
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2011-07-29 22:30:00 +04:00
|
|
|
if (ch == kQuote || ch == kLessThan) {
|
2003-10-05 11:29:50 +04:00
|
|
|
// quoted string
|
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
char16_t quote = ch;
|
2011-07-23 16:31:49 +04:00
|
|
|
if (quote == kLessThan) {
|
|
|
|
quote = kGreaterThan;
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2012-05-21 17:31:00 +04:00
|
|
|
wasQuotedString = (ch == kQuote);
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
char16_t* closeQuote = (end + 1);
|
2003-10-05 11:29:50 +04:00
|
|
|
|
|
|
|
// seek closing quote
|
|
|
|
while (*closeQuote != kNullCh && quote != *closeQuote) {
|
2011-07-23 16:31:49 +04:00
|
|
|
// in quoted-string, "\" is an escape character
|
2012-05-21 17:31:00 +04:00
|
|
|
if (wasQuotedString && *closeQuote == kBackSlash &&
|
|
|
|
*(closeQuote + 1) != kNullCh) {
|
2011-07-23 16:31:49 +04:00
|
|
|
++closeQuote;
|
|
|
|
}
|
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
++closeQuote;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (quote == *closeQuote) {
|
|
|
|
// found closer
|
|
|
|
|
|
|
|
// skip to close quote
|
|
|
|
end = closeQuote;
|
|
|
|
|
|
|
|
last = end - 1;
|
|
|
|
|
|
|
|
ch = *(end + 1);
|
|
|
|
|
2011-07-23 16:31:49 +04:00
|
|
|
if (ch != kNullCh && ch != kSemicolon && ch != kComma) {
|
2003-10-05 11:29:50 +04:00
|
|
|
// end string here
|
|
|
|
*(++end) = kNullCh;
|
|
|
|
|
|
|
|
ch = *(end + 1);
|
|
|
|
|
|
|
|
// keep going until semi or comma
|
2011-07-23 16:31:49 +04:00
|
|
|
while (ch != kNullCh && ch != kSemicolon && ch != kComma) {
|
2003-10-05 11:29:50 +04:00
|
|
|
++end;
|
|
|
|
|
2017-04-04 23:24:46 +03:00
|
|
|
ch = *(end + 1);
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
++end;
|
|
|
|
++last;
|
|
|
|
}
|
|
|
|
|
|
|
|
endCh = *end;
|
|
|
|
|
|
|
|
// end string here
|
|
|
|
*end = kNullCh;
|
|
|
|
|
|
|
|
if (start < end) {
|
2011-07-23 16:31:49 +04:00
|
|
|
if ((*start == kLessThan) && (*last == kGreaterThan)) {
|
2003-10-05 11:29:50 +04:00
|
|
|
*last = kNullCh;
|
|
|
|
|
2011-08-04 10:56:25 +04:00
|
|
|
// first instance of <...> wins
|
|
|
|
// also, do not allow hrefs after the first param was seen
|
|
|
|
if (href.IsEmpty() && !seenParameters) {
|
2003-10-05 11:29:50 +04:00
|
|
|
href = (start + 1);
|
|
|
|
href.StripWhitespace();
|
|
|
|
}
|
|
|
|
} else {
|
2014-01-04 19:02:17 +04:00
|
|
|
char16_t* equals = start;
|
2011-10-17 18:59:28 +04:00
|
|
|
seenParameters = true;
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2011-07-23 16:31:49 +04:00
|
|
|
while ((*equals != kNullCh) && (*equals != kEqual)) {
|
2003-10-05 11:29:50 +04:00
|
|
|
equals++;
|
|
|
|
}
|
|
|
|
|
2021-02-02 02:23:42 +03:00
|
|
|
const bool hadEquals = *equals != kNullCh;
|
|
|
|
*equals = kNullCh;
|
|
|
|
nsAutoString attr(start);
|
|
|
|
attr.StripWhitespace();
|
|
|
|
|
|
|
|
char16_t* value = hadEquals ? ++equals : equals;
|
|
|
|
while (nsCRT::IsAsciiSpace(*value)) {
|
|
|
|
value++;
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2021-02-02 02:23:42 +03:00
|
|
|
if ((*value == kQuote) && (*value == *last)) {
|
|
|
|
*last = kNullCh;
|
|
|
|
value++;
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2021-02-02 02:23:42 +03:00
|
|
|
if (wasQuotedString) {
|
|
|
|
// unescape in-place
|
|
|
|
char16_t* unescaped = value;
|
|
|
|
char16_t* src = value;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2021-02-02 02:23:42 +03:00
|
|
|
while (*src != kNullCh) {
|
|
|
|
if (*src == kBackSlash && *(src + 1) != kNullCh) {
|
|
|
|
src++;
|
2011-07-23 16:31:49 +04:00
|
|
|
}
|
2021-02-02 02:23:42 +03:00
|
|
|
*unescaped++ = *src++;
|
2011-07-23 16:31:49 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2021-02-02 02:23:42 +03:00
|
|
|
*unescaped = kNullCh;
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2021-02-02 02:23:42 +03:00
|
|
|
if (attr.LowerCaseEqualsLiteral("rel")) {
|
|
|
|
if (rel.IsEmpty()) {
|
|
|
|
rel = value;
|
|
|
|
rel.CompressWhitespace();
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("title")) {
|
|
|
|
if (title.IsEmpty()) {
|
|
|
|
title = value;
|
|
|
|
title.CompressWhitespace();
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("title*")) {
|
|
|
|
if (titleStar.IsEmpty() && !wasQuotedString) {
|
|
|
|
// RFC 5987 encoding; uses token format only, so skip if we get
|
|
|
|
// here with a quoted-string
|
|
|
|
nsAutoString tmp;
|
|
|
|
tmp = value;
|
|
|
|
if (Decode5987Format(tmp)) {
|
|
|
|
titleStar = tmp;
|
|
|
|
titleStar.CompressWhitespace();
|
|
|
|
} else {
|
|
|
|
// header value did not parse, throw it away
|
|
|
|
titleStar.Truncate();
|
2020-05-18 20:33:57 +03:00
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
2021-02-02 02:23:42 +03:00
|
|
|
} else if (attr.LowerCaseEqualsLiteral("type")) {
|
|
|
|
if (type.IsEmpty()) {
|
|
|
|
type = value;
|
|
|
|
type.StripWhitespace();
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("media")) {
|
|
|
|
if (media.IsEmpty()) {
|
|
|
|
media = value;
|
|
|
|
|
|
|
|
// The HTML5 spec is formulated in terms of the CSS3 spec,
|
|
|
|
// which specifies that media queries are case insensitive.
|
|
|
|
nsContentUtils::ASCIIToLower(media);
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("anchor")) {
|
|
|
|
if (anchor.IsEmpty()) {
|
|
|
|
anchor = value;
|
|
|
|
anchor.StripWhitespace();
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("crossorigin")) {
|
|
|
|
if (crossOrigin.IsVoid()) {
|
|
|
|
crossOrigin.SetIsVoid(false);
|
|
|
|
crossOrigin = value;
|
|
|
|
crossOrigin.StripWhitespace();
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("as")) {
|
|
|
|
if (as.IsEmpty()) {
|
|
|
|
as = value;
|
|
|
|
as.CompressWhitespace();
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("referrerpolicy")) {
|
|
|
|
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#referrer-policy-attribute
|
|
|
|
// Specs says referrer policy attribute is an enumerated attribute,
|
|
|
|
// case insensitive and includes the empty string
|
|
|
|
// We will parse the value with AttributeReferrerPolicyFromString
|
|
|
|
// later, which will handle parsing it as an enumerated attribute.
|
|
|
|
if (referrerPolicy.IsEmpty()) {
|
|
|
|
referrerPolicy = value;
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("integrity")) {
|
|
|
|
if (integrity.IsEmpty()) {
|
|
|
|
integrity = value;
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("imagesrcset")) {
|
|
|
|
if (srcset.IsEmpty()) {
|
|
|
|
srcset = value;
|
|
|
|
}
|
|
|
|
} else if (attr.LowerCaseEqualsLiteral("imagesizes")) {
|
|
|
|
if (sizes.IsEmpty()) {
|
|
|
|
sizes = value;
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 16:31:49 +04:00
|
|
|
if (endCh == kComma) {
|
2003-10-05 11:29:50 +04:00
|
|
|
// hit a comma, process what we've got so far
|
|
|
|
|
2011-05-11 13:46:59 +04:00
|
|
|
href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
|
2003-10-05 11:29:50 +04:00
|
|
|
if (!href.IsEmpty() && !rel.IsEmpty()) {
|
2017-12-22 00:43:24 +03:00
|
|
|
rv = ProcessLinkFromHeader(
|
|
|
|
anchor, href, rel,
|
|
|
|
// prefer RFC 5987 variant over non-I18zed version
|
2020-05-18 20:33:57 +03:00
|
|
|
titleStar.IsEmpty() ? title : titleStar, integrity, srcset, sizes,
|
|
|
|
type, media, crossOrigin, referrerPolicy, as);
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
href.Truncate();
|
|
|
|
rel.Truncate();
|
|
|
|
title.Truncate();
|
|
|
|
type.Truncate();
|
2020-05-18 20:33:57 +03:00
|
|
|
integrity.Truncate();
|
|
|
|
srcset.Truncate();
|
|
|
|
sizes.Truncate();
|
2003-10-05 11:29:50 +04:00
|
|
|
media.Truncate();
|
2011-06-08 00:19:06 +04:00
|
|
|
anchor.Truncate();
|
2017-08-15 07:05:00 +03:00
|
|
|
referrerPolicy.Truncate();
|
2015-06-20 00:11:42 +03:00
|
|
|
crossOrigin.SetIsVoid(true);
|
2017-12-04 19:48:56 +03:00
|
|
|
as.Truncate();
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
seenParameters = false;
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
start = ++end;
|
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-05-11 13:46:59 +04:00
|
|
|
href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
|
2003-10-05 11:29:50 +04:00
|
|
|
if (!href.IsEmpty() && !rel.IsEmpty()) {
|
2020-05-18 20:33:57 +03:00
|
|
|
rv = ProcessLinkFromHeader(
|
|
|
|
anchor, href, rel,
|
|
|
|
// prefer RFC 5987 variant over non-I18zed version
|
|
|
|
titleStar.IsEmpty() ? title : titleStar, integrity, srcset, sizes, type,
|
|
|
|
media, crossOrigin, referrerPolicy, as);
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2017-12-22 00:43:24 +03:00
|
|
|
nsresult nsContentSink::ProcessLinkFromHeader(
|
|
|
|
const nsAString& aAnchor, const nsAString& aHref, const nsAString& aRel,
|
2020-05-18 20:33:57 +03:00
|
|
|
const nsAString& aTitle, const nsAString& aIntegrity,
|
|
|
|
const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aType,
|
|
|
|
const nsAString& aMedia, const nsAString& aCrossOrigin,
|
|
|
|
const nsAString& aReferrerPolicy, const nsAString& aAs) {
|
2020-05-21 06:07:16 +03:00
|
|
|
uint32_t linkTypes = LinkStyle::ParseLinkTypes(aRel);
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2011-06-08 00:19:06 +04:00
|
|
|
// The link relation may apply to a different resource, specified
|
|
|
|
// in the anchor parameter. For the link relations supported so far,
|
|
|
|
// we simply abort if the link applies to a resource different to the
|
|
|
|
// one we've loaded
|
|
|
|
if (!LinkContextIsOurDocument(aAnchor)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-02-26 04:41:00 +03:00
|
|
|
|
2017-12-22 00:43:24 +03:00
|
|
|
if (nsContentUtils::PrefetchPreloadEnabled(mDocShell)) {
|
|
|
|
// prefetch href if relation is "next" or "prefetch"
|
2020-05-21 06:07:16 +03:00
|
|
|
if ((linkTypes & LinkStyle::eNEXT) || (linkTypes & LinkStyle::ePREFETCH)) {
|
2020-05-18 20:33:57 +03:00
|
|
|
PrefetchHref(aHref, aAs, aType, aMedia);
|
2017-12-22 00:43:24 +03:00
|
|
|
}
|
2007-03-14 04:52:07 +03:00
|
|
|
|
2020-05-21 06:07:16 +03:00
|
|
|
if (!aHref.IsEmpty() && (linkTypes & LinkStyle::eDNS_PREFETCH)) {
|
2017-12-22 00:43:24 +03:00
|
|
|
PrefetchDNS(aHref);
|
|
|
|
}
|
2008-11-08 02:00:26 +03:00
|
|
|
|
2020-05-21 06:07:16 +03:00
|
|
|
if (!aHref.IsEmpty() && (linkTypes & LinkStyle::ePRECONNECT)) {
|
2017-12-22 00:43:24 +03:00
|
|
|
Preconnect(aHref, aCrossOrigin);
|
|
|
|
}
|
2020-05-18 20:33:57 +03:00
|
|
|
|
2020-05-21 06:07:16 +03:00
|
|
|
if (linkTypes & LinkStyle::ePRELOAD) {
|
2020-05-18 20:33:57 +03:00
|
|
|
PreloadHref(aHref, aAs, aType, aMedia, aIntegrity, aSrcset, aSizes,
|
|
|
|
aCrossOrigin, aReferrerPolicy);
|
|
|
|
}
|
2015-02-21 01:01:36 +03:00
|
|
|
}
|
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
// is it a stylesheet link?
|
2020-05-21 06:07:16 +03:00
|
|
|
if (!(linkTypes & LinkStyle::eSTYLESHEET)) {
|
2003-10-05 11:29:50 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2020-05-21 06:07:16 +03:00
|
|
|
bool isAlternate = linkTypes & LinkStyle::eALTERNATE;
|
2020-05-18 20:33:57 +03:00
|
|
|
return ProcessStyleLinkFromHeader(aHref, isAlternate, aTitle, aIntegrity,
|
|
|
|
aType, aMedia, aReferrerPolicy);
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
2017-12-22 00:43:24 +03:00
|
|
|
nsresult nsContentSink::ProcessStyleLinkFromHeader(
|
|
|
|
const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
|
2020-05-18 20:33:57 +03:00
|
|
|
const nsAString& aIntegrity, const nsAString& aType,
|
|
|
|
const nsAString& aMedia, const nsAString& aReferrerPolicy) {
|
2003-10-05 11:29:50 +04:00
|
|
|
if (aAlternate && aTitle.IsEmpty()) {
|
|
|
|
// alternates must have title return without error, for now
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString mimeType;
|
|
|
|
nsAutoString params;
|
2012-02-27 15:57:48 +04:00
|
|
|
nsContentUtils::SplitMimeType(aType, mimeType, params);
|
2003-10-05 11:29:50 +04:00
|
|
|
|
|
|
|
// see bug 18817
|
2004-06-17 04:13:25 +04:00
|
|
|
if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
|
2003-10-05 11:29:50 +04:00
|
|
|
// Unknown stylesheet language
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> url;
|
2012-07-30 18:20:58 +04:00
|
|
|
nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr,
|
2010-04-19 19:40:15 +04:00
|
|
|
mDocument->GetDocBaseURI());
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2003-10-05 11:29:50 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
2004-01-10 02:54:21 +03:00
|
|
|
// The URI is bad, move along, don't propagate the error (for now)
|
2003-10-05 11:29:50 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2019-07-16 14:43:56 +03:00
|
|
|
// Link header is working like a <link> node, so referrerPolicy attr should
|
|
|
|
// have higher priority than referrer policy from document.
|
2019-08-21 15:09:06 +03:00
|
|
|
ReferrerPolicy policy =
|
|
|
|
ReferrerInfo::ReferrerPolicyAttributeFromString(aReferrerPolicy);
|
2019-07-16 14:43:56 +03:00
|
|
|
nsCOMPtr<nsIReferrerInfo> referrerInfo =
|
|
|
|
ReferrerInfo::CreateFromDocumentAndPolicyOverride(mDocument, policy);
|
|
|
|
|
2018-05-08 07:11:56 +03:00
|
|
|
Loader::SheetInfo info{
|
2018-05-06 17:10:09 +03:00
|
|
|
*mDocument,
|
|
|
|
nullptr,
|
|
|
|
url.forget(),
|
|
|
|
nullptr,
|
2019-07-16 14:43:56 +03:00
|
|
|
referrerInfo.forget(),
|
2018-05-06 17:10:09 +03:00
|
|
|
CORS_NONE,
|
|
|
|
aTitle,
|
|
|
|
aMedia,
|
2020-05-18 20:33:57 +03:00
|
|
|
aIntegrity,
|
2020-09-23 18:17:15 +03:00
|
|
|
/* nonce = */ u""_ns,
|
2018-05-06 17:10:09 +03:00
|
|
|
aAlternate ? Loader::HasAlternateRel::Yes : Loader::HasAlternateRel::No,
|
|
|
|
Loader::IsInline::No,
|
2019-04-19 16:31:05 +03:00
|
|
|
Loader::IsExplicitlyEnabled::No,
|
2018-05-06 17:10:09 +03:00
|
|
|
};
|
|
|
|
|
2018-04-24 15:56:02 +03:00
|
|
|
auto loadResultOrErr =
|
2018-05-06 17:10:09 +03:00
|
|
|
mCSSLoader->LoadStyleLink(info, mRunsToCompletion ? nullptr : this);
|
2018-04-24 15:56:02 +03:00
|
|
|
if (loadResultOrErr.isErr()) {
|
|
|
|
return loadResultOrErr.unwrapErr();
|
|
|
|
}
|
|
|
|
|
2019-08-13 11:26:18 +03:00
|
|
|
if (loadResultOrErr.inspect().ShouldBlock() && !mRunsToCompletion) {
|
2007-04-21 02:59:18 +04:00
|
|
|
++mPendingSheetCount;
|
2016-05-21 06:13:18 +03:00
|
|
|
mScriptLoader->AddParserBlockingScriptExecutionBlocker();
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
2007-04-21 02:59:18 +04:00
|
|
|
return NS_OK;
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
|
2020-05-18 20:33:57 +03:00
|
|
|
void nsContentSink::PrefetchHref(const nsAString& aHref, const nsAString& aAs,
|
|
|
|
const nsAString& aType,
|
|
|
|
const nsAString& aMedia) {
|
2018-12-17 04:27:58 +03:00
|
|
|
nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
|
2003-10-05 11:29:50 +04:00
|
|
|
if (prefetchService) {
|
|
|
|
// construct URI using document charset
|
2017-06-18 14:37:50 +03:00
|
|
|
auto encoding = mDocument->GetDocumentCharacterSet();
|
2003-10-05 11:29:50 +04:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
2017-06-18 14:37:50 +03:00
|
|
|
NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI());
|
2003-10-05 11:29:50 +04:00
|
|
|
if (uri) {
|
2020-05-04 21:50:20 +03:00
|
|
|
auto referrerInfo = MakeRefPtr<ReferrerInfo>(*mDocument);
|
|
|
|
referrerInfo = referrerInfo->CloneWithNewOriginalReferrer(mDocumentURI);
|
2017-07-10 16:05:56 +03:00
|
|
|
|
2020-05-18 20:33:57 +03:00
|
|
|
prefetchService->PrefetchURI(uri, referrerInfo, mDocument, true);
|
2003-10-05 11:29:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-18 20:33:57 +03:00
|
|
|
void nsContentSink::PreloadHref(const nsAString& aHref, const nsAString& aAs,
|
|
|
|
const nsAString& aType, const nsAString& aMedia,
|
|
|
|
const nsAString& aIntegrity,
|
|
|
|
const nsAString& aSrcset,
|
|
|
|
const nsAString& aSizes, const nsAString& aCORS,
|
|
|
|
const nsAString& aReferrerPolicy) {
|
2021-01-10 23:50:02 +03:00
|
|
|
auto encoding = mDocument->GetDocumentCharacterSet();
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI());
|
|
|
|
if (!uri) {
|
|
|
|
// URL parsing failed.
|
2020-05-18 20:33:57 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-10 23:50:02 +03:00
|
|
|
nsAttrValue asAttr;
|
|
|
|
HTMLLinkElement::ParseAsValue(aAs, asAttr);
|
|
|
|
|
2020-05-18 20:33:57 +03:00
|
|
|
nsAutoString mimeType;
|
|
|
|
nsAutoString notUsed;
|
|
|
|
nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
|
|
|
|
|
2021-01-10 23:50:02 +03:00
|
|
|
auto policyType = HTMLLinkElement::AsValueToContentPolicy(asAttr);
|
|
|
|
if (policyType == nsIContentPolicy::TYPE_INVALID ||
|
|
|
|
!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, aMedia,
|
|
|
|
mDocument)) {
|
|
|
|
// Ignore preload wrong or empty attributes.
|
|
|
|
HTMLLinkElement::WarnIgnoredPreload(*mDocument, *uri);
|
2020-07-18 16:54:22 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-22 17:18:19 +03:00
|
|
|
mDocument->Preloads().PreloadLinkHeader(uri, aHref, policyType, aAs, aType,
|
|
|
|
aIntegrity, aSrcset, aSizes, aCORS,
|
2021-01-11 05:37:15 +03:00
|
|
|
aReferrerPolicy);
|
2020-05-18 20:33:57 +03:00
|
|
|
}
|
|
|
|
|
2008-11-08 02:00:26 +03:00
|
|
|
void nsContentSink::PrefetchDNS(const nsAString& aHref) {
|
|
|
|
nsAutoString hostname;
|
2018-09-22 23:54:11 +03:00
|
|
|
bool isHttps = false;
|
2008-11-08 02:00:26 +03:00
|
|
|
|
|
|
|
if (StringBeginsWith(aHref, u"//"_ns)) {
|
|
|
|
hostname = Substring(aHref, 2);
|
2009-03-10 05:32:09 +03:00
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
NS_NewURI(getter_AddRefs(uri), aHref);
|
|
|
|
if (!uri) {
|
|
|
|
return;
|
|
|
|
}
|
2015-03-12 11:00:00 +03:00
|
|
|
nsresult rv;
|
|
|
|
bool isLocalResource = false;
|
|
|
|
rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
|
|
|
|
&isLocalResource);
|
|
|
|
if (NS_SUCCEEDED(rv) && !isLocalResource) {
|
|
|
|
nsAutoCString host;
|
|
|
|
uri->GetHost(host);
|
|
|
|
CopyUTF8toUTF16(host, hostname);
|
|
|
|
}
|
2019-07-30 20:51:37 +03:00
|
|
|
isHttps = uri->SchemeIs("https");
|
2009-03-10 05:32:09 +03:00
|
|
|
}
|
2008-12-05 23:53:24 +03:00
|
|
|
|
2021-01-27 07:37:58 +03:00
|
|
|
if (!hostname.IsEmpty() && HTMLDNSPrefetch::IsAllowed(mDocument)) {
|
2020-05-20 20:27:43 +03:00
|
|
|
OriginAttributes oa;
|
|
|
|
StoragePrincipalHelper::GetOriginAttributesForNetworkState(mDocument, oa);
|
|
|
|
|
2021-01-27 07:37:58 +03:00
|
|
|
HTMLDNSPrefetch::Prefetch(hostname, isHttps, oa,
|
|
|
|
mDocument->GetChannel()->GetTRRMode(),
|
|
|
|
HTMLDNSPrefetch::Priority::Low);
|
2008-11-08 02:00:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-20 00:11:42 +03:00
|
|
|
void nsContentSink::Preconnect(const nsAString& aHref,
|
|
|
|
const nsAString& aCrossOrigin) {
|
2015-02-21 01:01:36 +03:00
|
|
|
// construct URI using document charset
|
2017-06-18 14:37:50 +03:00
|
|
|
auto encoding = mDocument->GetDocumentCharacterSet();
|
2015-02-21 01:01:36 +03:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
2017-06-18 14:37:50 +03:00
|
|
|
NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI());
|
2015-05-06 03:55:18 +03:00
|
|
|
|
|
|
|
if (uri && mDocument) {
|
2015-06-20 00:11:42 +03:00
|
|
|
mDocument->MaybePreconnect(uri,
|
|
|
|
dom::Element::StringToCORSMode(aCrossOrigin));
|
2015-02-21 01:01:36 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-23 04:27:47 +03:00
|
|
|
void nsContentSink::ScrollToRef() {
|
|
|
|
RefPtr<Document> document = mDocument;
|
|
|
|
document->ScrollToRef();
|
|
|
|
}
|
2003-10-05 11:29:50 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
void nsContentSink::StartLayout(bool aIgnorePendingSheets) {
|
2018-05-29 00:49:44 +03:00
|
|
|
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("nsContentSink::StartLayout", LAYOUT,
|
|
|
|
mDocumentURI->GetSpecOrDefault());
|
|
|
|
|
2007-04-21 02:59:18 +04:00
|
|
|
if (mLayoutStarted) {
|
|
|
|
// Nothing to do here
|
|
|
|
return;
|
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mDeferredLayoutStart = true;
|
2007-04-21 02:59:18 +04:00
|
|
|
|
2019-01-26 02:14:03 +03:00
|
|
|
if (!aIgnorePendingSheets &&
|
|
|
|
(WaitForPendingSheets() || mDocument->HasPendingInitialTranslation())) {
|
|
|
|
// Bail out; we'll start layout when the sheets and l10n load
|
2007-04-21 02:59:18 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mDeferredLayoutStart = false;
|
2007-04-21 02:59:18 +04:00
|
|
|
|
2020-03-21 15:18:28 +03:00
|
|
|
if (aIgnorePendingSheets) {
|
|
|
|
nsContentUtils::ReportToConsole(
|
|
|
|
nsIScriptError::warningFlag, "Layout"_ns, mDocument,
|
|
|
|
nsContentUtils::eLAYOUT_PROPERTIES, "ForcedLayoutStart");
|
|
|
|
}
|
|
|
|
|
2007-04-26 22:57:58 +04:00
|
|
|
// Notify on all our content. If none of our presshells have started layout
|
|
|
|
// yet it'll be a no-op except for updating our data structures, a la
|
|
|
|
// UpdateChildCounts() (because we don't want to double-notify on whatever we
|
|
|
|
// have right now). If some of them _have_ started layout, we want to make
|
|
|
|
// sure to flush tags instead of just calling UpdateChildCounts() after we
|
|
|
|
// loop over the shells.
|
|
|
|
FlushTags();
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mLayoutStarted = true;
|
2007-01-31 00:21:06 +03:00
|
|
|
mLastNotificationTime = PR_Now();
|
2004-01-28 15:14:17 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mDocument->SetMayStartLayout(true);
|
2019-03-29 18:12:47 +03:00
|
|
|
RefPtr<PresShell> presShell = mDocument->GetPresShell();
|
2012-09-07 08:16:09 +04:00
|
|
|
// Make sure we don't call Initialize() for a shell that has
|
2010-01-07 13:36:11 +03:00
|
|
|
// already called it. This can happen when the layout frame for
|
|
|
|
// an iframe is constructed *between* the Embed() call for the
|
|
|
|
// docshell in the iframe, and the content sink's call to OpenBody().
|
|
|
|
// (Bug 153815)
|
2019-03-29 18:12:47 +03:00
|
|
|
if (presShell && !presShell->DidInitialize()) {
|
|
|
|
nsresult rv = presShell->Initialize();
|
2007-05-23 01:45:03 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
2004-01-28 15:14:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the document we are loading has a reference or it is a
|
|
|
|
// frameset document, disable the scroll bars on the views.
|
|
|
|
|
2014-08-29 23:34:35 +04:00
|
|
|
mDocument->SetScrollToRef(mDocument->GetDocumentURI());
|
2004-01-28 15:14:17 +03:00
|
|
|
}
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
void nsContentSink::NotifyAppend(nsIContent* aContainer, uint32_t aStartIndex) {
|
2007-01-31 00:21:06 +03:00
|
|
|
mInNotification++;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2007-03-10 02:43:50 +03:00
|
|
|
{
|
|
|
|
// Scope so we call EndUpdate before we decrease mInNotification
|
2019-03-29 12:55:10 +03:00
|
|
|
//
|
|
|
|
// Note that aContainer->OwnerDoc() may not be mDocument.
|
|
|
|
MOZ_AUTO_DOC_UPDATE(aContainer->OwnerDoc(), true);
|
2019-11-06 00:32:53 +03:00
|
|
|
MutationObservers::NotifyContentAppended(
|
2018-01-03 15:59:54 +03:00
|
|
|
aContainer, aContainer->GetChildAt_Deprecated(aStartIndex));
|
2007-03-10 02:43:50 +03:00
|
|
|
mLastNotificationTime = PR_Now();
|
|
|
|
}
|
2007-01-31 00:21:06 +03:00
|
|
|
|
|
|
|
mInNotification--;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsContentSink::Notify(nsITimer* timer) {
|
|
|
|
if (mParsing) {
|
|
|
|
// We shouldn't interfere with our normal DidProcessAToken logic
|
2011-10-17 18:59:28 +04:00
|
|
|
mDroppedTimer = true;
|
2007-01-31 00:21:06 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2007-07-11 07:42:11 +04:00
|
|
|
if (WaitForPendingSheets()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mDeferredFlushTags = true;
|
2007-07-11 07:42:11 +04:00
|
|
|
} else {
|
|
|
|
FlushTags();
|
|
|
|
|
|
|
|
// Now try and scroll to the reference
|
|
|
|
// XXX Should we scroll unconditionally for history loads??
|
2008-02-27 13:01:17 +03:00
|
|
|
ScrollToRef();
|
2007-07-11 07:42:11 +04:00
|
|
|
}
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
mNotificationTimer = nullptr;
|
2007-01-31 00:21:06 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool nsContentSink::IsTimeToNotify() {
|
2019-08-01 19:05:49 +03:00
|
|
|
if (!StaticPrefs::content_notify_ontimer() || !mLayoutStarted ||
|
|
|
|
!mBackoffCount || mInMonolithicContainer) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2007-01-31 00:21:06 +03:00
|
|
|
}
|
|
|
|
|
2007-07-11 07:42:11 +04:00
|
|
|
if (WaitForPendingSheets()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mDeferredFlushTags = true;
|
|
|
|
return false;
|
2007-07-11 07:42:11 +04:00
|
|
|
}
|
|
|
|
|
2007-01-31 00:21:06 +03:00
|
|
|
PRTime now = PR_Now();
|
|
|
|
|
2013-07-19 00:47:55 +04:00
|
|
|
int64_t interval = GetNotificationInterval();
|
|
|
|
int64_t diff = now - mLastNotificationTime;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2012-10-03 18:13:19 +04:00
|
|
|
if (diff > interval) {
|
2007-01-31 00:21:06 +03:00
|
|
|
mBackoffCount--;
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2007-01-31 00:21:06 +03:00
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2007-01-31 00:21:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsContentSink::WillInterruptImpl() {
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
|
2015-11-23 22:09:25 +03:00
|
|
|
SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
|
2007-01-31 00:21:06 +03:00
|
|
|
SINK_TRACE_CALLS, ("nsContentSink::WillInterrupt: this=%p", this));
|
|
|
|
#ifndef SINK_NO_INCREMENTAL
|
2007-07-11 07:42:11 +04:00
|
|
|
if (WaitForPendingSheets()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mDeferredFlushTags = true;
|
2019-08-01 19:05:49 +03:00
|
|
|
} else if (StaticPrefs::content_notify_ontimer() && mLayoutStarted) {
|
2007-01-31 00:21:06 +03:00
|
|
|
if (mBackoffCount && !mInMonolithicContainer) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int64_t now = PR_Now();
|
|
|
|
int64_t interval = GetNotificationInterval();
|
|
|
|
int64_t diff = now - mLastNotificationTime;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
|
|
|
// If it's already time for us to have a notification
|
|
|
|
if (diff > interval || mDroppedTimer) {
|
|
|
|
mBackoffCount--;
|
2015-11-23 22:09:25 +03:00
|
|
|
SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
|
|
|
|
SINK_TRACE_REFLOW,
|
2007-01-31 00:21:06 +03:00
|
|
|
("nsContentSink::WillInterrupt: flushing tags since we've "
|
|
|
|
"run out time; backoff count: %d",
|
|
|
|
mBackoffCount));
|
|
|
|
result = FlushTags();
|
|
|
|
if (mDroppedTimer) {
|
2008-02-27 13:01:17 +03:00
|
|
|
ScrollToRef();
|
2011-10-17 18:59:28 +04:00
|
|
|
mDroppedTimer = false;
|
2007-01-31 00:21:06 +03:00
|
|
|
}
|
|
|
|
} else if (!mNotificationTimer) {
|
|
|
|
interval -= diff;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t delay = interval;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
|
|
|
// Convert to milliseconds
|
|
|
|
delay /= PR_USEC_PER_MSEC;
|
|
|
|
|
2017-10-16 09:15:40 +03:00
|
|
|
NS_NewTimerWithCallback(getter_AddRefs(mNotificationTimer), this, delay,
|
|
|
|
nsITimer::TYPE_ONE_SHOT);
|
|
|
|
if (mNotificationTimer) {
|
2015-11-23 22:09:25 +03:00
|
|
|
SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
|
|
|
|
SINK_TRACE_REFLOW,
|
2007-01-31 00:21:06 +03:00
|
|
|
("nsContentSink::WillInterrupt: setting up timer with "
|
|
|
|
"delay %d",
|
|
|
|
delay));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2015-11-23 22:09:25 +03:00
|
|
|
SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
|
|
|
|
SINK_TRACE_REFLOW,
|
2007-01-31 00:21:06 +03:00
|
|
|
("nsContentSink::WillInterrupt: flushing tags "
|
|
|
|
"unconditionally"));
|
|
|
|
result = FlushTags();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mParsing = false;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsContentSink::WillResumeImpl() {
|
2015-11-23 22:09:25 +03:00
|
|
|
SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
|
2007-01-31 00:21:06 +03:00
|
|
|
SINK_TRACE_CALLS, ("nsContentSink::WillResume: this=%p", this));
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mParsing = true;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsContentSink::DidProcessATokenImpl() {
|
2012-01-20 16:03:49 +04:00
|
|
|
if (mRunsToCompletion || !mParser) {
|
2007-01-31 00:21:06 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the current user event time
|
2019-03-29 18:12:47 +03:00
|
|
|
PresShell* presShell = mDocument->GetPresShell();
|
|
|
|
if (!presShell) {
|
2007-01-31 00:21:06 +03:00
|
|
|
// If there's no pres shell in the document, return early since
|
|
|
|
// we're not laying anything out here.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-04-27 13:57:32 +04:00
|
|
|
// Increase before comparing to gEventProbeRate
|
2009-05-19 19:54:42 +04:00
|
|
|
++mDeflectedCount;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2009-05-19 19:54:42 +04:00
|
|
|
// Check if there's a pending event
|
2019-08-01 20:08:05 +03:00
|
|
|
if (StaticPrefs::content_sink_pending_event_mode() != 0 &&
|
2019-08-01 19:08:27 +03:00
|
|
|
!mHasPendingEvent &&
|
|
|
|
(mDeflectedCount % StaticPrefs::content_sink_event_probe_rate()) == 0) {
|
2019-03-29 18:12:47 +03:00
|
|
|
nsViewManager* vm = presShell->GetViewManager();
|
2009-05-19 19:54:42 +04:00
|
|
|
NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
2009-07-22 04:45:09 +04:00
|
|
|
vm->GetRootWidget(getter_AddRefs(widget));
|
2009-05-19 19:54:42 +04:00
|
|
|
mHasPendingEvent = widget && widget->HasPendingInputEvent();
|
2009-04-04 05:25:13 +04:00
|
|
|
}
|
2009-04-04 09:55:51 +04:00
|
|
|
|
2019-08-01 20:08:05 +03:00
|
|
|
if (mHasPendingEvent && StaticPrefs::content_sink_pending_event_mode() == 2) {
|
2009-05-19 19:54:42 +04:00
|
|
|
return NS_ERROR_HTMLPARSER_INTERRUPTED;
|
|
|
|
}
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2009-05-19 19:54:42 +04:00
|
|
|
// Have we processed enough tokens to check time?
|
|
|
|
if (!mHasPendingEvent &&
|
2019-08-01 20:05:57 +03:00
|
|
|
mDeflectedCount <
|
|
|
|
uint32_t(mDynamicLowerValue
|
|
|
|
? StaticPrefs::content_sink_interactive_deflect_count()
|
|
|
|
: StaticPrefs::content_sink_perf_deflect_count())) {
|
2009-05-19 19:54:42 +04:00
|
|
|
return NS_OK;
|
2009-04-04 09:55:51 +04:00
|
|
|
}
|
2009-04-04 05:25:13 +04:00
|
|
|
|
2009-05-19 19:54:42 +04:00
|
|
|
mDeflectedCount = 0;
|
|
|
|
|
|
|
|
// Check if it's time to return to the main event loop
|
|
|
|
if (PR_IntervalToMicroseconds(PR_IntervalNow()) > mCurrentParseEndTime) {
|
2007-01-31 00:21:06 +03:00
|
|
|
return NS_ERROR_HTMLPARSER_INTERRUPTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2015-04-13 19:02:27 +03:00
|
|
|
void nsContentSink::FavorPerformanceHint(bool perfOverStarvation,
|
|
|
|
uint32_t starvationDelay) {
|
|
|
|
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
|
|
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
|
|
|
if (appShell)
|
|
|
|
appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay);
|
|
|
|
}
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
void nsContentSink::BeginUpdate(Document* aDocument) {
|
2007-05-18 03:54:35 +04:00
|
|
|
// Remember nested updates from updates that we started.
|
2009-10-30 04:48:38 +03:00
|
|
|
if (mInNotification > 0 && mUpdatesInNotification < 2) {
|
2007-05-18 03:54:35 +04:00
|
|
|
++mUpdatesInNotification;
|
|
|
|
}
|
|
|
|
|
2007-01-31 00:21:06 +03:00
|
|
|
// If we're in a script and we didn't do the notification,
|
|
|
|
// something else in the script processing caused the
|
|
|
|
// notification to occur. Since this could result in frame
|
|
|
|
// creation, make sure we've flushed everything before we
|
|
|
|
// continue.
|
|
|
|
|
2011-06-01 01:38:25 +04:00
|
|
|
if (!mInNotification++) {
|
2007-01-31 00:21:06 +03:00
|
|
|
FlushTags();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
void nsContentSink::EndUpdate(Document* aDocument) {
|
2007-01-31 00:21:06 +03:00
|
|
|
// If we're in a script and we didn't do the notification,
|
|
|
|
// something else in the script processing caused the
|
|
|
|
// notification to occur. Update our notion of how much
|
|
|
|
// has been flushed to include any new content if ending
|
2011-06-01 01:38:25 +04:00
|
|
|
// this update leaves us not inside a notification.
|
|
|
|
if (!--mInNotification) {
|
2007-01-31 00:21:06 +03:00
|
|
|
UpdateChildCounts();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
void nsContentSink::DidBuildModelImpl(bool aTerminated) {
|
2020-03-20 16:33:11 +03:00
|
|
|
MOZ_ASSERT(aTerminated ||
|
|
|
|
mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING,
|
|
|
|
"Bad readyState");
|
|
|
|
mDocument->SetReadyStateInternal(Document::READYSTATE_INTERACTIVE);
|
2009-10-02 15:13:59 +04:00
|
|
|
|
|
|
|
if (mScriptLoader) {
|
|
|
|
mScriptLoader->ParsingComplete(aTerminated);
|
2020-03-20 16:33:11 +03:00
|
|
|
if (!mPendingSheetCount) {
|
|
|
|
mScriptLoader->DeferCheckpointReached();
|
|
|
|
}
|
2009-10-02 15:13:59 +04:00
|
|
|
}
|
|
|
|
|
2008-08-25 12:52:48 +04:00
|
|
|
if (!mDocument->HaveFiredDOMTitleChange()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mDocument->NotifyPossibleTitleChange(false);
|
2008-08-25 12:52:48 +04:00
|
|
|
}
|
|
|
|
|
2007-01-31 00:21:06 +03:00
|
|
|
// Cancel a timer if we had one out there
|
|
|
|
if (mNotificationTimer) {
|
2015-11-23 22:09:25 +03:00
|
|
|
SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
|
|
|
|
SINK_TRACE_REFLOW,
|
2007-01-31 00:21:06 +03:00
|
|
|
("nsContentSink::DidBuildModel: canceling notification "
|
|
|
|
"timeout"));
|
|
|
|
mNotificationTimer->Cancel();
|
2016-11-10 06:11:27 +03:00
|
|
|
mNotificationTimer = nullptr;
|
2007-01-31 00:21:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsContentSink::DropParserAndPerfHint(void) {
|
2007-04-27 08:05:08 +04:00
|
|
|
if (!mParser) {
|
|
|
|
// Make sure we don't unblock unload too many times
|
|
|
|
return;
|
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2007-01-31 00:21:06 +03:00
|
|
|
// Ref. Bug 49115
|
|
|
|
// Do this hack to make sure that the parser
|
|
|
|
// doesn't get destroyed, accidently, before
|
|
|
|
// the circularity, between sink & parser, is
|
2010-07-21 20:03:21 +04:00
|
|
|
// actually broken.
|
2007-01-31 00:21:06 +03:00
|
|
|
// Drop our reference to the parser to get rid of a circular
|
|
|
|
// reference.
|
2020-02-13 17:38:48 +03:00
|
|
|
RefPtr<nsParserBase> kungFuDeathGrip = std::move(mParser);
|
|
|
|
mozilla::Unused << kungFuDeathGrip;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
2015-04-13 19:02:27 +03:00
|
|
|
if (mDynamicLowerValue) {
|
|
|
|
// Reset the performance hint which was set to FALSE
|
|
|
|
// when mDynamicLowerValue was set.
|
|
|
|
FavorPerformanceHint(true, 0);
|
|
|
|
}
|
|
|
|
|
2018-02-16 00:15:01 +03:00
|
|
|
// Call UnblockOnload only if mRunsToComletion is false and if
|
|
|
|
// we have already started loading because it's possible that this function
|
|
|
|
// is called (i.e. the parser is terminated) before we start loading due to
|
|
|
|
// destroying the window inside unload event callbacks for the previous
|
|
|
|
// document.
|
|
|
|
if (!mRunsToCompletion && mIsBlockingOnload) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mDocument->UnblockOnload(true);
|
2018-02-16 00:15:01 +03:00
|
|
|
mIsBlockingOnload = false;
|
2007-01-31 00:21:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-16 02:34:50 +04:00
|
|
|
bool nsContentSink::IsScriptExecutingImpl() {
|
|
|
|
return !!mScriptLoader->GetCurrentScript();
|
|
|
|
}
|
|
|
|
|
2008-10-31 00:31:00 +03:00
|
|
|
nsresult nsContentSink::WillParseImpl(void) {
|
2013-07-12 06:39:06 +04:00
|
|
|
if (mRunsToCompletion || !mDocument) {
|
2009-05-19 19:54:42 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2019-03-29 18:12:47 +03:00
|
|
|
PresShell* presShell = mDocument->GetPresShell();
|
|
|
|
if (!presShell) {
|
2009-05-19 19:54:42 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t currentTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
2009-05-19 19:54:42 +04:00
|
|
|
|
2019-08-01 19:09:11 +03:00
|
|
|
if (StaticPrefs::content_sink_enable_perf_mode() == 0) {
|
2019-03-29 18:12:47 +03:00
|
|
|
nsViewManager* vm = presShell->GetViewManager();
|
2009-05-19 19:54:42 +04:00
|
|
|
NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t lastEventTime;
|
2009-05-19 19:54:42 +04:00
|
|
|
vm->GetLastUserEventTime(lastEventTime);
|
|
|
|
|
2012-06-14 22:00:05 +04:00
|
|
|
bool newDynLower = mDocument->IsInBackgroundWindow() ||
|
2019-08-01 20:38:26 +03:00
|
|
|
((currentTime - mBeginLoadTime) >
|
|
|
|
StaticPrefs::content_sink_initial_perf_time() &&
|
2019-08-01 20:37:18 +03:00
|
|
|
(currentTime - lastEventTime) <
|
|
|
|
StaticPrefs::content_sink_interactive_time());
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2009-05-19 19:54:42 +04:00
|
|
|
if (mDynamicLowerValue != newDynLower) {
|
2015-04-13 19:02:27 +03:00
|
|
|
FavorPerformanceHint(!newDynLower, 0);
|
2009-05-19 19:54:42 +04:00
|
|
|
mDynamicLowerValue = newDynLower;
|
|
|
|
}
|
2009-04-04 05:25:13 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2009-05-19 19:54:42 +04:00
|
|
|
mDeflectedCount = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
mHasPendingEvent = false;
|
2009-05-19 19:54:42 +04:00
|
|
|
|
|
|
|
mCurrentParseEndTime =
|
2019-08-01 20:15:49 +03:00
|
|
|
currentTime + (mDynamicLowerValue
|
|
|
|
? StaticPrefs::content_sink_interactive_parse_time()
|
|
|
|
: StaticPrefs::content_sink_perf_parse_time());
|
2009-04-04 05:25:13 +04:00
|
|
|
|
2007-01-31 00:21:06 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsContentSink::WillBuildModelImpl() {
|
2012-01-20 16:03:49 +04:00
|
|
|
if (!mRunsToCompletion) {
|
2007-02-09 07:50:13 +03:00
|
|
|
mDocument->BlockOnload();
|
2018-02-16 00:15:01 +03:00
|
|
|
mIsBlockingOnload = true;
|
2007-01-31 00:21:06 +03:00
|
|
|
|
|
|
|
mBeginLoadTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
|
|
|
}
|
|
|
|
|
2010-05-12 04:30:40 +04:00
|
|
|
mDocument->ResetScrolledToRefAlready();
|
2009-06-25 17:13:38 +04:00
|
|
|
|
|
|
|
if (mProcessLinkHeaderEvent.get()) {
|
|
|
|
mProcessLinkHeaderEvent.Revoke();
|
|
|
|
|
|
|
|
DoProcessLinkHeader();
|
|
|
|
}
|
2007-01-31 00:21:06 +03:00
|
|
|
}
|
2007-03-01 11:11:40 +03:00
|
|
|
|
2010-08-28 09:54:57 +04:00
|
|
|
/* static */
|
2019-01-02 16:05:23 +03:00
|
|
|
void nsContentSink::NotifyDocElementCreated(Document* aDoc) {
|
2018-04-20 23:55:51 +03:00
|
|
|
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
|
|
|
|
2010-08-28 09:54:57 +04:00
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
|
|
mozilla::services::GetObserverService();
|
2019-02-23 00:27:44 +03:00
|
|
|
MOZ_ASSERT(observerService);
|
|
|
|
|
|
|
|
auto* win = nsGlobalWindowInner::Cast(aDoc->GetInnerWindow());
|
|
|
|
bool fireInitialInsertion = !win || !win->DidFireDocElemInserted();
|
|
|
|
if (win) {
|
|
|
|
win->SetDidFireDocElemInserted();
|
|
|
|
}
|
|
|
|
if (fireInitialInsertion) {
|
|
|
|
observerService->NotifyObservers(ToSupports(aDoc),
|
2020-09-23 18:17:15 +03:00
|
|
|
"initial-document-element-inserted", u"");
|
2010-08-28 09:54:57 +04:00
|
|
|
}
|
2020-09-23 18:17:15 +03:00
|
|
|
observerService->NotifyObservers(ToSupports(aDoc),
|
|
|
|
"document-element-inserted", u"");
|
2015-03-04 01:07:08 +03:00
|
|
|
|
|
|
|
nsContentUtils::DispatchChromeEvent(aDoc, ToSupports(aDoc),
|
2018-12-26 05:32:55 +03:00
|
|
|
u"DOMDocElementInserted"_ns,
|
|
|
|
CanBubble::eYes, Cancelable::eNo);
|
2010-08-28 09:54:57 +04:00
|
|
|
}
|
2017-02-14 02:45:23 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsContentSink::GetName(nsACString& aName) {
|
2018-09-08 01:12:01 +03:00
|
|
|
aName.AssignLiteral("nsContentSink_timer");
|
2017-02-14 02:45:23 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|