зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1428473 Support X-Content-Type-Options: nosniff when navigating r=ckerschb,dragana,alchen
*** Apply Requested Revision Differential Revision: https://phabricator.services.mozilla.com/D33959 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
33327053e3
Коммит
6917b697b8
|
@ -0,0 +1,32 @@
|
|||
// Custom *.sjs file specifically for the needs of Bug 1286861
|
||||
|
||||
// small red image
|
||||
const IMG = atob(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
|
||||
"P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
|
||||
|
||||
function getSniffableContent(selector){
|
||||
switch(selector){
|
||||
case "xml":
|
||||
return `<?xml version="1.0"?><test/>`;
|
||||
case "html":
|
||||
return `<!Doctype html> <html> <head></head> <body> Test test </body></html>`;
|
||||
case "css":
|
||||
return `*{ color: pink !important; }`;
|
||||
case 'json':
|
||||
return `{ 'test':'yes' }`;
|
||||
case 'img':
|
||||
return IMG;
|
||||
}
|
||||
return "Basic UTF-8 Text";
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
// avoid confusing cache behaviors
|
||||
response.setHeader('X-Content-Type-Options', 'nosniff'); // Disable Sniffing
|
||||
response.setHeader("Content-Type","*/*"); // Try Browser to force sniffing.
|
||||
response.write(getSniffableContent(request.queryString));
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Custom *.sjs file specifically for the needs of Bug 1286861
|
||||
|
||||
// small red image
|
||||
const IMG = atob(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
|
||||
"P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
|
||||
|
||||
function getSniffableContent(selector){
|
||||
switch(selector){
|
||||
case "xml":
|
||||
return `<?xml version="1.0"?><test/>`;
|
||||
case "html":
|
||||
return `<!Doctype html> <html> <head></head> <body> Test test </body></html>`;
|
||||
case 'js':
|
||||
return `<script> alert("This shouldt not be executed"); </script>`
|
||||
case "css":
|
||||
return `*{ color: pink !important; }`;
|
||||
case 'json':
|
||||
return `{ 'test':'yes' }`;
|
||||
case 'img':
|
||||
return IMG;
|
||||
}
|
||||
return "Basic UTF-8 Text";
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
// avoid confusing cache behaviors
|
||||
response.setHeader('X-Content-Type-Options', 'nosniff'); // Disable Sniffing
|
||||
response.setHeader("Content-Type","garbage/garbage"); // Try Browser to force sniffing.
|
||||
response.write(getSniffableContent(request.queryString));
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Custom *.sjs file specifically for the needs of Bug 1286861
|
||||
|
||||
// small red image
|
||||
const IMG = atob(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
|
||||
"P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
|
||||
|
||||
function getSniffableContent(selector){
|
||||
switch(selector){
|
||||
case "xml":
|
||||
return `<?xml version="1.0"?><test/>`;
|
||||
case "html":
|
||||
return `<!Doctype html> <html> <head></head> <body> Test test </body></html>`;
|
||||
case 'js':
|
||||
return `<script> alert("This shouldt not be executed"); </script>`
|
||||
case "css":
|
||||
return `*{ color: pink !important; }`;
|
||||
case 'json':
|
||||
return `{ 'test':'yes' }`;
|
||||
case 'img':
|
||||
return IMG;
|
||||
}
|
||||
return "Basic UTF-8 Text";
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
// avoid confusing cache behaviors
|
||||
response.setHeader('X-Content-Type-Options', 'nosniff'); // Disable Sniffing
|
||||
response.setHeader("Content-Type","picture/png"); // Try Browser to force sniffing.
|
||||
response.write(getSniffableContent(request.queryString));
|
||||
return;
|
||||
}
|
|
@ -2,6 +2,9 @@
|
|||
support-files =
|
||||
file_contentpolicytype_targeted_link_iframe.sjs
|
||||
file_nosniff_testserver.sjs
|
||||
file_nosniff_navigation.sjs
|
||||
file_nosniff_navigation_mismatch.sjs
|
||||
file_nosniff_navigation_garbage.sjs
|
||||
file_block_script_wrong_mime_server.sjs
|
||||
file_block_toplevel_data_navigation.html
|
||||
file_block_toplevel_data_navigation2.html
|
||||
|
@ -24,6 +27,7 @@ support-files =
|
|||
|
||||
[test_contentpolicytype_targeted_link_iframe.html]
|
||||
[test_nosniff.html]
|
||||
[test_nosniff_navigation.html]
|
||||
[test_block_script_wrong_mime.html]
|
||||
[test_block_toplevel_data_navigation.html]
|
||||
skip-if = toolkit == 'android' # intermittent failure
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1428473 Support X-Content-Type-Options: nosniff when navigating</title>
|
||||
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
iframe{
|
||||
border: 1px solid orange;
|
||||
}
|
||||
</style>
|
||||
|
||||
<iframe src="file_nosniff_navigation.sjs?xml"> </iframe>
|
||||
<iframe src="file_nosniff_navigation.sjs?html"></iframe>
|
||||
<iframe src="file_nosniff_navigation.sjs?css" ></iframe>
|
||||
<iframe src="file_nosniff_navigation.sjs?json"></iframe>
|
||||
<iframe src="file_nosniff_navigation.sjs?img"></iframe>
|
||||
|
||||
<hr>
|
||||
<iframe src="file_nosniff_navigation_mismatch.sjs?html"></iframe>
|
||||
<iframe src="file_nosniff_navigation_mismatch.sjs?xml"></iframe>
|
||||
<iframe src="file_nosniff_navigation_mismatch.sjs"></iframe>
|
||||
|
||||
<iframe src="file_nosniff_navigation_garbage.sjs?xml"> </iframe>
|
||||
<iframe src="file_nosniff_navigation_garbage.sjs?html"></iframe>
|
||||
<iframe src="file_nosniff_navigation_garbage.sjs?css" ></iframe>
|
||||
<iframe src="file_nosniff_navigation_garbage.sjs?json"></iframe>
|
||||
<iframe src="file_nosniff_navigation_garbage.sjs?img"></iframe>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- add the two script tests -->
|
||||
<script id="scriptCorrectType"></script>
|
||||
<script id="scriptWrongType"></script>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* Description of the test:
|
||||
* We're testing if Firefox respects the nosniff Header for Top-Level
|
||||
* Navigations.
|
||||
* If Firefox cant Display the Page, it will prompt a download
|
||||
* and the URL of the Page will be about:blank.
|
||||
* So we will try to open different content send with
|
||||
* no-mime, mismatched-mime and garbage-mime types.
|
||||
*
|
||||
*/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("load", ()=>{
|
||||
let iframes = Array.from(document.querySelectorAll("iframe"));
|
||||
|
||||
iframes.forEach( frame => {
|
||||
let result = frame.contentWindow.document.URL == "about:blank";
|
||||
let sniffTarget = (new URL(frame.src)).search;
|
||||
ok(result, `${sniffTarget} - was not Sniffed`);
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -584,6 +584,7 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
|
|||
aLoadInfo->GetServiceWorkerTaintingSynthesized(),
|
||||
aLoadInfo->GetDocumentHasUserInteracted(),
|
||||
aLoadInfo->GetDocumentHasLoaded(), cspNonce,
|
||||
aLoadInfo->GetSkipContentSniffing(),
|
||||
aLoadInfo->GetIsFromProcessingFrameAttributes(), cookieSettingsArgs,
|
||||
aLoadInfo->GetRequestBlockingReason(), maybeCspToInheritInfo));
|
||||
|
||||
|
@ -746,7 +747,7 @@ nsresult LoadInfoArgsToLoadInfo(
|
|||
loadInfoArgs.serviceWorkerTaintingSynthesized(),
|
||||
loadInfoArgs.documentHasUserInteracted(),
|
||||
loadInfoArgs.documentHasLoaded(), loadInfoArgs.cspNonce(),
|
||||
loadInfoArgs.requestBlockingReason());
|
||||
loadInfoArgs.skipContentSniffing(), loadInfoArgs.requestBlockingReason());
|
||||
|
||||
if (loadInfoArgs.isFromProcessingFrameAttributes()) {
|
||||
loadInfo->SetIsFromProcessingFrameAttributes();
|
||||
|
@ -761,6 +762,7 @@ void LoadInfoToParentLoadInfoForwarder(
|
|||
if (!aLoadInfo) {
|
||||
*aForwarderArgsOut = ParentLoadInfoForwarderArgs(
|
||||
false, false, Nothing(), nsILoadInfo::TAINTING_BASIC,
|
||||
false, // SkipContentSniffing
|
||||
false, // serviceWorkerTaintingSynthesized
|
||||
false, // documentHasUserInteracted
|
||||
false, // documentHasLoaded
|
||||
|
@ -792,6 +794,7 @@ void LoadInfoToParentLoadInfoForwarder(
|
|||
*aForwarderArgsOut = ParentLoadInfoForwarderArgs(
|
||||
aLoadInfo->GetAllowInsecureRedirectToDataURI(),
|
||||
aLoadInfo->GetBypassCORSChecks(), ipcController, tainting,
|
||||
aLoadInfo->GetSkipContentSniffing(),
|
||||
aLoadInfo->GetServiceWorkerTaintingSynthesized(),
|
||||
aLoadInfo->GetDocumentHasUserInteracted(),
|
||||
aLoadInfo->GetDocumentHasLoaded(), cookieSettingsArgs,
|
||||
|
@ -826,6 +829,9 @@ nsresult MergeParentLoadInfoForwarder(
|
|||
aLoadInfo->MaybeIncreaseTainting(aForwarderArgs.tainting());
|
||||
}
|
||||
|
||||
rv = aLoadInfo->SetSkipContentSniffing(aForwarderArgs.skipContentSniffing());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(aLoadInfo->SetDocumentHasUserInteracted(
|
||||
aForwarderArgs.documentHasUserInteracted()));
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
|
|
|
@ -97,6 +97,7 @@ LoadInfo::LoadInfo(
|
|||
mServiceWorkerTaintingSynthesized(false),
|
||||
mDocumentHasUserInteracted(false),
|
||||
mDocumentHasLoaded(false),
|
||||
mSkipContentSniffing(false),
|
||||
mIsFromProcessingFrameAttributes(false) {
|
||||
MOZ_ASSERT(mLoadingPrincipal);
|
||||
MOZ_ASSERT(mTriggeringPrincipal);
|
||||
|
@ -358,6 +359,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
|
|||
mServiceWorkerTaintingSynthesized(false),
|
||||
mDocumentHasUserInteracted(false),
|
||||
mDocumentHasLoaded(false),
|
||||
mSkipContentSniffing(false),
|
||||
mIsFromProcessingFrameAttributes(false) {
|
||||
// Top-level loads are never third-party
|
||||
// Grab the information we can out of the window.
|
||||
|
@ -475,6 +477,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
|
|||
mDocumentHasUserInteracted(rhs.mDocumentHasUserInteracted),
|
||||
mDocumentHasLoaded(rhs.mDocumentHasLoaded),
|
||||
mCspNonce(rhs.mCspNonce),
|
||||
mSkipContentSniffing(rhs.mSkipContentSniffing),
|
||||
mIsFromProcessingFrameAttributes(rhs.mIsFromProcessingFrameAttributes) {}
|
||||
|
||||
LoadInfo::LoadInfo(
|
||||
|
@ -508,7 +511,7 @@ LoadInfo::LoadInfo(
|
|||
bool aIsPreflight, bool aLoadTriggeredFromExternal,
|
||||
bool aServiceWorkerTaintingSynthesized, bool aDocumentHasUserInteracted,
|
||||
bool aDocumentHasLoaded, const nsAString& aCspNonce,
|
||||
uint32_t aRequestBlockingReason)
|
||||
bool aSkipContentSniffing, uint32_t aRequestBlockingReason)
|
||||
: mLoadingPrincipal(aLoadingPrincipal),
|
||||
mTriggeringPrincipal(aTriggeringPrincipal),
|
||||
mPrincipalToInherit(aPrincipalToInherit),
|
||||
|
@ -559,6 +562,7 @@ LoadInfo::LoadInfo(
|
|||
mDocumentHasUserInteracted(aDocumentHasUserInteracted),
|
||||
mDocumentHasLoaded(aDocumentHasLoaded),
|
||||
mCspNonce(aCspNonce),
|
||||
mSkipContentSniffing(aSkipContentSniffing),
|
||||
mIsFromProcessingFrameAttributes(false) {
|
||||
// Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal
|
||||
MOZ_ASSERT(mLoadingPrincipal ||
|
||||
|
@ -1321,6 +1325,18 @@ LoadInfo::SetCspNonce(const nsAString& aCspNonce) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadInfo::GetSkipContentSniffing(bool* aSkipContentSniffing) {
|
||||
*aSkipContentSniffing = mSkipContentSniffing;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadInfo::SetSkipContentSniffing(bool aSkipContentSniffing) {
|
||||
mSkipContentSniffing = aSkipContentSniffing;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadInfo::GetIsTopLevelLoad(bool* aResult) {
|
||||
*aResult = mFrameOuterWindowID ? mFrameOuterWindowID == mOuterWindowID
|
||||
|
|
|
@ -154,7 +154,8 @@ class LoadInfo final : public nsILoadInfo {
|
|||
bool aIsPreflight, bool aLoadTriggeredFromExternal,
|
||||
bool aServiceWorkerTaintingSynthesized,
|
||||
bool aDocumentHasUserInteracted, bool aDocumentHasLoaded,
|
||||
const nsAString& aCspNonce, uint32_t aRequestBlockingReason);
|
||||
const nsAString& aCspNonce, bool aSkipContentSniffing,
|
||||
uint32_t aRequestBlockingReason);
|
||||
LoadInfo(const LoadInfo& rhs);
|
||||
|
||||
NS_IMETHOD GetRedirects(JSContext* aCx,
|
||||
|
@ -246,6 +247,7 @@ class LoadInfo final : public nsILoadInfo {
|
|||
bool mDocumentHasUserInteracted;
|
||||
bool mDocumentHasLoaded;
|
||||
nsString mCspNonce;
|
||||
bool mSkipContentSniffing;
|
||||
|
||||
// Is true if this load was triggered by processing the attributes of the
|
||||
// browsing context container.
|
||||
|
|
|
@ -413,6 +413,15 @@ interface nsILoadInfo : nsISupports
|
|||
*/
|
||||
[infallible] readonly attribute unsigned long securityMode;
|
||||
|
||||
|
||||
/**
|
||||
* This flag is used for any browsing context where we should not sniff
|
||||
* the content type. E.g if an iframe has the XCTO nosniff header, then
|
||||
* that flag is set to true so we skip content sniffing for that browsing
|
||||
* context.
|
||||
*/
|
||||
[infallible] attribute boolean skipContentSniffing;
|
||||
|
||||
/**
|
||||
* True if this request is embedded in a context that can't be third-party
|
||||
* (i.e. an iframe embedded in a cross-origin parent window). If this is
|
||||
|
|
|
@ -2703,6 +2703,15 @@ nsresult NS_GenerateHostPort(const nsCString& host, int32_t port,
|
|||
void NS_SniffContent(const char* aSnifferType, nsIRequest* aRequest,
|
||||
const uint8_t* aData, uint32_t aLength,
|
||||
nsACString& aSniffedType) {
|
||||
// In case XCTO nosniff was present, we could just skip sniffing here
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (channel) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
if (loadInfo->GetSkipContentSniffing()) {
|
||||
aSniffedType.Truncate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
typedef nsCategoryCache<nsIContentSniffer> ContentSnifferCache;
|
||||
extern ContentSnifferCache* gNetSniffers;
|
||||
extern ContentSnifferCache* gDataSniffers;
|
||||
|
|
|
@ -139,6 +139,7 @@ struct LoadInfoArgs
|
|||
bool documentHasUserInteracted;
|
||||
bool documentHasLoaded;
|
||||
nsString cspNonce;
|
||||
bool skipContentSniffing;
|
||||
bool isFromProcessingFrameAttributes;
|
||||
CookieSettingsArgs cookieSettings;
|
||||
uint32_t requestBlockingReason;
|
||||
|
@ -172,6 +173,12 @@ struct ParentLoadInfoForwarderArgs
|
|||
// tainting value.
|
||||
uint32_t tainting;
|
||||
|
||||
|
||||
// This flag is used for any browsing context where we should not sniff
|
||||
// the content type. E.g if an iframe has the XCTO nosniff header, then
|
||||
// that flag is set to true so we skip content sniffing for that browsing
|
||||
bool skipContentSniffing;
|
||||
|
||||
// We must also note that the tainting value was explicitly set
|
||||
// by the service worker.
|
||||
bool serviceWorkerTaintingSynthesized;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsHttpChannel.h"
|
||||
#include "nsHttpChannelAuthProvider.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
#include "nsICacheStorageService.h"
|
||||
|
@ -1449,6 +1450,16 @@ nsresult ProcessXCTO(nsHttpChannel* aChannel, nsIURI* aURI,
|
|||
Report::Error);
|
||||
return NS_ERROR_CORRUPTED_CONTENT;
|
||||
}
|
||||
auto policyType = aLoadInfo->GetExternalContentPolicyType();
|
||||
if (policyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
||||
policyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
// If the header XCTO nosniff is set for any browsing context, then
|
||||
// we set the skipContentSniffing flag on the Loadinfo. Within
|
||||
// NS_SniffContent we then bail early and do not do any sniffing.
|
||||
aLoadInfo->SetSkipContentSniffing(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -326,6 +326,11 @@ nsUnknownDecoder::GetMIMETypeFromContent(nsIRequest* aRequest,
|
|||
nsACString& type) {
|
||||
// This is only used by sniffer, therefore we do not need to lock anything
|
||||
// here.
|
||||
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
if (loadInfo->GetSkipContentSniffing()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mBuffer = const_cast<char*>(reinterpret_cast<const char*>(aData));
|
||||
mBufferLen = aLength;
|
||||
|
@ -355,6 +360,11 @@ bool nsUnknownDecoder::AllowSniffing(nsIRequest* aRequest) {
|
|||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
if (loadInfo->GetSkipContentSniffing()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isLocalFile = false;
|
||||
if (NS_FAILED(uri->SchemeIs("file", &isLocalFile)) || isLocalFile) {
|
||||
return false;
|
||||
|
@ -401,10 +411,17 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest) {
|
|||
if (!mContentType.IsEmpty()) return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(aRequest));
|
||||
if (channel) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
if (loadInfo->GetSkipContentSniffing()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char* testData = mBuffer;
|
||||
uint32_t testDataLen = mBufferLen;
|
||||
// Check if data are compressed.
|
||||
nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(aRequest));
|
||||
nsAutoCString decodedData;
|
||||
|
||||
if (channel) {
|
||||
|
@ -575,6 +592,11 @@ bool nsUnknownDecoder::SniffForXML(nsIRequest* aRequest) {
|
|||
}
|
||||
|
||||
bool nsUnknownDecoder::SniffURI(nsIRequest* aRequest) {
|
||||
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
if (loadInfo->GetSkipContentSniffing()) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1"));
|
||||
if (mimeService) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
|
@ -606,6 +628,12 @@ bool nsUnknownDecoder::LastDitchSniff(nsIRequest* aRequest) {
|
|||
// All we can do now is try to guess whether this is text/plain or
|
||||
// application/octet-stream
|
||||
|
||||
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
if (loadInfo->GetSkipContentSniffing()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
const char* testData;
|
||||
|
@ -827,6 +855,10 @@ void nsBinaryDetector::DetermineContentType(nsIRequest* aRequest) {
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->LoadInfo();
|
||||
if (loadInfo->GetSkipContentSniffing()) {
|
||||
return;
|
||||
}
|
||||
// It's an HTTP channel. Check for the text/plain mess
|
||||
nsAutoCString contentTypeHdr;
|
||||
Unused << httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
|
||||
|
|
|
@ -190,7 +190,8 @@ nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
|
|||
mFlushTimerMutex("nsHtml5StreamParser mFlushTimerMutex"),
|
||||
mFlushTimerArmed(false),
|
||||
mFlushTimerEverFired(false),
|
||||
mMode(aMode) {
|
||||
mMode(aMode),
|
||||
mSkipContentSniffing(false) {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
#ifdef DEBUG
|
||||
mAtomTable.SetPermittedLookupEventTarget(mEventTarget);
|
||||
|
@ -631,7 +632,7 @@ nsresult nsHtml5StreamParser::FinalizeSniffing(Span<const uint8_t> aFromSegment,
|
|||
}
|
||||
|
||||
// meta scan failed.
|
||||
if (mCharsetSource < kCharsetFromMetaPrescan) {
|
||||
if (!mSkipContentSniffing && mCharsetSource < kCharsetFromMetaPrescan) {
|
||||
// Check for BOMless UTF-16 with Basic
|
||||
// Latin content for compat with IE. See bug 631751.
|
||||
SniffBOMlessUTF16BasicLatin(aFromSegment.To(aCountToSniffingLimit));
|
||||
|
@ -662,6 +663,7 @@ nsresult nsHtml5StreamParser::SniffStreamBytes(
|
|||
Span<const uint8_t> aFromSegment) {
|
||||
NS_ASSERTION(IsParserThread(), "Wrong thread!");
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// mEncoding and mCharsetSource potentially have come from channel or higher
|
||||
// by now. If we find a BOM, SetupDecodingFromBom() will overwrite them.
|
||||
// If we don't find a BOM, the previously set values of mEncoding and
|
||||
|
@ -957,6 +959,13 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) {
|
|||
mObserver->OnStartRequest(aRequest);
|
||||
}
|
||||
mRequest = aRequest;
|
||||
nsCOMPtr<nsIChannel> myChannel(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = myChannel->LoadInfo();
|
||||
mSkipContentSniffing = loadInfo->GetSkipContentSniffing();
|
||||
|
||||
if (mSkipContentSniffing) {
|
||||
mFeedChardet = false;
|
||||
}
|
||||
|
||||
mStreamState = STREAM_BEING_READ;
|
||||
|
||||
|
|
|
@ -594,6 +594,11 @@ class nsHtml5StreamParser final : public nsICharsetDetectionObserver {
|
|||
* Whether the parser is doing a normal parse, view source or plain text.
|
||||
*/
|
||||
eParserMode mMode;
|
||||
|
||||
/**
|
||||
* Whether the parser should not sniff the content type.
|
||||
*/
|
||||
bool mSkipContentSniffing;
|
||||
};
|
||||
|
||||
#endif // nsHtml5StreamParser_h
|
||||
|
|
Загрузка…
Ссылка в новой задаче