1999-05-19 03:15:10 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2004-05-13 22:34:18 +04:00
|
|
|
* vim: ft=cpp tw=78 sw=2 et ts=2
|
1999-05-19 03:15:10 +04:00
|
|
|
*
|
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/.
|
2002-12-03 08:48:14 +03:00
|
|
|
*
|
2010-03-02 23:59:32 +03:00
|
|
|
* This Original Code has been modified by IBM Corporation.
|
|
|
|
* Modifications made by IBM described herein are Copyright (c)
|
|
|
|
* International Business Machines Corporation, 2000. Modifications
|
|
|
|
* to Mozilla code or documentation identified per MPL Section 3.3
|
2000-05-03 03:07:11 +04:00
|
|
|
*
|
|
|
|
* Date Modified by Description of modification
|
|
|
|
* 04/20/2000 IBM Corp. OS/2 VisualAge build.
|
1999-05-19 03:15:10 +04:00
|
|
|
*/
|
2006-03-25 08:47:31 +03:00
|
|
|
|
|
|
|
/* loading of CSS style sheets using the network APIs */
|
|
|
|
|
2017-02-14 22:23:11 +03:00
|
|
|
#include "mozilla/css/Loader.h"
|
|
|
|
|
2013-12-09 06:52:54 +04:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
2016-12-16 06:16:31 +03:00
|
|
|
#include "mozilla/IntegerPrintfMacros.h"
|
2014-07-10 10:56:38 +04:00
|
|
|
#include "mozilla/LoadInfo.h"
|
2013-06-23 16:03:39 +04:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2011-10-11 09:50:08 +04:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
#include "mozilla/StyleSheetInlines.h"
|
2010-03-02 23:59:32 +03:00
|
|
|
#include "nsIRunnable.h"
|
|
|
|
#include "nsIUnicharStreamLoader.h"
|
2011-05-19 05:22:59 +04:00
|
|
|
#include "nsSyncLoadService.h"
|
2010-03-02 23:59:32 +03:00
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsString.h"
|
1999-05-27 03:52:37 +04:00
|
|
|
#include "nsIContent.h"
|
2011-05-26 12:18:43 +04:00
|
|
|
#include "nsIDocument.h"
|
1999-05-19 03:15:10 +04:00
|
|
|
#include "nsIDOMNode.h"
|
2011-05-26 12:18:43 +04:00
|
|
|
#include "nsIDOMDocument.h"
|
2005-04-14 19:27:16 +04:00
|
|
|
#include "nsIURI.h"
|
1999-11-30 07:50:42 +03:00
|
|
|
#include "nsNetUtil.h"
|
2015-07-07 05:17:00 +03:00
|
|
|
#include "nsIProtocolHandler.h"
|
2003-10-30 06:01:25 +03:00
|
|
|
#include "nsContentUtils.h"
|
2000-05-27 03:28:40 +04:00
|
|
|
#include "nsIScriptSecurityManager.h"
|
2003-04-05 03:57:06 +04:00
|
|
|
#include "nsContentPolicyUtils.h"
|
2001-10-25 04:34:20 +04:00
|
|
|
#include "nsIHttpChannel.h"
|
2016-09-07 05:30:21 +03:00
|
|
|
#include "nsIHttpChannelInternal.h"
|
2014-12-06 22:26:50 +03:00
|
|
|
#include "nsIClassOfService.h"
|
2002-07-02 07:11:57 +04:00
|
|
|
#include "nsIScriptError.h"
|
2002-11-07 01:29:17 +03:00
|
|
|
#include "nsMimeTypes.h"
|
2005-04-14 19:27:16 +04:00
|
|
|
#include "nsIStyleSheetLinkingElement.h"
|
|
|
|
#include "nsICSSLoaderObserver.h"
|
2010-03-02 23:59:32 +03:00
|
|
|
#include "nsCSSParser.h"
|
2011-03-17 20:41:52 +03:00
|
|
|
#include "mozilla/css/ImportRule.h"
|
2006-05-10 21:30:15 +04:00
|
|
|
#include "nsThreadUtils.h"
|
2006-12-26 20:47:52 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2011-09-27 01:27:13 +04:00
|
|
|
#include "nsIThreadInternal.h"
|
2014-06-04 00:37:46 +04:00
|
|
|
#include "nsINetworkPredictor.h"
|
2013-12-02 14:26:12 +04:00
|
|
|
#include "mozilla/dom/ShadowRoot.h"
|
2013-11-20 20:29:03 +04:00
|
|
|
#include "mozilla/dom/URL.h"
|
2016-05-27 20:31:20 +03:00
|
|
|
#include "mozilla/AsyncEventDispatcher.h"
|
2016-12-17 12:58:56 +03:00
|
|
|
#include "mozilla/ServoBindings.h"
|
2016-09-26 15:03:25 +03:00
|
|
|
#include "mozilla/StyleSheet.h"
|
|
|
|
#include "mozilla/StyleSheetInlines.h"
|
2016-09-08 04:59:40 +03:00
|
|
|
#include "mozilla/ConsoleReportCollector.h"
|
2017-01-31 10:10:45 +03:00
|
|
|
#include "mozilla/ServoUtils.h"
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2003-04-11 04:56:27 +04:00
|
|
|
#ifdef MOZ_XUL
|
2007-03-12 08:53:33 +03:00
|
|
|
#include "nsXULPrototypeCache.h"
|
2000-07-28 13:36:51 +04:00
|
|
|
#endif
|
|
|
|
|
2016-12-16 06:50:36 +03:00
|
|
|
#include "nsMediaList.h"
|
2001-08-05 01:19:53 +04:00
|
|
|
#include "nsIDOMStyleSheet.h"
|
2012-07-27 18:03:27 +04:00
|
|
|
#include "nsError.h"
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2010-04-24 02:05:32 +04:00
|
|
|
#include "nsIContentSecurityPolicy.h"
|
2015-08-13 06:19:11 +03:00
|
|
|
#include "mozilla/dom/SRICheck.h"
|
2010-04-24 02:05:32 +04:00
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
#include "mozilla/dom/EncodingUtils.h"
|
|
|
|
using mozilla::dom::EncodingUtils;
|
2010-05-20 03:22:19 +04:00
|
|
|
|
2013-01-09 03:25:47 +04:00
|
|
|
using namespace mozilla::dom;
|
|
|
|
|
2010-03-02 23:59:32 +03:00
|
|
|
/**
|
|
|
|
* OVERALL ARCHITECTURE
|
|
|
|
*
|
|
|
|
* The CSS Loader gets requests to load various sorts of style sheets:
|
|
|
|
* inline style from <style> elements, linked style, @import-ed child
|
|
|
|
* sheets, non-document sheets. The loader handles the following tasks:
|
2016-02-03 07:35:02 +03:00
|
|
|
* 1) Creation of the actual style sheet objects: CreateSheet()
|
|
|
|
* 2) setting of the right media, title, enabled state, etc on the
|
2010-03-02 23:59:32 +03:00
|
|
|
* sheet: PrepareSheet()
|
2016-02-03 07:35:02 +03:00
|
|
|
* 3) Insertion of the sheet in the proper cascade order:
|
2010-03-02 23:59:32 +03:00
|
|
|
* InsertSheetInDoc() and InsertChildSheet()
|
2016-02-03 07:35:02 +03:00
|
|
|
* 4) Load of the sheet: LoadSheet() including security checks
|
|
|
|
* 5) Parsing of the sheet: ParseSheet()
|
|
|
|
* 6) Cleanup: SheetComplete()
|
2010-03-02 23:59:32 +03:00
|
|
|
*
|
|
|
|
* The detailed documentation for these functions is found with the
|
|
|
|
* function implementations.
|
|
|
|
*
|
|
|
|
* The following helper object is used:
|
|
|
|
* SheetLoadData -- a small class that is used to store all the
|
|
|
|
* information needed for the loading of a sheet;
|
|
|
|
* this class handles listening for the stream
|
|
|
|
* loader completion and also handles charset
|
|
|
|
* determination.
|
|
|
|
*/
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
namespace mozilla {
|
|
|
|
namespace css {
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
/*********************************************
|
|
|
|
* Data needed to properly load a stylesheet *
|
|
|
|
*********************************************/
|
|
|
|
|
2015-10-14 00:43:16 +03:00
|
|
|
static_assert(eAuthorSheetFeatures == 0 &&
|
|
|
|
eUserSheetFeatures == 1 &&
|
|
|
|
eAgentSheetFeatures == 2,
|
|
|
|
"sheet parsing mode constants won't fit "
|
|
|
|
"in SheetLoadData::mParsingMode");
|
|
|
|
|
2015-03-21 21:35:18 +03:00
|
|
|
class SheetLoadData final : public nsIRunnable,
|
|
|
|
public nsIUnicharStreamLoaderObserver,
|
|
|
|
public nsIThreadObserver
|
2010-03-02 23:59:32 +03:00
|
|
|
{
|
2014-06-24 02:40:01 +04:00
|
|
|
protected:
|
2010-03-02 23:59:32 +03:00
|
|
|
virtual ~SheetLoadData(void);
|
2014-06-24 02:40:01 +04:00
|
|
|
|
|
|
|
public:
|
2010-03-02 23:59:32 +03:00
|
|
|
// Data for loading a sheet linked from a document
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData(Loader* aLoader,
|
|
|
|
const nsSubstring& aTitle,
|
|
|
|
nsIURI* aURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aSheet,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsIStyleSheetLinkingElement* aOwningElement,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIsAlternate,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
nsIPrincipal* aLoaderPrincipal,
|
|
|
|
nsINode* aRequestingNode);
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// Data for loading a sheet linked from an @import rule
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData(Loader* aLoader,
|
|
|
|
nsIURI* aURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aSheet,
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData* aParentData,
|
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
nsIPrincipal* aLoaderPrincipal,
|
|
|
|
nsINode* aRequestingNode);
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// Data for loading a non-document sheet
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData(Loader* aLoader,
|
|
|
|
nsIURI* aURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aSheet,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aSyncLoad,
|
|
|
|
bool aUseSystemPrincipal,
|
2010-03-03 00:00:53 +03:00
|
|
|
const nsCString& aCharset,
|
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
nsIPrincipal* aLoaderPrincipal,
|
|
|
|
nsINode* aRequestingNode);
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
already_AddRefed<nsIURI> GetReferrerURI();
|
|
|
|
|
2011-09-27 01:27:13 +04:00
|
|
|
void ScheduleLoadEventIfNeeded(nsresult aStatus);
|
|
|
|
|
2010-03-02 23:59:32 +03:00
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIRUNNABLE
|
2011-09-27 01:27:13 +04:00
|
|
|
NS_DECL_NSITHREADOBSERVER
|
2010-03-02 23:59:32 +03:00
|
|
|
NS_DECL_NSIUNICHARSTREAMLOADEROBSERVER
|
|
|
|
|
|
|
|
// Hold a ref to the CSSLoader so we can call back to it to let it
|
|
|
|
// know the load finished
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Loader> mLoader;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// Title needed to pull datas out of the pending datas table when
|
|
|
|
// the preferred title is changed
|
|
|
|
nsString mTitle;
|
|
|
|
|
|
|
|
// Charset we decided to use for the sheet
|
|
|
|
nsCString mCharset;
|
|
|
|
|
|
|
|
// URI we're loading. Null for inline sheets
|
|
|
|
nsCOMPtr<nsIURI> mURI;
|
|
|
|
|
|
|
|
// Should be 1 for non-inline sheets.
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t mLineNumber;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// The sheet we're loading data for
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet> mSheet;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// Linked list of datas for the same URI as us
|
|
|
|
SheetLoadData* mNext; // strong ref
|
|
|
|
|
|
|
|
// Load data for the sheet that @import-ed us if we were @import-ed
|
|
|
|
// during the parse
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SheetLoadData> mParentData;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// Number of sheets we @import-ed that are still loading
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t mPendingChildren;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// mSyncLoad is true when the load needs to be synchronous -- right
|
|
|
|
// now only for LoadSheetSync and children of sync loads.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mSyncLoad : 1;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// mIsNonDocumentSheet is true if the load was triggered by LoadSheetSync or
|
|
|
|
// LoadSheet or an @import from such a sheet. Non-document sheet loads can
|
|
|
|
// proceed even if we have no document.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsNonDocumentSheet : 1;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// mIsLoading is true from the moment we are placed in the loader's
|
|
|
|
// "loading datas" table (right after the async channel is opened)
|
|
|
|
// to the moment we are removed from said table (due to the load
|
|
|
|
// completing or being cancelled).
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsLoading : 1;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// mIsCancelled is set to true when a sheet load is stopped by
|
2010-04-03 15:36:19 +04:00
|
|
|
// Stop() or StopLoadingSheet() (which was removed in Bug 556446).
|
2011-05-06 19:45:36 +04:00
|
|
|
// SheetLoadData::OnStreamComplete() checks this to avoid parsing
|
2010-04-03 15:36:19 +04:00
|
|
|
// sheets that have been cancelled and such.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsCancelled : 1;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// mMustNotify is true if the load data is being loaded async and
|
|
|
|
// the original function call that started the load has returned.
|
2011-09-27 01:27:00 +04:00
|
|
|
// This applies only to observer notifications; load/error events
|
|
|
|
// are fired for any SheetLoadData that has a non-null
|
|
|
|
// mOwningElement.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mMustNotify : 1;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// mWasAlternate is true if the sheet was an alternate when the load data was
|
|
|
|
// created.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mWasAlternate : 1;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
// mUseSystemPrincipal is true if the system principal should be used for
|
|
|
|
// this sheet, no matter what the channel principal is. Only true for sync
|
|
|
|
// loads.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mUseSystemPrincipal : 1;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
2011-09-27 01:26:54 +04:00
|
|
|
// If true, this SheetLoadData is being used as a way to handle
|
|
|
|
// async observer notification for an already-complete sheet.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mSheetAlreadyComplete : 1;
|
2011-09-27 01:26:54 +04:00
|
|
|
|
2010-03-02 23:59:32 +03:00
|
|
|
// This is the element that imported the sheet. Needed to get the
|
2011-09-27 01:27:00 +04:00
|
|
|
// charset set on it and to fire load/error events.
|
2010-03-02 23:59:32 +03:00
|
|
|
nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
|
|
|
|
|
|
|
|
// The observer that wishes to be notified of load completion
|
|
|
|
nsCOMPtr<nsICSSLoaderObserver> mObserver;
|
|
|
|
|
|
|
|
// The principal that identifies who started loading us.
|
2010-03-03 00:00:53 +03:00
|
|
|
nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
|
2010-03-02 23:59:32 +03:00
|
|
|
|
2014-09-21 20:41:26 +04:00
|
|
|
// The node that identifies who started loading us.
|
|
|
|
nsCOMPtr<nsINode> mRequestingNode;
|
|
|
|
|
2010-03-02 23:59:32 +03:00
|
|
|
// The charset to use if the transport and sheet don't indicate one.
|
|
|
|
// May be empty. Must be empty if mOwningElement is non-null.
|
2010-03-03 00:00:53 +03:00
|
|
|
nsCString mCharsetHint;
|
2011-09-27 01:27:13 +04:00
|
|
|
|
|
|
|
// The status our load ended up with; this determines whether we
|
|
|
|
// should fire error events or load events. This gets initialized
|
|
|
|
// by ScheduleLoadEventIfNeeded, and is only used after that has
|
|
|
|
// been called.
|
2016-09-26 17:55:53 +03:00
|
|
|
MOZ_INIT_OUTSIDE_CTOR nsresult mStatus;
|
2011-09-27 01:27:13 +04:00
|
|
|
|
|
|
|
private:
|
|
|
|
void FireLoadEvent(nsIThreadInternal* aThread);
|
2010-03-02 23:59:32 +03:00
|
|
|
};
|
|
|
|
|
2015-05-19 21:15:34 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2015-11-06 01:35:03 +03:00
|
|
|
static mozilla::LazyLogModule sCssLoaderLog("nsCSSLoader");
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2015-11-06 01:35:03 +03:00
|
|
|
static mozilla::LazyLogModule gSriPRLog("SRI");
|
2015-08-13 06:19:11 +03:00
|
|
|
|
2015-11-06 01:35:03 +03:00
|
|
|
#define LOG_ERROR(args) MOZ_LOG(sCssLoaderLog, mozilla::LogLevel::Error, args)
|
|
|
|
#define LOG_WARN(args) MOZ_LOG(sCssLoaderLog, mozilla::LogLevel::Warning, args)
|
|
|
|
#define LOG_DEBUG(args) MOZ_LOG(sCssLoaderLog, mozilla::LogLevel::Debug, args)
|
2002-12-03 08:48:14 +03:00
|
|
|
#define LOG(args) LOG_DEBUG(args)
|
|
|
|
|
2015-11-06 01:35:03 +03:00
|
|
|
#define LOG_ERROR_ENABLED() MOZ_LOG_TEST(sCssLoaderLog, mozilla::LogLevel::Error)
|
|
|
|
#define LOG_WARN_ENABLED() MOZ_LOG_TEST(sCssLoaderLog, mozilla::LogLevel::Warning)
|
|
|
|
#define LOG_DEBUG_ENABLED() MOZ_LOG_TEST(sCssLoaderLog, mozilla::LogLevel::Debug)
|
2002-12-03 08:48:14 +03:00
|
|
|
#define LOG_ENABLED() LOG_DEBUG_ENABLED()
|
|
|
|
|
|
|
|
#define LOG_URI(format, uri) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
NS_ASSERTION(uri, "Logging null uri"); \
|
|
|
|
if (LOG_ENABLED()) { \
|
2016-08-26 09:02:31 +03:00
|
|
|
LOG((format, uri->GetSpecOrDefault().get())); \
|
2002-12-03 08:48:14 +03:00
|
|
|
} \
|
|
|
|
PR_END_MACRO
|
2001-08-05 01:19:53 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// And some convenience strings...
|
|
|
|
static const char* const gStateStrings[] = {
|
|
|
|
"eSheetStateUnknown",
|
|
|
|
"eSheetNeedsParser",
|
|
|
|
"eSheetPending",
|
|
|
|
"eSheetLoading",
|
|
|
|
"eSheetComplete"
|
1999-05-19 03:15:10 +04:00
|
|
|
};
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/********************************
|
|
|
|
* SheetLoadData implementation *
|
|
|
|
********************************/
|
2014-04-27 11:06:00 +04:00
|
|
|
NS_IMPL_ISUPPORTS(SheetLoadData, nsIUnicharStreamLoaderObserver, nsIRunnable,
|
|
|
|
nsIThreadObserver)
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData::SheetLoadData(Loader* aLoader,
|
2005-03-30 04:36:57 +04:00
|
|
|
const nsSubstring& aTitle,
|
2002-12-03 08:48:14 +03:00
|
|
|
nsIURI* aURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aSheet,
|
2002-12-03 08:48:14 +03:00
|
|
|
nsIStyleSheetLinkingElement* aOwningElement,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIsAlternate,
|
2007-05-01 23:26:15 +04:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
nsIPrincipal* aLoaderPrincipal,
|
|
|
|
nsINode* aRequestingNode)
|
1999-05-19 03:15:10 +04:00
|
|
|
: mLoader(aLoader),
|
|
|
|
mTitle(aTitle),
|
2002-12-03 08:48:14 +03:00
|
|
|
mURI(aURI),
|
2004-09-09 21:32:35 +04:00
|
|
|
mLineNumber(1),
|
2002-12-03 08:48:14 +03:00
|
|
|
mSheet(aSheet),
|
2012-07-30 18:20:58 +04:00
|
|
|
mNext(nullptr),
|
1999-05-19 03:15:10 +04:00
|
|
|
mPendingChildren(0),
|
2011-10-17 18:59:28 +04:00
|
|
|
mSyncLoad(false),
|
|
|
|
mIsNonDocumentSheet(false),
|
|
|
|
mIsLoading(false),
|
|
|
|
mIsCancelled(false),
|
|
|
|
mMustNotify(false),
|
2005-09-12 22:41:15 +04:00
|
|
|
mWasAlternate(aIsAlternate),
|
2011-10-17 18:59:28 +04:00
|
|
|
mUseSystemPrincipal(false),
|
|
|
|
mSheetAlreadyComplete(false),
|
2002-12-03 08:48:14 +03:00
|
|
|
mOwningElement(aOwningElement),
|
2007-05-01 23:26:15 +04:00
|
|
|
mObserver(aObserver),
|
2014-09-21 20:41:26 +04:00
|
|
|
mLoaderPrincipal(aLoaderPrincipal),
|
|
|
|
mRequestingNode(aRequestingNode)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(mLoader, "Must have a loader!");
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData::SheetLoadData(Loader* aLoader,
|
2002-12-03 08:48:14 +03:00
|
|
|
nsIURI* aURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aSheet,
|
2002-12-03 08:48:14 +03:00
|
|
|
SheetLoadData* aParentData,
|
2007-05-01 23:26:15 +04:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
nsIPrincipal* aLoaderPrincipal,
|
|
|
|
nsINode* aRequestingNode)
|
1999-05-19 03:15:10 +04:00
|
|
|
: mLoader(aLoader),
|
2002-12-03 08:48:14 +03:00
|
|
|
mURI(aURI),
|
2004-09-09 21:32:35 +04:00
|
|
|
mLineNumber(1),
|
2002-12-03 08:48:14 +03:00
|
|
|
mSheet(aSheet),
|
2012-07-30 18:20:58 +04:00
|
|
|
mNext(nullptr),
|
2002-12-03 08:48:14 +03:00
|
|
|
mParentData(aParentData),
|
1999-05-19 03:15:10 +04:00
|
|
|
mPendingChildren(0),
|
2011-10-17 18:59:28 +04:00
|
|
|
mSyncLoad(false),
|
|
|
|
mIsNonDocumentSheet(false),
|
|
|
|
mIsLoading(false),
|
|
|
|
mIsCancelled(false),
|
|
|
|
mMustNotify(false),
|
|
|
|
mWasAlternate(false),
|
|
|
|
mUseSystemPrincipal(false),
|
|
|
|
mSheetAlreadyComplete(false),
|
2012-07-30 18:20:58 +04:00
|
|
|
mOwningElement(nullptr),
|
2007-05-01 23:26:15 +04:00
|
|
|
mObserver(aObserver),
|
2014-09-21 20:41:26 +04:00
|
|
|
mLoaderPrincipal(aLoaderPrincipal),
|
|
|
|
mRequestingNode(aRequestingNode)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(mLoader, "Must have a loader!");
|
|
|
|
if (mParentData) {
|
|
|
|
mSyncLoad = mParentData->mSyncLoad;
|
2005-09-12 22:41:15 +04:00
|
|
|
mIsNonDocumentSheet = mParentData->mIsNonDocumentSheet;
|
2009-03-17 04:38:36 +03:00
|
|
|
mUseSystemPrincipal = mParentData->mUseSystemPrincipal;
|
2002-12-03 08:48:14 +03:00
|
|
|
++(mParentData->mPendingChildren);
|
|
|
|
}
|
2009-03-17 04:38:36 +03:00
|
|
|
|
|
|
|
NS_POSTCONDITION(!mUseSystemPrincipal || mSyncLoad,
|
|
|
|
"Shouldn't use system principal for async loads");
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData::SheetLoadData(Loader* aLoader,
|
2002-12-03 08:48:14 +03:00
|
|
|
nsIURI* aURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aSheet,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aSyncLoad,
|
|
|
|
bool aUseSystemPrincipal,
|
2009-04-10 18:29:08 +04:00
|
|
|
const nsCString& aCharset,
|
2007-07-11 23:44:27 +04:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
nsIPrincipal* aLoaderPrincipal,
|
|
|
|
nsINode* aRequestingNode)
|
1999-05-27 03:52:37 +04:00
|
|
|
: mLoader(aLoader),
|
2002-12-03 08:48:14 +03:00
|
|
|
mURI(aURI),
|
2004-09-09 21:32:35 +04:00
|
|
|
mLineNumber(1),
|
2002-12-03 08:48:14 +03:00
|
|
|
mSheet(aSheet),
|
2012-07-30 18:20:58 +04:00
|
|
|
mNext(nullptr),
|
1999-05-27 03:52:37 +04:00
|
|
|
mPendingChildren(0),
|
2002-12-11 03:28:47 +03:00
|
|
|
mSyncLoad(aSyncLoad),
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsNonDocumentSheet(true),
|
|
|
|
mIsLoading(false),
|
|
|
|
mIsCancelled(false),
|
|
|
|
mMustNotify(false),
|
|
|
|
mWasAlternate(false),
|
2009-03-17 04:38:36 +03:00
|
|
|
mUseSystemPrincipal(aUseSystemPrincipal),
|
2011-10-17 18:59:28 +04:00
|
|
|
mSheetAlreadyComplete(false),
|
2012-07-30 18:20:58 +04:00
|
|
|
mOwningElement(nullptr),
|
2007-05-01 23:26:15 +04:00
|
|
|
mObserver(aObserver),
|
2009-04-10 18:29:08 +04:00
|
|
|
mLoaderPrincipal(aLoaderPrincipal),
|
2014-09-21 20:41:26 +04:00
|
|
|
mRequestingNode(aRequestingNode),
|
2009-04-10 18:29:08 +04:00
|
|
|
mCharsetHint(aCharset)
|
1999-05-27 03:52:37 +04:00
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(mLoader, "Must have a loader!");
|
2009-03-17 04:38:36 +03:00
|
|
|
NS_POSTCONDITION(!mUseSystemPrincipal || mSyncLoad,
|
|
|
|
"Shouldn't use system principal for async loads");
|
1999-05-27 03:52:37 +04:00
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
SheetLoadData::~SheetLoadData()
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2015-11-06 00:09:27 +03:00
|
|
|
NS_CSS_NS_RELEASE_LIST_MEMBER(SheetLoadData, this, mNext);
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2006-05-10 21:30:15 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
SheetLoadData::Run()
|
|
|
|
{
|
|
|
|
mLoader->HandleLoadEvent(this);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-27 01:27:13 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
SheetLoadData::OnDispatchedEvent(nsIThreadInternal* aThread)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
SheetLoadData::OnProcessNextEvent(nsIThreadInternal* aThread,
|
Bug 1179909: Refactor stable state handling. r=smaug
This is motivated by three separate but related problems:
1. Our concept of recursion depth is broken for things that run from AfterProcessNextEvent observers (e.g. Promises). We decrement the recursionDepth counter before firing observers, so a Promise callback running at the lowest event loop depth has a recursion depth of 0 (whereas a regular nsIRunnable would be 1). This is a problem because it's impossible to distinguish a Promise running after a sync XHR's onreadystatechange handler from a top-level event (since the former runs with depth 2 - 1 = 1, and the latter runs with just 1).
2. The nsIThreadObserver mechanism that is used by a lot of code to run "after" the current event is a poor fit for anything that runs script. First, the order the observers fire in is the order they were added, not anything fixed by spec. Additionally, running script can cause the event loop to spin, which is a big source of pain here (bholley has some nasty bug caused by this).
3. We run Promises from different points in the code for workers and main thread. The latter runs from XPConnect's nsIThreadObserver callbacks, while the former runs from a hardcoded call to run Promises in the worker event loop. What workers do is particularly problematic because it means we can't get the right recursion depth no matter what we do to nsThread.
The solve this, this patch does the following:
1. Consolidate some handling of microtasks and all handling of stable state from appshell and WorkerPrivate into CycleCollectedJSRuntime.
2. Make the recursionDepth counter only available to CycleCollectedJSRuntime (and its consumers) and remove it from the nsIThreadInternal and nsIThreadObserver APIs.
3. Adjust the recursionDepth counter so that microtasks run with the recursionDepth of the task they are associated with.
4. Introduce the concept of metastable state to replace appshell's RunBeforeNextEvent. Metastable state is reached after every microtask or task is completed. This provides the semantics that bent and I want for IndexedDB, where transactions autocommit at the end of a microtask and do not "spill" from one microtask into a subsequent microtask. This differs from appshell's RunBeforeNextEvent in two ways:
a) It fires between microtasks, which was the motivation for starting this.
b) It no longer ensures that we're at the same event loop depth in the native event queue. bent decided we don't care about this.
5. Reorder stable state to happen after microtasks such as Promises, per HTML. Right now we call the regular thread observers, including appshell, before the main thread observer (XPConnect), so stable state tasks happen before microtasks.
2015-08-11 16:10:46 +03:00
|
|
|
bool aMayWait)
|
2011-09-27 01:27:13 +04:00
|
|
|
{
|
Bug 1179909: Refactor stable state handling. r=smaug
This is motivated by three separate but related problems:
1. Our concept of recursion depth is broken for things that run from AfterProcessNextEvent observers (e.g. Promises). We decrement the recursionDepth counter before firing observers, so a Promise callback running at the lowest event loop depth has a recursion depth of 0 (whereas a regular nsIRunnable would be 1). This is a problem because it's impossible to distinguish a Promise running after a sync XHR's onreadystatechange handler from a top-level event (since the former runs with depth 2 - 1 = 1, and the latter runs with just 1).
2. The nsIThreadObserver mechanism that is used by a lot of code to run "after" the current event is a poor fit for anything that runs script. First, the order the observers fire in is the order they were added, not anything fixed by spec. Additionally, running script can cause the event loop to spin, which is a big source of pain here (bholley has some nasty bug caused by this).
3. We run Promises from different points in the code for workers and main thread. The latter runs from XPConnect's nsIThreadObserver callbacks, while the former runs from a hardcoded call to run Promises in the worker event loop. What workers do is particularly problematic because it means we can't get the right recursion depth no matter what we do to nsThread.
The solve this, this patch does the following:
1. Consolidate some handling of microtasks and all handling of stable state from appshell and WorkerPrivate into CycleCollectedJSRuntime.
2. Make the recursionDepth counter only available to CycleCollectedJSRuntime (and its consumers) and remove it from the nsIThreadInternal and nsIThreadObserver APIs.
3. Adjust the recursionDepth counter so that microtasks run with the recursionDepth of the task they are associated with.
4. Introduce the concept of metastable state to replace appshell's RunBeforeNextEvent. Metastable state is reached after every microtask or task is completed. This provides the semantics that bent and I want for IndexedDB, where transactions autocommit at the end of a microtask and do not "spill" from one microtask into a subsequent microtask. This differs from appshell's RunBeforeNextEvent in two ways:
a) It fires between microtasks, which was the motivation for starting this.
b) It no longer ensures that we're at the same event loop depth in the native event queue. bent decided we don't care about this.
5. Reorder stable state to happen after microtasks such as Promises, per HTML. Right now we call the regular thread observers, including appshell, before the main thread observer (XPConnect), so stable state tasks happen before microtasks.
2015-08-11 16:10:46 +03:00
|
|
|
// XXXkhuey this is insane!
|
2011-09-27 01:27:13 +04:00
|
|
|
// We want to fire our load even before or after event processing,
|
|
|
|
// whichever comes first.
|
|
|
|
FireLoadEvent(aThread);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
SheetLoadData::AfterProcessNextEvent(nsIThreadInternal* aThread,
|
2013-10-23 16:01:20 +04:00
|
|
|
bool aEventWasProcessed)
|
2011-09-27 01:27:13 +04:00
|
|
|
{
|
Bug 1179909: Refactor stable state handling. r=smaug
This is motivated by three separate but related problems:
1. Our concept of recursion depth is broken for things that run from AfterProcessNextEvent observers (e.g. Promises). We decrement the recursionDepth counter before firing observers, so a Promise callback running at the lowest event loop depth has a recursion depth of 0 (whereas a regular nsIRunnable would be 1). This is a problem because it's impossible to distinguish a Promise running after a sync XHR's onreadystatechange handler from a top-level event (since the former runs with depth 2 - 1 = 1, and the latter runs with just 1).
2. The nsIThreadObserver mechanism that is used by a lot of code to run "after" the current event is a poor fit for anything that runs script. First, the order the observers fire in is the order they were added, not anything fixed by spec. Additionally, running script can cause the event loop to spin, which is a big source of pain here (bholley has some nasty bug caused by this).
3. We run Promises from different points in the code for workers and main thread. The latter runs from XPConnect's nsIThreadObserver callbacks, while the former runs from a hardcoded call to run Promises in the worker event loop. What workers do is particularly problematic because it means we can't get the right recursion depth no matter what we do to nsThread.
The solve this, this patch does the following:
1. Consolidate some handling of microtasks and all handling of stable state from appshell and WorkerPrivate into CycleCollectedJSRuntime.
2. Make the recursionDepth counter only available to CycleCollectedJSRuntime (and its consumers) and remove it from the nsIThreadInternal and nsIThreadObserver APIs.
3. Adjust the recursionDepth counter so that microtasks run with the recursionDepth of the task they are associated with.
4. Introduce the concept of metastable state to replace appshell's RunBeforeNextEvent. Metastable state is reached after every microtask or task is completed. This provides the semantics that bent and I want for IndexedDB, where transactions autocommit at the end of a microtask and do not "spill" from one microtask into a subsequent microtask. This differs from appshell's RunBeforeNextEvent in two ways:
a) It fires between microtasks, which was the motivation for starting this.
b) It no longer ensures that we're at the same event loop depth in the native event queue. bent decided we don't care about this.
5. Reorder stable state to happen after microtasks such as Promises, per HTML. Right now we call the regular thread observers, including appshell, before the main thread observer (XPConnect), so stable state tasks happen before microtasks.
2015-08-11 16:10:46 +03:00
|
|
|
// XXXkhuey this too!
|
2011-09-27 01:27:13 +04:00
|
|
|
// We want to fire our load even before or after event processing,
|
|
|
|
// whichever comes first.
|
|
|
|
FireLoadEvent(aThread);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SheetLoadData::FireLoadEvent(nsIThreadInternal* aThread)
|
|
|
|
{
|
2016-05-31 12:14:00 +03:00
|
|
|
|
2011-09-27 01:27:13 +04:00
|
|
|
// First remove ourselves as a thread observer. But we need to keep
|
|
|
|
// ourselves alive while doing that!
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SheetLoadData> kungFuDeathGrip(this);
|
2011-09-27 01:27:13 +04:00
|
|
|
aThread->RemoveObserver(this);
|
|
|
|
|
|
|
|
// Now fire the event
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(mOwningElement);
|
|
|
|
NS_ASSERTION(node, "How did that happen???");
|
|
|
|
|
2011-10-18 14:53:36 +04:00
|
|
|
nsContentUtils::DispatchTrustedEvent(node->OwnerDoc(),
|
2011-09-27 01:27:13 +04:00
|
|
|
node,
|
|
|
|
NS_SUCCEEDED(mStatus) ?
|
|
|
|
NS_LITERAL_STRING("load") :
|
|
|
|
NS_LITERAL_STRING("error"),
|
2011-10-17 18:59:28 +04:00
|
|
|
false, false);
|
2011-09-27 01:27:13 +04:00
|
|
|
|
|
|
|
// And unblock onload
|
|
|
|
if (mLoader->mDocument) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mLoader->mDocument->UnblockOnload(true);
|
2016-05-31 12:14:00 +03:00
|
|
|
}
|
2011-09-27 01:27:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SheetLoadData::ScheduleLoadEventIfNeeded(nsresult aStatus)
|
|
|
|
{
|
|
|
|
if (!mOwningElement) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mStatus = aStatus;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIThread> thread = do_GetMainThread();
|
|
|
|
nsCOMPtr<nsIThreadInternal> internalThread = do_QueryInterface(thread);
|
|
|
|
if (NS_SUCCEEDED(internalThread->AddObserver(this))) {
|
|
|
|
// Make sure to block onload here
|
|
|
|
if (mLoader->mDocument) {
|
|
|
|
mLoader->mDocument->BlockOnload();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-18 08:27:00 +03:00
|
|
|
/*********************
|
|
|
|
* Style sheet reuse *
|
|
|
|
*********************/
|
|
|
|
|
|
|
|
bool
|
|
|
|
LoaderReusableStyleSheets::FindReusableStyleSheet(nsIURI* aURL,
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<CSSStyleSheet>& aResult)
|
2015-09-18 08:27:00 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aURL);
|
|
|
|
for (size_t i = mReusableSheets.Length(); i > 0; --i) {
|
|
|
|
size_t index = i - 1;
|
|
|
|
bool sameURI;
|
|
|
|
MOZ_ASSERT(mReusableSheets[index]->GetOriginalURI());
|
|
|
|
nsresult rv = aURL->Equals(mReusableSheets[index]->GetOriginalURI(),
|
|
|
|
&sameURI);
|
|
|
|
if (!NS_FAILED(rv) && sameURI) {
|
|
|
|
aResult = mReusableSheets[index];
|
|
|
|
mReusableSheets.RemoveElementAt(index);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/*************************
|
|
|
|
* Loader Implementation *
|
|
|
|
*************************/
|
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
Loader::Loader(StyleBackendType aType)
|
2012-07-30 18:20:58 +04:00
|
|
|
: mDocument(nullptr)
|
2010-03-03 00:00:53 +03:00
|
|
|
, mDatasToNotifyOn(0)
|
|
|
|
, mCompatMode(eCompatibility_FullStandards)
|
2016-02-24 10:01:12 +03:00
|
|
|
, mStyleBackendType(Some(aType))
|
2011-10-17 18:59:28 +04:00
|
|
|
, mEnabled(true)
|
2016-09-08 04:59:40 +03:00
|
|
|
, mReporter(new ConsoleReportCollector())
|
2010-03-03 00:00:53 +03:00
|
|
|
#ifdef DEBUG
|
2011-10-17 18:59:28 +04:00
|
|
|
, mSyncCallback(false)
|
2010-03-03 00:00:53 +03:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Loader::Loader(nsIDocument* aDocument)
|
|
|
|
: mDocument(aDocument)
|
|
|
|
, mDatasToNotifyOn(0)
|
|
|
|
, mCompatMode(eCompatibility_FullStandards)
|
2011-10-17 18:59:28 +04:00
|
|
|
, mEnabled(true)
|
2016-09-08 04:59:40 +03:00
|
|
|
, mReporter(new ConsoleReportCollector())
|
2010-03-03 00:00:53 +03:00
|
|
|
#ifdef DEBUG
|
2011-10-17 18:59:28 +04:00
|
|
|
, mSyncCallback(false)
|
2010-03-03 00:00:53 +03:00
|
|
|
#endif
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
// We can just use the preferred set, since there are no sheets in the
|
|
|
|
// document yet (if there are, how did they get there? _we_ load the sheets!)
|
|
|
|
// and hence the selected set makes no sense at this time.
|
2011-05-26 12:18:43 +04:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
2010-03-03 00:00:53 +03:00
|
|
|
if (domDoc) {
|
|
|
|
domDoc->GetPreferredStyleSheetSet(mPreferredSheet);
|
|
|
|
}
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::~Loader()
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2013-09-02 12:41:57 +04:00
|
|
|
NS_ASSERTION(!mSheets || mSheets->mLoadingDatas.Count() == 0,
|
2002-12-03 08:48:14 +03:00
|
|
|
"How did we get destroyed when there are loading data?");
|
2013-09-02 12:41:57 +04:00
|
|
|
NS_ASSERTION(!mSheets || mSheets->mPendingDatas.Count() == 0,
|
2002-12-03 08:48:14 +03:00
|
|
|
"How did we get destroyed when there are pending data?");
|
2005-09-12 22:41:15 +04:00
|
|
|
// Note: no real need to revoke our stylesheet loaded events -- they
|
|
|
|
// hold strong references to us, so if we're going away that means
|
|
|
|
// they're all done.
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
void
|
|
|
|
Loader::DropDocumentReference(void)
|
1999-05-27 03:52:37 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
mDocument = nullptr;
|
2002-12-03 08:48:14 +03:00
|
|
|
// Flush out pending datas just so we don't leak by accident. These
|
|
|
|
// loads should short-circuit through the mDocument check in
|
|
|
|
// LoadSheet and just end up in SheetComplete immediately
|
2013-09-02 12:41:57 +04:00
|
|
|
if (mSheets) {
|
2007-05-31 05:42:48 +04:00
|
|
|
StartAlternateLoads();
|
|
|
|
}
|
2010-03-02 23:59:32 +03:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
|
|
|
Loader::SetPreferredSheet(const nsAString& aTitle)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2007-01-11 22:32:31 +03:00
|
|
|
#ifdef DEBUG
|
2011-05-26 12:18:43 +04:00
|
|
|
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
|
2007-01-11 22:32:31 +03:00
|
|
|
if (doc) {
|
|
|
|
nsAutoString currentPreferred;
|
|
|
|
doc->GetLastStyleSheetSet(currentPreferred);
|
|
|
|
if (DOMStringIsNull(currentPreferred)) {
|
|
|
|
doc->GetPreferredStyleSheetSet(currentPreferred);
|
|
|
|
}
|
|
|
|
NS_ASSERTION(currentPreferred.Equals(aTitle),
|
2011-05-06 19:45:36 +04:00
|
|
|
"Unexpected argument to SetPreferredSheet");
|
2007-01-11 22:32:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
2011-05-06 19:45:36 +04:00
|
|
|
|
1999-05-19 03:15:10 +04:00
|
|
|
mPreferredSheet = aTitle;
|
|
|
|
|
|
|
|
// start any pending alternates that aren't alternates anymore
|
2013-09-02 12:41:57 +04:00
|
|
|
if (mSheets) {
|
|
|
|
LoadDataArray arr(mSheets->mPendingDatas.Count());
|
2015-11-23 08:20:54 +03:00
|
|
|
for (auto iter = mSheets->mPendingDatas.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
SheetLoadData* data = iter.Data();
|
|
|
|
MOZ_ASSERT(data, "Must have a data");
|
|
|
|
|
|
|
|
// Note that we don't want to affect what the selected style set is, so
|
|
|
|
// use true for aHasAlternateRel.
|
|
|
|
if (!data->mLoader->IsAlternate(data->mTitle, true)) {
|
|
|
|
arr.AppendElement(data);
|
|
|
|
iter.Remove();
|
|
|
|
}
|
|
|
|
}
|
2007-05-31 05:42:48 +04:00
|
|
|
|
|
|
|
mDatasToNotifyOn += arr.Length();
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < arr.Length(); ++i) {
|
2007-05-31 05:42:48 +04:00
|
|
|
--mDatasToNotifyOn;
|
2015-09-21 00:56:10 +03:00
|
|
|
LoadSheet(arr[i], eSheetNeedsParser, false);
|
2007-05-31 05:42:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-05-19 03:15:10 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-11-12 06:36:20 +03:00
|
|
|
static const char kCharsetSym[] = "@charset \"";
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
static bool GetCharsetFromData(const char* aStyleSheetData,
|
|
|
|
uint32_t aDataLength,
|
|
|
|
nsACString& aCharset)
|
2002-08-28 03:47:25 +04:00
|
|
|
{
|
|
|
|
aCharset.Truncate();
|
|
|
|
if (aDataLength <= sizeof(kCharsetSym) - 1)
|
2012-11-15 12:47:30 +04:00
|
|
|
return false;
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
if (strncmp(aStyleSheetData,
|
|
|
|
kCharsetSym,
|
|
|
|
sizeof(kCharsetSym) - 1)) {
|
|
|
|
return false;
|
2002-08-28 03:47:25 +04:00
|
|
|
}
|
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
for (uint32_t i = sizeof(kCharsetSym) - 1; i < aDataLength; ++i) {
|
|
|
|
char c = aStyleSheetData[i];
|
|
|
|
if (c == '"') {
|
|
|
|
++i;
|
|
|
|
if (i < aDataLength && aStyleSheetData[i] == ';') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// fail
|
2002-08-28 03:47:25 +04:00
|
|
|
break;
|
|
|
|
}
|
2012-11-15 12:47:30 +04:00
|
|
|
aCharset.Append(c);
|
2002-08-28 03:47:25 +04:00
|
|
|
}
|
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
// Did not see end quote or semicolon
|
|
|
|
aCharset.Truncate();
|
|
|
|
return false;
|
2002-08-28 03:47:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
SheetLoadData::OnDetermineCharset(nsIUnicharStreamLoader* aLoader,
|
|
|
|
nsISupports* aContext,
|
2011-05-19 05:22:59 +04:00
|
|
|
nsACString const& aSegment,
|
2002-08-28 03:47:25 +04:00
|
|
|
nsACString& aCharset)
|
|
|
|
{
|
2009-04-10 18:29:08 +04:00
|
|
|
NS_PRECONDITION(!mOwningElement || mCharsetHint.IsEmpty(),
|
|
|
|
"Can't have element _and_ charset hint");
|
|
|
|
|
2004-01-13 22:01:26 +03:00
|
|
|
LOG_URI("SheetLoadData::OnDetermineCharset for '%s'", mURI);
|
2012-11-15 12:47:30 +04:00
|
|
|
|
|
|
|
// The precedence is (per CSS3 Syntax 2012-11-08 ED):
|
|
|
|
// BOM
|
|
|
|
// Channel
|
|
|
|
// @charset rule
|
|
|
|
// charset attribute on the referrer
|
|
|
|
// encoding of the referrer
|
|
|
|
// UTF-8
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2003-06-23 09:04:43 +04:00
|
|
|
aCharset.Truncate();
|
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
if (nsContentUtils::CheckForBOM((const unsigned char*)aSegment.BeginReading(),
|
|
|
|
aSegment.Length(),
|
|
|
|
aCharset)) {
|
2013-04-16 16:19:29 +04:00
|
|
|
// aCharset is now either "UTF-16BE", "UTF-16BE" or "UTF-8"
|
|
|
|
// which will swallow the BOM.
|
2012-11-15 12:47:30 +04:00
|
|
|
mCharset.Assign(aCharset);
|
|
|
|
LOG((" Setting from BOM to: %s", PromiseFlatCString(aCharset).get()));
|
|
|
|
return NS_OK;
|
2002-08-28 03:47:25 +04:00
|
|
|
}
|
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
nsCOMPtr<nsIChannel> channel;
|
|
|
|
nsAutoCString specified;
|
|
|
|
aLoader->GetChannel(getter_AddRefs(channel));
|
|
|
|
if (channel) {
|
|
|
|
channel->GetContentCharset(specified);
|
|
|
|
if (EncodingUtils::FindEncodingForLabel(specified, aCharset)) {
|
|
|
|
mCharset.Assign(aCharset);
|
|
|
|
LOG((" Setting from HTTP to: %s", PromiseFlatCString(aCharset).get()));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
if (GetCharsetFromData(aSegment.BeginReading(),
|
|
|
|
aSegment.Length(),
|
|
|
|
specified)) {
|
|
|
|
if (EncodingUtils::FindEncodingForLabel(specified, aCharset)) {
|
|
|
|
// FindEncodingForLabel currently never returns UTF-16LE but will
|
|
|
|
// probably change to never return UTF-16 instead, so check both here
|
|
|
|
// to avoid relying on the exact behavior.
|
|
|
|
if (aCharset.EqualsLiteral("UTF-16") ||
|
|
|
|
aCharset.EqualsLiteral("UTF-16BE") ||
|
|
|
|
aCharset.EqualsLiteral("UTF-16LE")) {
|
|
|
|
// Be consistent with HTML <meta> handling in face of impossibility.
|
|
|
|
// When the @charset rule itself evidently was not UTF-16-encoded,
|
|
|
|
// it saying UTF-16 has to be a lie.
|
|
|
|
aCharset.AssignLiteral("UTF-8");
|
|
|
|
}
|
|
|
|
mCharset.Assign(aCharset);
|
|
|
|
LOG((" Setting from @charset rule to: %s",
|
|
|
|
PromiseFlatCString(aCharset).get()));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-08-28 03:47:25 +04:00
|
|
|
}
|
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
// Now try the charset on the <link> or processing instruction
|
|
|
|
// that loaded us
|
|
|
|
if (mOwningElement) {
|
|
|
|
nsAutoString specified16;
|
|
|
|
mOwningElement->GetCharset(specified16);
|
|
|
|
if (EncodingUtils::FindEncodingForLabel(specified16, aCharset)) {
|
|
|
|
mCharset.Assign(aCharset);
|
|
|
|
LOG((" Setting from charset attribute to: %s",
|
|
|
|
PromiseFlatCString(aCharset).get()));
|
|
|
|
return NS_OK;
|
2002-08-28 03:47:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
// In the preload case, the value of the charset attribute on <link> comes
|
|
|
|
// in via mCharsetHint instead.
|
|
|
|
if (EncodingUtils::FindEncodingForLabel(mCharsetHint, aCharset)) {
|
|
|
|
mCharset.Assign(aCharset);
|
|
|
|
LOG((" Setting from charset attribute (preload case) to: %s",
|
|
|
|
PromiseFlatCString(aCharset).get()));
|
|
|
|
return NS_OK;
|
2004-01-13 22:01:26 +03:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
// Try charset from the parent stylesheet.
|
|
|
|
if (mParentData) {
|
|
|
|
aCharset = mParentData->mCharset;
|
|
|
|
if (!aCharset.IsEmpty()) {
|
|
|
|
mCharset.Assign(aCharset);
|
|
|
|
LOG((" Setting from parent sheet to: %s",
|
|
|
|
PromiseFlatCString(aCharset).get()));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
}
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
if (mLoader->mDocument) {
|
|
|
|
// no useful data on charset. Try the document charset.
|
|
|
|
aCharset = mLoader->mDocument->GetDocumentCharacterSet();
|
|
|
|
MOZ_ASSERT(!aCharset.IsEmpty());
|
|
|
|
mCharset.Assign(aCharset);
|
|
|
|
LOG((" Setting from document to: %s", PromiseFlatCString(aCharset).get()));
|
|
|
|
return NS_OK;
|
2002-08-28 03:47:25 +04:00
|
|
|
}
|
2004-01-13 22:01:26 +03:00
|
|
|
|
2012-11-15 12:47:30 +04:00
|
|
|
aCharset.AssignLiteral("UTF-8");
|
2004-01-13 22:01:26 +03:00
|
|
|
mCharset = aCharset;
|
2012-11-15 12:47:30 +04:00
|
|
|
LOG((" Setting from default to: %s", PromiseFlatCString(aCharset).get()));
|
2002-08-28 03:47:25 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-08-18 06:32:25 +04:00
|
|
|
already_AddRefed<nsIURI>
|
|
|
|
SheetLoadData::GetReferrerURI()
|
|
|
|
{
|
2010-05-13 00:18:47 +04:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
2004-08-18 06:32:25 +04:00
|
|
|
if (mParentData)
|
2010-05-13 00:18:47 +04:00
|
|
|
uri = mParentData->mSheet->GetSheetURI();
|
2004-08-18 06:32:25 +04:00
|
|
|
if (!uri && mLoader->mDocument)
|
2010-05-13 00:18:47 +04:00
|
|
|
uri = mLoader->mDocument->GetDocumentURI();
|
|
|
|
return uri.forget();
|
2004-08-18 06:32:25 +04:00
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/*
|
|
|
|
* Here we need to check that the load did not give us an http error
|
|
|
|
* page and check the mimetype on the channel to make sure we're not
|
|
|
|
* loading non-text/css data in standards mode.
|
|
|
|
*/
|
1999-11-02 09:49:44 +03:00
|
|
|
NS_IMETHODIMP
|
2002-08-28 03:47:25 +04:00
|
|
|
SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
2001-10-25 04:34:20 +04:00
|
|
|
nsISupports* aContext,
|
2000-02-03 02:04:47 +03:00
|
|
|
nsresult aStatus,
|
2011-05-19 05:22:59 +04:00
|
|
|
const nsAString& aBuffer)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
LOG(("SheetLoadData::OnStreamComplete"));
|
|
|
|
NS_ASSERTION(!mLoader->mSyncCallback, "Synchronous callback from necko");
|
|
|
|
|
|
|
|
if (mIsCancelled) {
|
|
|
|
// Just return. Don't call SheetComplete -- it's already been
|
|
|
|
// called and calling it again will lead to an extra NS_RELEASE on
|
|
|
|
// this data and a likely crash.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
if (!mLoader->mDocument && !mIsNonDocumentSheet) {
|
2002-12-03 08:48:14 +03:00
|
|
|
// Sorry, we don't care about this load anymore
|
2005-09-12 22:41:15 +04:00
|
|
|
LOG_WARN((" No document and not non-document sheet; dropping load"));
|
|
|
|
mLoader->SheetComplete(this, NS_BINDING_ABORTED);
|
2002-12-03 08:48:14 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2007-05-01 23:26:15 +04:00
|
|
|
if (NS_FAILED(aStatus)) {
|
2016-12-16 06:16:31 +03:00
|
|
|
LOG_WARN((" Load failed: status 0x%" PRIx32, static_cast<uint32_t>(aStatus)));
|
2014-08-09 02:16:34 +04:00
|
|
|
// Handle sheet not loading error because source was a tracking URL.
|
|
|
|
// We make a note of this sheet node by including it in a dedicated
|
|
|
|
// array of blocked tracking nodes under its parent document.
|
|
|
|
//
|
|
|
|
// Multiple sheet load instances might be tied to this request,
|
|
|
|
// we annotate each one linked to a valid owning element (node).
|
|
|
|
if (aStatus == NS_ERROR_TRACKING_URI) {
|
|
|
|
nsIDocument* doc = mLoader->GetDocument();
|
|
|
|
if (doc) {
|
|
|
|
for (SheetLoadData* data = this; data; data = data->mNext) {
|
|
|
|
// mOwningElement may be null but AddBlockTrackingNode can cope
|
|
|
|
nsCOMPtr<nsIContent> content = do_QueryInterface(data->mOwningElement);
|
|
|
|
doc->AddBlockedTrackingNode(content);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-01 23:26:15 +04:00
|
|
|
mLoader->SheetComplete(this, aStatus);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-08-28 03:47:25 +04:00
|
|
|
nsCOMPtr<nsIChannel> channel;
|
|
|
|
nsresult result = aLoader->GetChannel(getter_AddRefs(channel));
|
2007-05-01 23:26:15 +04:00
|
|
|
if (NS_FAILED(result)) {
|
|
|
|
LOG_WARN((" No channel from loader"));
|
|
|
|
mLoader->SheetComplete(this, result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2007-10-24 01:56:41 +04:00
|
|
|
nsCOMPtr<nsIURI> originalURI;
|
|
|
|
channel->GetOriginalURI(getter_AddRefs(originalURI));
|
|
|
|
|
2007-05-01 23:26:15 +04:00
|
|
|
// If the channel's original URI is "chrome:", we want that, since
|
|
|
|
// the observer code in nsXULPrototypeCache depends on chrome stylesheets
|
|
|
|
// having a chrome URI. (Whether or not chrome stylesheets come through
|
|
|
|
// this codepath seems nondeterministic.)
|
|
|
|
// Otherwise we want the potentially-HTTP-redirected URI.
|
2007-10-24 01:56:41 +04:00
|
|
|
nsCOMPtr<nsIURI> channelURI;
|
|
|
|
NS_GetFinalChannelURI(channel, getter_AddRefs(channelURI));
|
2007-05-01 23:26:15 +04:00
|
|
|
|
2007-10-24 01:56:41 +04:00
|
|
|
if (!channelURI || !originalURI) {
|
2007-05-01 23:26:15 +04:00
|
|
|
NS_ERROR("Someone just violated the nsIRequest contract");
|
|
|
|
LOG_WARN((" Channel without a URI. Bad!"));
|
|
|
|
mLoader->SheetComplete(this, NS_ERROR_UNEXPECTED);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrincipal> principal;
|
|
|
|
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
|
|
|
result = NS_ERROR_NOT_AVAILABLE;
|
|
|
|
if (secMan) { // Could be null if we already shut down
|
2011-05-19 05:22:59 +04:00
|
|
|
if (mUseSystemPrincipal) {
|
|
|
|
result = secMan->GetSystemPrincipal(getter_AddRefs(principal));
|
|
|
|
} else {
|
2014-08-07 03:05:40 +04:00
|
|
|
result = secMan->GetChannelResultPrincipal(channel, getter_AddRefs(principal));
|
2011-05-19 05:22:59 +04:00
|
|
|
}
|
2007-05-01 23:26:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(result)) {
|
|
|
|
LOG_WARN((" Couldn't get principal"));
|
|
|
|
mLoader->SheetComplete(this, result);
|
|
|
|
return NS_OK;
|
2003-07-18 04:35:49 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2007-05-01 23:26:15 +04:00
|
|
|
mSheet->SetPrincipal(principal);
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-06-18 06:46:11 +04:00
|
|
|
// If it's an HTTP channel, we want to make sure this is not an
|
|
|
|
// error document we got.
|
2002-08-28 03:47:25 +04:00
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
2002-06-18 06:46:11 +04:00
|
|
|
if (httpChannel) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool requestSucceeded;
|
2002-07-02 03:12:13 +04:00
|
|
|
result = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
|
|
|
if (NS_SUCCEEDED(result) && !requestSucceeded) {
|
2002-12-03 08:48:14 +03:00
|
|
|
LOG((" Load returned an error page"));
|
2005-09-12 22:41:15 +04:00
|
|
|
mLoader->SheetComplete(this, NS_ERROR_NOT_AVAILABLE);
|
2002-12-03 08:48:14 +03:00
|
|
|
return NS_OK;
|
2002-06-18 06:46:11 +04:00
|
|
|
}
|
|
|
|
}
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString contentType;
|
2009-12-23 21:01:51 +03:00
|
|
|
if (channel) {
|
|
|
|
channel->GetContentType(contentType);
|
|
|
|
}
|
|
|
|
|
|
|
|
// In standards mode, a style sheet must have one of these MIME
|
|
|
|
// types to be processed at all. In quirks mode, we accept any
|
|
|
|
// MIME type, but only if the style sheet is same-origin with the
|
|
|
|
// requesting document or parent sheet. See bug 524223.
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool validType = contentType.EqualsLiteral("text/css") ||
|
2009-12-23 21:01:51 +03:00
|
|
|
contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE) ||
|
|
|
|
contentType.IsEmpty();
|
|
|
|
|
|
|
|
if (!validType) {
|
|
|
|
const char *errorMessage;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t errorFlag;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool sameOrigin = true;
|
2009-12-23 21:01:51 +03:00
|
|
|
|
|
|
|
if (mLoaderPrincipal) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool subsumed;
|
2009-12-23 21:01:51 +03:00
|
|
|
result = mLoaderPrincipal->Subsumes(principal, &subsumed);
|
|
|
|
if (NS_FAILED(result) || !subsumed) {
|
2011-10-17 18:59:28 +04:00
|
|
|
sameOrigin = false;
|
2009-12-23 21:01:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sameOrigin && mLoader->mCompatMode == eCompatibility_NavQuirks) {
|
|
|
|
errorMessage = "MimeNotCssWarn";
|
|
|
|
errorFlag = nsIScriptError::warningFlag;
|
|
|
|
} else {
|
|
|
|
errorMessage = "MimeNotCss";
|
|
|
|
errorFlag = nsIScriptError::errorFlag;
|
|
|
|
}
|
|
|
|
|
2016-08-26 09:02:31 +03:00
|
|
|
const nsAFlatString& specUTF16 =
|
|
|
|
NS_ConvertUTF8toUTF16(channelURI->GetSpecOrDefault());
|
2009-12-23 21:01:51 +03:00
|
|
|
const nsAFlatString& ctypeUTF16 = NS_ConvertASCIItoUTF16(contentType);
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t *strings[] = { specUTF16.get(), ctypeUTF16.get() };
|
2009-12-23 21:01:51 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> referrer = GetReferrerURI();
|
2011-12-15 18:47:03 +04:00
|
|
|
nsContentUtils::ReportToConsole(errorFlag,
|
2013-08-21 23:28:26 +04:00
|
|
|
NS_LITERAL_CSTRING("CSS Loader"),
|
|
|
|
mLoader->mDocument,
|
2011-12-15 18:47:03 +04:00
|
|
|
nsContentUtils::eCSS_PROPERTIES,
|
2009-12-23 21:01:51 +03:00
|
|
|
errorMessage,
|
2011-10-11 09:50:08 +04:00
|
|
|
strings, ArrayLength(strings),
|
2011-12-15 18:47:03 +04:00
|
|
|
referrer);
|
2009-12-23 21:01:51 +03:00
|
|
|
|
|
|
|
if (errorFlag == nsIScriptError::errorFlag) {
|
|
|
|
LOG_WARN((" Ignoring sheet with improper MIME type %s",
|
|
|
|
contentType.get()));
|
|
|
|
mLoader->SheetComplete(this, NS_ERROR_NOT_AVAILABLE);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2005-09-12 22:41:15 +04:00
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
SRIMetadata sriMetadata;
|
|
|
|
mSheet->GetIntegrity(sriMetadata);
|
2016-03-16 06:13:26 +03:00
|
|
|
if (sriMetadata.IsEmpty()) {
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
2017-02-07 06:49:34 +03:00
|
|
|
if (loadInfo && loadInfo->GetEnforceSRI()) {
|
2016-03-16 06:13:26 +03:00
|
|
|
LOG((" Load was blocked by SRI"));
|
|
|
|
MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
|
|
|
|
("css::Loader::OnStreamComplete, required SRI not found"));
|
|
|
|
mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
|
2016-05-31 12:14:00 +03:00
|
|
|
// log the failed load to web console
|
|
|
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
|
|
|
loadInfo->LoadingPrincipal()->GetCsp(getter_AddRefs(csp));
|
|
|
|
nsAutoCString spec;
|
|
|
|
mLoader->mDocument->GetDocumentURI()->GetAsciiSpec(spec);
|
|
|
|
// line number unknown. mRequestingNode doesn't bear this info.
|
|
|
|
csp->LogViolationDetails(
|
|
|
|
nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_STYLE,
|
|
|
|
NS_ConvertUTF8toUTF16(spec), EmptyString(),
|
|
|
|
0, EmptyString(), EmptyString());
|
2016-03-16 06:13:26 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
} else {
|
2016-09-08 04:59:40 +03:00
|
|
|
nsAutoCString sourceUri;
|
|
|
|
if (mLoader->mDocument && mLoader->mDocument->GetDocumentURI()) {
|
|
|
|
mLoader->mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
|
|
|
|
}
|
|
|
|
nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader, aBuffer,
|
|
|
|
sourceUri, mLoader->mReporter);
|
2017-02-06 04:19:34 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
|
|
|
channel->GetLoadGroup(getter_AddRefs(loadGroup));
|
|
|
|
if (loadGroup) {
|
|
|
|
mLoader->mReporter->FlushConsoleReports(loadGroup);
|
|
|
|
} else {
|
|
|
|
mLoader->mReporter->FlushConsoleReports(mLoader->mDocument);
|
|
|
|
}
|
|
|
|
|
2016-03-16 06:13:26 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG((" Load was blocked by SRI"));
|
|
|
|
MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
|
|
|
|
("css::Loader::OnStreamComplete, bad metadata"));
|
|
|
|
mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-08-13 06:19:11 +03:00
|
|
|
}
|
|
|
|
|
2007-10-24 01:56:41 +04:00
|
|
|
// Enough to set the URIs on mSheet, since any sibling datas we have share
|
2007-05-01 23:26:15 +04:00
|
|
|
// the same mInner as mSheet and will thus get the same URI.
|
2007-10-24 01:56:41 +04:00
|
|
|
mSheet->SetURIs(channelURI, originalURI, channelURI);
|
2009-12-23 21:01:51 +03:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool completed;
|
2011-05-19 05:22:59 +04:00
|
|
|
result = mLoader->ParseSheet(aBuffer, this, completed);
|
|
|
|
NS_ASSERTION(completed || !mSyncLoad, "sync load did not complete");
|
|
|
|
return result;
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
|
|
|
Loader::IsAlternate(const nsAString& aTitle, bool aHasAlternateRel)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2005-09-12 22:41:15 +04:00
|
|
|
// A sheet is alternate if it has a nonempty title that doesn't match the
|
|
|
|
// currently selected style set. But if there _is_ no currently selected
|
|
|
|
// style set, the sheet wasn't marked as an alternate explicitly, and aTitle
|
|
|
|
// is nonempty, we should select the style set corresponding to aTitle, since
|
|
|
|
// that's a preferred sheet.
|
|
|
|
if (aTitle.IsEmpty()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
if (!aHasAlternateRel && mDocument && mPreferredSheet.IsEmpty()) {
|
|
|
|
// There's no preferred set yet, and we now have a sheet with a title.
|
|
|
|
// Make that be the preferred set.
|
2006-12-26 20:47:52 +03:00
|
|
|
mDocument->SetHeaderData(nsGkAtoms::headerDefaultStyle, aTitle);
|
2005-09-12 22:41:15 +04:00
|
|
|
// We're definitely not an alternate
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2005-09-12 22:41:15 +04:00
|
|
|
}
|
|
|
|
|
2007-01-11 22:32:31 +03:00
|
|
|
return !aTitle.Equals(mPreferredSheet);
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2013-07-16 01:28:33 +04:00
|
|
|
nsresult
|
|
|
|
Loader::ObsoleteSheet(nsIURI* aURI)
|
|
|
|
{
|
2013-09-02 12:41:57 +04:00
|
|
|
if (!mSheets) {
|
2013-07-16 01:28:33 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (!aURI) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
2015-11-23 08:20:54 +03:00
|
|
|
for (auto iter = mSheets->mCompleteSheets.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
nsIURI* sheetURI = iter.Key()->GetURI();
|
|
|
|
bool areEqual;
|
|
|
|
nsresult rv = sheetURI->Equals(aURI, &areEqual);
|
|
|
|
if (NS_SUCCEEDED(rv) && areEqual) {
|
|
|
|
iter.Remove();
|
|
|
|
}
|
|
|
|
}
|
2013-07-16 01:28:33 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-02-03 07:35:30 +03:00
|
|
|
nsresult
|
|
|
|
Loader::CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
|
|
|
|
nsIURI* aTargetURI,
|
|
|
|
nsISupports* aContext,
|
|
|
|
bool aIsPreload)
|
|
|
|
{
|
2016-02-05 22:07:04 +03:00
|
|
|
// When performing a system load (e.g. aUseSystemPrincipal = true)
|
|
|
|
// then aSourcePrincipal == null; don't consult content policies.
|
|
|
|
if (!aSourcePrincipal) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-02-03 07:35:30 +03:00
|
|
|
nsContentPolicyType contentPolicyType =
|
|
|
|
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
|
|
|
|
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
|
|
|
|
|
|
|
|
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
|
|
|
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
|
|
|
|
aTargetURI,
|
|
|
|
aSourcePrincipal,
|
|
|
|
aContext,
|
|
|
|
NS_LITERAL_CSTRING("text/css"),
|
|
|
|
nullptr, //extra param
|
|
|
|
&shouldLoad,
|
|
|
|
nsContentUtils::GetContentPolicy(),
|
|
|
|
nsContentUtils::GetSecurityManager());
|
|
|
|
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
|
|
|
return NS_ERROR_CONTENT_BLOCKED;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/**
|
2014-06-20 14:32:49 +04:00
|
|
|
* CreateSheet() creates a CSSStyleSheet object for the given URI,
|
2002-12-03 08:48:14 +03:00
|
|
|
* if any. If there is no URI given, we just create a new style sheet
|
|
|
|
* object. Otherwise, we check for an existing style sheet object for
|
|
|
|
* that uri in various caches and clone it if we find it. Cloned
|
|
|
|
* sheets will have the title/media/enabled state of the sheet they
|
|
|
|
* are clones off; make sure to call PrepareSheet() on the result of
|
|
|
|
* CreateSheet().
|
|
|
|
*/
|
1999-05-19 03:15:10 +04:00
|
|
|
nsresult
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::CreateSheet(nsIURI* aURI,
|
|
|
|
nsIContent* aLinkingContent,
|
|
|
|
nsIPrincipal* aLoaderPrincipal,
|
2016-08-02 23:12:27 +03:00
|
|
|
css::SheetParsingMode aParsingMode,
|
2012-08-28 21:10:08 +04:00
|
|
|
CORSMode aCORSMode,
|
2014-11-18 16:46:47 +03:00
|
|
|
ReferrerPolicy aReferrerPolicy,
|
2015-08-13 06:19:11 +03:00
|
|
|
const nsAString& aIntegrity,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aSyncLoad,
|
2011-11-08 08:41:17 +04:00
|
|
|
bool aHasAlternateRel,
|
2014-11-18 16:46:47 +03:00
|
|
|
const nsAString& aTitle,
|
2010-03-03 00:00:53 +03:00
|
|
|
StyleSheetState& aSheetState,
|
2011-11-08 08:41:17 +04:00
|
|
|
bool *aIsAlternate,
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet>* aSheet)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::CreateSheet"));
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aSheet, "Null out param!");
|
2003-07-27 19:20:11 +04:00
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
if (!mSheets) {
|
|
|
|
mSheets = new Sheets();
|
2012-05-18 21:30:49 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
*aSheet = nullptr;
|
2002-12-03 08:48:14 +03:00
|
|
|
aSheetState = eSheetStateUnknown;
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2011-11-08 08:41:17 +04:00
|
|
|
// Check the alternate state before doing anything else, because it
|
|
|
|
// can mess with our hashtables.
|
|
|
|
*aIsAlternate = IsAlternate(aTitle, aHasAlternateRel);
|
|
|
|
|
2017-02-22 01:05:24 +03:00
|
|
|
if (aURI) {
|
2002-12-03 08:48:14 +03:00
|
|
|
aSheetState = eSheetComplete;
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet> sheet;
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2002-12-11 03:28:47 +03:00
|
|
|
// First, the XUL cache
|
2003-04-11 04:56:27 +04:00
|
|
|
#ifdef MOZ_XUL
|
2017-02-15 01:44:37 +03:00
|
|
|
// The XUL cache is a singleton that only holds Gecko-style sheets, so
|
|
|
|
// only use the cache if the loader is also Gecko.
|
|
|
|
if (IsChromeURI(aURI) &&
|
|
|
|
GetStyleBackendType() == StyleBackendType::Gecko) {
|
2007-03-12 08:53:33 +03:00
|
|
|
nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
|
2016-06-08 22:03:31 +03:00
|
|
|
if (cache) {
|
|
|
|
if (cache->IsEnabled()) {
|
|
|
|
sheet = cache->GetStyleSheet(aURI);
|
2016-09-26 15:03:25 +03:00
|
|
|
LOG((" From XUL cache: %p", sheet.get()));
|
2016-06-08 22:03:31 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-04-24 22:59:14 +04:00
|
|
|
bool fromCompleteSheets = false;
|
2002-12-03 08:48:14 +03:00
|
|
|
if (!sheet) {
|
2008-10-21 00:33:03 +04:00
|
|
|
// Then our per-document complete sheets.
|
2014-11-18 16:46:47 +03:00
|
|
|
URIPrincipalReferrerPolicyAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* completeSheet = nullptr;
|
2016-02-24 10:01:12 +03:00
|
|
|
mSheets->mCompleteSheets.Get(&key, &completeSheet);
|
|
|
|
sheet = completeSheet;
|
2016-09-26 15:03:25 +03:00
|
|
|
LOG((" From completed: %p", sheet.get()));
|
2013-04-24 22:59:14 +04:00
|
|
|
|
|
|
|
fromCompleteSheets = !!sheet;
|
2008-10-21 00:33:03 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2008-10-21 00:33:03 +04:00
|
|
|
if (sheet) {
|
|
|
|
// This sheet came from the XUL cache or our per-document hashtable; it
|
|
|
|
// better be a complete sheet.
|
2017-02-22 01:05:24 +03:00
|
|
|
NS_ASSERTION(sheet->IsComplete(),
|
2008-10-21 00:33:03 +04:00
|
|
|
"Sheet thinks it's not complete while we think it is");
|
2010-05-14 23:05:14 +04:00
|
|
|
|
2008-10-21 00:33:03 +04:00
|
|
|
// Make sure it hasn't been modified; if it has, we can't use it
|
2017-02-22 01:05:24 +03:00
|
|
|
if (sheet->IsModified()) {
|
2008-10-21 00:33:03 +04:00
|
|
|
LOG((" Not cloning completed sheet %p because it's been modified",
|
2016-09-26 15:03:25 +03:00
|
|
|
sheet.get()));
|
2012-07-30 18:20:58 +04:00
|
|
|
sheet = nullptr;
|
2013-05-23 17:20:52 +04:00
|
|
|
fromCompleteSheets = false;
|
2008-10-21 00:33:03 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then loading sheets
|
|
|
|
if (!sheet && !aSyncLoad) {
|
|
|
|
aSheetState = eSheetLoading;
|
2012-07-30 18:20:58 +04:00
|
|
|
SheetLoadData* loadData = nullptr;
|
2014-11-18 16:46:47 +03:00
|
|
|
URIPrincipalReferrerPolicyAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mLoadingDatas.Get(&key, &loadData);
|
2008-10-21 00:33:03 +04:00
|
|
|
if (loadData) {
|
|
|
|
sheet = loadData->mSheet;
|
2016-09-26 15:03:25 +03:00
|
|
|
LOG((" From loading: %p", sheet.get()));
|
2008-10-21 00:33:03 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2011-09-29 10:19:26 +04:00
|
|
|
bool debugEqual;
|
2008-10-21 00:33:03 +04:00
|
|
|
NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
|
|
|
|
(aLoaderPrincipal && loadData->mLoaderPrincipal &&
|
|
|
|
NS_SUCCEEDED(aLoaderPrincipal->
|
|
|
|
Equals(loadData->mLoaderPrincipal,
|
|
|
|
&debugEqual)) && debugEqual),
|
|
|
|
"Principals should be the same");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then alternate sheets
|
|
|
|
if (!sheet) {
|
|
|
|
aSheetState = eSheetPending;
|
2013-02-18 10:56:32 +04:00
|
|
|
loadData = nullptr;
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mPendingDatas.Get(&key, &loadData);
|
2002-12-11 03:28:47 +03:00
|
|
|
if (loadData) {
|
|
|
|
sheet = loadData->mSheet;
|
2016-09-26 15:03:25 +03:00
|
|
|
LOG((" From pending: %p", sheet.get()));
|
2007-05-01 23:26:15 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2011-09-29 10:19:26 +04:00
|
|
|
bool debugEqual;
|
2007-05-01 23:26:15 +04:00
|
|
|
NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
|
|
|
|
(aLoaderPrincipal && loadData->mLoaderPrincipal &&
|
|
|
|
NS_SUCCEEDED(aLoaderPrincipal->
|
2008-10-21 00:33:03 +04:00
|
|
|
Equals(loadData->mLoaderPrincipal,
|
|
|
|
&debugEqual)) && debugEqual),
|
2007-05-01 23:26:15 +04:00
|
|
|
"Principals should be the same");
|
|
|
|
#endif
|
2002-12-11 03:28:47 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sheet) {
|
2008-10-21 00:33:03 +04:00
|
|
|
// The sheet we have now should be either incomplete or unmodified
|
2017-02-22 01:05:24 +03:00
|
|
|
NS_ASSERTION(!sheet->IsModified() ||
|
|
|
|
!sheet->IsComplete(),
|
2008-10-21 00:33:03 +04:00
|
|
|
"Unexpected modified complete sheet");
|
2017-02-22 01:05:24 +03:00
|
|
|
NS_ASSERTION(sheet->IsComplete() ||
|
2016-02-24 10:01:12 +03:00
|
|
|
aSheetState != eSheetComplete,
|
2008-10-21 00:33:03 +04:00
|
|
|
"Sheet thinks it's not complete while we think it is");
|
2010-05-14 23:05:14 +04:00
|
|
|
|
2017-02-16 00:33:17 +03:00
|
|
|
RefPtr<StyleSheet> clonedSheet =
|
|
|
|
sheet->Clone(nullptr, nullptr, nullptr, nullptr);
|
2016-02-24 10:01:12 +03:00
|
|
|
*aSheet = Move(clonedSheet);
|
2013-04-24 22:59:14 +04:00
|
|
|
if (*aSheet && fromCompleteSheets &&
|
2017-02-22 01:05:24 +03:00
|
|
|
!sheet->GetOwnerNode() &&
|
|
|
|
!sheet->GetParentSheet()) {
|
2016-06-08 22:03:31 +03:00
|
|
|
// The sheet we're cloning isn't actually referenced by
|
|
|
|
// anyone. Replace it in the cache, so that if our CSSOM is
|
|
|
|
// later modified we don't end up with two copies of our inner
|
|
|
|
// hanging around.
|
|
|
|
URIPrincipalReferrerPolicyAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
|
2017-02-22 01:05:24 +03:00
|
|
|
NS_ASSERTION((*aSheet)->IsComplete(),
|
2016-06-08 22:03:31 +03:00
|
|
|
"Should only be caching complete sheets");
|
|
|
|
mSheets->mCompleteSheets.Put(&key, *aSheet);
|
2013-04-24 22:59:14 +04:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
if (!*aSheet) {
|
|
|
|
aSheetState = eSheetNeedsParser;
|
2007-10-24 01:56:41 +04:00
|
|
|
nsIURI *sheetURI;
|
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
|
|
|
nsIURI* originalURI;
|
2004-09-10 10:45:59 +04:00
|
|
|
if (!aURI) {
|
2003-10-06 17:24:55 +04:00
|
|
|
// Inline style. Use the document's base URL so that @import in
|
|
|
|
// the inline sheet picks up the right base.
|
|
|
|
NS_ASSERTION(aLinkingContent, "Inline stylesheet without linking content?");
|
2004-09-10 10:45:59 +04:00
|
|
|
baseURI = aLinkingContent->GetBaseURI();
|
2014-06-07 12:42:54 +04:00
|
|
|
sheetURI = aLinkingContent->OwnerDoc()->GetDocumentURI();
|
2012-07-30 18:20:58 +04:00
|
|
|
originalURI = nullptr;
|
2007-10-24 01:56:41 +04:00
|
|
|
} else {
|
|
|
|
baseURI = aURI;
|
|
|
|
sheetURI = aURI;
|
|
|
|
originalURI = aURI;
|
2003-10-06 17:24:55 +04:00
|
|
|
}
|
|
|
|
|
2015-08-13 06:19:11 +03:00
|
|
|
SRIMetadata sriMetadata;
|
|
|
|
if (!aIntegrity.IsEmpty()) {
|
2015-11-06 01:35:03 +03:00
|
|
|
MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
|
2015-08-13 06:19:11 +03:00
|
|
|
("css::Loader::CreateSheet, integrity=%s",
|
|
|
|
NS_ConvertUTF16toUTF8(aIntegrity).get()));
|
2016-09-08 04:59:40 +03:00
|
|
|
nsAutoCString sourceUri;
|
|
|
|
if (mDocument && mDocument->GetDocumentURI()) {
|
|
|
|
mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
|
|
|
|
}
|
|
|
|
SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter,
|
|
|
|
&sriMetadata);
|
2015-08-13 06:19:11 +03:00
|
|
|
}
|
|
|
|
|
2016-02-26 04:51:02 +03:00
|
|
|
if (GetStyleBackendType() == StyleBackendType::Gecko) {
|
2016-08-02 23:12:27 +03:00
|
|
|
*aSheet = new CSSStyleSheet(aParsingMode, aCORSMode, aReferrerPolicy, sriMetadata);
|
2016-02-26 04:51:02 +03:00
|
|
|
} else {
|
2016-08-02 23:12:27 +03:00
|
|
|
*aSheet = new ServoStyleSheet(aParsingMode, aCORSMode, aReferrerPolicy, sriMetadata);
|
2016-02-26 04:51:02 +03:00
|
|
|
}
|
2016-02-24 10:01:12 +03:00
|
|
|
(*aSheet)->SetURIs(sheetURI, originalURI, baseURI);
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(*aSheet, "We should have a sheet by now!");
|
|
|
|
NS_ASSERTION(aSheetState != eSheetStateUnknown, "Have to set a state!");
|
|
|
|
LOG((" State: %s", gStateStrings[aSheetState]));
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
return NS_OK;
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/**
|
|
|
|
* PrepareSheet() handles setting the media and title on the sheet, as
|
2005-09-12 22:41:15 +04:00
|
|
|
* well as setting the enabled state based on the title and whether
|
|
|
|
* the sheet had "alternate" in its rel.
|
2002-12-03 08:48:14 +03:00
|
|
|
*/
|
2013-11-11 11:57:53 +04:00
|
|
|
void
|
2016-09-26 15:03:25 +03:00
|
|
|
Loader::PrepareSheet(StyleSheet* aSheet,
|
2010-03-03 00:00:53 +03:00
|
|
|
const nsSubstring& aTitle,
|
|
|
|
const nsSubstring& aMediaString,
|
|
|
|
nsMediaList* aMediaList,
|
2013-01-09 03:25:47 +04:00
|
|
|
Element* aScopeElement,
|
2017-01-06 10:05:24 +03:00
|
|
|
bool aIsAlternate)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aSheet, "Must have a sheet!");
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsMediaList> mediaList(aMediaList);
|
2005-03-30 04:36:57 +04:00
|
|
|
|
|
|
|
if (!aMediaString.IsEmpty()) {
|
|
|
|
NS_ASSERTION(!aMediaList,
|
|
|
|
"must not provide both aMediaString and aMediaList");
|
|
|
|
mediaList = new nsMediaList();
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
nsCSSParser mediumParser(this);
|
|
|
|
|
2005-03-30 04:36:57 +04:00
|
|
|
// We have aMediaString only when linked from link elements, style
|
2011-10-17 18:59:28 +04:00
|
|
|
// elements, or PIs, so pass true.
|
2016-12-11 21:27:33 +03:00
|
|
|
mediumParser.ParseMediaList(aMediaString, nullptr, 0, mediaList);
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
2005-03-30 04:36:57 +04:00
|
|
|
|
2017-01-06 10:05:24 +03:00
|
|
|
aSheet->SetMedia(mediaList);
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2017-01-06 10:05:24 +03:00
|
|
|
aSheet->SetTitle(aTitle);
|
2017-01-06 10:05:24 +03:00
|
|
|
aSheet->SetEnabled(!aIsAlternate);
|
2017-01-06 10:05:24 +03:00
|
|
|
|
|
|
|
if (aSheet->IsGecko()) {
|
|
|
|
aSheet->AsGecko()->SetScopeElement(aScopeElement);
|
|
|
|
} else {
|
|
|
|
if (aScopeElement) {
|
|
|
|
NS_WARNING("stylo: scoped style sheets not supported");
|
|
|
|
}
|
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/**
|
|
|
|
* InsertSheetInDoc handles ordering of sheets in the document. Here
|
|
|
|
* we have two types of sheets -- those with linking elements and
|
|
|
|
* those without. The latter are loaded by Link: headers.
|
|
|
|
* The following constraints are observed:
|
|
|
|
* 1) Any sheet with a linking element comes after all sheets without
|
|
|
|
* linking elements
|
|
|
|
* 2) Sheets without linking elements are inserted in the order in
|
|
|
|
* which the inserting requests come in, since all of these are
|
|
|
|
* inserted during header data processing in the content sink
|
|
|
|
* 3) Sheets with linking elements are ordered based on document order
|
2002-12-04 08:18:39 +03:00
|
|
|
* as determined by CompareDocumentPosition.
|
2002-12-03 08:48:14 +03:00
|
|
|
*/
|
|
|
|
nsresult
|
2016-09-26 15:03:25 +03:00
|
|
|
Loader::InsertSheetInDoc(StyleSheet* aSheet,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsIContent* aLinkingContent,
|
|
|
|
nsIDocument* aDocument)
|
2002-12-03 08:48:14 +03:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::InsertSheetInDoc"));
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aSheet, "Nothing to insert");
|
|
|
|
NS_PRECONDITION(aDocument, "Must have a document to insert into");
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// XXX Need to cancel pending sheet loads for this element, if any
|
2001-10-31 22:03:46 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t sheetCount = aDocument->GetNumberOfStyleSheets();
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Start the walk at the _end_ of the list, since in the typical
|
|
|
|
* case we'll just want to append anyway. We want to break out of
|
|
|
|
* the loop when insertionPoint points to just before the index we
|
|
|
|
* want to insert at. In other words, when we leave the loop
|
|
|
|
* insertionPoint is the index of the stylesheet that immediately
|
|
|
|
* precedes the one we're inserting.
|
|
|
|
*/
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t insertionPoint;
|
2002-12-03 08:48:14 +03:00
|
|
|
for (insertionPoint = sheetCount - 1; insertionPoint >= 0; --insertionPoint) {
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* curSheet = aDocument->GetStyleSheetAt(insertionPoint);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ASSERTION(curSheet, "There must be a sheet here!");
|
2016-02-24 10:01:12 +03:00
|
|
|
nsCOMPtr<nsINode> sheetOwner = curSheet->GetOwnerNode();
|
2006-05-16 19:50:47 +04:00
|
|
|
if (sheetOwner && !aLinkingContent) {
|
2002-12-03 08:48:14 +03:00
|
|
|
// Keep moving; all sheets with a sheetOwner come after all
|
2011-05-06 19:45:36 +04:00
|
|
|
// sheets without a linkingNode
|
2002-12-03 08:48:14 +03:00
|
|
|
continue;
|
2001-10-31 22:03:46 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
if (!sheetOwner) {
|
|
|
|
// Aha! The current sheet has no sheet owner, so we want to
|
|
|
|
// insert after it no matter whether we have a linkingNode
|
|
|
|
break;
|
2001-10-31 22:03:46 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
NS_ASSERTION(aLinkingContent != sheetOwner,
|
2006-05-16 19:50:47 +04:00
|
|
|
"Why do we still have our old sheet?");
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// Have to compare
|
2016-02-24 10:01:12 +03:00
|
|
|
if (nsContentUtils::PositionIsBefore(sheetOwner, aLinkingContent)) {
|
2002-12-03 08:48:14 +03:00
|
|
|
// The current sheet comes before us, and it better be the first
|
|
|
|
// such, because now we break
|
|
|
|
break;
|
2001-10-31 22:03:46 +03:00
|
|
|
}
|
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
++insertionPoint; // adjust the index to the spot we want to insert in
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// XXX <meta> elements do not implement nsIStyleSheetLinkingElement;
|
|
|
|
// need to fix this for them to be ordered correctly.
|
|
|
|
nsCOMPtr<nsIStyleSheetLinkingElement>
|
2003-07-03 06:45:34 +04:00
|
|
|
linkingElement = do_QueryInterface(aLinkingContent);
|
2002-12-03 08:48:14 +03:00
|
|
|
if (linkingElement) {
|
|
|
|
linkingElement->SetStyleSheet(aSheet); // This sets the ownerNode on the sheet
|
|
|
|
}
|
|
|
|
|
2003-10-03 01:29:40 +04:00
|
|
|
aDocument->BeginUpdate(UPDATE_STYLE);
|
2002-12-03 08:48:14 +03:00
|
|
|
aDocument->InsertStyleSheetAt(aSheet, insertionPoint);
|
2003-10-03 01:29:40 +04:00
|
|
|
aDocument->EndUpdate(UPDATE_STYLE);
|
2002-12-03 08:48:14 +03:00
|
|
|
LOG((" Inserting into document at position %d", insertionPoint));
|
|
|
|
|
|
|
|
return NS_OK;
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/**
|
|
|
|
* InsertChildSheet handles ordering of @import-ed sheet in their
|
|
|
|
* parent sheets. Here we want to just insert based on order of the
|
|
|
|
* @import rules that imported the sheets. In theory we can't just
|
|
|
|
* append to the end because the CSSOM can insert @import rules. In
|
|
|
|
* practice, we get the call to load the child sheet before the CSSOM
|
|
|
|
* has finished inserting the @import rule, so we have no idea where
|
2015-11-05 11:02:59 +03:00
|
|
|
* to put it anyway. So just append for now. (In the future if we
|
|
|
|
* want to insert the sheet at the correct position, we'll need to
|
|
|
|
* restore CSSStyleSheet::InsertStyleSheetAt, which was removed in
|
|
|
|
* bug 1220506.)
|
2002-12-03 08:48:14 +03:00
|
|
|
*/
|
1999-05-19 03:15:10 +04:00
|
|
|
nsresult
|
2016-09-26 15:03:25 +03:00
|
|
|
Loader::InsertChildSheet(StyleSheet* aSheet,
|
|
|
|
StyleSheet* aParentSheet,
|
2016-12-17 12:58:56 +03:00
|
|
|
ImportRule* aGeckoParentRule,
|
2016-12-29 20:33:47 +03:00
|
|
|
const RawServoImportRule* aServoParentRule)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::InsertChildSheet"));
|
2016-12-17 12:58:56 +03:00
|
|
|
MOZ_ASSERT(aSheet, "Nothing to insert");
|
|
|
|
MOZ_ASSERT(aParentSheet, "Need a parent to insert into");
|
|
|
|
MOZ_ASSERT_IF(aSheet->IsGecko(), aGeckoParentRule && !aServoParentRule);
|
|
|
|
MOZ_ASSERT_IF(aSheet->IsServo(), aServoParentRule && !aGeckoParentRule);
|
|
|
|
if (aSheet->IsGecko()) {
|
|
|
|
// child sheets should always start out enabled, even if they got
|
|
|
|
// cloned off of top-level sheets which were disabled
|
|
|
|
aSheet->AsGecko()->SetEnabled(true);
|
|
|
|
aGeckoParentRule->SetSheet(aSheet->AsGecko()); // This sets the ownerRule on the sheet
|
|
|
|
} else {
|
2017-02-22 01:05:24 +03:00
|
|
|
// No matter what, consume the sheet, but we might not use it.
|
2016-12-17 12:58:56 +03:00
|
|
|
RefPtr<RawServoStyleSheet> sheet =
|
|
|
|
Servo_ImportRule_GetSheet(aServoParentRule).Consume();
|
2017-02-22 01:05:24 +03:00
|
|
|
if (!aSheet->AsServo()->RawSheet()) {
|
|
|
|
aSheet->AsServo()->SetSheetForImport(sheet);
|
|
|
|
}
|
2016-02-24 10:01:12 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
aParentSheet->AppendStyleSheet(aSheet);
|
|
|
|
|
|
|
|
LOG((" Inserting into parent sheet"));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* LoadSheet handles the actual load of a sheet. If the load is
|
|
|
|
* supposed to be synchronous it just opens a channel synchronously
|
|
|
|
* using the given uri, wraps the resulting stream in a converter
|
|
|
|
* stream and calls ParseSheet. Otherwise it tries to look for an
|
|
|
|
* existing load for this URI and piggyback on it. Failing all that,
|
|
|
|
* a new load is kicked off asynchronously.
|
|
|
|
*/
|
|
|
|
nsresult
|
2015-09-21 00:56:10 +03:00
|
|
|
Loader::LoadSheet(SheetLoadData* aLoadData,
|
|
|
|
StyleSheetState aSheetState,
|
|
|
|
bool aIsPreload)
|
2002-12-03 08:48:14 +03:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::LoadSheet"));
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aLoadData, "Need a load data");
|
|
|
|
NS_PRECONDITION(aLoadData->mURI, "Need a URI to load");
|
|
|
|
NS_PRECONDITION(aLoadData->mSheet, "Need a sheet to load into");
|
|
|
|
NS_PRECONDITION(aSheetState != eSheetComplete, "Why bother?");
|
2009-03-17 04:38:36 +03:00
|
|
|
NS_PRECONDITION(!aLoadData->mUseSystemPrincipal || aLoadData->mSyncLoad,
|
|
|
|
"Shouldn't use system principal for async loads");
|
2013-09-02 12:41:57 +04:00
|
|
|
NS_ASSERTION(mSheets, "mLoadingDatas should be initialized by now.");
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
LOG_URI(" Load from: '%s'", aLoadData->mURI);
|
2011-05-06 19:45:36 +04:00
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
if (!mDocument && !aLoadData->mIsNonDocumentSheet) {
|
2002-12-03 08:48:14 +03:00
|
|
|
// No point starting the load; just release all the data and such.
|
2005-09-12 22:41:15 +04:00
|
|
|
LOG_WARN((" No document and not non-document sheet; pre-dropping load"));
|
|
|
|
SheetComplete(aLoadData, NS_BINDING_ABORTED);
|
|
|
|
return NS_BINDING_ABORTED;
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
SRIMetadata sriMetadata;
|
|
|
|
aLoadData->mSheet->GetIntegrity(sriMetadata);
|
2015-08-13 06:19:11 +03:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (aLoadData->mSyncLoad) {
|
|
|
|
LOG((" Synchronous load"));
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_ASSERTION(!aLoadData->mObserver, "Observer for a sync load?");
|
2002-12-11 03:28:47 +03:00
|
|
|
NS_ASSERTION(aSheetState == eSheetNeedsParser,
|
|
|
|
"Sync loads can't reuse existing async loads");
|
2003-07-18 04:35:49 +04:00
|
|
|
|
2011-05-19 05:22:59 +04:00
|
|
|
// Create a nsIUnicharStreamLoader instance to which we will feed
|
|
|
|
// the data from the sync load. Do this before creating the
|
|
|
|
// channel to make error recovery simpler.
|
|
|
|
nsCOMPtr<nsIUnicharStreamLoader> streamLoader;
|
|
|
|
rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader), aLoadData);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG_ERROR((" Failed to create stream loader for sync load"));
|
|
|
|
SheetComplete(aLoadData, rv);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-10-26 01:56:56 +04:00
|
|
|
if (mDocument) {
|
2014-06-04 00:37:46 +04:00
|
|
|
mozilla::net::PredictorLearn(aLoadData->mURI, mDocument->GetDocumentURI(),
|
|
|
|
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE,
|
|
|
|
mDocument);
|
2013-10-26 01:56:56 +04:00
|
|
|
}
|
|
|
|
|
2016-02-03 07:35:02 +03:00
|
|
|
nsSecurityFlags securityFlags =
|
|
|
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
|
|
|
nsILoadInfo::SEC_ALLOW_CHROME;
|
|
|
|
|
|
|
|
nsContentPolicyType contentPolicyType =
|
|
|
|
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
|
|
|
|
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
|
|
|
|
|
2002-12-11 03:28:47 +03:00
|
|
|
// Just load it
|
2007-05-01 23:26:15 +04:00
|
|
|
nsCOMPtr<nsIChannel> channel;
|
2015-01-12 07:26:40 +03:00
|
|
|
// Note that we are calling NS_NewChannelWithTriggeringPrincipal() with both
|
|
|
|
// a node and a principal.
|
|
|
|
// This is because of a case where the node is the document being styled and
|
|
|
|
// the principal is the stylesheet (perhaps from a different origin) that is
|
|
|
|
// applying the styles.
|
2016-02-05 22:07:04 +03:00
|
|
|
if (aLoadData->mRequestingNode && aLoadData->mLoaderPrincipal) {
|
2015-01-12 07:26:40 +03:00
|
|
|
rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
|
|
|
|
aLoadData->mURI,
|
|
|
|
aLoadData->mRequestingNode,
|
2016-02-05 22:07:04 +03:00
|
|
|
aLoadData->mLoaderPrincipal,
|
2016-02-03 07:35:02 +03:00
|
|
|
securityFlags,
|
|
|
|
contentPolicyType);
|
2014-11-14 19:56:55 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// either we are loading something inside a document, in which case
|
|
|
|
// we should always have a requestingNode, or we are loading something
|
2016-02-05 22:07:04 +03:00
|
|
|
// outside a document, in which case the loadingPrincipal and the
|
|
|
|
// triggeringPrincipal should always be the systemPrincipal.
|
2015-01-12 07:26:40 +03:00
|
|
|
rv = NS_NewChannel(getter_AddRefs(channel),
|
|
|
|
aLoadData->mURI,
|
2016-02-05 22:07:04 +03:00
|
|
|
nsContentUtils::GetSystemPrincipal(),
|
2016-02-03 07:35:02 +03:00
|
|
|
securityFlags,
|
|
|
|
contentPolicyType);
|
|
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG_ERROR((" Failed to create channel"));
|
|
|
|
SheetComplete(aLoadData, rv);
|
|
|
|
return rv;
|
2014-11-14 19:56:55 +03:00
|
|
|
}
|
2015-01-12 07:26:40 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
2016-02-03 07:35:02 +03:00
|
|
|
rv = channel->Open2(getter_AddRefs(stream));
|
2014-09-21 20:41:26 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG_ERROR((" Failed to open URI synchronously"));
|
2005-09-12 22:41:15 +04:00
|
|
|
SheetComplete(aLoadData, rv);
|
2002-12-03 08:48:14 +03:00
|
|
|
return rv;
|
2001-10-31 22:03:46 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2011-05-19 05:22:59 +04:00
|
|
|
// Force UA sheets to be UTF-8.
|
|
|
|
// XXX this is only necessary because the default in
|
|
|
|
// SheetLoadData::OnDetermineCharset is wrong (bug 521039).
|
|
|
|
channel->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
|
|
|
|
|
2015-01-12 07:26:40 +03:00
|
|
|
// Manually feed the streamloader the contents of the stream.
|
|
|
|
// This will call back into OnStreamComplete
|
2011-05-19 05:22:59 +04:00
|
|
|
// and thence to ParseSheet. Regardless of whether this fails,
|
|
|
|
// SheetComplete has been called.
|
|
|
|
return nsSyncLoadService::PushSyncStreamToListener(stream,
|
|
|
|
streamLoader,
|
|
|
|
channel);
|
2001-10-31 22:03:46 +03:00
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
SheetLoadData* existingData = nullptr;
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2014-11-18 16:46:47 +03:00
|
|
|
URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData->mURI,
|
2012-08-28 21:10:08 +04:00
|
|
|
aLoadData->mLoaderPrincipal,
|
2014-11-18 16:46:47 +03:00
|
|
|
aLoadData->mSheet->GetCORSMode(),
|
|
|
|
aLoadData->mSheet->GetReferrerPolicy());
|
2002-12-03 08:48:14 +03:00
|
|
|
if (aSheetState == eSheetLoading) {
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mLoadingDatas.Get(&key, &existingData);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ASSERTION(existingData, "CreateSheet lied about the state");
|
|
|
|
}
|
|
|
|
else if (aSheetState == eSheetPending){
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mPendingDatas.Get(&key, &existingData);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ASSERTION(existingData, "CreateSheet lied about the state");
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (existingData) {
|
|
|
|
LOG((" Glomming on to existing load"));
|
|
|
|
SheetLoadData* data = existingData;
|
|
|
|
while (data->mNext) {
|
|
|
|
data = data->mNext;
|
2001-10-31 22:03:46 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
data->mNext = aLoadData; // transfer ownership
|
2005-09-12 22:41:15 +04:00
|
|
|
if (aSheetState == eSheetPending && !aLoadData->mWasAlternate) {
|
2002-12-03 08:48:14 +03:00
|
|
|
// Kick the load off; someone cares about it right away
|
2003-07-27 19:20:11 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
#ifdef DEBUG
|
2003-07-27 19:20:11 +04:00
|
|
|
SheetLoadData* removedData;
|
2013-09-02 12:41:57 +04:00
|
|
|
NS_ASSERTION(mSheets->mPendingDatas.Get(&key, &removedData) &&
|
2003-07-27 19:20:11 +04:00
|
|
|
removedData == existingData,
|
|
|
|
"Bad pending table.");
|
2002-12-03 08:48:14 +03:00
|
|
|
#endif
|
2003-07-27 19:20:11 +04:00
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mPendingDatas.Remove(&key);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
LOG((" Forcing load of pending data"));
|
2015-09-21 00:56:10 +03:00
|
|
|
return LoadSheet(existingData, eSheetNeedsParser, aIsPreload);
|
2001-10-31 22:03:46 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
// All done here; once the load completes we'll be marked complete
|
|
|
|
// automatically
|
2001-10-31 22:03:46 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
|
|
|
if (mDocument) {
|
2003-10-22 10:09:48 +04:00
|
|
|
loadGroup = mDocument->GetDocumentLoadGroup();
|
2016-02-03 07:35:02 +03:00
|
|
|
// load for a document with no loadgrup indicates that something is
|
|
|
|
// completely bogus, let's bail out early.
|
|
|
|
if (!loadGroup) {
|
|
|
|
LOG_ERROR((" Failed to query loadGroup from document"));
|
|
|
|
SheetComplete(aLoadData, NS_ERROR_UNEXPECTED);
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
2016-02-03 07:35:02 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
mSyncCallback = true;
|
|
|
|
#endif
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2016-02-03 07:35:02 +03:00
|
|
|
CORSMode ourCORSMode = aLoadData->mSheet->GetCORSMode();
|
|
|
|
nsSecurityFlags securityFlags =
|
|
|
|
ourCORSMode == CORS_NONE
|
|
|
|
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS
|
|
|
|
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
|
|
|
|
if (ourCORSMode == CORS_ANONYMOUS) {
|
|
|
|
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
|
|
|
|
} else if (ourCORSMode == CORS_USE_CREDENTIALS) {
|
|
|
|
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
|
2014-09-21 20:41:26 +04:00
|
|
|
}
|
2016-02-03 07:35:02 +03:00
|
|
|
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
|
2014-09-21 20:41:26 +04:00
|
|
|
|
2015-09-21 00:56:10 +03:00
|
|
|
nsContentPolicyType contentPolicyType =
|
|
|
|
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
|
|
|
|
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
nsCOMPtr<nsIChannel> channel;
|
2014-11-14 19:56:55 +03:00
|
|
|
// Note we are calling NS_NewChannelWithTriggeringPrincipal here with a node
|
|
|
|
// and a principal. This is because of a case where the node is the document
|
|
|
|
// being styled and the principal is the stylesheet (perhaps from a different
|
|
|
|
// origin) that is applying the styles.
|
2016-02-05 22:07:04 +03:00
|
|
|
if (aLoadData->mRequestingNode && aLoadData->mLoaderPrincipal) {
|
2014-11-14 19:56:55 +03:00
|
|
|
rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
|
|
|
|
aLoadData->mURI,
|
|
|
|
aLoadData->mRequestingNode,
|
2016-02-05 22:07:04 +03:00
|
|
|
aLoadData->mLoaderPrincipal,
|
2014-11-14 19:56:55 +03:00
|
|
|
securityFlags,
|
2015-09-21 00:56:10 +03:00
|
|
|
contentPolicyType,
|
2014-11-14 19:56:55 +03:00
|
|
|
loadGroup,
|
|
|
|
nullptr, // aCallbacks
|
|
|
|
nsIChannel::LOAD_NORMAL |
|
|
|
|
nsIChannel::LOAD_CLASSIFY_URI);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// either we are loading something inside a document, in which case
|
|
|
|
// we should always have a requestingNode, or we are loading something
|
2016-02-05 22:07:04 +03:00
|
|
|
// outside a document, in which case the loadingPrincipal and the
|
|
|
|
// triggeringPrincipal should always be the systemPrincipal.
|
2014-11-14 19:56:55 +03:00
|
|
|
rv = NS_NewChannel(getter_AddRefs(channel),
|
|
|
|
aLoadData->mURI,
|
2016-02-05 22:07:04 +03:00
|
|
|
nsContentUtils::GetSystemPrincipal(),
|
2014-11-14 19:56:55 +03:00
|
|
|
securityFlags,
|
2015-09-21 00:56:10 +03:00
|
|
|
contentPolicyType,
|
2014-11-14 19:56:55 +03:00
|
|
|
loadGroup,
|
|
|
|
nullptr, // aCallbacks
|
|
|
|
nsIChannel::LOAD_NORMAL |
|
|
|
|
nsIChannel::LOAD_CLASSIFY_URI);
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
2008-07-12 01:13:01 +04:00
|
|
|
#ifdef DEBUG
|
2011-10-17 18:59:28 +04:00
|
|
|
mSyncCallback = false;
|
2008-07-12 01:13:01 +04:00
|
|
|
#endif
|
2002-12-03 08:48:14 +03:00
|
|
|
LOG_ERROR((" Failed to create channel"));
|
2005-09-12 22:41:15 +04:00
|
|
|
SheetComplete(aLoadData, rv);
|
2002-12-03 08:48:14 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-12-06 22:26:50 +03:00
|
|
|
if (!aLoadData->mWasAlternate) {
|
|
|
|
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
|
|
|
if (cos) {
|
|
|
|
cos->AddClassFlags(nsIClassOfService::Leader);
|
|
|
|
}
|
|
|
|
}
|
2012-12-05 03:06:29 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
|
|
|
if (httpChannel) {
|
2015-08-13 06:19:11 +03:00
|
|
|
// Send a minimal Accept header for text/css
|
2002-12-03 08:48:14 +03:00
|
|
|
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
|
|
|
NS_LITERAL_CSTRING("text/css,*/*;q=0.1"),
|
2011-10-17 18:59:28 +04:00
|
|
|
false);
|
2004-08-18 06:32:25 +04:00
|
|
|
nsCOMPtr<nsIURI> referrerURI = aLoadData->GetReferrerURI();
|
|
|
|
if (referrerURI)
|
2014-11-18 16:46:47 +03:00
|
|
|
httpChannel->SetReferrerWithPolicy(referrerURI,
|
|
|
|
aLoadData->mSheet->GetReferrerPolicy());
|
2013-10-16 05:35:44 +04:00
|
|
|
|
2016-09-07 05:30:21 +03:00
|
|
|
nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(httpChannel);
|
|
|
|
if (internalChannel) {
|
|
|
|
internalChannel->SetIntegrityMetadata(sriMetadata.GetIntegrityString());
|
|
|
|
}
|
|
|
|
|
2013-10-16 05:35:44 +04:00
|
|
|
// Set the initiator type
|
|
|
|
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
|
|
|
|
if (timedChannel) {
|
|
|
|
if (aLoadData->mParentData) {
|
|
|
|
timedChannel->SetInitiatorType(NS_LITERAL_STRING("css"));
|
|
|
|
} else {
|
|
|
|
timedChannel->SetInitiatorType(NS_LITERAL_STRING("link"));
|
|
|
|
}
|
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
|
2003-06-24 01:00:46 +04:00
|
|
|
// Now tell the channel we expect text/css data back.... We do
|
|
|
|
// this before opening it, so it's only treated as a hint.
|
|
|
|
channel->SetContentType(NS_LITERAL_CSTRING("text/css"));
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// We don't have to hold on to the stream loader. The ownership
|
|
|
|
// model is: Necko owns the stream loader, which owns the load data,
|
|
|
|
// which owns us
|
|
|
|
nsCOMPtr<nsIUnicharStreamLoader> streamLoader;
|
2008-03-22 19:50:47 +03:00
|
|
|
rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader), aLoadData);
|
2012-08-28 21:10:08 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
mSyncCallback = false;
|
|
|
|
#endif
|
|
|
|
LOG_ERROR((" Failed to create stream loader"));
|
|
|
|
SheetComplete(aLoadData, rv);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-10-26 01:56:56 +04:00
|
|
|
if (mDocument) {
|
2014-06-04 00:37:46 +04:00
|
|
|
mozilla::net::PredictorLearn(aLoadData->mURI, mDocument->GetDocumentURI(),
|
|
|
|
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE,
|
|
|
|
mDocument);
|
2013-10-26 01:56:56 +04:00
|
|
|
}
|
|
|
|
|
2016-02-03 07:35:02 +03:00
|
|
|
rv = channel->AsyncOpen2(streamLoader);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2011-10-17 18:59:28 +04:00
|
|
|
mSyncCallback = false;
|
2002-12-03 08:48:14 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG_ERROR((" Failed to create stream loader"));
|
2005-09-12 22:41:15 +04:00
|
|
|
SheetComplete(aLoadData, rv);
|
2002-12-03 08:48:14 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mLoadingDatas.Put(&key, aLoadData);
|
2011-10-17 18:59:28 +04:00
|
|
|
aLoadData->mIsLoading = true;
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
return NS_OK;
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
/**
|
|
|
|
* ParseSheet handles parsing the data stream. The main idea here is
|
|
|
|
* to push the current load data onto the parse stack before letting
|
|
|
|
* the CSS parser at the data stream. That lets us handle @import
|
|
|
|
* correctly.
|
|
|
|
*/
|
1999-05-19 03:15:10 +04:00
|
|
|
nsresult
|
2011-05-19 05:22:59 +04:00
|
|
|
Loader::ParseSheet(const nsAString& aInput,
|
2010-03-03 00:00:53 +03:00
|
|
|
SheetLoadData* aLoadData,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool& aCompleted)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::ParseSheet"));
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aLoadData, "Must have load data");
|
|
|
|
NS_PRECONDITION(aLoadData->mSheet, "Must have sheet to parse into");
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
aCompleted = false;
|
2003-07-18 04:35:49 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// Push our load data on the stack so any kids can pick it up
|
|
|
|
mParsingDatas.AppendElement(aLoadData);
|
2010-05-18 08:00:40 +04:00
|
|
|
nsIURI* sheetURI = aLoadData->mSheet->GetSheetURI();
|
|
|
|
nsIURI* baseURI = aLoadData->mSheet->GetBaseURI();
|
2016-02-26 04:51:02 +03:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (aLoadData->mSheet->IsGecko()) {
|
|
|
|
nsCSSParser parser(this, aLoadData->mSheet->AsGecko());
|
|
|
|
rv = parser.ParseSheet(aInput, sheetURI, baseURI,
|
|
|
|
aLoadData->mSheet->Principal(),
|
2016-08-02 23:12:27 +03:00
|
|
|
aLoadData->mLineNumber);
|
2016-02-26 04:51:02 +03:00
|
|
|
} else {
|
2016-08-31 13:10:10 +03:00
|
|
|
rv =
|
2016-12-17 12:58:56 +03:00
|
|
|
aLoadData->mSheet->AsServo()->ParseSheet(this,
|
|
|
|
aInput, sheetURI, baseURI,
|
2016-08-31 13:10:10 +03:00
|
|
|
aLoadData->mSheet->Principal(),
|
|
|
|
aLoadData->mLineNumber);
|
2016-02-26 04:51:02 +03:00
|
|
|
}
|
|
|
|
|
2009-02-03 17:42:18 +03:00
|
|
|
mParsingDatas.RemoveElementAt(mParsingDatas.Length() - 1);
|
2010-03-02 23:59:32 +03:00
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG_ERROR((" Low-level error in parser!"));
|
|
|
|
SheetComplete(aLoadData, rv);
|
|
|
|
return rv;
|
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2002-12-11 03:28:47 +03:00
|
|
|
NS_ASSERTION(aLoadData->mPendingChildren == 0 || !aLoadData->mSyncLoad,
|
|
|
|
"Sync load has leftover pending children!");
|
2010-03-02 23:59:32 +03:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (aLoadData->mPendingChildren == 0) {
|
|
|
|
LOG((" No pending kids from parse"));
|
2011-10-17 18:59:28 +04:00
|
|
|
aCompleted = true;
|
2005-09-12 22:41:15 +04:00
|
|
|
SheetComplete(aLoadData, NS_OK);
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
// Otherwise, the children are holding strong refs to the data and
|
|
|
|
// will call SheetComplete() on it when they complete.
|
2010-03-02 23:59:32 +03:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SheetComplete is the do-it-all cleanup function. It removes the
|
|
|
|
* load data from the "loading" hashtable, adds the sheet to the
|
|
|
|
* "completed" hashtable, massages the XUL cache, handles siblings of
|
2005-09-12 22:41:15 +04:00
|
|
|
* the load data (other loads for the same URI), handles unblocking
|
2002-12-03 08:48:14 +03:00
|
|
|
* blocked parent loads as needed, and most importantly calls
|
|
|
|
* NS_RELEASE on the load data to destroy the whole mess.
|
|
|
|
*/
|
|
|
|
void
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::SheetComplete(SheetLoadData* aLoadData, nsresult aStatus)
|
2002-12-03 08:48:14 +03:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::SheetComplete"));
|
2007-04-21 02:59:18 +04:00
|
|
|
|
2016-10-25 20:15:38 +03:00
|
|
|
if (aLoadData->mSheet->IsServo() && NS_FAILED(aStatus)) {
|
|
|
|
aLoadData->mSheet->AsServo()->LoadFailed();
|
|
|
|
}
|
|
|
|
|
2007-04-21 02:59:18 +04:00
|
|
|
// 8 is probably big enough for all our common cases. It's not likely that
|
|
|
|
// imports will nest more than 8 deep, and multiple sheets with the same URI
|
|
|
|
// are rare.
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<RefPtr<SheetLoadData>, 8> datasToNotify;
|
2007-04-21 02:59:18 +04:00
|
|
|
DoSheetComplete(aLoadData, aStatus, datasToNotify);
|
|
|
|
|
|
|
|
// Now it's safe to go ahead and notify observers
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = datasToNotify.Length();
|
2007-05-31 05:42:48 +04:00
|
|
|
mDatasToNotifyOn += count;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2007-05-31 05:42:48 +04:00
|
|
|
--mDatasToNotifyOn;
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2007-04-21 02:59:18 +04:00
|
|
|
SheetLoadData* data = datasToNotify[i];
|
2007-05-31 05:42:48 +04:00
|
|
|
NS_ASSERTION(data && data->mMustNotify, "How did this data get here?");
|
|
|
|
if (data->mObserver) {
|
2015-12-25 02:04:20 +03:00
|
|
|
LOG((" Notifying observer %p for data %p. wasAlternate: %d",
|
2007-05-31 05:42:48 +04:00
|
|
|
data->mObserver.get(), data, data->mWasAlternate));
|
|
|
|
data->mObserver->StyleSheetLoaded(data->mSheet, data->mWasAlternate,
|
|
|
|
aStatus);
|
|
|
|
}
|
|
|
|
|
2007-12-22 03:56:28 +03:00
|
|
|
nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver> >::ForwardIterator iter(mObservers);
|
2007-05-31 05:42:48 +04:00
|
|
|
nsCOMPtr<nsICSSLoaderObserver> obs;
|
2007-12-20 10:30:04 +03:00
|
|
|
while (iter.HasMore()) {
|
|
|
|
obs = iter.GetNext();
|
2015-12-25 02:04:20 +03:00
|
|
|
LOG((" Notifying global observer %p for data %p. wasAlternate: %d",
|
2007-05-31 05:42:48 +04:00
|
|
|
obs.get(), data, data->mWasAlternate));
|
|
|
|
obs->StyleSheetLoaded(data->mSheet, data->mWasAlternate, aStatus);
|
|
|
|
}
|
2007-04-21 02:59:18 +04:00
|
|
|
}
|
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
if (mSheets->mLoadingDatas.Count() == 0 && mSheets->mPendingDatas.Count() > 0) {
|
2007-04-21 02:59:18 +04:00
|
|
|
LOG((" No more loading sheets; starting alternates"));
|
2007-05-31 05:42:48 +04:00
|
|
|
StartAlternateLoads();
|
2007-04-21 02:59:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
|
|
|
|
LoadDataArray& aDatasToNotify)
|
2007-04-21 02:59:18 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::DoSheetComplete"));
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aLoadData, "Must have a load data!");
|
|
|
|
NS_PRECONDITION(aLoadData->mSheet, "Must have a sheet");
|
2013-09-02 12:41:57 +04:00
|
|
|
NS_ASSERTION(mSheets, "mLoadingDatas should be initialized by now.");
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2016-12-16 06:16:31 +03:00
|
|
|
LOG(("Load completed, status: 0x%" PRIx32, static_cast<uint32_t>(aStatus)));
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
// Twiddle the hashtables
|
|
|
|
if (aLoadData->mURI) {
|
|
|
|
LOG_URI(" Finished loading: '%s'", aLoadData->mURI);
|
|
|
|
// Remove the data from the list of loading datas
|
|
|
|
if (aLoadData->mIsLoading) {
|
2014-11-18 16:46:47 +03:00
|
|
|
URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData->mURI,
|
2012-08-28 21:10:08 +04:00
|
|
|
aLoadData->mLoaderPrincipal,
|
2014-11-18 16:46:47 +03:00
|
|
|
aLoadData->mSheet->GetCORSMode(),
|
|
|
|
aLoadData->mSheet->GetReferrerPolicy());
|
2003-07-27 19:46:52 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
SheetLoadData *loadingData;
|
2017-01-31 10:10:45 +03:00
|
|
|
// XXXheycam Temporarily downgrade this assertion (bug 1314045).
|
|
|
|
NS_ASSERTION_STYLO_WARNING(
|
|
|
|
mSheets->mLoadingDatas.Get(&key, &loadingData) &&
|
|
|
|
loadingData == aLoadData,
|
|
|
|
"Bad loading table");
|
2003-07-27 19:46:52 +04:00
|
|
|
#endif
|
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mLoadingDatas.Remove(&key);
|
2011-10-17 18:59:28 +04:00
|
|
|
aLoadData->mIsLoading = false;
|
1999-09-30 05:39:57 +04:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// Go through and deal with the whole linked list.
|
|
|
|
SheetLoadData* data = aLoadData;
|
|
|
|
while (data) {
|
2011-09-27 01:26:54 +04:00
|
|
|
if (!data->mSheetAlreadyComplete) {
|
2011-10-03 23:11:59 +04:00
|
|
|
// If mSheetAlreadyComplete, then the sheet could well be modified between
|
|
|
|
// when we posted the async call to SheetComplete and now, since the sheet
|
|
|
|
// was page-accessible during that whole time.
|
2016-02-24 10:01:12 +03:00
|
|
|
MOZ_ASSERT(!(data->mSheet->IsGecko() &&
|
|
|
|
data->mSheet->AsGecko()->IsModified()),
|
2015-02-10 01:34:50 +03:00
|
|
|
"should not get marked modified during parsing");
|
2016-09-26 15:03:25 +03:00
|
|
|
data->mSheet->SetComplete();
|
2011-09-27 01:27:13 +04:00
|
|
|
data->ScheduleLoadEventIfNeeded(aStatus);
|
2011-09-27 01:26:54 +04:00
|
|
|
}
|
2007-05-31 05:42:48 +04:00
|
|
|
if (data->mMustNotify && (data->mObserver || !mObservers.IsEmpty())) {
|
2007-04-21 02:59:18 +04:00
|
|
|
// Don't notify here so we don't trigger script. Remember the
|
|
|
|
// info we need to notify, then do it later when it's safe.
|
|
|
|
aDatasToNotify.AppendElement(data);
|
2005-09-12 22:41:15 +04:00
|
|
|
|
2007-04-21 02:59:18 +04:00
|
|
|
// On append failure, just press on. We'll fail to notify the observer,
|
|
|
|
// but not much we can do about that....
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2003-01-07 03:37:19 +03:00
|
|
|
NS_ASSERTION(!data->mParentData ||
|
|
|
|
data->mParentData->mPendingChildren != 0,
|
|
|
|
"Broken pending child count on our parent");
|
|
|
|
|
2003-01-07 04:13:07 +03:00
|
|
|
// If we have a parent, our parent is no longer being parsed, and
|
|
|
|
// we are the last pending child, then our load completion
|
|
|
|
// completes the parent too. Note that the parent _can_ still be
|
|
|
|
// being parsed (eg if the child (us) failed to open the channel
|
|
|
|
// or some such).
|
2002-12-03 08:48:14 +03:00
|
|
|
if (data->mParentData &&
|
|
|
|
--(data->mParentData->mPendingChildren) == 0 &&
|
2009-02-03 17:42:18 +03:00
|
|
|
!mParsingDatas.Contains(data->mParentData)) {
|
2007-04-21 02:59:18 +04:00
|
|
|
DoSheetComplete(data->mParentData, aStatus, aDatasToNotify);
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
data = data->mNext;
|
|
|
|
}
|
2002-08-28 03:47:25 +04:00
|
|
|
|
2011-09-27 01:27:13 +04:00
|
|
|
// Now that it's marked complete, put the sheet in our cache.
|
|
|
|
// If we ever start doing this for failure aStatus, we'll need to
|
|
|
|
// adjust the PostLoadEvent code that thinks anything already
|
|
|
|
// complete must have loaded succesfully.
|
2005-09-12 22:41:15 +04:00
|
|
|
if (NS_SUCCEEDED(aStatus) && aLoadData->mURI) {
|
2013-04-24 22:59:14 +04:00
|
|
|
// Pick our sheet to cache carefully. Ideally, we want to cache
|
|
|
|
// one of the sheets that will be kept alive by a document or
|
|
|
|
// parent sheet anyway, so that if someone then accesses it via
|
|
|
|
// CSSOM we won't have extra clones of the inner lying around.
|
2017-02-22 01:05:24 +03:00
|
|
|
data = aLoadData;
|
|
|
|
StyleSheet* sheet = aLoadData->mSheet;
|
|
|
|
while (data) {
|
|
|
|
if (data->mSheet->GetParentSheet() || data->mSheet->GetOwnerNode()) {
|
|
|
|
sheet = data->mSheet;
|
|
|
|
break;
|
2013-04-24 22:59:14 +04:00
|
|
|
}
|
2017-02-22 01:05:24 +03:00
|
|
|
data = data->mNext;
|
|
|
|
}
|
2003-04-11 04:56:27 +04:00
|
|
|
#ifdef MOZ_XUL
|
2017-02-22 01:05:24 +03:00
|
|
|
if (IsChromeURI(aLoadData->mURI) &&
|
|
|
|
GetStyleBackendType() == StyleBackendType::Gecko) {
|
|
|
|
nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
|
|
|
|
if (cache && cache->IsEnabled()) {
|
|
|
|
if (!cache->GetStyleSheet(aLoadData->mURI)) {
|
|
|
|
LOG((" Putting sheet in XUL prototype cache"));
|
|
|
|
NS_ASSERTION(sheet->IsComplete(),
|
|
|
|
"Should only be caching complete sheets");
|
|
|
|
cache->PutStyleSheet(sheet);
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
}
|
2017-02-22 01:05:24 +03:00
|
|
|
}
|
|
|
|
else {
|
2002-12-03 08:48:14 +03:00
|
|
|
#endif
|
2017-02-22 01:05:24 +03:00
|
|
|
URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData->mURI,
|
|
|
|
aLoadData->mLoaderPrincipal,
|
|
|
|
aLoadData->mSheet->GetCORSMode(),
|
|
|
|
aLoadData->mSheet->GetReferrerPolicy());
|
|
|
|
NS_ASSERTION(sheet->IsComplete(),
|
|
|
|
"Should only be caching complete sheets");
|
|
|
|
mSheets->mCompleteSheets.Put(&key, sheet);
|
2003-04-11 04:56:27 +04:00
|
|
|
#ifdef MOZ_XUL
|
2016-02-24 10:01:12 +03:00
|
|
|
}
|
2017-02-22 01:05:24 +03:00
|
|
|
#endif
|
2003-01-17 07:20:03 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
NS_RELEASE(aLoadData); // this will release parents and siblings and all that
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
|
|
|
Loader::LoadInlineStyle(nsIContent* aElement,
|
2011-05-19 05:22:59 +04:00
|
|
|
const nsAString& aBuffer,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aLineNumber,
|
2010-03-08 12:34:55 +03:00
|
|
|
const nsAString& aTitle,
|
|
|
|
const nsAString& aMedia,
|
2013-01-09 03:25:47 +04:00
|
|
|
Element* aScopeElement,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool* aCompleted,
|
|
|
|
bool* aIsAlternate)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::LoadInlineStyle"));
|
2016-12-13 14:14:36 +03:00
|
|
|
MOZ_ASSERT(mParsingDatas.IsEmpty(), "We're in the middle of a parse?");
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
*aCompleted = true;
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
if (!mEnabled) {
|
|
|
|
LOG_WARN((" Not enabled"));
|
2002-10-11 04:38:29 +04:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
2002-10-11 04:38:29 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
|
|
|
|
NS_ASSERTION(owningElement, "Element is not a style linking element!");
|
2007-05-01 23:26:15 +04:00
|
|
|
|
|
|
|
// Since we're not planning to load a URI, no need to hand a principal to the
|
2012-08-28 21:10:08 +04:00
|
|
|
// load data or to CreateSheet(). Also, OK to use CORS_NONE for the CORS
|
2014-11-18 16:46:47 +03:00
|
|
|
// mode and mDocument's ReferrerPolicy.
|
2002-12-03 08:48:14 +03:00
|
|
|
StyleSheetState state;
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet> sheet;
|
2016-08-02 23:12:27 +03:00
|
|
|
nsresult rv = CreateSheet(nullptr, aElement, nullptr, eAuthorSheetFeatures,
|
|
|
|
CORS_NONE, mDocument->GetReferrerPolicy(),
|
2015-08-13 06:19:11 +03:00
|
|
|
EmptyString(), // no inline integrity checks
|
|
|
|
false, false, aTitle, state, aIsAlternate,
|
2016-02-24 10:01:12 +03:00
|
|
|
&sheet);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ASSERTION(state == eSheetNeedsParser,
|
|
|
|
"Inline sheets should not be cached");
|
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
LOG((" Sheet is alternate: %d", *aIsAlternate));
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2013-11-11 11:57:53 +04:00
|
|
|
PrepareSheet(sheet, aTitle, aMedia, nullptr, aScopeElement, *aIsAlternate);
|
2011-11-08 08:41:17 +04:00
|
|
|
|
2013-12-02 14:26:12 +04:00
|
|
|
if (aElement->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
|
|
|
|
ShadowRoot* containingShadow = aElement->GetContainingShadow();
|
|
|
|
MOZ_ASSERT(containingShadow);
|
|
|
|
containingShadow->InsertSheet(sheet, aElement);
|
|
|
|
} else {
|
|
|
|
rv = InsertSheetInDoc(sheet, aElement, mDocument);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
SheetLoadData* data = new SheetLoadData(this, aTitle, nullptr, sheet,
|
2007-04-21 02:59:18 +04:00
|
|
|
owningElement, *aIsAlternate,
|
2014-09-21 20:41:26 +04:00
|
|
|
aObserver, nullptr, static_cast<nsINode*>(aElement));
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2007-05-01 23:26:15 +04:00
|
|
|
// We never actually load this, so just set its principal directly
|
|
|
|
sheet->SetPrincipal(aElement->NodePrincipal());
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ADDREF(data);
|
2004-09-09 21:32:35 +04:00
|
|
|
data->mLineNumber = aLineNumber;
|
2002-12-03 08:48:14 +03:00
|
|
|
// Parse completion releases the load data
|
2011-05-19 05:22:59 +04:00
|
|
|
rv = ParseSheet(aBuffer, data, *aCompleted);
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// If aCompleted is true, |data| may well be deleted by now.
|
|
|
|
if (!*aCompleted) {
|
2011-10-17 18:59:28 +04:00
|
|
|
data->mMustNotify = true;
|
2005-09-12 22:41:15 +04:00
|
|
|
}
|
|
|
|
return rv;
|
2011-05-06 19:45:36 +04:00
|
|
|
}
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
|
|
|
Loader::LoadStyleLink(nsIContent* aElement,
|
2011-05-06 19:45:36 +04:00
|
|
|
nsIURI* aURL,
|
2010-03-08 12:34:55 +03:00
|
|
|
const nsAString& aTitle,
|
|
|
|
const nsAString& aMedia,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aHasAlternateRel,
|
2012-08-28 21:10:07 +04:00
|
|
|
CORSMode aCORSMode,
|
2014-11-18 16:46:47 +03:00
|
|
|
ReferrerPolicy aReferrerPolicy,
|
2015-08-13 06:19:11 +03:00
|
|
|
const nsAString& aIntegrity,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool* aIsAlternate)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::LoadStyleLink"));
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aURL, "Must have URL to load");
|
2009-02-03 17:42:18 +03:00
|
|
|
NS_ASSERTION(mParsingDatas.Length() == 0, "We're in the middle of a parse?");
|
2002-10-11 04:38:29 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
LOG_URI(" Link uri: '%s'", aURL);
|
2005-09-12 22:41:15 +04:00
|
|
|
LOG((" Link title: '%s'", NS_ConvertUTF16toUTF8(aTitle).get()));
|
|
|
|
LOG((" Link media: '%s'", NS_ConvertUTF16toUTF8(aMedia).get()));
|
|
|
|
LOG((" Link alternate rel: %d", aHasAlternateRel));
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
if (!mEnabled) {
|
|
|
|
LOG_WARN((" Not enabled"));
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
1999-05-27 03:52:37 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
|
2000-05-27 09:22:39 +04:00
|
|
|
|
2007-05-01 23:26:15 +04:00
|
|
|
nsIPrincipal* principal =
|
|
|
|
aElement ? aElement->NodePrincipal() : mDocument->NodePrincipal();
|
|
|
|
|
2004-07-27 21:15:53 +04:00
|
|
|
nsISupports* context = aElement;
|
|
|
|
if (!context) {
|
|
|
|
context = mDocument;
|
2004-05-13 22:34:18 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2016-02-03 07:35:30 +03:00
|
|
|
nsresult rv = CheckContentPolicy(principal, aURL, context, false);
|
2016-05-27 20:31:20 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2016-06-09 21:49:28 +03:00
|
|
|
// Don't fire the error event if our document is loaded as data. We're
|
|
|
|
// supposed to not even try to do loads in that case... Unfortunately, we
|
|
|
|
// implement that via nsDataDocumentContentPolicy, which doesn't have a good
|
|
|
|
// way to communicate back to us that _it_ is the thing that blocked the
|
|
|
|
// load.
|
|
|
|
if (aElement && !mDocument->IsLoadedAsData()) {
|
2016-05-27 20:31:20 +03:00
|
|
|
// Fire an async error event on it.
|
|
|
|
RefPtr<AsyncEventDispatcher> loadBlockingAsyncDispatcher =
|
|
|
|
new LoadBlockingAsyncEventDispatcher(aElement,
|
|
|
|
NS_LITERAL_STRING("error"),
|
|
|
|
false, false);
|
|
|
|
loadBlockingAsyncDispatcher->PostDOMEvent();
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
2016-02-03 07:35:30 +03:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
StyleSheetState state;
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet> sheet;
|
2016-08-02 23:12:27 +03:00
|
|
|
rv = CreateSheet(aURL, aElement, principal, eAuthorSheetFeatures,
|
|
|
|
aCORSMode, aReferrerPolicy, aIntegrity, false,
|
2016-02-03 07:35:30 +03:00
|
|
|
aHasAlternateRel, aTitle, state, aIsAlternate,
|
2016-02-24 10:01:12 +03:00
|
|
|
&sheet);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2005-09-12 22:41:15 +04:00
|
|
|
|
|
|
|
LOG((" Sheet is alternate: %d", *aIsAlternate));
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2013-11-11 11:57:53 +04:00
|
|
|
PrepareSheet(sheet, aTitle, aMedia, nullptr, nullptr, *aIsAlternate);
|
2011-11-08 08:41:17 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
rv = InsertSheetInDoc(sheet, aElement, mDocument);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2011-09-27 01:27:00 +04:00
|
|
|
nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (state == eSheetComplete) {
|
2016-09-26 15:03:25 +03:00
|
|
|
LOG((" Sheet already complete: 0x%p", sheet.get()));
|
2011-09-27 01:27:00 +04:00
|
|
|
if (aObserver || !mObservers.IsEmpty() || owningElement) {
|
|
|
|
rv = PostLoadEvent(aURL, sheet, aObserver, *aIsAlternate,
|
|
|
|
owningElement);
|
2007-04-21 02:59:18 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
2000-07-28 13:36:51 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// Now we need to actually load it
|
2014-09-21 20:41:26 +04:00
|
|
|
nsCOMPtr<nsINode> requestingNode = do_QueryInterface(context);
|
2007-04-21 02:59:18 +04:00
|
|
|
SheetLoadData* data = new SheetLoadData(this, aTitle, aURL, sheet,
|
|
|
|
owningElement, *aIsAlternate,
|
2014-09-21 20:41:26 +04:00
|
|
|
aObserver, principal, requestingNode);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ADDREF(data);
|
|
|
|
|
|
|
|
// If we have to parse and it's an alternate non-inline, defer it
|
2013-09-02 12:41:57 +04:00
|
|
|
if (aURL && state == eSheetNeedsParser && mSheets->mLoadingDatas.Count() != 0 &&
|
2005-09-12 22:41:15 +04:00
|
|
|
*aIsAlternate) {
|
2002-12-03 08:48:14 +03:00
|
|
|
LOG((" Deferring alternate sheet load"));
|
2014-11-18 16:46:47 +03:00
|
|
|
URIPrincipalReferrerPolicyAndCORSModeHashKey key(data->mURI,
|
|
|
|
data->mLoaderPrincipal,
|
|
|
|
data->mSheet->GetCORSMode(),
|
|
|
|
data->mSheet->GetReferrerPolicy());
|
2013-09-02 12:41:57 +04:00
|
|
|
mSheets->mPendingDatas.Put(&key, data);
|
2005-09-12 22:41:15 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
data->mMustNotify = true;
|
2002-12-03 08:48:14 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load completion will free the data
|
2015-09-21 00:56:10 +03:00
|
|
|
rv = LoadSheet(data, state, false);
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
data->mMustNotify = true;
|
2005-09-12 22:41:15 +04:00
|
|
|
return rv;
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2011-08-08 06:23:51 +04:00
|
|
|
HaveAncestorDataWithURI(SheetLoadData *aData, nsIURI *aURI)
|
|
|
|
{
|
|
|
|
if (!aData->mURI) {
|
|
|
|
// Inline style; this won't have any ancestors
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(!aData->mParentData,
|
|
|
|
"How does inline style have a parent?");
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2011-08-08 06:23:51 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool equal;
|
2011-08-08 06:23:51 +04:00
|
|
|
if (NS_FAILED(aData->mURI->Equals(aURI, &equal)) || equal) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2011-08-08 06:23:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Datas down the mNext chain have the same URI as aData, so we
|
|
|
|
// don't have to compare to them. But they might have different
|
|
|
|
// parents, and we have to check all of those.
|
|
|
|
while (aData) {
|
|
|
|
if (aData->mParentData &&
|
|
|
|
HaveAncestorDataWithURI(aData->mParentData, aURI)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2011-08-08 06:23:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
aData = aData->mNext;
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2011-08-08 06:23:51 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
2016-09-26 15:03:25 +03:00
|
|
|
Loader::LoadChildSheet(StyleSheet* aParentSheet,
|
2011-05-06 19:45:36 +04:00
|
|
|
nsIURI* aURL,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsMediaList* aMedia,
|
2016-12-17 12:58:56 +03:00
|
|
|
ImportRule* aGeckoParentRule,
|
2016-12-29 20:33:47 +03:00
|
|
|
const RawServoImportRule* aServoParentRule,
|
2015-09-18 08:27:00 +03:00
|
|
|
LoaderReusableStyleSheets* aReusableSheets)
|
1999-05-19 03:15:10 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::LoadChildSheet"));
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_PRECONDITION(aURL, "Must have a URI to load");
|
2007-05-01 23:26:15 +04:00
|
|
|
NS_PRECONDITION(aParentSheet, "Must have a parent sheet");
|
2002-10-11 04:38:29 +04:00
|
|
|
|
2016-12-17 12:58:56 +03:00
|
|
|
// Servo doesn't support reusable sheets.
|
|
|
|
MOZ_ASSERT_IF(aReusableSheets, aParentSheet->IsGecko());
|
|
|
|
MOZ_ASSERT_IF(aParentSheet->IsGecko(), aGeckoParentRule && !aServoParentRule);
|
|
|
|
MOZ_ASSERT_IF(aParentSheet->IsServo(), aServoParentRule && !aGeckoParentRule);
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (!mEnabled) {
|
|
|
|
LOG_WARN((" Not enabled"));
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
LOG_URI(" Child uri: '%s'", aURL);
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
nsCOMPtr<nsINode> owningNode;
|
2004-05-13 22:34:18 +04:00
|
|
|
|
2017-01-20 07:49:44 +03:00
|
|
|
// check for an associated document: if none, don't bother walking up the
|
|
|
|
// parent sheets
|
2016-12-17 12:58:56 +03:00
|
|
|
//
|
|
|
|
// FIXME(emilio): Figure out whether this walk up is necessary (try seems
|
|
|
|
// green without it), and fix the parenting of stylesheets in the servo case
|
|
|
|
// if that's the case.
|
2017-01-20 07:49:44 +03:00
|
|
|
if (aParentSheet->GetAssociatedDocument() && aParentSheet->IsGecko()) {
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* topSheet = aParentSheet;
|
|
|
|
while (StyleSheet* parent = topSheet->GetParentSheet()) {
|
2016-02-24 10:01:12 +03:00
|
|
|
topSheet = parent;
|
|
|
|
}
|
|
|
|
owningNode = topSheet->GetOwnerNode();
|
2004-05-13 22:34:18 +04:00
|
|
|
}
|
|
|
|
|
2004-07-27 21:15:53 +04:00
|
|
|
nsISupports* context = owningNode;
|
|
|
|
if (!context) {
|
|
|
|
context = mDocument;
|
2004-05-13 22:34:18 +04:00
|
|
|
}
|
2007-05-01 23:26:15 +04:00
|
|
|
|
2016-02-03 07:35:30 +03:00
|
|
|
nsIPrincipal* principal = aParentSheet->Principal();
|
|
|
|
nsresult rv = CheckContentPolicy(principal, aURL, context, false);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
SheetLoadData* parentData = nullptr;
|
2002-12-03 08:48:14 +03:00
|
|
|
nsCOMPtr<nsICSSLoaderObserver> observer;
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t count = mParsingDatas.Length();
|
2002-12-03 08:48:14 +03:00
|
|
|
if (count > 0) {
|
|
|
|
LOG((" Have a parent load"));
|
2009-02-03 17:42:18 +03:00
|
|
|
parentData = mParsingDatas.ElementAt(count - 1);
|
2002-12-03 08:48:14 +03:00
|
|
|
// Check for cycles
|
2011-08-08 06:23:51 +04:00
|
|
|
if (HaveAncestorDataWithURI(parentData, aURL)) {
|
|
|
|
// Houston, we have a loop, blow off this child and pretend this never
|
|
|
|
// happened
|
|
|
|
LOG_ERROR((" @import cycle detected, dropping load"));
|
|
|
|
return NS_OK;
|
2000-07-28 13:36:51 +04:00
|
|
|
}
|
|
|
|
|
2003-07-09 05:48:20 +04:00
|
|
|
NS_ASSERTION(parentData->mSheet == aParentSheet,
|
2002-12-03 08:48:14 +03:00
|
|
|
"Unexpected call to LoadChildSheet");
|
|
|
|
} else {
|
|
|
|
LOG((" No parent load; must be CSSOM"));
|
|
|
|
// No parent load data, so the sheet will need to be notified when
|
|
|
|
// we finish, if it can be, if we do the load asynchronously.
|
2016-02-24 10:01:12 +03:00
|
|
|
// XXXheycam ServoStyleSheet doesn't implement nsICSSLoaderObserver yet.
|
|
|
|
MOZ_ASSERT(aParentSheet->IsGecko(),
|
|
|
|
"stylo: ServoStyleSheets don't support child sheet loading yet");
|
|
|
|
observer = aParentSheet->AsGecko();
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
// Now that we know it's safe to load this (passes security check and not a
|
2012-08-28 21:10:08 +04:00
|
|
|
// loop) do so.
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet> sheet;
|
2016-02-24 10:01:12 +03:00
|
|
|
RefPtr<CSSStyleSheet> reusableSheet;
|
2002-12-03 08:48:14 +03:00
|
|
|
StyleSheetState state;
|
2016-02-24 10:01:12 +03:00
|
|
|
if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, reusableSheet)) {
|
|
|
|
sheet = reusableSheet;
|
2016-12-17 12:58:56 +03:00
|
|
|
aGeckoParentRule->SetSheet(reusableSheet);
|
2015-09-18 08:27:00 +03:00
|
|
|
state = eSheetComplete;
|
|
|
|
} else {
|
|
|
|
bool isAlternate;
|
|
|
|
const nsSubstring& empty = EmptyString();
|
|
|
|
// For now, use CORS_NONE for child sheets
|
2016-08-02 23:12:27 +03:00
|
|
|
rv = CreateSheet(aURL, nullptr, principal,
|
2016-09-26 15:03:25 +03:00
|
|
|
aParentSheet->ParsingMode(),
|
2016-08-02 23:12:27 +03:00
|
|
|
CORS_NONE, aParentSheet->GetReferrerPolicy(),
|
2015-09-18 08:27:00 +03:00
|
|
|
EmptyString(), // integrity is only checked on main sheet
|
|
|
|
parentData ? parentData->mSyncLoad : false,
|
2016-02-24 10:01:12 +03:00
|
|
|
false, empty, state, &isAlternate, &sheet);
|
2015-09-18 08:27:00 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2015-09-18 08:27:00 +03:00
|
|
|
PrepareSheet(sheet, empty, empty, aMedia, nullptr, isAlternate);
|
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2016-12-17 12:58:56 +03:00
|
|
|
rv = InsertChildSheet(sheet, aParentSheet, aGeckoParentRule,
|
|
|
|
aServoParentRule);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (state == eSheetComplete) {
|
|
|
|
LOG((" Sheet already complete"));
|
|
|
|
// We're completely done. No need to notify, even, since the
|
|
|
|
// @import rule addition/modification will trigger the right style
|
|
|
|
// changes automatically.
|
|
|
|
return NS_OK;
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2014-09-21 20:41:26 +04:00
|
|
|
nsCOMPtr<nsINode> requestingNode = do_QueryInterface(context);
|
2002-12-03 08:48:14 +03:00
|
|
|
SheetLoadData* data = new SheetLoadData(this, aURL, sheet, parentData,
|
2014-09-21 20:41:26 +04:00
|
|
|
observer, principal, requestingNode);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
NS_ADDREF(data);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool syncLoad = data->mSyncLoad;
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
// Load completion will release the data
|
2015-09-21 00:56:10 +03:00
|
|
|
rv = LoadSheet(data, state, false);
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2005-09-16 19:38:04 +04:00
|
|
|
// If syncLoad is true, |data| will be deleted by now.
|
|
|
|
if (!syncLoad) {
|
2011-10-17 18:59:28 +04:00
|
|
|
data->mMustNotify = true;
|
2005-09-16 19:38:04 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
return rv;
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
2015-10-14 00:43:16 +03:00
|
|
|
Loader::LoadSheetSync(nsIURI* aURL,
|
|
|
|
SheetParsingMode aParsingMode,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aUseSystemPrincipal,
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet>* aSheet)
|
2002-12-03 08:48:14 +03:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::LoadSheetSync"));
|
2015-10-14 00:43:16 +03:00
|
|
|
return InternalLoadNonDocumentSheet(aURL,
|
|
|
|
false, aParsingMode, aUseSystemPrincipal,
|
|
|
|
nullptr, EmptyCString(),
|
|
|
|
aSheet, nullptr);
|
1999-05-19 03:15:10 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
|
|
|
Loader::LoadSheet(nsIURI* aURL,
|
|
|
|
nsIPrincipal* aOriginPrincipal,
|
|
|
|
const nsCString& aCharset,
|
|
|
|
nsICSSLoaderObserver* aObserver,
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet>* aSheet)
|
2006-11-12 01:27:00 +03:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::LoadSheet(aURL, aObserver, aSheet) api call"));
|
2006-11-12 01:27:00 +03:00
|
|
|
NS_PRECONDITION(aSheet, "aSheet is null");
|
2015-10-14 00:43:16 +03:00
|
|
|
return InternalLoadNonDocumentSheet(aURL,
|
|
|
|
false, eAuthorSheetFeatures, false,
|
2009-04-10 18:29:08 +04:00
|
|
|
aOriginPrincipal, aCharset,
|
2007-08-08 05:16:09 +04:00
|
|
|
aSheet, aObserver);
|
2006-11-12 01:27:00 +03:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
|
|
|
Loader::LoadSheet(nsIURI* aURL,
|
2015-09-21 00:56:10 +03:00
|
|
|
bool aIsPreload,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsIPrincipal* aOriginPrincipal,
|
|
|
|
const nsCString& aCharset,
|
2012-08-28 21:10:08 +04:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-11-18 16:46:47 +03:00
|
|
|
CORSMode aCORSMode,
|
2015-08-13 06:19:11 +03:00
|
|
|
ReferrerPolicy aReferrerPolicy,
|
|
|
|
const nsAString& aIntegrity)
|
1999-05-27 03:52:37 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::LoadSheet(aURL, aObserver) api call"));
|
2015-10-14 00:43:16 +03:00
|
|
|
return InternalLoadNonDocumentSheet(aURL,
|
|
|
|
aIsPreload, eAuthorSheetFeatures, false,
|
2009-04-10 18:29:08 +04:00
|
|
|
aOriginPrincipal, aCharset,
|
2015-10-14 00:43:16 +03:00
|
|
|
nullptr, aObserver,
|
|
|
|
aCORSMode, aReferrerPolicy, aIntegrity);
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2011-05-06 19:45:36 +04:00
|
|
|
Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
|
2015-09-21 00:56:10 +03:00
|
|
|
bool aIsPreload,
|
2015-10-14 00:43:16 +03:00
|
|
|
SheetParsingMode aParsingMode,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aUseSystemPrincipal,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsIPrincipal* aOriginPrincipal,
|
|
|
|
const nsCString& aCharset,
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet>* aSheet,
|
2012-08-28 21:10:08 +04:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2014-11-18 16:46:47 +03:00
|
|
|
CORSMode aCORSMode,
|
2015-08-13 06:19:11 +03:00
|
|
|
ReferrerPolicy aReferrerPolicy,
|
|
|
|
const nsAString& aIntegrity)
|
2002-12-03 08:48:14 +03:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aURL, "Must have a URI to load");
|
2006-11-18 01:45:52 +03:00
|
|
|
NS_PRECONDITION(aSheet || aObserver, "Sheet and observer can't both be null");
|
2009-03-17 04:38:36 +03:00
|
|
|
NS_PRECONDITION(!aUseSystemPrincipal || !aObserver,
|
|
|
|
"Shouldn't load system-principal sheets async");
|
2009-02-03 17:42:18 +03:00
|
|
|
NS_ASSERTION(mParsingDatas.Length() == 0, "We're in the middle of a parse?");
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
LOG_URI(" Non-document sheet uri: '%s'", aURL);
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
if (aSheet) {
|
2012-07-30 18:20:58 +04:00
|
|
|
*aSheet = nullptr;
|
2005-09-12 22:41:15 +04:00
|
|
|
}
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (!mEnabled) {
|
|
|
|
LOG_WARN((" Not enabled"));
|
2002-10-11 04:38:29 +04:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
|
2016-02-03 07:35:30 +03:00
|
|
|
nsresult rv = CheckContentPolicy(aOriginPrincipal, aURL, mDocument, aIsPreload);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
StyleSheetState state;
|
2011-11-08 08:41:17 +04:00
|
|
|
bool isAlternate;
|
2016-09-26 15:03:25 +03:00
|
|
|
RefPtr<StyleSheet> sheet;
|
2012-07-30 18:20:58 +04:00
|
|
|
bool syncLoad = (aObserver == nullptr);
|
2011-11-08 08:41:17 +04:00
|
|
|
const nsSubstring& empty = EmptyString();
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2016-08-02 23:12:27 +03:00
|
|
|
rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aParsingMode,
|
|
|
|
aCORSMode, aReferrerPolicy, aIntegrity, syncLoad,
|
|
|
|
false, empty, state, &isAlternate, &sheet);
|
2002-12-03 08:48:14 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2013-11-11 11:57:53 +04:00
|
|
|
PrepareSheet(sheet, empty, empty, nullptr, nullptr, isAlternate);
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
if (state == eSheetComplete) {
|
|
|
|
LOG((" Sheet already complete"));
|
2011-09-27 01:26:54 +04:00
|
|
|
if (aObserver || !mObservers.IsEmpty()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
rv = PostLoadEvent(aURL, sheet, aObserver, false, nullptr);
|
2006-11-12 01:27:00 +03:00
|
|
|
}
|
2002-12-03 08:48:14 +03:00
|
|
|
if (aSheet) {
|
2005-09-12 22:41:15 +04:00
|
|
|
sheet.swap(*aSheet);
|
1999-05-27 03:52:37 +04:00
|
|
|
}
|
2005-09-12 22:41:15 +04:00
|
|
|
return rv;
|
1999-05-27 03:52:37 +04:00
|
|
|
}
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2006-06-15 07:20:19 +04:00
|
|
|
SheetLoadData* data =
|
2016-08-02 23:12:27 +03:00
|
|
|
new SheetLoadData(this, aURL, sheet, syncLoad,
|
2009-04-10 18:29:08 +04:00
|
|
|
aUseSystemPrincipal, aCharset, aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
aOriginPrincipal, mDocument);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
|
|
|
NS_ADDREF(data);
|
2015-09-21 00:56:10 +03:00
|
|
|
rv = LoadSheet(data, state, aIsPreload);
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2002-12-03 08:48:14 +03:00
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
if (aSheet) {
|
|
|
|
sheet.swap(*aSheet);
|
2006-11-12 01:27:00 +03:00
|
|
|
}
|
|
|
|
if (aObserver) {
|
2011-10-17 18:59:28 +04:00
|
|
|
data->mMustNotify = true;
|
2002-12-03 08:48:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
1999-05-19 03:15:10 +04:00
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
nsresult
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::PostLoadEvent(nsIURI* aURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aSheet,
|
2010-03-03 00:00:53 +03:00
|
|
|
nsICSSLoaderObserver* aObserver,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aWasAlternate,
|
2011-09-27 01:27:00 +04:00
|
|
|
nsIStyleSheetLinkingElement* aElement)
|
2005-09-12 22:41:15 +04:00
|
|
|
{
|
2010-03-03 00:00:53 +03:00
|
|
|
LOG(("css::Loader::PostLoadEvent"));
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_PRECONDITION(aSheet, "Must have sheet");
|
2011-09-27 01:27:00 +04:00
|
|
|
NS_PRECONDITION(aObserver || !mObservers.IsEmpty() || aElement,
|
|
|
|
"Must have observer or element");
|
2005-09-12 22:41:15 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SheetLoadData> evt =
|
2005-09-12 22:41:15 +04:00
|
|
|
new SheetLoadData(this, EmptyString(), // title doesn't matter here
|
|
|
|
aURI,
|
|
|
|
aSheet,
|
2011-09-27 01:27:00 +04:00
|
|
|
aElement,
|
2005-09-12 22:41:15 +04:00
|
|
|
aWasAlternate,
|
2007-05-01 23:26:15 +04:00
|
|
|
aObserver,
|
2014-09-21 20:41:26 +04:00
|
|
|
nullptr,
|
|
|
|
mDocument);
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
2006-05-10 21:30:15 +04:00
|
|
|
if (!mPostedEvents.AppendElement(evt)) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
2005-09-12 22:41:15 +04:00
|
|
|
|
2006-05-10 21:30:15 +04:00
|
|
|
nsresult rv = NS_DispatchToCurrentThread(evt);
|
2005-09-12 22:41:15 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
2006-05-10 21:30:15 +04:00
|
|
|
NS_WARNING("failed to dispatch stylesheet load event");
|
2007-02-05 21:09:26 +03:00
|
|
|
mPostedEvents.RemoveElement(evt);
|
2005-09-12 22:41:15 +04:00
|
|
|
} else {
|
2007-02-05 21:09:26 +03:00
|
|
|
// We'll unblock onload when we handle the event.
|
|
|
|
if (mDocument) {
|
|
|
|
mDocument->BlockOnload();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We want to notify the observer for this data.
|
2011-10-17 18:59:28 +04:00
|
|
|
evt->mMustNotify = true;
|
|
|
|
evt->mSheetAlreadyComplete = true;
|
2011-09-27 01:27:13 +04:00
|
|
|
|
|
|
|
// If we get to this code, aSheet loaded correctly at some point, so
|
|
|
|
// we can just use NS_OK for the status. Note that we do this here
|
|
|
|
// and not from inside our SheetComplete so that we don't end up
|
|
|
|
// running the load event async.
|
|
|
|
evt->ScheduleLoadEventIfNeeded(NS_OK);
|
2005-09-12 22:41:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::HandleLoadEvent(SheetLoadData* aEvent)
|
2005-09-12 22:41:15 +04:00
|
|
|
{
|
|
|
|
// XXXbz can't assert this yet.... May not have an observer because
|
|
|
|
// we're unblocking the parser
|
|
|
|
// NS_ASSERTION(aEvent->mObserver, "Must have observer");
|
|
|
|
NS_ASSERTION(aEvent->mSheet, "Must have sheet");
|
2011-09-27 01:26:05 +04:00
|
|
|
|
|
|
|
// Very important: this needs to come before the SheetComplete call
|
|
|
|
// below, so that HasPendingLoads() will test true as needed under
|
|
|
|
// notifications we send from that SheetComplete call.
|
|
|
|
mPostedEvents.RemoveElement(aEvent);
|
|
|
|
|
2005-09-12 22:41:15 +04:00
|
|
|
if (!aEvent->mIsCancelled) {
|
2007-02-05 21:09:26 +03:00
|
|
|
// SheetComplete will call Release(), so give it a reference to do
|
|
|
|
// that with.
|
2005-09-12 22:41:15 +04:00
|
|
|
NS_ADDREF(aEvent);
|
|
|
|
SheetComplete(aEvent, NS_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mDocument) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mDocument->UnblockOnload(true);
|
2005-09-12 22:41:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-23 08:35:32 +03:00
|
|
|
static void
|
|
|
|
StopLoadingSheets(
|
|
|
|
nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey, SheetLoadData*>& aDatas,
|
|
|
|
Loader::LoadDataArray& aArr)
|
2001-05-19 06:59:15 +04:00
|
|
|
{
|
2015-11-23 08:35:32 +03:00
|
|
|
for (auto iter = aDatas.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
SheetLoadData* data = iter.Data();
|
|
|
|
MOZ_ASSERT(data, "Must have a data!");
|
2001-05-19 06:59:15 +04:00
|
|
|
|
2015-11-23 08:35:32 +03:00
|
|
|
data->mIsLoading = false; // we will handle the removal right here
|
|
|
|
data->mIsCancelled = true;
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2015-11-23 08:35:32 +03:00
|
|
|
aArr.AppendElement(data);
|
2001-05-19 06:59:15 +04:00
|
|
|
|
2015-11-23 08:35:32 +03:00
|
|
|
iter.Remove();
|
|
|
|
}
|
2001-05-19 06:59:15 +04:00
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
|
|
|
Loader::Stop()
|
2001-05-19 06:59:15 +04:00
|
|
|
{
|
2015-11-23 08:35:32 +03:00
|
|
|
uint32_t pendingCount = mSheets ? mSheets->mPendingDatas.Count() : 0;
|
|
|
|
uint32_t loadingCount = mSheets ? mSheets->mLoadingDatas.Count() : 0;
|
2007-05-31 05:42:48 +04:00
|
|
|
LoadDataArray arr(pendingCount + loadingCount + mPostedEvents.Length());
|
2011-05-06 19:45:36 +04:00
|
|
|
|
2007-05-31 05:42:48 +04:00
|
|
|
if (pendingCount) {
|
2015-11-23 08:35:32 +03:00
|
|
|
StopLoadingSheets(mSheets->mPendingDatas, arr);
|
2001-05-19 06:59:15 +04:00
|
|
|
}
|
2007-05-31 05:42:48 +04:00
|
|
|
if (loadingCount) {
|
2015-11-23 08:35:32 +03:00
|
|
|
StopLoadingSheets(mSheets->mLoadingDatas, arr);
|
2007-05-01 23:26:15 +04:00
|
|
|
}
|
2007-05-31 05:42:48 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t i;
|
2007-05-31 05:42:48 +04:00
|
|
|
for (i = 0; i < mPostedEvents.Length(); ++i) {
|
2007-02-05 21:09:26 +03:00
|
|
|
SheetLoadData* data = mPostedEvents[i];
|
2011-10-17 18:59:28 +04:00
|
|
|
data->mIsCancelled = true;
|
2007-05-31 05:42:48 +04:00
|
|
|
if (arr.AppendElement(data)) {
|
|
|
|
// SheetComplete() calls Release(), so give this an extra ref.
|
|
|
|
NS_ADDREF(data);
|
|
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
else {
|
|
|
|
NS_NOTREACHED("We preallocated this memory... shouldn't really fail, "
|
|
|
|
"except we never check that preallocation succeeds.");
|
|
|
|
}
|
|
|
|
#endif
|
2007-02-05 21:09:26 +03:00
|
|
|
}
|
2005-09-12 22:41:15 +04:00
|
|
|
mPostedEvents.Clear();
|
2007-05-31 05:42:48 +04:00
|
|
|
|
|
|
|
mDatasToNotifyOn += arr.Length();
|
|
|
|
for (i = 0; i < arr.Length(); ++i) {
|
|
|
|
--mDatasToNotifyOn;
|
|
|
|
SheetComplete(arr[i], NS_BINDING_ABORTED);
|
|
|
|
}
|
2001-05-19 06:59:15 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::HasPendingLoads()
|
2007-05-31 05:42:48 +04:00
|
|
|
{
|
|
|
|
return
|
2013-09-02 12:41:57 +04:00
|
|
|
(mSheets && mSheets->mLoadingDatas.Count() != 0) ||
|
|
|
|
(mSheets && mSheets->mPendingDatas.Count() != 0) ||
|
2007-05-31 05:42:48 +04:00
|
|
|
mPostedEvents.Length() != 0 ||
|
|
|
|
mDatasToNotifyOn != 0;
|
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
nsresult
|
|
|
|
Loader::AddObserver(nsICSSLoaderObserver* aObserver)
|
2007-05-31 05:42:48 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aObserver, "Must have observer");
|
2007-12-20 10:30:04 +03:00
|
|
|
if (mObservers.AppendElementUnlessExists(aObserver)) {
|
2007-05-31 05:42:48 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
void
|
|
|
|
Loader::RemoveObserver(nsICSSLoaderObserver* aObserver)
|
2007-05-31 05:42:48 +04:00
|
|
|
{
|
2007-12-22 03:56:28 +03:00
|
|
|
mObservers.RemoveElement(aObserver);
|
2007-05-31 05:42:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-03-03 00:00:53 +03:00
|
|
|
Loader::StartAlternateLoads()
|
2007-05-31 05:42:48 +04:00
|
|
|
{
|
2013-09-02 12:41:57 +04:00
|
|
|
NS_PRECONDITION(mSheets, "Don't call me!");
|
|
|
|
LoadDataArray arr(mSheets->mPendingDatas.Count());
|
2015-11-23 08:37:07 +03:00
|
|
|
for (auto iter = mSheets->mPendingDatas.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
arr.AppendElement(iter.Data());
|
|
|
|
iter.Remove();
|
|
|
|
}
|
2007-05-31 05:42:48 +04:00
|
|
|
|
|
|
|
mDatasToNotifyOn += arr.Length();
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < arr.Length(); ++i) {
|
2007-05-31 05:42:48 +04:00
|
|
|
--mDatasToNotifyOn;
|
2015-09-21 00:56:10 +03:00
|
|
|
LoadSheet(arr[i], eSheetNeedsParser, false);
|
2007-05-31 05:42:48 +04:00
|
|
|
}
|
|
|
|
}
|
2010-03-03 00:00:53 +03:00
|
|
|
|
2014-07-02 02:37:09 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(Loader)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Loader)
|
|
|
|
if (tmp->mSheets) {
|
2015-10-23 07:17:36 +03:00
|
|
|
for (auto iter = tmp->mSheets->mCompleteSheets.Iter();
|
|
|
|
!iter.Done();
|
|
|
|
iter.Next()) {
|
|
|
|
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "Sheet cache nsCSSLoader");
|
2016-02-24 10:01:12 +03:00
|
|
|
if (iter.UserData()->IsGecko()) {
|
|
|
|
CSSStyleSheet* sheet = iter.UserData()->AsGecko();
|
|
|
|
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, sheet));
|
|
|
|
}
|
2015-10-23 07:17:36 +03:00
|
|
|
}
|
2012-10-08 06:39:09 +04:00
|
|
|
}
|
2014-07-02 02:37:09 +04:00
|
|
|
nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver>>::ForwardIterator
|
|
|
|
it(tmp->mObservers);
|
|
|
|
while (it.HasMore()) {
|
|
|
|
ImplCycleCollectionTraverse(cb, it.GetNext(),
|
|
|
|
"mozilla::css::Loader.mObservers");
|
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
2012-10-08 06:39:09 +04:00
|
|
|
|
2014-07-02 02:37:09 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Loader)
|
|
|
|
if (tmp->mSheets) {
|
|
|
|
tmp->mSheets->mCompleteSheets.Clear();
|
2012-10-08 06:39:09 +04:00
|
|
|
}
|
2014-07-02 02:37:09 +04:00
|
|
|
tmp->mObservers.Clear();
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Loader, AddRef)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Loader, Release)
|
2012-10-08 06:39:09 +04:00
|
|
|
|
2012-10-18 01:01:56 +04:00
|
|
|
size_t
|
2013-06-23 16:03:39 +04:00
|
|
|
Loader::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
2012-10-18 01:01:56 +04:00
|
|
|
{
|
2015-07-31 07:19:57 +03:00
|
|
|
size_t n = aMallocSizeOf(this);
|
2012-10-18 01:01:56 +04:00
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
if (mSheets) {
|
2015-07-31 07:19:57 +03:00
|
|
|
n += mSheets->mCompleteSheets.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = mSheets->mCompleteSheets.ConstIter();
|
|
|
|
!iter.Done();
|
|
|
|
iter.Next()) {
|
|
|
|
// If aSheet has a parent, then its parent will report it so we don't
|
|
|
|
// have to worry about it here. Likewise, if aSheet has an owning node,
|
|
|
|
// then the document that node is in will report it.
|
2016-09-26 15:03:25 +03:00
|
|
|
const StyleSheet* sheet = iter.UserData();
|
2016-02-24 10:01:12 +03:00
|
|
|
n += (sheet->GetOwnerNode() || sheet->GetParentSheet())
|
2015-07-31 07:19:57 +03:00
|
|
|
? 0
|
2016-02-24 10:01:12 +03:00
|
|
|
: sheet->SizeOfIncludingThis(aMallocSizeOf);
|
2015-07-31 07:19:57 +03:00
|
|
|
}
|
2013-09-02 12:41:57 +04:00
|
|
|
}
|
2015-07-31 07:19:57 +03:00
|
|
|
n += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2012-10-18 01:01:56 +04:00
|
|
|
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
|
|
// worthwhile:
|
|
|
|
// - mLoadingDatas: transient, and should be small
|
|
|
|
// - mPendingDatas: transient, and should be small
|
|
|
|
// - mParsingDatas: transient, and should be small
|
|
|
|
// - mPostedEvents: transient, and should be small
|
|
|
|
//
|
|
|
|
// The following members aren't measured:
|
|
|
|
// - mDocument, because it's a weak backpointer
|
|
|
|
// - mPreferredSheet, because it can be a shared string
|
|
|
|
|
2015-07-31 07:19:57 +03:00
|
|
|
return n;
|
2012-10-18 01:01:56 +04:00
|
|
|
}
|
|
|
|
|
2016-02-24 10:01:12 +03:00
|
|
|
StyleBackendType
|
|
|
|
Loader::GetStyleBackendType() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mStyleBackendType || mDocument,
|
|
|
|
"you must construct a Loader with a document or set a "
|
|
|
|
"StyleBackendType on it before calling GetStyleBackendType");
|
|
|
|
if (mStyleBackendType) {
|
|
|
|
return *mStyleBackendType;
|
|
|
|
}
|
|
|
|
return mDocument->GetStyleBackendType();
|
|
|
|
}
|
|
|
|
|
2010-03-03 00:00:53 +03:00
|
|
|
} // namespace css
|
|
|
|
} // namespace mozilla
|