| author | Jonathan Kingston <jkt@mozilla.com> |
| Thu, 01 Dec 2016 07:41:22 +0000 (2016-12-01) | |
| changeset 328589 | 0d48c28cc547dd6c4cd8a71b9e9c878319fbed31 |
| parent 328588 | 5a792df3106ce6d7ca7c107d5197d53387a8cfd4 |
| child 328590 | 83fbff91e9d2aec7ebc92c3c2017af39ebc49a36 |
| push id | 31181 |
| push user | cbook@mozilla.com |
| push date | Tue, 10 Jan 2017 11:09:50 +0000 (2017-01-10) |
| treeherder | mozilla-central@acd4177b28d7 [default view] [failures only] |
| reviewers | hsivonen, smaug |
| bugs | 1216893 |
| milestone | 53.0a1 |
| first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
| last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/NameSpaceConstants.h +++ b/dom/base/NameSpaceConstants.h @@ -19,11 +19,12 @@ static const int32_t kNameSpaceID_None = #define kNameSpaceID_XLink 4 #define kNameSpaceID_XSLT 5 #define kNameSpaceID_XBL 6 #define kNameSpaceID_MathML 7 #define kNameSpaceID_RDF 8 #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__
--- a/dom/base/nsNameSpaceManager.cpp +++ b/dom/base/nsNameSpaceManager.cpp @@ -23,19 +23,21 @@ #include "mozilla/ClearOnShutdown.h" #include "mozilla/dom/XBLChildrenElement.h" #include "mozilla/dom/Element.h" #include "mozilla/Preferences.h" 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; /* static */ nsNameSpaceManager* nsNameSpaceManager::GetInstance() { if (!sInstance) { sInstance = new nsNameSpaceManager(); @@ -58,32 +60,34 @@ bool nsNameSpaceManager::Init() NS_ENSURE_SUCCESS(rv, false) #define REGISTER_DISABLED_NAMESPACE(uri, id) \ rv = AddDisabledNameSpace(dont_AddRef(uri), id); \ NS_ENSURE_SUCCESS(rv, false) mozilla::Preferences::AddStrongObservers(this, kObservedPrefs); mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled); + mSVGDisabled = mozilla::Preferences::GetBool(kPrefSVGDisabled); // Need to be ordered according to ID. MOZ_ASSERT(mURIArray.IsEmpty()); REGISTER_NAMESPACE(nsGkAtoms::empty, kNameSpaceID_None); REGISTER_NAMESPACE(nsGkAtoms::nsuri_xmlns, kNameSpaceID_XMLNS); REGISTER_NAMESPACE(nsGkAtoms::nsuri_xml, kNameSpaceID_XML); REGISTER_NAMESPACE(nsGkAtoms::nsuri_xhtml, kNameSpaceID_XHTML); REGISTER_NAMESPACE(nsGkAtoms::nsuri_xlink, kNameSpaceID_XLink); REGISTER_NAMESPACE(nsGkAtoms::nsuri_xslt, kNameSpaceID_XSLT); REGISTER_NAMESPACE(nsGkAtoms::nsuri_xbl, kNameSpaceID_XBL); REGISTER_NAMESPACE(nsGkAtoms::nsuri_mathml, kNameSpaceID_MathML); REGISTER_NAMESPACE(nsGkAtoms::nsuri_rdf, kNameSpaceID_RDF); 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 return true; } nsresult @@ -146,19 +150,21 @@ int32_t nsNameSpaceManager::GetNameSpaceID(nsIAtom* aURI, bool aInChromeDoc) { if (aURI == nsGkAtoms::_empty) { return kNameSpaceID_None; // xmlns="", see bug 75700 for details } 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; } if (mURIToIDTable.Get(aURI, &nameSpaceID)) { NS_POSTCONDITION(nameSpaceID >= 0, "Bogus namespace ID"); return nameSpaceID; } @@ -181,28 +187,59 @@ NS_NewElement(Element** aResult, return NS_NewXULElement(aResult, ni.forget()); } #endif if (ns == kNameSpaceID_MathML) { // If the mathml.disabled pref. is true, convert all MathML nodes into // 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()); } RefPtr<mozilla::dom::NodeInfo> genericXMLNI = ni->NodeInfoManager()-> GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(), kNameSpaceID_disabled_MathML, ni->NodeType(), ni->GetExtraName()); 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())); return NS_OK; } return NS_NewXMLElement(aResult, ni.forget()); } @@ -257,10 +294,11 @@ NS_IMPL_ISUPPORTS(nsNameSpaceManager, nsIObserver) // nsIObserver NS_IMETHODIMP nsNameSpaceManager::Observe(nsISupports* aObject, const char* aTopic, const char16_t* aMessage) { mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled); + mSVGDisabled = mozilla::Preferences::GetBool(kPrefSVGDisabled); return NS_OK; }
--- a/dom/base/nsNameSpaceManager.h +++ b/dom/base/nsNameSpaceManager.h @@ -61,16 +61,17 @@ public: bool aInChromeDoc); int32_t GetNameSpaceID(nsIAtom* aURI, bool aInChromeDoc); bool HasElementCreator(int32_t aNameSpaceID); static nsNameSpaceManager* GetInstance(); bool mMathMLDisabled; + bool mSVGDisabled; private: bool Init(); nsresult AddNameSpace(already_AddRefed<nsIAtom> aURI, const int32_t aNameSpaceID); nsresult AddDisabledNameSpace(already_AddRefed<nsIAtom> aURI, const int32_t aNameSpaceID); ~nsNameSpaceManager() {}; nsDataHashtable<nsISupportsHashKey, int32_t> mURIToIDTable;
--- a/dom/xml/nsXMLContentSink.cpp +++ b/dom/xml/nsXMLContentSink.cpp @@ -1054,16 +1054,19 @@ nsXMLContentSink::HandleEndElement(const // elements do not get pushed on the stack, the template // element content is pushed instead. bool isTemplateElement = debugTagAtom == nsGkAtoms::_template && debugNameSpaceID == kNameSpaceID_XHTML; NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID) || (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 result = CloseElement(content); if (mCurrentHead == content) { mCurrentHead = nullptr; }
--- a/layout/svg/moz.build +++ b/layout/svg/moz.build @@ -2,16 +2,24 @@ # vim: set filetype=python: # 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/. 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', 'nsSVGFilterInstance.h', 'nsSVGForeignObjectFrame.h', 'nsSVGIntegrationUtils.h', 'nsSVGUtils.h', 'SVGImageContext.h',
new file mode 100644 --- /dev/null +++ b/layout/svg/tests/chrome.ini @@ -0,0 +1,6 @@ +[DEFAULT] + +support-files = + svg_example_test.html + +[test_disabled_chrome.html]
new file mode 100644 --- /dev/null +++ b/layout/svg/tests/mochitest.ini @@ -0,0 +1,3 @@ +[DEFAULT] + +[test_disabled.html]
new file mode 100644 --- /dev/null +++ b/layout/svg/tests/svg_example_test.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>
new file mode 100644 --- /dev/null +++ b/layout/svg/tests/test_disabled.html @@ -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><foo></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&2<3>4 \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&2<3>4 \u003C/style></svg>'); + + SimpleTest.finish(); + } +</script> +</pre> +</body> +</html> +
new file mode 100644 --- /dev/null +++ b/layout/svg/tests/test_disabled_chrome.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> +
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2874,16 +2874,19 @@ pref("dom.ipc.plugins.asyncInit.enabled" pref("dom.ipc.plugins.asyncdrawing.enabled", false); #else // Allow the AsyncDrawing mode to be used for plugins in dev channels. pref("dom.ipc.plugins.asyncdrawing.enabled", true); #endif 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); // Pref to control whether we use separate content processes for top-level load // of file:// URIs. #if defined(NIGHTLY_BUILD) pref("browser.tabs.remote.separateFileUriProcess", true); #else
--- a/parser/html/nsHtml5DocumentBuilder.cpp +++ b/parser/html/nsHtml5DocumentBuilder.cpp @@ -5,16 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsHtml5DocumentBuilder.h" #include "nsIStyleSheetLinkingElement.h" #include "nsStyleLinkElement.h" #include "nsScriptLoader.h" #include "nsIHTMLDocument.h" +#include "nsNameSpaceManager.h" NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHtml5DocumentBuilder, nsContentSink, mOwnedElements) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsHtml5DocumentBuilder) NS_INTERFACE_MAP_END_INHERITING(nsContentSink) NS_IMPL_ADDREF_INHERITED(nsHtml5DocumentBuilder, nsContentSink) @@ -52,28 +53,31 @@ nsHtml5DocumentBuilder::SetDocumentChars mDocument->SetDocumentCharacterSetSource(aCharsetSource); mDocument->SetDocumentCharacterSet(aCharset); } } 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(); if (MOZ_UNLIKELY(!mParser)) { // EndDocUpdate ran stuff that called nsIParser::Terminate() return; } - nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aElement)); - NS_ASSERTION(ssle, "Node didn't QI to style."); - ssle->SetEnableUpdates(true); bool willNotify; bool isAlternate; nsresult rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this, &willNotify, &isAlternate); if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) {
--- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -819,18 +819,21 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre } case eTreeOpStreamEnded: { aBuilder->DidBuildModel(false); // this causes a notifications flush anyway return NS_OK; } 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: { nsIContent* node = *(mOne.node); nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node); NS_ASSERTION(sele, "Node didn't QI to script."); sele->SetScriptLineNumber(mFour.integer); sele->FreezeUriAsyncDefer();
new file mode 100644 --- /dev/null +++ b/toolkit/components/contextualidentity/tests/unit/test_basic.html @@ -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"); +});