Bug 1216893 - Add in disabled namespace for SVG r=hsivonen,smaug

MozReview-Commit-ID: 7Gum6wazraS

--HG--
extra : rebase_source : a2348710908e160cb09e48f15adfb50cd485f151
This commit is contained in:
Jonathan Kingston 2016-12-01 07:41:22 +00:00
Родитель 1a6470f3a1
Коммит 91e141995c
14 изменённых файлов: 271 добавлений и 11 удалений

Просмотреть файл

@ -24,6 +24,7 @@ static const int32_t kNameSpaceID_None = 0;
#define kNameSpaceID_XUL 9
#define kNameSpaceID_SVG 10
#define kNameSpaceID_disabled_MathML 11
#define kNameSpaceID_LastBuiltin 11 // last 'built-in' namespace
#define kNameSpaceID_disabled_SVG 12
#define kNameSpaceID_LastBuiltin 12 // last 'built-in' namespace
#endif // mozilla_dom_NameSpaceConstants_h__

Просмотреть файл

@ -28,9 +28,11 @@
using namespace mozilla;
using namespace mozilla::dom;
static const char* kPrefSVGDisabled = "svg.disabled";
static const char* kPrefMathMLDisabled = "mathml.disabled";
static const char* kObservedPrefs[] = {
kPrefMathMLDisabled,
kPrefSVGDisabled,
nullptr
};
StaticRefPtr<nsNameSpaceManager> nsNameSpaceManager::sInstance;
@ -63,6 +65,7 @@ bool nsNameSpaceManager::Init()
mozilla::Preferences::AddStrongObservers(this, kObservedPrefs);
mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled);
mSVGDisabled = mozilla::Preferences::GetBool(kPrefSVGDisabled);
// Need to be ordered according to ID.
@ -79,6 +82,7 @@ bool nsNameSpaceManager::Init()
REGISTER_NAMESPACE(nsGkAtoms::nsuri_xul, kNameSpaceID_XUL);
REGISTER_NAMESPACE(nsGkAtoms::nsuri_svg, kNameSpaceID_SVG);
REGISTER_DISABLED_NAMESPACE(nsGkAtoms::nsuri_mathml, kNameSpaceID_disabled_MathML);
REGISTER_DISABLED_NAMESPACE(nsGkAtoms::nsuri_svg, kNameSpaceID_disabled_SVG);
#undef REGISTER_NAMESPACE
#undef REGISTER_DISABLED_NAMESPACE
@ -151,9 +155,11 @@ nsNameSpaceManager::GetNameSpaceID(nsIAtom* aURI,
}
int32_t nameSpaceID;
if (mMathMLDisabled &&
mDisabledURIToIDTable.Get(aURI, &nameSpaceID) &&
!aInChromeDoc) {
if (!aInChromeDoc
&& (mMathMLDisabled || mSVGDisabled)
&& mDisabledURIToIDTable.Get(aURI, &nameSpaceID)
&& ((mMathMLDisabled && kNameSpaceID_disabled_MathML == nameSpaceID) ||
(mSVGDisabled && kNameSpaceID_disabled_SVG == nameSpaceID))) {
NS_POSTCONDITION(nameSpaceID >= 0, "Bogus namespace ID");
return nameSpaceID;
}
@ -186,7 +192,7 @@ NS_NewElement(Element** aResult,
// disabled MathML nodes by swapping the namespace.
nsNameSpaceManager* nsmgr = nsNameSpaceManager::GetInstance();
if ((nsmgr && !nsmgr->mMathMLDisabled) ||
nsContentUtils::IsChromeDoc(ni->GetDocument())) {
nsContentUtils::IsSystemPrincipal(ni->GetDocument()->NodePrincipal())) {
return NS_NewMathMLElement(aResult, ni.forget());
}
@ -197,7 +203,38 @@ NS_NewElement(Element** aResult,
return NS_NewXMLElement(aResult, genericXMLNI.forget());
}
if (ns == kNameSpaceID_SVG) {
return NS_NewSVGElement(aResult, ni.forget(), aFromParser);
// If the svg.disabled pref. is true, convert all SVG nodes into
// disabled SVG nodes by swapping the namespace.
nsNameSpaceManager* nsmgr = nsNameSpaceManager::GetInstance();
nsCOMPtr<nsILoadInfo> loadInfo;
bool SVGEnabled = false;
if (nsmgr && !nsmgr->mSVGDisabled) {
SVGEnabled = true;
} else {
nsCOMPtr<nsIChannel> channel = ni->GetDocument()->GetChannel();
// We don't have a channel for SVGs constructed inside a SVG script
if (channel) {
loadInfo = channel->GetLoadInfo();
}
}
if (SVGEnabled ||
nsContentUtils::IsSystemPrincipal(ni->GetDocument()->NodePrincipal()) ||
(loadInfo &&
(loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_IMAGE ||
loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_OTHER) &&
(nsContentUtils::IsSystemPrincipal(loadInfo->LoadingPrincipal()) ||
nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal())
)
)
) {
return NS_NewSVGElement(aResult, ni.forget(), aFromParser);
}
RefPtr<mozilla::dom::NodeInfo> genericXMLNI =
ni->NodeInfoManager()->
GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(),
kNameSpaceID_disabled_SVG, ni->NodeType(), ni->GetExtraName());
return NS_NewXMLElement(aResult, genericXMLNI.forget());
}
if (ns == kNameSpaceID_XBL && ni->Equals(nsGkAtoms::children)) {
NS_ADDREF(*aResult = new XBLChildrenElement(ni.forget()));
@ -262,5 +299,6 @@ nsNameSpaceManager::Observe(nsISupports* aObject, const char* aTopic,
const char16_t* aMessage)
{
mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled);
mSVGDisabled = mozilla::Preferences::GetBool(kPrefSVGDisabled);
return NS_OK;
}

