Bug 1089255 - Implement and test manifest-src CSP directive. r=bholley, r=dveditz, r=ckerschb

---
 dom/base/nsContentPolicyUtils.h                    |   1 +
 dom/base/nsDataDocumentContentPolicy.cpp           |   3 +-
 dom/base/nsIContentPolicy.idl                      |   2 +-
 dom/base/nsIContentPolicyBase.idl                  |   7 +-
 dom/base/nsISimpleContentPolicy.idl                |   2 +-
 dom/base/test/csp/browser.ini                      |   4 +
 dom/base/test/csp/browser_test_web_manifest.js     | 265 +++++++++++++++++++++
 .../csp/browser_test_web_manifest_mixed_content.js |  55 +++++
 dom/base/test/csp/file_CSP_web_manifest.html       |   6 +
 dom/base/test/csp/file_CSP_web_manifest.json       |   1 +
 .../test/csp/file_CSP_web_manifest.json^headers^   |   1 +
 dom/base/test/csp/file_CSP_web_manifest_https.html |   4 +
 dom/base/test/csp/file_CSP_web_manifest_https.json |   1 +
 .../csp/file_CSP_web_manifest_mixed_content.html   |   9 +
 .../test/csp/file_CSP_web_manifest_remote.html     |   8 +
 dom/base/test/csp/file_csp_testserver.sjs          |  14 +-
 dom/base/test/csp/mochitest.ini                    |   7 +
 dom/base/test/moz.build                            |   5 +-
 dom/fetch/InternalRequest.cpp                      |   3 +
 dom/fetch/InternalRequest.h                        |   2 +-
 .../security/nsIContentSecurityPolicy.idl          |   3 +-
 dom/ipc/manifestMessages.js                        |  25 +-
 dom/security/nsCSPUtils.cpp                        |   7 +
 dom/security/nsCSPUtils.h                          |  10 +-
 dom/security/nsMixedContentBlocker.cpp             |   1 +
 dom/webidl/CSPDictionaries.webidl                  |   1 +
 extensions/permissions/nsContentBlocker.cpp        |   6 +-
 netwerk/mime/nsMimeTypes.h                         |   1 +
 28 files changed, 439 insertions(+), 15 deletions(-)
 create mode 100644 dom/base/test/csp/browser.ini
 create mode 100644 dom/base/test/csp/browser_test_web_manifest.js
 create mode 100644 dom/base/test/csp/browser_test_web_manifest_mixed_content.js
 create mode 100644 dom/base/test/csp/file_CSP_web_manifest.html
 create mode 100644 dom/base/test/csp/file_CSP_web_manifest.json
 create mode 100644 dom/base/test/csp/file_CSP_web_manifest.json^headers^
 create mode 100644 dom/base/test/csp/file_CSP_web_manifest_https.html
 create mode 100644 dom/base/test/csp/file_CSP_web_manifest_https.json
 create mode 100644 dom/base/test/csp/file_CSP_web_manifest_mixed_content.html
 create mode 100644 dom/base/test/csp/file_CSP_web_manifest_remote.html
This commit is contained in:
Marcos Caceres 2015-06-02 15:42:19 -04:00
parent c58028f897
commit 21c80fd7b7
28 changed files with 439 additions and 15 deletions

View File

@ -113,6 +113,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
CASE_RETURN( TYPE_BEACON );
CASE_RETURN( TYPE_FETCH );
CASE_RETURN( TYPE_IMAGESET );
CASE_RETURN( TYPE_WEB_MANIFEST );
default:
return "<Unknown Type>";
}

View File

@ -123,7 +123,8 @@ nsDataDocumentContentPolicy::ShouldLoad(uint32_t aContentType,
aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
aContentType == nsIContentPolicy::TYPE_SCRIPT ||
aContentType == nsIContentPolicy::TYPE_XSLT ||
aContentType == nsIContentPolicy::TYPE_FETCH) {
aContentType == nsIContentPolicy::TYPE_FETCH ||
aContentType == nsIContentPolicy::TYPE_WEB_MANIFEST) {
*aDecision = nsIContentPolicy::REJECT_TYPE;
}

