mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 18:04:46 +00:00
Bug 1354989 - Avoid pivoting via UTF-16 when loading CSS in the Stylo mode. r=jdm,SimonSapin
MozReview-Commit-ID: Llt29dvB4Io --HG-- extra : rebase_source : 3ae51dc8beff3fb19e9318a6c7c30c9ab08a5b57
This commit is contained in:
parent
7d07e19274
commit
3c8567b60d
@ -9997,7 +9997,8 @@ NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
|
||||
} // namespace
|
||||
|
||||
void
|
||||
nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset,
|
||||
nsDocument::PreloadStyle(nsIURI* uri,
|
||||
const Encoding* aEncoding,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
const ReferrerPolicy aReferrerPolicy,
|
||||
const nsAString& aIntegrity)
|
||||
@ -10006,11 +10007,14 @@ nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset,
|
||||
nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
|
||||
|
||||
// Charset names are always ASCII.
|
||||
CSSLoader()->LoadSheet(uri, true, NodePrincipal(),
|
||||
NS_LossyConvertUTF16toASCII(charset),
|
||||
CSSLoader()->LoadSheet(uri,
|
||||
true,
|
||||
NodePrincipal(),
|
||||
aEncoding,
|
||||
obs,
|
||||
Element::StringToCORSMode(aCrossOriginAttr),
|
||||
aReferrerPolicy, aIntegrity);
|
||||
aReferrerPolicy,
|
||||
aIntegrity);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -836,7 +836,8 @@ public:
|
||||
virtual void MaybePreconnect(nsIURI* uri,
|
||||
mozilla::CORSMode aCORSMode) override;
|
||||
|
||||
virtual void PreloadStyle(nsIURI* uri, const nsAString& charset,
|
||||
virtual void PreloadStyle(nsIURI* uri,
|
||||
const mozilla::Encoding* aEncoding,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicy aReferrerPolicy,
|
||||
const nsAString& aIntegrity) override;
|
||||
|
@ -2464,7 +2464,8 @@ public:
|
||||
* parser if and when the parser is merged with libgklayout. aCrossOriginAttr
|
||||
* should be a void string if the attr is not present.
|
||||
*/
|
||||
virtual void PreloadStyle(nsIURI* aURI, const nsAString& aCharset,
|
||||
virtual void PreloadStyle(nsIURI* aURI,
|
||||
const mozilla::Encoding* aEncoding,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicyEnum aReferrerPolicy,
|
||||
const nsAString& aIntegrity) = 0;
|
||||
|
@ -182,22 +182,18 @@ SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
|
||||
|
||||
/* static */ nsresult
|
||||
SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
|
||||
nsIUnicharStreamLoader* aLoader,
|
||||
const nsAString& aString,
|
||||
nsIChannel* aChannel,
|
||||
const nsACString& aBytes,
|
||||
const nsACString& aSourceFileURI,
|
||||
nsIConsoleReportCollector* aReporter)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoader);
|
||||
NS_ENSURE_ARG_POINTER(aReporter);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
aLoader->GetChannel(getter_AddRefs(channel));
|
||||
|
||||
if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
|
||||
nsAutoCString requestURL;
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
if (channel &&
|
||||
NS_SUCCEEDED(channel->GetOriginalURI(getter_AddRefs(originalURI))) &&
|
||||
if (aChannel &&
|
||||
NS_SUCCEEDED(aChannel->GetOriginalURI(getter_AddRefs(originalURI))) &&
|
||||
originalURI) {
|
||||
originalURI->GetAsciiSpec(requestURL);
|
||||
}
|
||||
@ -205,14 +201,11 @@ SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
|
||||
}
|
||||
|
||||
SRICheckDataVerifier verifier(aMetadata, aSourceFileURI, aReporter);
|
||||
nsresult rv;
|
||||
nsDependentCString rawBuffer;
|
||||
rv = aLoader->GetRawBuffer(rawBuffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = verifier.Update(rawBuffer.Length(), (const uint8_t*)rawBuffer.get());
|
||||
nsresult rv =
|
||||
verifier.Update(aBytes.Length(), (const uint8_t*)aBytes.BeginReading());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return verifier.Verify(aMetadata, channel, aSourceFileURI, aReporter);
|
||||
return verifier.Verify(aMetadata, aChannel, aSourceFileURI, aReporter);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "nsICryptoHash.h"
|
||||
|
||||
class nsIChannel;
|
||||
class nsIUnicharStreamLoader;
|
||||
class nsIConsoleReportCollector;
|
||||
|
||||
namespace mozilla {
|
||||
@ -39,8 +38,8 @@ public:
|
||||
* must prevent the resource from loading.
|
||||
*/
|
||||
static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
|
||||
nsIUnicharStreamLoader* aLoader,
|
||||
const nsAString& aString,
|
||||
nsIChannel* aChannel,
|
||||
const nsACString& aBytes,
|
||||
const nsACString& aSourceFileURI,
|
||||
nsIConsoleReportCollector* aReporter);
|
||||
};
|
||||
|
@ -151,7 +151,7 @@ nsXBLResourceLoader::LoadResources(nsIContent* aBoundElement)
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = cssLoader->LoadSheet(url, false, docPrincipal, EmptyCString(), this);
|
||||
rv = cssLoader->LoadSheet(url, false, docPrincipal, nullptr, this);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
++mPendingSheets;
|
||||
}
|
||||
|
@ -3738,10 +3738,8 @@ XULDocument::AddPrototypeSheets()
|
||||
nsCOMPtr<nsIURI> uri = sheets[i];
|
||||
|
||||
RefPtr<StyleSheet> incompleteSheet;
|
||||
rv = CSSLoader()->LoadSheet(uri,
|
||||
mCurrentPrototype->DocumentPrincipal(),
|
||||
EmptyCString(), this,
|
||||
&incompleteSheet);
|
||||
rv = CSSLoader()->LoadSheet(
|
||||
uri, mCurrentPrototype->DocumentPrincipal(), this, &incompleteSheet);
|
||||
|
||||
// XXXldb We need to prevent bogus sheets from being held in the
|
||||
// prototype's list, but until then, don't propagate the failure
|
||||
|
@ -2839,8 +2839,8 @@ HTMLEditor::ReplaceStyleSheet(const nsAString& aURL)
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uaURI), aURL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return ps->GetDocument()->CSSLoader()->
|
||||
LoadSheet(uaURI, false, nullptr, EmptyCString(), this);
|
||||
return ps->GetDocument()->CSSLoader()->LoadSheet(
|
||||
uaURI, false, nullptr, nullptr, this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -88,6 +88,14 @@ mozilla_encoding_decode_to_nscstring_without_bom_handling(
|
||||
nsACString const* src,
|
||||
nsACString* dst);
|
||||
|
||||
nsresult
|
||||
mozilla_encoding_decode_from_slice_to_nscstring_without_bom_handling(
|
||||
mozilla::Encoding const* encoding,
|
||||
uint8_t const* src,
|
||||
size_t src_len,
|
||||
nsACString* dst,
|
||||
size_t already_validated);
|
||||
|
||||
nsresult
|
||||
mozilla_encoding_decode_to_nscstring_without_bom_handling_and_without_replacement(
|
||||
mozilla::Encoding const* encoding,
|
||||
@ -552,6 +560,41 @@ public:
|
||||
this, bytes, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode complete input to `nsACString` _without BOM handling_ and
|
||||
* with malformed sequences replaced with the REPLACEMENT CHARACTER when
|
||||
* the entire input is available as a single buffer (i.e. the end of the
|
||||
* buffer marks the end of the stream) _asserting that a number of bytes
|
||||
* from the start are already known to be valid UTF-8_.
|
||||
*
|
||||
* The use case for this method is avoiding copying when dealing with
|
||||
* input that has a UTF-8 BOM. _When in doubt, do not use this method._
|
||||
*
|
||||
* When invoked on `UTF_8`, this method implements the (non-streaming
|
||||
* version of) the _UTF-8 decode without BOM_
|
||||
* (https://encoding.spec.whatwg.org/#utf-8-decode-without-bom) spec concept.
|
||||
*
|
||||
* Returns `NS_ERROR_OUT_OF_MEMORY` upon OOM, `NS_OK_HAD_REPLACEMENTS`
|
||||
* if there were malformed sequences (that were replaced with the
|
||||
* REPLACEMENT CHARACTER) and `NS_OK` otherwise.
|
||||
*
|
||||
* _Note:_ It is wrong to use this when the input buffer represents only
|
||||
* a segment of the input instead of the whole input. Use
|
||||
* `NewDecoderWithoutBOMHandling()` when decoding segmented input.
|
||||
*
|
||||
* # Safety
|
||||
*
|
||||
* The first `aAlreadyValidated` bytes of `aBytes` _must_ be valid UTF-8.
|
||||
* `aBytes` _must not_ alias the buffer (if any) of `aOut`.
|
||||
*/
|
||||
inline nsresult DecodeWithoutBOMHandling(Span<const uint8_t> aBytes,
|
||||
nsACString& aOut,
|
||||
size_t aAlreadyValidated) const
|
||||
{
|
||||
return mozilla_encoding_decode_from_slice_to_nscstring_without_bom_handling(
|
||||
this, aBytes.Elements(), aBytes.Length(), &aOut, aAlreadyValidated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode complete input to `nsAString` _without BOM handling_ and
|
||||
* _with malformed sequences treated as fatal_ when the entire input is
|
||||
|
@ -421,6 +421,11 @@ pub fn decode_to_nscstring_without_bom_handling(encoding: &'static Encoding,
|
||||
decode_from_slice_to_nscstring_without_bom_handling(encoding, src, dst, valid_up_to)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mozilla_encoding_decode_from_slice_to_nscstring_without_bom_handling(encoding: *const Encoding, src: *const u8, src_len: usize, dst: *mut nsACString, already_validated: usize) -> nsresult {
|
||||
decode_from_slice_to_nscstring_without_bom_handling(&*encoding, slice::from_raw_parts(src, src_len), &mut *dst, already_validated)
|
||||
}
|
||||
|
||||
fn decode_from_slice_to_nscstring_without_bom_handling(encoding: &'static Encoding,
|
||||
src: &[u8],
|
||||
dst: &mut nsACString,
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
#include "mozilla/ConsoleReportCollector.h"
|
||||
#include "mozilla/ServoUtils.h"
|
||||
#include "mozilla/css/StreamLoader.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPrototypeCache.h"
|
||||
@ -68,6 +69,9 @@
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
// 1024 bytes is specified in https://drafts.csswg.org/css-syntax/
|
||||
#define SNIFFING_BUFFER_SIZE 1024
|
||||
|
||||
/**
|
||||
* OVERALL ARCHITECTURE
|
||||
*
|
||||
@ -97,162 +101,6 @@ using namespace mozilla::dom;
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
/*********************************************
|
||||
* Data needed to properly load a stylesheet *
|
||||
*********************************************/
|
||||
|
||||
static_assert(eAuthorSheetFeatures == 0 &&
|
||||
eUserSheetFeatures == 1 &&
|
||||
eAgentSheetFeatures == 2,
|
||||
"sheet parsing mode constants won't fit "
|
||||
"in SheetLoadData::mParsingMode");
|
||||
|
||||
class SheetLoadData final : public nsIRunnable,
|
||||
public nsIUnicharStreamLoaderObserver,
|
||||
public nsIThreadObserver
|
||||
{
|
||||
protected:
|
||||
virtual ~SheetLoadData(void);
|
||||
|
||||
public:
|
||||
// Data for loading a sheet linked from a document
|
||||
SheetLoadData(Loader* aLoader,
|
||||
const nsAString& aTitle,
|
||||
nsIURI* aURI,
|
||||
StyleSheet* aSheet,
|
||||
nsIStyleSheetLinkingElement* aOwningElement,
|
||||
bool aIsAlternate,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode);
|
||||
|
||||
// Data for loading a sheet linked from an @import rule
|
||||
SheetLoadData(Loader* aLoader,
|
||||
nsIURI* aURI,
|
||||
StyleSheet* aSheet,
|
||||
SheetLoadData* aParentData,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode);
|
||||
|
||||
// Data for loading a non-document sheet
|
||||
SheetLoadData(Loader* aLoader,
|
||||
nsIURI* aURI,
|
||||
StyleSheet* aSheet,
|
||||
bool aSyncLoad,
|
||||
bool aUseSystemPrincipal,
|
||||
const nsCString& aCharset,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode);
|
||||
|
||||
already_AddRefed<nsIURI> GetReferrerURI();
|
||||
|
||||
void ScheduleLoadEventIfNeeded(nsresult aStatus);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSITHREADOBSERVER
|
||||
NS_DECL_NSIUNICHARSTREAMLOADEROBSERVER
|
||||
|
||||
// Hold a ref to the CSSLoader so we can call back to it to let it
|
||||
// know the load finished
|
||||
RefPtr<Loader> mLoader;
|
||||
|
||||
// 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.
|
||||
uint32_t mLineNumber;
|
||||
|
||||
// The sheet we're loading data for
|
||||
RefPtr<StyleSheet> mSheet;
|
||||
|
||||
// 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
|
||||
RefPtr<SheetLoadData> mParentData;
|
||||
|
||||
// Number of sheets we @import-ed that are still loading
|
||||
uint32_t mPendingChildren;
|
||||
|
||||
// mSyncLoad is true when the load needs to be synchronous -- right
|
||||
// now only for LoadSheetSync and children of sync loads.
|
||||
bool mSyncLoad : 1;
|
||||
|
||||
// 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.
|
||||
bool mIsNonDocumentSheet : 1;
|
||||
|
||||
// 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).
|
||||
bool mIsLoading : 1;
|
||||
|
||||
// mIsCancelled is set to true when a sheet load is stopped by
|
||||
// Stop() or StopLoadingSheet() (which was removed in Bug 556446).
|
||||
// SheetLoadData::OnStreamComplete() checks this to avoid parsing
|
||||
// sheets that have been cancelled and such.
|
||||
bool mIsCancelled : 1;
|
||||
|
||||
// mMustNotify is true if the load data is being loaded async and
|
||||
// the original function call that started the load has returned.
|
||||
// This applies only to observer notifications; load/error events
|
||||
// are fired for any SheetLoadData that has a non-null
|
||||
// mOwningElement.
|
||||
bool mMustNotify : 1;
|
||||
|
||||
// mWasAlternate is true if the sheet was an alternate when the load data was
|
||||
// created.
|
||||
bool mWasAlternate : 1;
|
||||
|
||||
// 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.
|
||||
bool mUseSystemPrincipal : 1;
|
||||
|
||||
// If true, this SheetLoadData is being used as a way to handle
|
||||
// async observer notification for an already-complete sheet.
|
||||
bool mSheetAlreadyComplete : 1;
|
||||
|
||||
// This is the element that imported the sheet. Needed to get the
|
||||
// charset set on it and to fire load/error events.
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
|
||||
|
||||
// The observer that wishes to be notified of load completion
|
||||
nsCOMPtr<nsICSSLoaderObserver> mObserver;
|
||||
|
||||
// The principal that identifies who started loading us.
|
||||
nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
|
||||
|
||||
// The node that identifies who started loading us.
|
||||
nsCOMPtr<nsINode> mRequestingNode;
|
||||
|
||||
// The charset to use if the transport and sheet don't indicate one.
|
||||
// May be empty. Must be empty if mOwningElement is non-null.
|
||||
nsCString mCharsetHint;
|
||||
|
||||
// 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.
|
||||
MOZ_INIT_OUTSIDE_CTOR nsresult mStatus;
|
||||
|
||||
private:
|
||||
void FireLoadEvent(nsIThreadInternal* aThread);
|
||||
};
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
static mozilla::LazyLogModule sCssLoaderLog("nsCSSLoader");
|
||||
@ -301,25 +149,27 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode)
|
||||
: mLoader(aLoader),
|
||||
mTitle(aTitle),
|
||||
mURI(aURI),
|
||||
mLineNumber(1),
|
||||
mSheet(aSheet),
|
||||
mNext(nullptr),
|
||||
mPendingChildren(0),
|
||||
mSyncLoad(false),
|
||||
mIsNonDocumentSheet(false),
|
||||
mIsLoading(false),
|
||||
mIsCancelled(false),
|
||||
mMustNotify(false),
|
||||
mWasAlternate(aIsAlternate),
|
||||
mUseSystemPrincipal(false),
|
||||
mSheetAlreadyComplete(false),
|
||||
mOwningElement(aOwningElement),
|
||||
mObserver(aObserver),
|
||||
mLoaderPrincipal(aLoaderPrincipal),
|
||||
mRequestingNode(aRequestingNode)
|
||||
: mLoader(aLoader)
|
||||
, mTitle(aTitle)
|
||||
, mEncoding(nullptr)
|
||||
, mURI(aURI)
|
||||
, mLineNumber(1)
|
||||
, mSheet(aSheet)
|
||||
, mNext(nullptr)
|
||||
, mPendingChildren(0)
|
||||
, mSyncLoad(false)
|
||||
, mIsNonDocumentSheet(false)
|
||||
, mIsLoading(false)
|
||||
, mIsCancelled(false)
|
||||
, mMustNotify(false)
|
||||
, mWasAlternate(aIsAlternate)
|
||||
, mUseSystemPrincipal(false)
|
||||
, mSheetAlreadyComplete(false)
|
||||
, mOwningElement(aOwningElement)
|
||||
, mObserver(aObserver)
|
||||
, mLoaderPrincipal(aLoaderPrincipal)
|
||||
, mRequestingNode(aRequestingNode)
|
||||
, mPreloadEncoding(nullptr)
|
||||
{
|
||||
NS_PRECONDITION(mLoader, "Must have a loader!");
|
||||
}
|
||||
@ -331,25 +181,27 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode)
|
||||
: mLoader(aLoader),
|
||||
mURI(aURI),
|
||||
mLineNumber(1),
|
||||
mSheet(aSheet),
|
||||
mNext(nullptr),
|
||||
mParentData(aParentData),
|
||||
mPendingChildren(0),
|
||||
mSyncLoad(false),
|
||||
mIsNonDocumentSheet(false),
|
||||
mIsLoading(false),
|
||||
mIsCancelled(false),
|
||||
mMustNotify(false),
|
||||
mWasAlternate(false),
|
||||
mUseSystemPrincipal(false),
|
||||
mSheetAlreadyComplete(false),
|
||||
mOwningElement(nullptr),
|
||||
mObserver(aObserver),
|
||||
mLoaderPrincipal(aLoaderPrincipal),
|
||||
mRequestingNode(aRequestingNode)
|
||||
: mLoader(aLoader)
|
||||
, mEncoding(nullptr)
|
||||
, mURI(aURI)
|
||||
, mLineNumber(1)
|
||||
, mSheet(aSheet)
|
||||
, mNext(nullptr)
|
||||
, mParentData(aParentData)
|
||||
, mPendingChildren(0)
|
||||
, mSyncLoad(false)
|
||||
, mIsNonDocumentSheet(false)
|
||||
, mIsLoading(false)
|
||||
, mIsCancelled(false)
|
||||
, mMustNotify(false)
|
||||
, mWasAlternate(false)
|
||||
, mUseSystemPrincipal(false)
|
||||
, mSheetAlreadyComplete(false)
|
||||
, mOwningElement(nullptr)
|
||||
, mObserver(aObserver)
|
||||
, mLoaderPrincipal(aLoaderPrincipal)
|
||||
, mRequestingNode(aRequestingNode)
|
||||
, mPreloadEncoding(nullptr)
|
||||
{
|
||||
NS_PRECONDITION(mLoader, "Must have a loader!");
|
||||
if (mParentData) {
|
||||
@ -368,29 +220,30 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
|
||||
StyleSheet* aSheet,
|
||||
bool aSyncLoad,
|
||||
bool aUseSystemPrincipal,
|
||||
const nsCString& aCharset,
|
||||
const Encoding* aPreloadEncoding,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode)
|
||||
: mLoader(aLoader),
|
||||
mURI(aURI),
|
||||
mLineNumber(1),
|
||||
mSheet(aSheet),
|
||||
mNext(nullptr),
|
||||
mPendingChildren(0),
|
||||
mSyncLoad(aSyncLoad),
|
||||
mIsNonDocumentSheet(true),
|
||||
mIsLoading(false),
|
||||
mIsCancelled(false),
|
||||
mMustNotify(false),
|
||||
mWasAlternate(false),
|
||||
mUseSystemPrincipal(aUseSystemPrincipal),
|
||||
mSheetAlreadyComplete(false),
|
||||
mOwningElement(nullptr),
|
||||
mObserver(aObserver),
|
||||
mLoaderPrincipal(aLoaderPrincipal),
|
||||
mRequestingNode(aRequestingNode),
|
||||
mCharsetHint(aCharset)
|
||||
: mLoader(aLoader)
|
||||
, mEncoding(nullptr)
|
||||
, mURI(aURI)
|
||||
, mLineNumber(1)
|
||||
, mSheet(aSheet)
|
||||
, mNext(nullptr)
|
||||
, mPendingChildren(0)
|
||||
, mSyncLoad(aSyncLoad)
|
||||
, mIsNonDocumentSheet(true)
|
||||
, mIsLoading(false)
|
||||
, mIsCancelled(false)
|
||||
, mMustNotify(false)
|
||||
, mWasAlternate(false)
|
||||
, mUseSystemPrincipal(aUseSystemPrincipal)
|
||||
, mSheetAlreadyComplete(false)
|
||||
, mOwningElement(nullptr)
|
||||
, mObserver(aObserver)
|
||||
, mLoaderPrincipal(aLoaderPrincipal)
|
||||
, mRequestingNode(aRequestingNode)
|
||||
, mPreloadEncoding(aPreloadEncoding)
|
||||
{
|
||||
NS_PRECONDITION(mLoader, "Must have a loader!");
|
||||
NS_POSTCONDITION(!mUseSystemPrincipal || mSyncLoad,
|
||||
@ -645,123 +498,90 @@ static bool GetCharsetFromData(const char* aStyleSheetData,
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SheetLoadData::OnDetermineCharset(nsIUnicharStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsACString const& aSegment,
|
||||
nsACString& aCharset)
|
||||
NotNull<const Encoding*>
|
||||
SheetLoadData::DetermineNonBOMEncoding(nsACString const& aSegment,
|
||||
nsIChannel* aChannel)
|
||||
{
|
||||
NS_PRECONDITION(!mOwningElement || mCharsetHint.IsEmpty(),
|
||||
"Can't have element _and_ charset hint");
|
||||
|
||||
LOG_URI("SheetLoadData::OnDetermineCharset for '%s'", mURI);
|
||||
|
||||
// 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
|
||||
|
||||
aCharset.Truncate();
|
||||
|
||||
const Encoding* encoding;
|
||||
size_t bomLength;
|
||||
Tie(encoding, bomLength) = Encoding::ForBOM(aSegment);
|
||||
Unused << bomLength;
|
||||
if (encoding) {
|
||||
encoding->Name(aCharset);
|
||||
// aCharset is now either "UTF-16BE", "UTF-16BE" or "UTF-8"
|
||||
// which will swallow the BOM.
|
||||
mCharset.Assign(aCharset);
|
||||
LOG((" Setting from BOM to: %s", PromiseFlatCString(aCharset).get()));
|
||||
return NS_OK;
|
||||
}
|
||||
nsAutoCString label;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsAutoCString specified;
|
||||
aLoader->GetChannel(getter_AddRefs(channel));
|
||||
if (channel) {
|
||||
channel->GetContentCharset(specified);
|
||||
encoding = Encoding::ForLabel(specified);
|
||||
// Check HTTP
|
||||
if (aChannel && NS_SUCCEEDED(aChannel->GetContentCharset(label))) {
|
||||
encoding = Encoding::ForLabel(label);
|
||||
if (encoding) {
|
||||
encoding->Name(aCharset);
|
||||
mCharset.Assign(aCharset);
|
||||
LOG((" Setting from HTTP to: %s", PromiseFlatCString(aCharset).get()));
|
||||
return NS_OK;
|
||||
return WrapNotNull(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetCharsetFromData(aSegment.BeginReading(),
|
||||
aSegment.Length(),
|
||||
specified)) {
|
||||
encoding = Encoding::ForLabel(specified);
|
||||
// Check @charset
|
||||
auto sniffingLength = aSegment.Length();
|
||||
if (sniffingLength > SNIFFING_BUFFER_SIZE) {
|
||||
sniffingLength = SNIFFING_BUFFER_SIZE;
|
||||
}
|
||||
if (GetCharsetFromData(aSegment.BeginReading(), sniffingLength, label)) {
|
||||
encoding = Encoding::ForLabel(label);
|
||||
if (encoding == UTF_16BE_ENCODING || encoding == UTF_16LE_ENCODING) {
|
||||
return UTF_8_ENCODING;
|
||||
}
|
||||
if (encoding) {
|
||||
encoding->Name(aCharset);
|
||||
if (encoding == UTF_16BE_ENCODING ||
|
||||
encoding == UTF_16LE_ENCODING) {
|
||||
// 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;
|
||||
return WrapNotNull(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
// Now try the charset on the <link> or processing instruction
|
||||
// that loaded us
|
||||
if (mOwningElement) {
|
||||
nsAutoString specified16;
|
||||
mOwningElement->GetCharset(specified16);
|
||||
encoding = Encoding::ForLabel(specified16);
|
||||
nsAutoString label16;
|
||||
mOwningElement->GetCharset(label16);
|
||||
encoding = Encoding::ForLabel(label16);
|
||||
if (encoding) {
|
||||
encoding->Name(aCharset);
|
||||
mCharset.Assign(aCharset);
|
||||
LOG((" Setting from charset attribute to: %s",
|
||||
PromiseFlatCString(aCharset).get()));
|
||||
return NS_OK;
|
||||
return WrapNotNull(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
// In the preload case, the value of the charset attribute on <link> comes
|
||||
// in via mCharsetHint instead.
|
||||
encoding = Encoding::ForLabel(mCharsetHint);
|
||||
if (encoding) {
|
||||
encoding->Name(aCharset);
|
||||
mCharset.Assign(aCharset);
|
||||
LOG((" Setting from charset attribute (preload case) to: %s",
|
||||
PromiseFlatCString(aCharset).get()));
|
||||
return NS_OK;
|
||||
// in via mPreloadEncoding instead.
|
||||
if (mPreloadEncoding) {
|
||||
return WrapNotNull(mPreloadEncoding);
|
||||
}
|
||||
|
||||
// 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;
|
||||
encoding = mParentData->mEncoding;
|
||||
if (encoding) {
|
||||
return WrapNotNull(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
if (mLoader->mDocument) {
|
||||
// no useful data on charset. Try the document charset.
|
||||
auto encoding = mLoader->mDocument->GetDocumentCharacterSet();
|
||||
encoding->Name(aCharset);
|
||||
mCharset.Assign(aCharset);
|
||||
LOG((" Setting from document to: %s", PromiseFlatCString(aCharset).get()));
|
||||
return NS_OK;
|
||||
// Use the document charset.
|
||||
return mLoader->mDocument->GetDocumentCharacterSet();
|
||||
}
|
||||
|
||||
aCharset.AssignLiteral("UTF-8");
|
||||
mCharset = aCharset;
|
||||
LOG((" Setting from default to: %s", PromiseFlatCString(aCharset).get()));
|
||||
return UTF_8_ENCODING;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoding decision for the old style system
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
SheetLoadData::OnDetermineCharset(nsIUnicharStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsACString const& aSegment,
|
||||
nsACString& aCharset)
|
||||
{
|
||||
const Encoding* encoding;
|
||||
size_t bomLength;
|
||||
Tie(encoding, bomLength) = Encoding::ForBOM(aSegment);
|
||||
Unused << bomLength;
|
||||
if (!encoding) {
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
aLoader->GetChannel(getter_AddRefs(channel));
|
||||
encoding = DetermineNonBOMEncoding(aSegment, channel);
|
||||
}
|
||||
|
||||
encoding->Name(aCharset);
|
||||
mEncoding = encoding;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -777,15 +597,41 @@ SheetLoadData::GetReferrerURI()
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Load completion for the old style system.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
const nsAString& aBuffer)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
aLoader->GetChannel(getter_AddRefs(channel));
|
||||
nsCString bytes;
|
||||
aLoader->GetRawBuffer(bytes);
|
||||
|
||||
nsresult rv = VerifySheetReadyToParse(aStatus, bytes, channel);
|
||||
if (rv != NS_OK_PARSE_SHEET) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool completed;
|
||||
rv = mLoader->ParseSheet(aBuffer, Span<const uint8_t>(), this, completed);
|
||||
NS_ASSERTION(completed || !mSyncLoad, "sync load did not complete");
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stream completion code shared by Stylo and the old style system.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
nsresult
|
||||
SheetLoadData::VerifySheetReadyToParse(nsresult aStatus,
|
||||
const nsACString& aBytes,
|
||||
nsIChannel* aChannel)
|
||||
{
|
||||
LOG(("SheetLoadData::OnStreamComplete"));
|
||||
NS_ASSERTION(!mLoader->mSyncCallback, "Synchronous callback from necko");
|
||||
@ -826,16 +672,13 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult result = aLoader->GetChannel(getter_AddRefs(channel));
|
||||
if (NS_FAILED(result)) {
|
||||
LOG_WARN((" No channel from loader"));
|
||||
mLoader->SheetComplete(this, result);
|
||||
if (!aChannel) {
|
||||
mLoader->SheetComplete(this, NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
channel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||
aChannel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||
|
||||
// If the channel's original URI is "chrome:", we want that, since
|
||||
// the observer code in nsXULPrototypeCache depends on chrome stylesheets
|
||||
@ -843,7 +686,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
// this codepath seems nondeterministic.)
|
||||
// Otherwise we want the potentially-HTTP-redirected URI.
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
NS_GetFinalChannelURI(channel, getter_AddRefs(channelURI));
|
||||
NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
|
||||
|
||||
if (!channelURI || !originalURI) {
|
||||
NS_ERROR("Someone just violated the nsIRequest contract");
|
||||
@ -854,12 +697,13 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
result = NS_ERROR_NOT_AVAILABLE;
|
||||
nsresult result = NS_ERROR_NOT_AVAILABLE;
|
||||
if (secMan) { // Could be null if we already shut down
|
||||
if (mUseSystemPrincipal) {
|
||||
result = secMan->GetSystemPrincipal(getter_AddRefs(principal));
|
||||
} else {
|
||||
result = secMan->GetChannelResultPrincipal(channel, getter_AddRefs(principal));
|
||||
result =
|
||||
secMan->GetChannelResultPrincipal(aChannel, getter_AddRefs(principal));
|
||||
}
|
||||
}
|
||||
|
||||
@ -873,7 +717,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
|
||||
// If it's an HTTP channel, we want to make sure this is not an
|
||||
// error document we got.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
|
||||
if (httpChannel) {
|
||||
bool requestSucceeded;
|
||||
result = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
||||
@ -890,9 +734,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
}
|
||||
|
||||
nsAutoCString contentType;
|
||||
if (channel) {
|
||||
channel->GetContentType(contentType);
|
||||
}
|
||||
aChannel->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
|
||||
@ -949,7 +791,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
SRIMetadata sriMetadata;
|
||||
mSheet->GetIntegrity(sriMetadata);
|
||||
if (sriMetadata.IsEmpty()) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
if (loadInfo && loadInfo->GetEnforceSRI()) {
|
||||
LOG((" Load was blocked by SRI"));
|
||||
MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
|
||||
@ -972,11 +814,11 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
if (mLoader->mDocument && mLoader->mDocument->GetDocumentURI()) {
|
||||
mLoader->mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
|
||||
}
|
||||
nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader, aBuffer,
|
||||
sourceUri, mLoader->mReporter);
|
||||
nsresult rv = SRICheck::VerifyIntegrity(
|
||||
sriMetadata, aChannel, aBytes, sourceUri, mLoader->mReporter);
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
channel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
if (loadGroup) {
|
||||
mLoader->mReporter->FlushConsoleReports(loadGroup);
|
||||
} else {
|
||||
@ -995,11 +837,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
||||
// Enough to set the URIs on mSheet, since any sibling datas we have share
|
||||
// the same mInner as mSheet and will thus get the same URI.
|
||||
mSheet->SetURIs(channelURI, originalURI, channelURI);
|
||||
|
||||
bool completed;
|
||||
result = mLoader->ParseSheet(aBuffer, this, completed);
|
||||
NS_ASSERTION(completed || !mSyncLoad, "sync load did not complete");
|
||||
return result;
|
||||
return NS_OK_PARSE_SHEET;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1469,12 +1307,19 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
|
||||
// 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;
|
||||
nsCOMPtr<nsIStreamListener> streamLoader;
|
||||
if (aLoadData->mSheet->IsGecko()) {
|
||||
nsCOMPtr<nsIUnicharStreamLoader> unicharStreamLoader;
|
||||
rv = NS_NewUnicharStreamLoader(getter_AddRefs(unicharStreamLoader),
|
||||
aLoadData);
|
||||
streamLoader = unicharStreamLoader;
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG_ERROR((" Failed to create stream loader for sync load"));
|
||||
SheetComplete(aLoadData, rv);
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
streamLoader = new StreamLoader(aLoadData);
|
||||
}
|
||||
|
||||
if (mDocument) {
|
||||
@ -1707,15 +1552,22 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
|
||||
// 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;
|
||||
rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader), aLoadData);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCOMPtr<nsIStreamListener> streamLoader;
|
||||
if (aLoadData->mSheet->IsGecko()) {
|
||||
nsCOMPtr<nsIUnicharStreamLoader> unicharStreamLoader;
|
||||
rv =
|
||||
NS_NewUnicharStreamLoader(getter_AddRefs(unicharStreamLoader), aLoadData);
|
||||
streamLoader = unicharStreamLoader;
|
||||
if (NS_FAILED(rv)) {
|
||||
#ifdef DEBUG
|
||||
mSyncCallback = false;
|
||||
mSyncCallback = false;
|
||||
#endif
|
||||
LOG_ERROR((" Failed to create stream loader"));
|
||||
SheetComplete(aLoadData, rv);
|
||||
return rv;
|
||||
LOG_ERROR((" Failed to create stream loader"));
|
||||
SheetComplete(aLoadData, rv);
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
streamLoader = new StreamLoader(aLoadData);
|
||||
}
|
||||
|
||||
if (mDocument) {
|
||||
@ -1749,7 +1601,8 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
|
||||
* correctly.
|
||||
*/
|
||||
nsresult
|
||||
Loader::ParseSheet(const nsAString& aInput,
|
||||
Loader::ParseSheet(const nsAString& aUTF16,
|
||||
Span<const uint8_t> aUTF8,
|
||||
SheetLoadData* aLoadData,
|
||||
bool& aCompleted)
|
||||
{
|
||||
@ -1768,16 +1621,20 @@ Loader::ParseSheet(const nsAString& aInput,
|
||||
|
||||
if (aLoadData->mSheet->IsGecko()) {
|
||||
nsCSSParser parser(this, aLoadData->mSheet->AsGecko());
|
||||
rv = parser.ParseSheet(aInput, sheetURI, baseURI,
|
||||
rv = parser.ParseSheet(aUTF16,
|
||||
sheetURI,
|
||||
baseURI,
|
||||
aLoadData->mSheet->Principal(),
|
||||
aLoadData->mLineNumber);
|
||||
} else {
|
||||
rv =
|
||||
aLoadData->mSheet->AsServo()->ParseSheet(this,
|
||||
aInput, sheetURI, baseURI,
|
||||
aLoadData->mSheet->Principal(),
|
||||
aLoadData->mLineNumber,
|
||||
GetCompatibilityMode());
|
||||
rv = aLoadData->mSheet->AsServo()->ParseSheet(
|
||||
this,
|
||||
aUTF8.IsEmpty() ? NS_ConvertUTF16toUTF8(aUTF16) : aUTF8,
|
||||
sheetURI,
|
||||
baseURI,
|
||||
aLoadData->mSheet->Principal(),
|
||||
aLoadData->mLineNumber,
|
||||
GetCompatibilityMode());
|
||||
}
|
||||
|
||||
mParsingDatas.RemoveElementAt(mParsingDatas.Length() - 1);
|
||||
@ -2036,7 +1893,7 @@ Loader::LoadInlineStyle(nsIContent* aElement,
|
||||
NS_ADDREF(data);
|
||||
data->mLineNumber = aLineNumber;
|
||||
// Parse completion releases the load data
|
||||
rv = ParseSheet(aBuffer, data, *aCompleted);
|
||||
rv = ParseSheet(aBuffer, Span<const uint8_t>(), data, *aCompleted);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If aCompleted is true, |data| may well be deleted by now.
|
||||
@ -2312,9 +2169,13 @@ Loader::LoadSheetSync(nsIURI* aURL,
|
||||
{
|
||||
LOG(("css::Loader::LoadSheetSync"));
|
||||
return InternalLoadNonDocumentSheet(aURL,
|
||||
false, aParsingMode, aUseSystemPrincipal,
|
||||
nullptr, EmptyCString(),
|
||||
aSheet, nullptr);
|
||||
false,
|
||||
aParsingMode,
|
||||
aUseSystemPrincipal,
|
||||
nullptr,
|
||||
nullptr,
|
||||
aSheet,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2326,31 +2187,38 @@ Loader::LoadSheet(nsIURI* aURL,
|
||||
{
|
||||
LOG(("css::Loader::LoadSheet(aURL, aParsingMode, aUseSystemPrincipal, aObserver, aSheet)"));
|
||||
return InternalLoadNonDocumentSheet(aURL,
|
||||
false, aParsingMode, aUseSystemPrincipal,
|
||||
nullptr, EmptyCString(),
|
||||
aSheet, aObserver);
|
||||
false,
|
||||
aParsingMode,
|
||||
aUseSystemPrincipal,
|
||||
nullptr,
|
||||
nullptr,
|
||||
aSheet,
|
||||
aObserver);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Loader::LoadSheet(nsIURI* aURL,
|
||||
nsIPrincipal* aOriginPrincipal,
|
||||
const nsCString& aCharset,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
RefPtr<StyleSheet>* aSheet)
|
||||
{
|
||||
LOG(("css::Loader::LoadSheet(aURL, aObserver, aSheet) api call"));
|
||||
NS_PRECONDITION(aSheet, "aSheet is null");
|
||||
return InternalLoadNonDocumentSheet(aURL,
|
||||
false, eAuthorSheetFeatures, false,
|
||||
aOriginPrincipal, aCharset,
|
||||
aSheet, aObserver);
|
||||
false,
|
||||
eAuthorSheetFeatures,
|
||||
false,
|
||||
aOriginPrincipal,
|
||||
nullptr,
|
||||
aSheet,
|
||||
aObserver);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Loader::LoadSheet(nsIURI* aURL,
|
||||
bool aIsPreload,
|
||||
nsIPrincipal* aOriginPrincipal,
|
||||
const nsCString& aCharset,
|
||||
const Encoding* aPreloadEncoding,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode,
|
||||
ReferrerPolicy aReferrerPolicy,
|
||||
@ -2358,10 +2226,16 @@ Loader::LoadSheet(nsIURI* aURL,
|
||||
{
|
||||
LOG(("css::Loader::LoadSheet(aURL, aObserver) api call"));
|
||||
return InternalLoadNonDocumentSheet(aURL,
|
||||
aIsPreload, eAuthorSheetFeatures, false,
|
||||
aOriginPrincipal, aCharset,
|
||||
nullptr, aObserver,
|
||||
aCORSMode, aReferrerPolicy, aIntegrity);
|
||||
aIsPreload,
|
||||
eAuthorSheetFeatures,
|
||||
false,
|
||||
aOriginPrincipal,
|
||||
aPreloadEncoding,
|
||||
nullptr,
|
||||
aObserver,
|
||||
aCORSMode,
|
||||
aReferrerPolicy,
|
||||
aIntegrity);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2370,7 +2244,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
|
||||
SheetParsingMode aParsingMode,
|
||||
bool aUseSystemPrincipal,
|
||||
nsIPrincipal* aOriginPrincipal,
|
||||
const nsCString& aCharset,
|
||||
const Encoding* aPreloadEncoding,
|
||||
RefPtr<StyleSheet>* aSheet,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode,
|
||||
@ -2421,10 +2295,15 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
|
||||
return rv;
|
||||
}
|
||||
|
||||
SheetLoadData* data =
|
||||
new SheetLoadData(this, aURL, sheet, syncLoad,
|
||||
aUseSystemPrincipal, aCharset, aObserver,
|
||||
aOriginPrincipal, mDocument);
|
||||
SheetLoadData* data = new SheetLoadData(this,
|
||||
aURL,
|
||||
sheet,
|
||||
syncLoad,
|
||||
aUseSystemPrincipal,
|
||||
aPreloadEncoding,
|
||||
aObserver,
|
||||
aOriginPrincipal,
|
||||
mDocument);
|
||||
|
||||
NS_ADDREF(data);
|
||||
rv = LoadSheet(data, state, aIsPreload);
|
||||
|
@ -375,11 +375,6 @@ public:
|
||||
* @param aOriginPrincipal the principal to use for security checks. This
|
||||
* can be null to indicate that these checks should
|
||||
* be skipped.
|
||||
* @param aCharset the encoding to use for converting the sheet data
|
||||
* from bytes to Unicode. May be empty to indicate that the
|
||||
* charset of the CSSLoader's document should be used. This
|
||||
* is only used if neither the network transport nor the
|
||||
* sheet itself indicate an encoding.
|
||||
* @param aObserver the observer to notify when the load completes.
|
||||
* Must not be null.
|
||||
* @param [out] aSheet the sheet to load. Note that the sheet may well
|
||||
@ -387,7 +382,6 @@ public:
|
||||
*/
|
||||
nsresult LoadSheet(nsIURI* aURL,
|
||||
nsIPrincipal* aOriginPrincipal,
|
||||
const nsCString& aCharset,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
RefPtr<StyleSheet>* aSheet);
|
||||
|
||||
@ -398,7 +392,7 @@ public:
|
||||
nsresult LoadSheet(nsIURI* aURL,
|
||||
bool aIsPreload,
|
||||
nsIPrincipal* aOriginPrincipal,
|
||||
const nsCString& aCharset,
|
||||
const Encoding* aPreloadEncoding,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode = CORS_NONE,
|
||||
ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset,
|
||||
@ -477,6 +471,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class SheetLoadData;
|
||||
friend class StreamLoader;
|
||||
|
||||
nsresult CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
|
||||
nsIURI* aTargetURI,
|
||||
@ -520,17 +515,18 @@ private:
|
||||
StyleSheet* aParentSheet,
|
||||
ImportRule* aGeckoParentRule);
|
||||
|
||||
nsresult InternalLoadNonDocumentSheet(nsIURI* aURL,
|
||||
bool aIsPreload,
|
||||
SheetParsingMode aParsingMode,
|
||||
bool aUseSystemPrincipal,
|
||||
nsIPrincipal* aOriginPrincipal,
|
||||
const nsCString& aCharset,
|
||||
RefPtr<StyleSheet>* aSheet,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode = CORS_NONE,
|
||||
ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset,
|
||||
const nsAString& aIntegrity = EmptyString());
|
||||
nsresult InternalLoadNonDocumentSheet(
|
||||
nsIURI* aURL,
|
||||
bool aIsPreload,
|
||||
SheetParsingMode aParsingMode,
|
||||
bool aUseSystemPrincipal,
|
||||
nsIPrincipal* aOriginPrincipal,
|
||||
const Encoding* aPreloadEncoding,
|
||||
RefPtr<StyleSheet>* aSheet,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
CORSMode aCORSMode = CORS_NONE,
|
||||
ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset,
|
||||
const nsAString& aIntegrity = EmptyString());
|
||||
|
||||
// Post a load event for aObserver to be notified about aSheet. The
|
||||
// notification will be sent with status NS_OK unless the load event is
|
||||
@ -557,11 +553,13 @@ private:
|
||||
StyleSheetState aSheetState,
|
||||
bool aIsPreLoad);
|
||||
|
||||
// Parse the stylesheet in aLoadData. The sheet data comes from aInput.
|
||||
// Set aCompleted to true if the parse finished, false otherwise (e.g. if the
|
||||
// Parse the stylesheet in aLoadData. The sheet data comes from aUTF16 if
|
||||
// UTF-16 and from aUTF8 if UTF-8.
|
||||
// Sets aCompleted to true if the parse finished, false otherwise (e.g. if the
|
||||
// sheet had an @import). If aCompleted is true when this returns, then
|
||||
// ParseSheet also called SheetComplete on aLoadData.
|
||||
nsresult ParseSheet(const nsAString& aInput,
|
||||
nsresult ParseSheet(const nsAString& aUTF16,
|
||||
Span<const uint8_t> aUTF8,
|
||||
SheetLoadData* aLoadData,
|
||||
bool& aCompleted);
|
||||
|
||||
|
@ -38,10 +38,12 @@ SERVO_BINDING_FUNC(Servo_Element_IsDisplayNone,
|
||||
RawGeckoElementBorrowed element)
|
||||
|
||||
// Styleset and Stylesheet management
|
||||
SERVO_BINDING_FUNC(Servo_StyleSheet_FromUTF8Bytes, RawServoStyleSheetContentsStrong,
|
||||
SERVO_BINDING_FUNC(Servo_StyleSheet_FromUTF8Bytes,
|
||||
RawServoStyleSheetContentsStrong,
|
||||
mozilla::css::Loader* loader,
|
||||
mozilla::ServoStyleSheet* gecko_stylesheet,
|
||||
const nsACString* data,
|
||||
const uint8_t* data,
|
||||
size_t data_len,
|
||||
mozilla::css::SheetParsingMode parsing_mode,
|
||||
RawGeckoURLExtraData* extra_data,
|
||||
uint32_t line_number_offset,
|
||||
|
@ -195,7 +195,7 @@ ServoStyleSheet::HasRules() const
|
||||
|
||||
nsresult
|
||||
ServoStyleSheet::ParseSheet(css::Loader* aLoader,
|
||||
const nsAString& aInput,
|
||||
Span<const uint8_t> aInput,
|
||||
nsIURI* aSheetURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aSheetPrincipal,
|
||||
@ -207,12 +207,16 @@ ServoStyleSheet::ParseSheet(css::Loader* aLoader,
|
||||
RefPtr<URLExtraData> extraData =
|
||||
new URLExtraData(aBaseURI, aSheetURI, aSheetPrincipal);
|
||||
|
||||
NS_ConvertUTF16toUTF8 input(aInput);
|
||||
Inner()->mContents =
|
||||
Servo_StyleSheet_FromUTF8Bytes(
|
||||
aLoader, this, &input, mParsingMode, extraData,
|
||||
aLineNumber, aCompatMode, aReusableSheets
|
||||
).Consume();
|
||||
Inner()->mContents = Servo_StyleSheet_FromUTF8Bytes(aLoader,
|
||||
this,
|
||||
aInput.Elements(),
|
||||
aInput.Length(),
|
||||
mParsingMode,
|
||||
extraData,
|
||||
aLineNumber,
|
||||
aCompatMode,
|
||||
aReusableSheets)
|
||||
.Consume();
|
||||
|
||||
Inner()->mURLData = extraData.forget();
|
||||
return NS_OK;
|
||||
@ -291,9 +295,14 @@ ServoStyleSheet::ReparseSheet(const nsAString& aInput)
|
||||
|
||||
DropRuleList();
|
||||
|
||||
nsresult rv = ParseSheet(loader, aInput, mInner->mSheetURI, mInner->mBaseURI,
|
||||
mInner->mPrincipal, lineNumber,
|
||||
eCompatibility_FullStandards, &reusableSheets);
|
||||
nsresult rv = ParseSheet(loader,
|
||||
NS_ConvertUTF16toUTF8(aInput),
|
||||
mInner->mSheetURI,
|
||||
mInner->mBaseURI,
|
||||
mInner->mPrincipal,
|
||||
lineNumber,
|
||||
eCompatibility_FullStandards,
|
||||
&reusableSheets);
|
||||
DidDirty();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -84,14 +84,15 @@ public:
|
||||
|
||||
bool HasRules() const;
|
||||
|
||||
MOZ_MUST_USE nsresult ParseSheet(css::Loader* aLoader,
|
||||
const nsAString& aInput,
|
||||
nsIURI* aSheetURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aSheetPrincipal,
|
||||
uint32_t aLineNumber,
|
||||
nsCompatibility aCompatMode,
|
||||
css::LoaderReusableStyleSheets* aReusableSheets = nullptr);
|
||||
MOZ_MUST_USE nsresult
|
||||
ParseSheet(css::Loader* aLoader,
|
||||
Span<const uint8_t> aInput,
|
||||
nsIURI* aSheetURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aSheetPrincipal,
|
||||
uint32_t aLineNumber,
|
||||
nsCompatibility aCompatMode,
|
||||
css::LoaderReusableStyleSheets* aReusableSheets = nullptr);
|
||||
|
||||
nsresult ReparseSheet(const nsAString& aInput);
|
||||
|
||||
|
183
layout/style/SheetLoadData.h
Normal file
183
layout/style/SheetLoadData.h
Normal file
@ -0,0 +1,183 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: ft=cpp tw=78 sw=2 et ts=2
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_css_SheetLoadData_h
|
||||
#define mozilla_css_SheetLoadData_h
|
||||
|
||||
#include "nsIUnicharStreamLoader.h"
|
||||
#include "nsIThreadInternal.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
/*********************************************
|
||||
* Data needed to properly load a stylesheet *
|
||||
*********************************************/
|
||||
|
||||
static_assert(eAuthorSheetFeatures == 0 && eUserSheetFeatures == 1 &&
|
||||
eAgentSheetFeatures == 2,
|
||||
"sheet parsing mode constants won't fit "
|
||||
"in SheetLoadData::mParsingMode");
|
||||
|
||||
class SheetLoadData final
|
||||
: public nsIRunnable
|
||||
, public nsIUnicharStreamLoaderObserver
|
||||
, public nsIThreadObserver
|
||||
{
|
||||
protected:
|
||||
virtual ~SheetLoadData(void);
|
||||
|
||||
public:
|
||||
// Data for loading a sheet linked from a document
|
||||
SheetLoadData(Loader* aLoader,
|
||||
const nsAString& aTitle,
|
||||
nsIURI* aURI,
|
||||
StyleSheet* aSheet,
|
||||
nsIStyleSheetLinkingElement* aOwningElement,
|
||||
bool aIsAlternate,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode);
|
||||
|
||||
// Data for loading a sheet linked from an @import rule
|
||||
SheetLoadData(Loader* aLoader,
|
||||
nsIURI* aURI,
|
||||
StyleSheet* aSheet,
|
||||
SheetLoadData* aParentData,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode);
|
||||
|
||||
// Data for loading a non-document sheet
|
||||
SheetLoadData(Loader* aLoader,
|
||||
nsIURI* aURI,
|
||||
StyleSheet* aSheet,
|
||||
bool aSyncLoad,
|
||||
bool aUseSystemPrincipal,
|
||||
const Encoding* aPreloadEncoding,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsINode* aRequestingNode);
|
||||
|
||||
already_AddRefed<nsIURI> GetReferrerURI();
|
||||
|
||||
void ScheduleLoadEventIfNeeded(nsresult aStatus);
|
||||
|
||||
NotNull<const Encoding*> DetermineNonBOMEncoding(nsACString const& aSegment,
|
||||
nsIChannel* aChannel);
|
||||
|
||||
nsresult VerifySheetReadyToParse(nsresult aStatus,
|
||||
const nsACString& aBytes,
|
||||
nsIChannel* aChannel);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSITHREADOBSERVER
|
||||
NS_DECL_NSIUNICHARSTREAMLOADEROBSERVER
|
||||
|
||||
// Hold a ref to the CSSLoader so we can call back to it to let it
|
||||
// know the load finished
|
||||
RefPtr<Loader> mLoader;
|
||||
|
||||
// Title needed to pull datas out of the pending datas table when
|
||||
// the preferred title is changed
|
||||
nsString mTitle;
|
||||
|
||||
// The encoding we decided to use for the sheet
|
||||
const Encoding* mEncoding;
|
||||
|
||||
// URI we're loading. Null for inline sheets
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
||||
// Should be 1 for non-inline sheets.
|
||||
uint32_t mLineNumber;
|
||||
|
||||
// The sheet we're loading data for
|
||||
RefPtr<StyleSheet> mSheet;
|
||||
|
||||
// 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
|
||||
RefPtr<SheetLoadData> mParentData;
|
||||
|
||||
// Number of sheets we @import-ed that are still loading
|
||||
uint32_t mPendingChildren;
|
||||
|
||||
// mSyncLoad is true when the load needs to be synchronous -- right
|
||||
// now only for LoadSheetSync and children of sync loads.
|
||||
bool mSyncLoad : 1;
|
||||
|
||||
// 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.
|
||||
bool mIsNonDocumentSheet : 1;
|
||||
|
||||
// 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).
|
||||
bool mIsLoading : 1;
|
||||
|
||||
// mIsCancelled is set to true when a sheet load is stopped by
|
||||
// Stop() or StopLoadingSheet() (which was removed in Bug 556446).
|
||||
// SheetLoadData::OnStreamComplete() checks this to avoid parsing
|
||||
// sheets that have been cancelled and such.
|
||||
bool mIsCancelled : 1;
|
||||
|
||||
// mMustNotify is true if the load data is being loaded async and
|
||||
// the original function call that started the load has returned.
|
||||
// This applies only to observer notifications; load/error events
|
||||
// are fired for any SheetLoadData that has a non-null
|
||||
// mOwningElement.
|
||||
bool mMustNotify : 1;
|
||||
|
||||
// mWasAlternate is true if the sheet was an alternate when the load data was
|
||||
// created.
|
||||
bool mWasAlternate : 1;
|
||||
|
||||
// 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.
|
||||
bool mUseSystemPrincipal : 1;
|
||||
|
||||
// If true, this SheetLoadData is being used as a way to handle
|
||||
// async observer notification for an already-complete sheet.
|
||||
bool mSheetAlreadyComplete : 1;
|
||||
|
||||
// This is the element that imported the sheet. Needed to get the
|
||||
// charset set on it and to fire load/error events.
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
|
||||
|
||||
// The observer that wishes to be notified of load completion
|
||||
nsCOMPtr<nsICSSLoaderObserver> mObserver;
|
||||
|
||||
// The principal that identifies who started loading us.
|
||||
nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
|
||||
|
||||
// The node that identifies who started loading us.
|
||||
nsCOMPtr<nsINode> mRequestingNode;
|
||||
|
||||
// The encoding to use for preloading Must be empty if mOwningElement
|
||||
// is non-null.
|
||||
const Encoding* mPreloadEncoding;
|
||||
|
||||
// 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.
|
||||
MOZ_INIT_OUTSIDE_CTOR nsresult mStatus;
|
||||
|
||||
private:
|
||||
void FireLoadEvent(nsIThreadInternal* aThread);
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_css_SheetLoadData_h
|
172
layout/style/StreamLoader.cpp
Normal file
172
layout/style/StreamLoader.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/css/StreamLoader.h"
|
||||
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
#include "mozilla/Encoding.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
StreamLoader::StreamLoader(mozilla::css::SheetLoadData* aSheetLoadData)
|
||||
: mSheetLoadData(aSheetLoadData)
|
||||
, mStatus(NS_OK)
|
||||
{
|
||||
MOZ_ASSERT(!aSheetLoadData->mSheet->IsGecko());
|
||||
}
|
||||
|
||||
StreamLoader::~StreamLoader()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(StreamLoader, nsIStreamListener)
|
||||
|
||||
/* nsIRequestObserver implementation */
|
||||
NS_IMETHODIMP
|
||||
StreamLoader::OnStartRequest(nsIRequest* aRequest, nsISupports*)
|
||||
{
|
||||
// It's kinda bad to let Web content send a number that results
|
||||
// in a potentially large allocation directly, but efficiency of
|
||||
// compression bombs is so great that it doesn't make much sense
|
||||
// to require a site to send one before going ahead and allocating.
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (channel) {
|
||||
int64_t length;
|
||||
nsresult rv = channel->GetContentLength(&length);
|
||||
if (NS_SUCCEEDED(rv) && length > 0) {
|
||||
if (length > MaxValue<nsACString::size_type>::value) {
|
||||
return (mStatus = NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
if (!mBytes.SetCapacity(length, mozilla::fallible_t())) {
|
||||
return (mStatus = NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
StreamLoader::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus)
|
||||
{
|
||||
// Decoded data
|
||||
nsCString utf8String;
|
||||
// How many bytes of decoded data to skip (3 when skipping UTF-8 BOM needed,
|
||||
// 0 otherwise)
|
||||
size_t skip = 0;
|
||||
|
||||
const Encoding* encoding;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
{
|
||||
// Hold the nsStringBuffer for the bytes from the stack to ensure release
|
||||
// no matter which return branch is taken.
|
||||
nsCString bytes(mBytes);
|
||||
mBytes.Truncate();
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
|
||||
if (NS_FAILED(mStatus)) {
|
||||
mSheetLoadData->VerifySheetReadyToParse(mStatus, EmptyCString(), channel);
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
mSheetLoadData->VerifySheetReadyToParse(aStatus, bytes, channel);
|
||||
if (rv != NS_OK_PARSE_SHEET) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = NS_OK;
|
||||
|
||||
size_t bomLength;
|
||||
Tie(encoding, bomLength) = Encoding::ForBOM(bytes);
|
||||
if (!encoding) {
|
||||
// No BOM
|
||||
encoding = mSheetLoadData->DetermineNonBOMEncoding(bytes, channel);
|
||||
|
||||
rv = encoding->DecodeWithoutBOMHandling(bytes, utf8String);
|
||||
} else if (encoding == UTF_8_ENCODING) {
|
||||
// UTF-8 BOM; handling this manually because mozilla::Encoding
|
||||
// can't handle this without copying with C++ types and uses
|
||||
// infallible allocation with Rust types (which could avoid
|
||||
// the copy).
|
||||
|
||||
// First, chop off the BOM.
|
||||
auto tail = Span<const uint8_t>(bytes).From(bomLength);
|
||||
size_t upTo = Encoding::UTF8ValidUpTo(tail);
|
||||
if (upTo == tail.Length()) {
|
||||
// No need to copy
|
||||
skip = bomLength;
|
||||
utf8String.Assign(bytes);
|
||||
} else {
|
||||
rv = encoding->DecodeWithoutBOMHandling(tail, utf8String, upTo);
|
||||
}
|
||||
} else {
|
||||
// UTF-16LE or UTF-16BE
|
||||
rv = encoding->DecodeWithBOMRemoval(bytes, utf8String);
|
||||
}
|
||||
} // run destructor for `bytes`
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// For reasons I don't understand, factoring the below lines into
|
||||
// a method on SheetLoadData resulted in a linker error. Hence,
|
||||
// accessing fields of mSheetLoadData from here.
|
||||
mSheetLoadData->mEncoding = encoding;
|
||||
bool dummy;
|
||||
return mSheetLoadData->mLoader->ParseSheet(
|
||||
EmptyString(),
|
||||
Span<const uint8_t>(utf8String).From(skip),
|
||||
mSheetLoadData,
|
||||
dummy);
|
||||
}
|
||||
|
||||
/* nsIStreamListener implementation */
|
||||
NS_IMETHODIMP
|
||||
StreamLoader::OnDataAvailable(nsIRequest*,
|
||||
nsISupports*,
|
||||
nsIInputStream* aInputStream,
|
||||
uint64_t,
|
||||
uint32_t aCount)
|
||||
{
|
||||
if (NS_FAILED(mStatus)) {
|
||||
return mStatus;
|
||||
}
|
||||
uint32_t dummy;
|
||||
return aInputStream->ReadSegments(WriteSegmentFun, this, aCount, &dummy);
|
||||
}
|
||||
|
||||
nsresult
|
||||
StreamLoader::WriteSegmentFun(nsIInputStream*,
|
||||
void* aClosure,
|
||||
const char* aSegment,
|
||||
uint32_t,
|
||||
uint32_t aCount,
|
||||
uint32_t* aWriteCount)
|
||||
{
|
||||
StreamLoader* self = static_cast<StreamLoader*>(aClosure);
|
||||
if (NS_FAILED(self->mStatus)) {
|
||||
return self->mStatus;
|
||||
}
|
||||
if (!self->mBytes.Append(aSegment, aCount, mozilla::fallible_t())) {
|
||||
self->mBytes.Truncate();
|
||||
return (self->mStatus = NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
*aWriteCount = aCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
47
layout/style/StreamLoader.h
Normal file
47
layout/style/StreamLoader.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_css_StreamLoader_h
|
||||
#define mozilla_css_StreamLoader_h
|
||||
|
||||
#include "nsString.h"
|
||||
#include "mozilla/css/SheetLoadData.h"
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
class StreamLoader : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
explicit StreamLoader(mozilla::css::SheetLoadData* aSheetLoadData);
|
||||
|
||||
private:
|
||||
virtual ~StreamLoader();
|
||||
|
||||
/**
|
||||
* callback method used for ReadSegments
|
||||
*/
|
||||
static nsresult WriteSegmentFun(nsIInputStream*,
|
||||
void*,
|
||||
const char*,
|
||||
uint32_t,
|
||||
uint32_t,
|
||||
uint32_t*);
|
||||
|
||||
RefPtr<mozilla::css::SheetLoadData> mSheetLoadData;
|
||||
nsCString mBytes;
|
||||
nsresult mStatus;
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_css_StreamLoader_h
|
@ -170,7 +170,9 @@ EXPORTS.mozilla.css += [
|
||||
'Loader.h',
|
||||
'NameSpaceRule.h',
|
||||
'Rule.h',
|
||||
'SheetLoadData.h',
|
||||
'SheetParsingMode.h',
|
||||
'StreamLoader.h',
|
||||
'StyleRule.h',
|
||||
'URLMatchingFunction.h',
|
||||
]
|
||||
@ -266,6 +268,7 @@ UNIFIED_SOURCES += [
|
||||
'ServoStyleSet.cpp',
|
||||
'ServoStyleSheet.cpp',
|
||||
'ServoSupportsRule.cpp',
|
||||
'StreamLoader.cpp',
|
||||
'StyleAnimationValue.cpp',
|
||||
'StylePrefs.cpp',
|
||||
'StyleRule.cpp',
|
||||
|
@ -907,7 +907,7 @@ nsLayoutStylesheetCache::BuildPreferenceSheet(RefPtr<StyleSheet>* aSheet,
|
||||
|
||||
static const uint32_t kPreallocSize = 1024;
|
||||
|
||||
nsString sheetText;
|
||||
nsCString sheetText;
|
||||
sheetText.SetCapacity(kPreallocSize);
|
||||
|
||||
#define NS_GET_R_G_B(color_) \
|
||||
@ -990,13 +990,12 @@ nsLayoutStylesheetCache::BuildPreferenceSheet(RefPtr<StyleSheet>* aSheet,
|
||||
"sheet without reallocation");
|
||||
|
||||
if (sheet->IsGecko()) {
|
||||
sheet->AsGecko()->ReparseSheet(sheetText);
|
||||
sheet->AsGecko()->ReparseSheet(NS_ConvertUTF8toUTF16(sheetText));
|
||||
} else {
|
||||
ServoStyleSheet* servoSheet = sheet->AsServo();
|
||||
// NB: The pref sheet never has @import rules.
|
||||
nsresult rv =
|
||||
servoSheet->ParseSheet(nullptr, sheetText, uri, uri, nullptr, 0,
|
||||
eCompatibility_FullStandards);
|
||||
nsresult rv = servoSheet->ParseSheet(
|
||||
nullptr, sheetText, uri, uri, nullptr, 0, eCompatibility_FullStandards);
|
||||
// Parsing the about:PreferenceStyleSheet URI can only fail on OOM. If we
|
||||
// are OOM before we parsed any documents we might as well abort.
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "ServoBindings.h"
|
||||
#include "NullPrincipalURI.h"
|
||||
#include "nsCSSParser.h"
|
||||
#include "mozilla/Encoding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::css;
|
||||
@ -23,18 +24,23 @@ using namespace mozilla::net;
|
||||
#ifdef MOZ_STYLO
|
||||
|
||||
static void ServoParsingBench() {
|
||||
NS_NAMED_LITERAL_CSTRING(css_, EXAMPLE_STYLESHEET);
|
||||
const nsACString& css = css_;
|
||||
ASSERT_TRUE(IsUTF8(css));
|
||||
auto css = AsBytes(MakeStringSpan(EXAMPLE_STYLESHEET));
|
||||
ASSERT_EQ(Encoding::UTF8ValidUpTo(css), css.Length());
|
||||
|
||||
RefPtr<URLExtraData> data = new URLExtraData(
|
||||
NullPrincipalURI::Create(), nullptr, NullPrincipal::Create());
|
||||
for (int i = 0; i < PARSING_REPETITIONS; i++) {
|
||||
RefPtr<RawServoStyleSheetContents> stylesheet =
|
||||
Servo_StyleSheet_FromUTF8Bytes(
|
||||
nullptr, nullptr, &css, eAuthorSheetFeatures,
|
||||
data, 0, eCompatibility_FullStandards, nullptr
|
||||
).Consume();
|
||||
Servo_StyleSheet_FromUTF8Bytes(nullptr,
|
||||
nullptr,
|
||||
css.Elements(),
|
||||
css.Length(),
|
||||
eAuthorSheetFeatures,
|
||||
data,
|
||||
0,
|
||||
eCompatibility_FullStandards,
|
||||
nullptr)
|
||||
.Consume();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -984,7 +984,10 @@ nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL,
|
||||
referrerPolicy = styleReferrerPolicy;
|
||||
}
|
||||
|
||||
mDocument->PreloadStyle(uri, aCharset, aCrossOrigin, referrerPolicy,
|
||||
mDocument->PreloadStyle(uri,
|
||||
Encoding::ForLabel(aCharset),
|
||||
aCrossOrigin,
|
||||
referrerPolicy,
|
||||
aIntegrity);
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ with modules["NETWORK"]:
|
||||
# The async request completed successfully.
|
||||
errors["NS_BINDING_SUCCEEDED"] = errors["NS_OK"]
|
||||
|
||||
# The async request failed for some unknown reason.
|
||||
# The async request failed for some unknown reason.
|
||||
errors["NS_BINDING_FAILED"] = FAILURE(1)
|
||||
# The async request failed because it was aborted by some user action.
|
||||
errors["NS_BINDING_ABORTED"] = FAILURE(2)
|
||||
@ -314,7 +314,7 @@ with modules["NETWORK"]:
|
||||
# The connection attempt failed, for example, because no server was
|
||||
# listening at specified host:port.
|
||||
errors["NS_ERROR_CONNECTION_REFUSED"] = FAILURE(13)
|
||||
# The connection was lost due to a timeout error.
|
||||
# The connection was lost due to a timeout error.
|
||||
errors["NS_ERROR_NET_TIMEOUT"] = FAILURE(14)
|
||||
# The requested action could not be completed while the networking library
|
||||
# is in the offline state.
|
||||
@ -339,7 +339,7 @@ with modules["NETWORK"]:
|
||||
# This request is not resumable, but it was tried to resume it, or to
|
||||
# request resume-specific data.
|
||||
errors["NS_ERROR_NOT_RESUMABLE"] = FAILURE(25)
|
||||
# The request failed as a result of a detected redirection loop.
|
||||
# The request failed as a result of a detected redirection loop.
|
||||
errors["NS_ERROR_REDIRECT_LOOP"] = FAILURE(31)
|
||||
# It was attempted to resume the request, but the entity has changed in the
|
||||
# meantime.
|
||||
@ -474,6 +474,8 @@ with modules["PLUGINS"]:
|
||||
with modules["LAYOUT"]:
|
||||
# Return code for nsITableLayout
|
||||
errors["NS_TABLELAYOUT_CELL_NOT_FOUND"] = SUCCESS(0)
|
||||
# Return code for SheetLoadData::VerifySheetReadyToParse
|
||||
errors["NS_OK_PARSE_SHEET"] = SUCCESS(1)
|
||||
# Return code for nsFrame::GetNextPrevLineFromeBlockFrame
|
||||
errors["NS_POSITION_BEFORE_TABLE"] = SUCCESS(3)
|
||||
# Return codes for nsPresState::GetProperty()
|
||||
|
Loading…
Reference in New Issue
Block a user