Просмотреть файл

@ -66,6 +66,7 @@ public:
static nsNameSpaceManager* GetInstance();
bool mMathMLDisabled;
bool mSVGDisabled;
private:
bool Init();

Просмотреть файл

@ -1059,6 +1059,9 @@ nsXMLContentSink::HandleEndElement(const char16_t *aName,
(debugNameSpaceID == kNameSpaceID_MathML &&
content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_MathML &&
content->NodeInfo()->Equals(debugTagAtom)) ||
(debugNameSpaceID == kNameSpaceID_SVG &&
content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_SVG &&
content->NodeInfo()->Equals(debugTagAtom)) ||
isTemplateElement, "Wrong element being closed");
#endif

Просмотреть файл

@ -7,6 +7,14 @@
with Files('**'):
BUG_COMPONENT = ('Core', 'SVG')
if CONFIG['ENABLE_TESTS']:
MOCHITEST_MANIFESTS += [
'tests/mochitest.ini',
]
MOCHITEST_CHROME_MANIFESTS += [
'tests/chrome.ini',
]
EXPORTS += [
'nsFilterInstance.h',
'nsSVGEffects.h',

Просмотреть файл

@ -0,0 +1,6 @@
[DEFAULT]
support-files =
svg_example_test.html
[test_disabled_chrome.html]

Просмотреть файл

@ -0,0 +1,3 @@
[DEFAULT]
[test_disabled.html]

Просмотреть файл

@ -0,0 +1,7 @@
<svg id="layout" viewBox="0 0 120 120" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle cx="60" cy="60" r="50"/>
</svg>
<svg id="svgel">
</svg>

После

Ширина:  |  Высота:  |  Размер: 158 B

Просмотреть файл

@ -0,0 +1,59 @@
<!DOCTYPE HTML>
<html>
<!--
Copied from
https://bugzilla.mozilla.org/show_bug.cgi?id=744830
-->
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=166235">Mozilla Bug 166235</a>
<div id="testnodes"><span>hi</span> there <!-- mon ami --></div>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["svg.disabled", true]]}, doTest);
function doTest() {
let t = document.getElementById('testnodes');
t.innerHTML = null;
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg:svg"));
t.firstChild.textContent = "<foo>";
is(t.innerHTML, "<svg:svg>&lt;foo&gt;</svg:svg>");
// This test crashes if the style tags are not handled correctly
t.innerHTML = `<svg version="1.1">
<style>
circle {
fill: currentColor;
}
</style>
<g><circle cx="25.8" cy="9.3" r="1.5"/></g>
</svg>
`;
is(t.firstChild.tagName.toLowerCase(), 'svg');
t.innerHTML = null;
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg"));
is(t.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "script"));
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
is(t.innerHTML, '<svg><script>1&amp;2&lt;3&gt;4&nbsp;\u003C/script></svg>');
t.innerHTML = null;
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg"));
is(t.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "style"));
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
is(t.innerHTML, '<svg><style>1&amp;2&lt;3&gt;4&nbsp;\u003C/style></svg>');
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,53 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=744830
-->
<head>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=166235">Mozilla Bug 166235</a>
<div id="testnodes"><span>hi</span> there <!-- mon ami --></div>
<pre id="test">
<script type="application/javascript">
add_task(function* () {
const initialPrefValue = SpecialPowers.getBoolPref("svg.disabled");
SpecialPowers.setBoolPref("svg.disabled", true);
const Cu = SpecialPowers.Components.utils;
const { ContentTaskUtils } = Cu.import("resource://testing-common/ContentTaskUtils.jsm", {});
let t = document.getElementById('testnodes');
let url = 'chrome://mochitests/content/chrome/layout/svg/tests/svg_example_test.html'
const chromeIframeEl = document.createElement('iframe');
let chromeLoadPromise = ContentTaskUtils.waitForEvent(chromeIframeEl, 'load', false);
chromeIframeEl.src = url;
t.appendChild(chromeIframeEl);
yield chromeLoadPromise;
const chromeBR = chromeIframeEl.contentDocument.body.getBoundingClientRect();
url = "http://mochi.test:8888/chrome/layout/svg/tests/svg_example_test.html";
const iframeEl = document.createElement('iframe');
iframeEl.src = url;
let loadPromise = ContentTaskUtils.waitForEvent(iframeEl, 'load', false);
t.appendChild(iframeEl);
yield loadPromise;
const contentBR = iframeEl.contentDocument.body.getBoundingClientRect();
yield new Promise(_ => setTimeout(_, 1000));
ok(chromeBR.height > contentBR.height, "Chrome content height should be bigger than content due to layout");
ok(!("hasExtension" in iframeEl.contentDocument.getElementById('svgel')), 'SVG is disabled so no hasExtension support is available in content iframe');
ok(chromeIframeEl.contentDocument.getElementById('svgel').hasExtension("http://www.w3.org/1998/Math/MathML"), 'SVG namespace support is enabled in chrome iframe');
SpecialPowers.setBoolPref("svg.disabled", initialPrefValue);
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -2879,6 +2879,9 @@ pref("dom.ipc.plugins.asyncdrawing.enabled", true);
pref("dom.ipc.processCount", 1);
// Disable support for SVG
pref("svg.disabled", false);
// Override default dom.ipc.processCount for some remote content process types.
pref("dom.ipc.processCount.webLargeAllocation", 2);

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsStyleLinkElement.h"
#include "nsScriptLoader.h"
#include "nsIHTMLDocument.h"
#include "nsNameSpaceManager.h"
NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHtml5DocumentBuilder, nsContentSink,
mOwnedElements)
@ -57,6 +58,12 @@ nsHtml5DocumentBuilder::SetDocumentCharsetAndSource(nsACString& aCharset, int32_
void
nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement)
{
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aElement));
if (!ssle) {
MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, "Node didn't QI to style, but SVG wasn't disabled.");
return;
}
// Break out of the doc update created by Flush() to zap a runnable
// waiting to call UpdateStyleSheet without the right observer
EndDocUpdate();
@ -66,9 +73,6 @@ nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement)
return;
}
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aElement));
NS_ASSERTION(ssle, "Node didn't QI to style.");
ssle->SetEnableUpdates(true);
bool willNotify;