View File

@ -20,7 +20,7 @@ interface nsIPrincipal;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(447a2300-ab3c-11e4-bcd8-0800200c9a66)]
[scriptable,uuid(cb978019-0c5b-4067-abb6-c914461208c1)]
interface nsIContentPolicy : nsIContentPolicyBase
{
/**

View File

@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(21bb54b0-ab3c-11e4-bcd8-0800200c9a66)]
[scriptable,uuid(4f2655e8-6365-4583-8510-732bff2186c5)]
interface nsIContentPolicyBase : nsISupports
{
/**
@ -172,6 +172,11 @@ interface nsIContentPolicyBase : nsISupports
*/
const nsContentPolicyType TYPE_IMAGESET = 21;
/**
* Indicates a web manifest.
*/
const nsContentPolicyType TYPE_WEB_MANIFEST = 22;
/* When adding new content types, please update nsContentBlocker,
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
* implementations, and other things that are not listed here that are

View File

@ -28,7 +28,7 @@ interface nsIDOMElement;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(83d93c70-ab46-11e4-bcd8-0800200c9a66)]
[scriptable,uuid(704b4b8e-2287-498a-9c0a-d1bde547a2d4)]
interface nsISimpleContentPolicy : nsIContentPolicyBase
{
/**

View File

@ -0,0 +1,4 @@
[DEFAULT]
skip-if = e10s # Bug 1170385 - csp-on-violate-policy message not sent in browser tests with e10s
[browser_test_web_manifest.js]
[browser_test_web_manifest_mixed_content.js]

View File

@ -0,0 +1,265 @@
/*
* Description of the tests:
* These tests check for conformance to the CSP spec as they relate to Web Manifests.
*
* In particular, the tests check that default-src and manifest-src directives are
* are respected by the ManifestObtainer.
*/
/*globals Components*/
'use strict';
requestLongerTimeout(10); // e10s tests take time.
const {
ManifestObtainer
} = Components.utils.import('resource://gre/modules/WebManifest.jsm', {});
const path = '/tests/dom/base/test/csp/';
const testFile = `file=${path}file_CSP_web_manifest.html`;
const remoteFile = `file=${path}file_CSP_web_manifest_remote.html`;
const httpsManifest = `file=${path}file_CSP_web_manifest_https.html`;
const mixedContent = `file=${path}file_CSP_web_manifest_mixed_content.html`;
const server = 'file_csp_testserver.sjs';
const defaultURL = `http://example.org${path}${server}`;
const remoteURL = `http://mochi.test:8888`;
const secureURL = `https://example.com${path}${server}`;
const tests = [
// CSP block everything, so trying to load a manifest
// will result in a policy violation.
{
expected: `default-src 'none' blocks fetching manifest.`,
get tabURL() {
let queryParts = [
`csp=default-src 'none'`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(topic) {
is(topic, 'csp-on-violate-policy', this.expected);
}
},
// CSP allows fetching only from mochi.test:8888,
// so trying to load a manifest from same origin
// triggers a CSP violation.
{
expected: `default-src mochi.test:8888 blocks manifest fetching.`,
get tabURL() {
let queryParts = [
`csp=default-src mochi.test:8888`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(topic) {
is(topic, 'csp-on-violate-policy', this.expected);
}
},
// CSP restricts fetching to 'self', so allowing the manifest
// to load. The name of the manifest is then checked.
{
expected: `CSP default-src 'self' allows fetch of manifest.`,
get tabURL() {
let queryParts = [
`csp=default-src 'self'`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// CSP only allows fetching from mochi.test:8888 and remoteFile
// requests a manifest from that origin, so manifest should load.
{
expected: 'CSP default-src mochi.test:8888 allows fetching manifest.',
get tabURL() {
let queryParts = [
`csp=default-src http://mochi.test:8888`,
remoteFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// default-src blocks everything, so any attempt to
// fetch a manifest from another origin will trigger a
// policy violation.
{
expected: `default-src 'none' blocks mochi.test:8888`,
get tabURL() {
let queryParts = [
`csp=default-src 'none'`,
remoteFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(topic) {
is(topic, 'csp-on-violate-policy', this.expected);
}
},
// CSP allows fetching from self, so manifest should load.
{
expected: `CSP manifest-src allows self`,
get tabURL() {
let queryParts = [
`manifest-src 'self'`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// CSP allows fetching from example.org, so manifest should load.
{
expected: `CSP manifest-src allows http://example.org`,
get tabURL() {
let queryParts = [
`manifest-src http://example.org`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// Check interaction with default-src and another origin,
// CSP allows fetching from example.org, so manifest should load.
{
expected: `CSP manifest-src overrides default-src of elsewhere.com`,
get tabURL() {
let queryParts = [
`default-src: http://elsewhere.com; manifest-src http://example.org`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// Check interaction with default-src none,
// CSP allows fetching manifest from example.org, so manifest should load.
{
expected: `CSP manifest-src overrides default-src`,
get tabURL() {
let queryParts = [
`default-src: 'none'; manifest-src 'self'`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// CSP allows fetching from mochi.test:8888, which has a
// CORS header set to '*'. So the manifest should load.
{
expected: `CSP manifest-src allows mochi.test:8888`,
get tabURL() {
let queryParts = [
`csp=default-src *; manifest-src http://mochi.test:8888`,
remoteFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// CSP restricts fetching to mochi.test:8888, but the test
// file is at example.org. Hence, a policy violation is
// triggered.
{
expected: `CSP blocks manifest fetching from example.org.`,
get tabURL() {
let queryParts = [
`csp=manifest-src mochi.test:8888`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(topic) {
is(topic, 'csp-on-violate-policy', this.expected);
}
},
// CSP is set to only allow manifest to be loaded from same origin,
// but the remote file attempts to load from a different origin. Thus
// this causes a CSP violation.
{
expected: `CSP manifest-src 'self' blocks cross-origin fetch.`,
get tabURL() {
let queryParts = [
`csp=manifest-src 'self'`,
remoteFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(topic) {
is(topic, 'csp-on-violate-policy', this.expected);
}
}
];
//jscs:disable
add_task(function* () {
//jscs:enable
for (let test of tests) {
let tabOptions = {
gBrowser: gBrowser,
url: test.tabURL,
};
yield BrowserTestUtils.withNewTab(
tabOptions,
browser => testObtainingManifest(browser, test)
);
}
function* testObtainingManifest(aBrowser, aTest) {
const observer = (/blocks/.test(aTest.expected)) ? new NetworkObserver(aTest) : null;
const obtainer = new ManifestObtainer();
let manifest;
// Expect an exception (from promise rejection) if there a content policy
// that is violated.
try {
manifest = yield obtainer.obtainManifest(aBrowser);
} catch (e) {
const msg = `Expected promise rejection obtaining.`;
ok(/blocked the loading of a resource/.test(e.message), msg);
if (observer) {
yield observer.finished;
}
return;
}
// otherwise, we test manifest's content.
if (manifest) {
aTest.run(manifest);
}
}
});
// Helper object used to observe policy violations. It waits 10 seconds
// for a response, and then times out causing its associated test to fail.
function NetworkObserver(test) {
let finishedTest;
let success = false;
this.finished = new Promise((resolver) => {
finishedTest = resolver;
})
this.observe = function observer(subject, topic) {
SpecialPowers.removeObserver(this, 'csp-on-violate-policy');
test.run(topic);
finishedTest();
success = true;
};
SpecialPowers.addObserver(this, 'csp-on-violate-policy', false);
setTimeout(() => {
if (!success) {
test.run('This test timed out.');
finishedTest();
}
}, 1000);
}

View File

@ -0,0 +1,55 @@
/*
* Description of the test:
* Check that mixed content blocker works prevents fetches of
* mixed content manifests.
*/
'use strict';
const {
ManifestObtainer
} = Components.utils.import('resource://gre/modules/WebManifest.jsm', {});
const path = '/tests/dom/base/test/csp/';
const mixedContent = `file=${path}file_CSP_web_manifest_mixed_content.html`;
const server = 'file_csp_testserver.sjs';
const secureURL = `https://example.com${path}${server}`;
const tests = [
// Trying to load mixed content in file_CSP_web_manifest_mixed_content.html
// needs to result in an error.
{
expected: `Mixed Content Blocker prevents fetching manifest.`,
get tabURL() {
let queryParts = [
mixedContent
];
return `${secureURL}?${queryParts.join('&')}`;
},
run(error) {
// Check reason for error.
const check = /blocked the loading of a resource/.test(error.message);
ok(check, this.expected);
}
}
];
//jscs:disable
add_task(function*() {
//jscs:enable
for (let test of tests) {
let tabOptions = {
gBrowser: gBrowser,
url: test.tabURL,
};
yield BrowserTestUtils.withNewTab(
tabOptions,
browser => testObtainingManifest(browser, test)
);
}
function* testObtainingManifest(aBrowser, aTest) {
const obtainer = new ManifestObtainer();
try {
yield obtainer.obtainManifest(aBrowser);
} catch (e) {
aTest.run(e)
}
}
});

View File

@ -0,0 +1,6 @@
<!doctype html>
<meta charset=utf-8>
<head>
<link rel="manifest" href="file_CSP_web_manifest.json">
</head>
<h1>Support Page for Web Manifest Tests</h1>

View File

@ -0,0 +1 @@
{"name": "loaded"}

View File

@ -0,0 +1 @@
Access-Control-Allow-Origin: http://example.org

View File

@ -0,0 +1,4 @@
<!doctype html>
<meta charset=utf-8>
<link rel="manifest" href="https://example.com:443/tests/dom/base/test/csp/file_CSP_web_manifest_https.json">
<h1>Support Page for Web Manifest Tests</h1>

View File

@ -0,0 +1 @@
{"name": "loaded"}

View File

@ -0,0 +1,9 @@
<!doctype html>
<meta charset=utf-8>
<head>
<link
rel="manifest"
href="http://example.org/tests/dom/base/test/csp/file_csp_testserver.sjs?file=/test/dom/base/test/csp/file_CSP_web_manifest.json&amp;cors=*">
</head>
<h1>Support Page for Web Manifest Tests</h1>
<p>Used to try to load a resource over an insecure connection to trigger mixed content blocking.</p>

View File

@ -0,0 +1,8 @@
<!doctype html>
<meta charset=utf-8>
<link rel="manifest"
crossorigin
href="//mochi.test:8888/tests/dom/base/test/csp/file_csp_testserver.sjs?file=/tests/dom/base/test/csp/file_CSP_web_manifest.json&amp;cors=*">
<h1>Support Page for Web Manifest Tests</h1>
<p>Loads a manifest from mochi.test:8888 with CORS set to "*".</p>

View File

@ -22,6 +22,7 @@ function loadHTMLFromFile(path) {
return testHTML;
}
function handleRequest(request, response)
{
var query = {};
@ -30,16 +31,23 @@ function handleRequest(request, response)
query[name] = unescape(value);
});
var csp = unescape(query['csp']);
var csp = (query['csp']) ? unescape(query['csp']) : "";
var file = unescape(query['file']);
var cors = unescape(query['cors']);
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
// Deliver the CSP policy encoded in the URI
response.setHeader("Content-Security-Policy", csp, false);
if(csp){
response.setHeader("Content-Security-Policy", csp, false);
}
// Deliver the CORS header in the URI
if(cors){
response.setHeader("Access-Control-Allow-Origin", cors, false);
}
// Send HTML to test allowed/blocked behaviors
response.setHeader("Content-Type", "text/html", false);
response.write(loadHTMLFromFile(file));
}

View File

@ -43,6 +43,13 @@ support-files =
file_CSP_main.html
file_CSP_main.html^headers^
file_CSP_main.js
file_CSP_web_manifest.html
file_CSP_web_manifest_remote.html
file_CSP_web_manifest_https.html
file_CSP_web_manifest.json
file_CSP_web_manifest.json^headers^
file_CSP_web_manifest_https.json
file_CSP_web_manifest_mixed_content.html
file_bug836922_npolicies.html
file_bug836922_npolicies.html^headers^
file_bug836922_npolicies_ro_violation.sjs

View File

@ -37,4 +37,7 @@ MOCHITEST_CHROME_MANIFESTS += [
'csp/chrome.ini',
]
BROWSER_CHROME_MANIFESTS += ['browser.ini']
BROWSER_CHROME_MANIFESTS += [
'browser.ini',
'csp/browser.ini',
]

View File

@ -168,6 +168,9 @@ InternalRequest::SetContentPolicyType(nsContentPolicyType aContentPolicyType)
case nsIContentPolicy::TYPE_IMAGESET:
mContext = RequestContext::Imageset;
break;
case nsIContentPolicy::TYPE_WEB_MANIFEST:
mContext = RequestContext::Manifest;
break;
default:
MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
mContext = RequestContext::Internal;

View File

@ -49,7 +49,7 @@ namespace dom {
* import | Not supported by Gecko
* internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER
* location |
* manifest |
* manifest | TYPE_WEB_MANIFEST
* object | TYPE_OBJECT
* ping | TYPE_PING
* plugin | TYPE_OBJECT_SUBREQUEST

View File

@ -20,7 +20,7 @@ interface nsIURI;
typedef unsigned short CSPDirective;
[scriptable, uuid(459fe61a-203e-4460-9ced-352a9bd3aa71)]
[scriptable, uuid(059b94e3-45c2-4794-ac2a-5b66a66b5967)]
interface nsIContentSecurityPolicy : nsISerializable
{
/**
@ -48,6 +48,7 @@ interface nsIContentSecurityPolicy : nsISerializable
const unsigned short BASE_URI_DIRECTIVE = 13;
const unsigned short FORM_ACTION_DIRECTIVE = 14;
const unsigned short REFERRER_DIRECTIVE = 15;
const unsigned short WEB_MANIFEST_SRC_DIRECTIVE = 16;
/**
* Accessor method for a read-only string version of the policy at a given

View File

@ -14,7 +14,9 @@
/*globals content, sendAsyncMessage, addMessageListener, Components*/
'use strict';
const {
utils: Cu
utils: Cu,
classes: Cc,
interfaces: Ci
} = Components;
const {
ManifestProcessor
@ -34,6 +36,7 @@ addMessageListener('DOM:ManifestObtainer:Obtain', async(function* (aMsg) {
try {
response.result = yield fetchManifest();
} catch (err) {
response.success = false;
response.result = cloneError(err);
}
sendAsyncMessage('DOM:ManifestObtainer:Obtain', response);
@ -64,6 +67,11 @@ function fetchManifest() {
}
// Throws on malformed URLs
const manifestURL = new content.URL(elem.href, elem.baseURI);
if (!canLoadManifest(elem)) {
let msg = `Content Security Policy: The page's settings blocked the `;
msg += `loading of a resource at ${elem.href}`;
throw new Error(msg);
}
const reqInit = {
mode: 'cors'
};
@ -78,6 +86,21 @@ function fetchManifest() {
});
}
function canLoadManifest(aElem) {
const contentPolicy = Cc['@mozilla.org/layout/content-policy;1']
.getService(Ci.nsIContentPolicy);
const mimeType = aElem.type || 'application/manifest+json';
const elemURI = BrowserUtils.makeURI(
aElem.href, aElem.ownerDocument.characterSet
);
const shouldLoad = contentPolicy.shouldLoad(
Ci.nsIContentPolicy.TYPE_WEB_MANIFEST, elemURI,
aElem.ownerDocument.documentURIObject,
aElem, mimeType, null
);
return shouldLoad === Ci.nsIContentPolicy.ACCEPT;
}
function processResponse(aResp, aContentWindow) {
return spawn(function* () {
const badStatus = aResp.status < 200 || aResp.status >= 300;

View File

@ -149,6 +149,9 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType)
case nsIContentPolicy::TYPE_MEDIA:
return nsIContentSecurityPolicy::MEDIA_SRC_DIRECTIVE;
case nsIContentPolicy::TYPE_WEB_MANIFEST:
return nsIContentSecurityPolicy::WEB_MANIFEST_SRC_DIRECTIVE;
case nsIContentPolicy::TYPE_SUBDOCUMENT:
return nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE;
@ -836,6 +839,10 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
outCSP.mFrame_ancestors.Value() = srcs;
return;
case nsIContentSecurityPolicy::WEB_MANIFEST_SRC_DIRECTIVE:
outCSP.mManifest_src.Construct();
outCSP.mManifest_src.Value() = srcs;
return;
// not supporting REFLECTED_XSS_DIRECTIVE
case nsIContentSecurityPolicy::BASE_URI_DIRECTIVE:

View File

@ -64,8 +64,11 @@ void CSP_LogMessage(const nsAString& aMessage,
// these strings map to the CSPDirectives in nsIContentSecurityPolicy
// NOTE: When implementing a new directive, you will need to add it here but also
// add a corresponding entry to the constants in nsIContentSecurityPolicy.idl and
// also create an entry for the new directive in nsCSPDirective::toDomCSPStruct().
// add a corresponding entry to the constants in nsIContentSecurityPolicy.idl
// and also create an entry for the new directive in
// nsCSPDirective::toDomCSPStruct() and add it to CSPDictionaries.webidl.
// Order of elements below important! Make sure it matches the order as in
// nsIContentSecurityPolicy.idl
static const char* CSPStrDirectives[] = {
"-error-", // NO_DIRECTIVE
"default-src", // DEFAULT_SRC_DIRECTIVE
@ -82,7 +85,8 @@ static const char* CSPStrDirectives[] = {
"reflected-xss", // REFLECTED_XSS_DIRECTIVE
"base-uri", // BASE_URI_DIRECTIVE
"form-action", // FORM_ACTION_DIRECTIVE
"referrer" // REFERRER_DIRECTIVE
"referrer", // REFERRER_DIRECTIVE
"manifest-src" // MANIFEST_SRC_DIRECTIVE
};
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)

View File

@ -439,6 +439,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
case TYPE_SCRIPT:
case TYPE_STYLESHEET:
case TYPE_SUBDOCUMENT:
case TYPE_WEB_MANIFEST:
case TYPE_XBL:
case TYPE_XMLHTTPREQUEST:
case TYPE_XSLT:

View File

@ -24,6 +24,7 @@ dictionary CSP {
sequence<DOMString> base-uri;
sequence<DOMString> form-action;
sequence<DOMString> referrer;
sequence<DOMString> manifest-src;
};
dictionary CSPPolicies {

View File

@ -39,7 +39,11 @@ static const char *kTypeString[] = {"other",
"media",
"websocket",
"csp_report",
"xslt"};
"xslt",
"beacon",
"fetch",
"imageset",
"manifest"};
#define NUMBER_OF_TYPES MOZ_ARRAY_LENGTH(kTypeString)
uint8_t nsContentBlocker::mBehaviorPref[NUMBER_OF_TYPES];

View File

@ -64,6 +64,7 @@
#define APPLICATION_OLEOBJECT2 "application/x-oleobject"
#define APPLICATION_JAVAARCHIVE "application/java-archive"
#define APPLICATION_MARIMBA "application/marimba"
#define APPLICATION_WEB_MANIFEST "application/manifest+json"
#define APPLICATION_XMARIMBA "application/x-marimba"
#define APPLICATION_XPINSTALL "application/x-xpinstall"
#define APPLICATION_XML "application/xml"