Просмотреть файл

@ -824,8 +824,11 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
case eTreeOpSetStyleLineNumber: {
nsIContent* node = *(mOne.node);
nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(node);
NS_ASSERTION(ssle, "Node didn't QI to style.");
ssle->SetLineNumber(mFour.integer);
if (ssle) {
ssle->SetLineNumber(mFour.integer);
} else {
MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, "Node didn't QI to style, but SVG wasn't disabled.");
}
return NS_OK;
}
case eTreeOpSetScriptLineNumberAndFreeze: {

Просмотреть файл

@ -0,0 +1,71 @@
"use strict";
do_get_profile();
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/ContextualIdentityService.jsm");
const TEST_STORE_FILE_NAME = "test-containers.json";
let cis;
// Basic tests
add_task(function() {
ok(!!ContextualIdentityService, "ContextualIdentityService exists");
cis = ContextualIdentityService.createNewInstanceForTesting(TEST_STORE_FILE_NAME);
ok(!!cis, "We have our instance of ContextualIdentityService");
equal(cis.getIdentities().length, 4, "By default, 4 containers.");
equal(cis.getIdentityFromId(0), null, "No identity with id 0");
ok(!!cis.getIdentityFromId(1), "Identity 1 exists");
ok(!!cis.getIdentityFromId(2), "Identity 2 exists");
ok(!!cis.getIdentityFromId(3), "Identity 3 exists");
ok(!!cis.getIdentityFromId(4), "Identity 4 exists");
});
// Create a new identity
add_task(function() {
equal(cis.getIdentities().length, 4, "By default, 4 containers.");
let identity = cis.create("New Container", "Icon", "Color");
ok(!!identity, "New container created");
equal(identity.name, "New Container", "Name matches");
equal(identity.icon, "Icon", "Icon matches");
equal(identity.color, "Color", "Color matches");
equal(cis.getIdentities().length, 5, "Expected 5 containers.");
ok(!!cis.getIdentityFromId(identity.userContextId), "Identity exists");
equal(cis.getIdentityFromId(identity.userContextId).name, "New Container", "Identity name is OK");
equal(cis.getIdentityFromId(identity.userContextId).icon, "Icon", "Identity icon is OK");
equal(cis.getIdentityFromId(identity.userContextId).color, "Color", "Identity color is OK");
equal(cis.getUserContextLabel(identity.userContextId), "New Container", "Identity label is OK");
});
// Remove an identity
add_task(function() {
equal(cis.getIdentities().length, 5, "Expected 5 containers.");
equal(cis.remove(-1), false, "cis.remove() returns false if identity doesn't exist.");
equal(cis.remove(1), true, "cis.remove() returns true if identity exists.");
equal(cis.getIdentities().length, 4, "Expected 4 containers.");
});
// Update an identity
add_task(function() {
ok(!!cis.getIdentityFromId(2), "Identity 2 exists");
equal(cis.update(-1, "Container", "Icon", "Color"), false, "Update returns true if everything is OK");
equal(cis.update(2, "Container", "Icon", "Color"), true, "Update returns true if everything is OK");
ok(!!cis.getIdentityFromId(2), "Identity exists");
equal(cis.getIdentityFromId(2).name, "Container", "Identity name is OK");
equal(cis.getIdentityFromId(2).icon, "Icon", "Identity icon is OK");
equal(cis.getIdentityFromId(2).color, "Color", "Identity color is OK");
equal(cis.getUserContextLabel(2), "Container", "Identity label is OK");
});