author | Alex Catarineu <acat@torproject.org> |
Mon, 08 Jul 2019 10:47:05 +0000 (2019-07-08) | |
changeset 481641 | 9276e88ea3fed58b881ae3eff4580d04e54a6e14 |
parent 481640 | bdec71eff3a6a92dee514cc049f8a3d04609936f |
child 481642 | a07109e6cefea72b8ae9b884cb21d16eacd78ae6 |
push id | 36261 |
push user | nbeleuzu@mozilla.com |
push date | Tue, 09 Jul 2019 03:44:14 +0000 (2019-07-09) |
treeherder | mozilla-central@b782ed36b2e8 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Gijs, bzbarsky |
bugs | 467035 |
milestone | 69.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/browser/base/content/test/static/browser_misused_characters_in_strings.js +++ b/browser/base/content/test/static/browser_misused_characters_in_strings.js @@ -267,16 +267,17 @@ add_task(async function checkAllTheDTDs( add_task(async function checkAllTheFluents() { let uris = await getAllTheFiles(".ftl"); let { FluentResource } = ChromeUtils.import( "resource://gre/modules/Fluent.jsm", {} ); let domParser = new DOMParser(); + domParser.forceEnableDTD(); for (let uri of uris) { let rawContents = await fetchFile(uri.spec); let resource = FluentResource.fromString(rawContents); if (!resource) { return; } for (let [key, val] of resource) {
--- a/browser/components/payments/test/mochitest/formautofill/mochitest.ini +++ b/browser/components/payments/test/mochitest/formautofill/mochitest.ini @@ -1,9 +1,10 @@ [DEFAULT] # This manifest mostly exists so that the support-files below can be referenced # from a relative path of formautofill/* from the tests in the above directory # to resemble the layout in the shipped JAR file. support-files = ../../../../../../browser/extensions/formautofill/content/editCreditCard.xhtml ../../../../../../browser/extensions/formautofill/content/editAddress.xhtml +skip-if = true # Bug 1446164 [test_editCreditCard.html]
--- a/dom/base/DOMParser.cpp +++ b/dom/base/DOMParser.cpp @@ -28,17 +28,18 @@ using namespace mozilla; using namespace mozilla::dom; DOMParser::DOMParser(nsIGlobalObject* aOwner, nsIPrincipal* aDocPrincipal, nsIURI* aDocumentURI, nsIURI* aBaseURI) : mOwner(aOwner), mPrincipal(aDocPrincipal), mDocumentURI(aDocumentURI), mBaseURI(aBaseURI), - mForceEnableXULXBL(false) { + mForceEnableXULXBL(false), + mForceEnableDTD(false) { MOZ_ASSERT(aDocPrincipal); MOZ_ASSERT(aDocumentURI); } DOMParser::~DOMParser() {} // QueryInterface implementation for DOMParser NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMParser) @@ -64,16 +65,20 @@ already_AddRefed<Document> DOMParser::Pa return nullptr; } // Keep the XULXBL state in sync with the XML case. if (mForceEnableXULXBL) { document->ForceEnableXULXBL(); } + if (mForceEnableDTD) { + document->ForceSkipDTDSecurityChecks(); + } + nsresult rv = nsContentUtils::ParseDocumentHTML(aStr, document, false); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.Throw(rv); return nullptr; } return document.forget(); } @@ -178,16 +183,20 @@ already_AddRefed<Document> DOMParser::Pa // Tell the document to start loading nsCOMPtr<nsIStreamListener> listener; // Keep the XULXBL state in sync with the HTML case if (mForceEnableXULXBL) { document->ForceEnableXULXBL(); } + if (mForceEnableDTD) { + document->ForceSkipDTDSecurityChecks(); + } + // Have to pass false for reset here, else the reset will remove // our event listener. Should that listener addition move to later // than this call? nsresult rv = document->StartDocumentLoad(kLoadAsData, parserChannel, nullptr, nullptr, getter_AddRefs(listener), false); if (NS_FAILED(rv) || !listener) {
--- a/dom/base/DOMParser.h +++ b/dom/base/DOMParser.h @@ -48,17 +48,22 @@ class DOMParser final : public nsISuppor ErrorResult& aRv); already_AddRefed<Document> ParseFromStream(nsIInputStream* aStream, const nsAString& aCharset, int32_t aContentLength, SupportedType aType, ErrorResult& aRv); - void ForceEnableXULXBL() { mForceEnableXULXBL = true; } + void ForceEnableXULXBL() { + mForceEnableXULXBL = true; + ForceEnableDTD(); + } + + void ForceEnableDTD() { mForceEnableDTD = true; } nsIGlobalObject* GetParentObject() const { return mOwner; } virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override { return mozilla::dom::DOMParser_Binding::Wrap(aCx, this, aGivenProto); } @@ -73,14 +78,15 @@ class DOMParser final : public nsISuppor ErrorResult& aRv); nsCOMPtr<nsIGlobalObject> mOwner; nsCOMPtr<nsIPrincipal> mPrincipal; nsCOMPtr<nsIURI> mDocumentURI; nsCOMPtr<nsIURI> mBaseURI; bool mForceEnableXULXBL; + bool mForceEnableDTD; }; } // namespace dom } // namespace mozilla #endif
--- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -1295,16 +1295,17 @@ Document::Document(const char* aContentT #ifdef MOZILLA_INTERNAL_API mVisibilityState(dom::VisibilityState::Hidden), #else mDummy(0), #endif mType(eUnknown), mDefaultElementType(0), mAllowXULXBL(eTriUnset), + mSkipDTDSecurityChecks(false), mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS), mSandboxFlags(0), mPartID(0), mMarkedCCGeneration(0), mPresShell(nullptr), mSubtreeModifiedDepth(0), mPreloadPictureDepth(0), mEventsSuppressed(0), @@ -2282,48 +2283,16 @@ void Document::Reset(nsIChannel* aChanne mDocumentBaseURI = baseURI; mChromeXHRDocBaseURI = nullptr; } } mChannel = aChannel; } -/** - * Determine whether the principal is allowed access to the localization system. - * We don't want the web to ever see this but all our UI including in content - * pages should pass this test. - */ -bool PrincipalAllowsL10n(nsIPrincipal* principal) { - // The system principal is always allowed. - if (nsContentUtils::IsSystemPrincipal(principal)) { - return true; - } - - nsCOMPtr<nsIURI> uri; - nsresult rv = principal->GetURI(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, false); - - bool hasFlags; - - // Allow access to uris that cannot be loaded by web content. - rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD, - &hasFlags); - NS_ENSURE_SUCCESS(rv, false); - if (hasFlags) { - return true; - } - - // UI resources also get access. - rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, - &hasFlags); - NS_ENSURE_SUCCESS(rv, false); - return hasFlags; -} - void Document::DisconnectNodeTree() { // Delete references to sub-documents and kill the subdocument map, // if any. This is not strictly needed, but makes the node tree // teardown a bit faster. delete mSubDocuments; mSubDocuments = nullptr; // Destroy link map now so we don't waste time removing @@ -3647,21 +3616,21 @@ void Document::InitializeLocalization(ns mDocumentL10n = l10n; } DocumentL10n* Document::GetL10n() { return mDocumentL10n; } bool Document::DocumentSupportsL10n(JSContext* aCx, JSObject* aObject) { nsCOMPtr<nsIPrincipal> callerPrincipal = nsContentUtils::SubjectPrincipal(aCx); - return PrincipalAllowsL10n(callerPrincipal); + return nsContentUtils::PrincipalAllowsL10n(callerPrincipal); } void Document::LocalizationLinkAdded(Element* aLinkElement) { - if (!PrincipalAllowsL10n(NodePrincipal())) { + if (!nsContentUtils::PrincipalAllowsL10n(NodePrincipal())) { return; } nsAutoString href; aLinkElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href); // If the link is added after the DocumentL10n instance // has been initialized, just pass the resource ID to it. if (mDocumentL10n) { @@ -3689,17 +3658,17 @@ void Document::LocalizationLinkAdded(Ele BlockOnload(); } mPendingInitialTranslation = true; } } void Document::LocalizationLinkRemoved(Element* aLinkElement) { - if (!PrincipalAllowsL10n(NodePrincipal())) { + if (!nsContentUtils::PrincipalAllowsL10n(NodePrincipal())) { return; } nsAutoString href; aLinkElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href); if (mDocumentL10n) { AutoTArray<nsString, 1> resourceIds; resourceIds.AppendElement(href);
--- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -2992,18 +2992,26 @@ class Document : public nsINode, * use non-builtin XBL bindings. */ bool AllowXULXBL() { return mAllowXULXBL == eTriTrue ? true : mAllowXULXBL == eTriFalse ? false : InternalAllowXULXBL(); } + /** + * Returns true if this document is allowed to load DTDs from UI resources + * no matter what. + */ + bool SkipDTDSecurityChecks() { return mSkipDTDSecurityChecks; } + void ForceEnableXULXBL() { mAllowXULXBL = eTriTrue; } + void ForceSkipDTDSecurityChecks() { mSkipDTDSecurityChecks = true; } + /** * Returns the template content owner document that owns the content of * HTMLTemplateElement. */ Document* GetTemplateContentsOwner(); /** * Returns true if this document is a static clone of a normal document. @@ -4806,16 +4814,18 @@ class Document : public nsINode, Type mType; uint8_t mDefaultElementType; enum Tri { eTriUnset = 0, eTriFalse, eTriTrue }; Tri mAllowXULXBL; + bool mSkipDTDSecurityChecks; + // The document's script global object, the object from which the // document can get its script context and scope. This is the // *inner* window object. nsCOMPtr<nsIScriptGlobalObject> mScriptGlobalObject; // If mIsStaticDocument is true, mOriginalDocument points to the original // document. RefPtr<Document> mOriginalDocument;
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -1680,16 +1680,44 @@ bool nsContentUtils::OfflineAppAllowed(n } bool allowed; nsresult rv = updateService->OfflineAppAllowed( aPrincipal, Preferences::GetRootBranch(), &allowed); return NS_SUCCEEDED(rv) && allowed; } +/* static */ +bool nsContentUtils::PrincipalAllowsL10n(nsIPrincipal* aPrincipal) { + // The system principal is always allowed. + if (IsSystemPrincipal(aPrincipal)) { + return true; + } + + nsCOMPtr<nsIURI> uri; + nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, false); + + bool hasFlags; + + // Allow access to uris that cannot be loaded by web content. + rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD, + &hasFlags); + NS_ENSURE_SUCCESS(rv, false); + if (hasFlags) { + return true; + } + + // UI resources also get access. + rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, + &hasFlags); + NS_ENSURE_SUCCESS(rv, false); + return hasFlags; +} + bool nsContentUtils::MaybeAllowOfflineAppByDefault(nsIPrincipal* aPrincipal) { if (!Preferences::GetRootBranch()) return false; nsresult rv; bool allowedByDefault; rv = Preferences::GetRootBranch()->GetBoolPref( "offline-apps.allow_by_default", &allowedByDefault);
--- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1972,16 +1972,23 @@ class nsContentUtils { static bool OfflineAppAllowed(nsIURI* aURI); /** * Check whether an application should be allowed to use offline APIs. */ static bool OfflineAppAllowed(nsIPrincipal* aPrincipal); /** + * Determine whether the principal is allowed access to the localization + * system. We don't want the web to ever see this but all our UI including in + * content pages should pass this test. + */ + static bool PrincipalAllowsL10n(nsIPrincipal* aPrincipal); + + /** * If offline-apps.allow_by_default is true, we set offline-app permission * for the principal and return true. Otherwise false. */ static bool MaybeAllowOfflineAppByDefault(nsIPrincipal* aPrincipal); /** * Increases the count of blockers preventing scripts from running. * NOTE: You might want to use nsAutoScriptBlocker rather than calling
--- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -323,18 +323,30 @@ static bool IsImageLoadInEditorAppType(n if (docShell) { appType = docShell->GetAppType(); } return appType == nsIDocShell::APP_TYPE_EDITOR; } static nsresult DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) { - // Bug 1228117: determine the correct security policy for DTD loads - if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DTD) { + // In practice, these DTDs are just used for localization, so applying the + // same principal check as Fluent. + if (aLoadInfo->InternalContentPolicyType() == + nsIContentPolicy::TYPE_INTERNAL_DTD) { + return nsContentUtils::PrincipalAllowsL10n(aLoadInfo->TriggeringPrincipal()) + ? NS_OK + : NS_ERROR_DOM_BAD_URI; + } + + // This is used in order to allow a privileged DOMParser to parse documents + // that need to access localization DTDs. We just allow through + // TYPE_INTERNAL_FORCE_ALLOWED_DTD no matter what the triggering principal is. + if (aLoadInfo->InternalContentPolicyType() == + nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD) { return NS_OK; } if (IsImageLoadInEditorAppType(aLoadInfo)) { return NS_OK; } uint32_t flags = nsIScriptSecurityManager::STANDARD;
--- a/dom/tests/mochitest/bugs/mochitest.ini +++ b/dom/tests/mochitest/bugs/mochitest.ini @@ -149,10 +149,11 @@ skip-if = toolkit == 'android' #Windows [test_window_bar.html] skip-if = toolkit == 'android' [test_bug1022869.html] [test_bug1112040.html] [test_bug1160342_marquee.html] [test_bug1171215.html] support-files = window_bug1171215.html [test_bug1530292.html] +[test_bug467035.html] [test_no_find_showDialog.html] skip-if = toolkit == 'android' # Bug 1358633 - window.find doesn't work for Android
new file mode 100644 --- /dev/null +++ b/dom/tests/mochitest/bugs/test_bug467035.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=467035 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 467035</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 467035 **/ + SimpleTest.waitForExplicitFinish(); + addLoadEvent(() => { + const s = `<!DOCTYPE html SYSTEM \"chrome://branding/locale/brand.dtd\"> + <html xmlns=\"http://www.w3.org/1999/xhtml\"> + <head> + <meta charset=\"utf-8\"/> + <title>&brandShortName;</title> + </head> + </html>`; + + const parser = new DOMParser(); + let doc = parser.parseFromString(s, 'application/xhtml+xml'); + is(doc.getElementsByTagName('parsererror').length, 1, 'parseFromString cannot access locale DTD'); + + SpecialPowers.wrap(parser).forceEnableDTD(); + doc = parser.parseFromString(s, 'application/xhtml+xml'); + const isTitleLocalized = doc.getElementsByTagName('parsererror').length === 0 && + typeof doc.title === 'string' && + !!doc.title; + ok(isTitleLocalized, 'parseFromString can access locale DTD with forceEnableDTD'); + + SimpleTest.finish(); + }); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=467035">Mozilla Bug 467035</a> +<p id="display"></p> +<pre id="test"> +</pre> +</body> +</html>
--- a/dom/webidl/DOMParser.webidl +++ b/dom/webidl/DOMParser.webidl @@ -31,10 +31,15 @@ interface DOMParser { Document parseFromBuffer(Uint8Array buf, SupportedType type); [NewObject, Throws, ChromeOnly] Document parseFromStream(InputStream stream, DOMString? charset, long contentLength, SupportedType type); // Can be used to allow a DOMParser to parse XUL/XBL no matter what // principal it's using for the document. [ChromeOnly] void forceEnableXULXBL(); + + // Can be used to allow a DOMParser to load DTDs from URLs that + // normally would not be allowed based on the document principal. + [Func="IsChromeOrXBLOrUAWidget"] + void forceEnableDTD(); };
--- a/parser/htmlparser/nsExpatDriver.cpp +++ b/parser/htmlparser/nsExpatDriver.cpp @@ -638,32 +638,36 @@ nsresult nsExpatDriver::OpenInputStreamF nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nsIContentPolicy::TYPE_DTD); } else { NS_ASSERTION( mSink == nsCOMPtr<nsIExpatSink>(do_QueryInterface(mOriginalSink)), "In nsExpatDriver::OpenInputStreamFromExternalDTD: " "mOriginalSink not the same object as mSink?"); + nsContentPolicyType policyType = nsIContentPolicy::TYPE_INTERNAL_DTD; nsCOMPtr<nsIPrincipal> loadingPrincipal; if (mOriginalSink) { nsCOMPtr<Document> doc; doc = do_QueryInterface(mOriginalSink->GetTarget()); if (doc) { loadingPrincipal = doc->NodePrincipal(); + if (doc->SkipDTDSecurityChecks()) { + policyType = nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD; + } } } if (!loadingPrincipal) { loadingPrincipal = mozilla::NullPrincipal::CreateWithoutOriginAttributes(); } rv = NS_NewChannel(getter_AddRefs(channel), uri, loadingPrincipal, nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS | nsILoadInfo::SEC_ALLOW_CHROME, - nsIContentPolicy::TYPE_DTD); + policyType); } NS_ENSURE_SUCCESS(rv, rv); nsAutoCString absURL; rv = uri->GetSpec(absURL); NS_ENSURE_SUCCESS(rv, rv); CopyUTF8toUTF16(absURL, aAbsURL);
--- a/testing/marionette/l10n.js +++ b/testing/marionette/l10n.js @@ -16,17 +16,21 @@ */ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); const { XPCOMUtils } = ChromeUtils.import( "resource://gre/modules/XPCOMUtils.jsm" ); XPCOMUtils.defineLazyGlobalGetters(this, ["DOMParser"]); -XPCOMUtils.defineLazyGetter(this, "domParser", () => new DOMParser()); +XPCOMUtils.defineLazyGetter(this, "domParser", () => { + const parser = new DOMParser(); + parser.forceEnableDTD(); + return parser; +}); const { NoSuchElementError } = ChromeUtils.import( "chrome://marionette/content/error.js" ); this.EXPORTED_SYMBOLS = ["l10n"]; /** @namespace */
--- a/testing/marionette/puppeteer/firefox/firefox_puppeteer/api/l10n.py +++ b/testing/marionette/puppeteer/firefox/firefox_puppeteer/api/l10n.py @@ -70,16 +70,17 @@ class L10n(BaseLib): <!DOCTYPE elem [%s]> <elem id="entity">&%s;</elem>""" % (dtd_refs, entity_id) with self.marionette.using_context('chrome'): value = self.marionette.execute_script(""" Cu.importGlobalProperties(["DOMParser"]); var parser = new DOMParser(); + parser.forceEnableDTD(); var doc = parser.parseFromString(arguments[0], "text/xml"); var node = doc.querySelector("elem[id='entity']"); return node ? node.textContent : null; """, script_args=[contents]) if not value: raise NoSuchElementException('DTD Entity not found: %s' % entity_id)
--- a/toolkit/content/widgets/datetimebox.js +++ b/toolkit/content/widgets/datetimebox.js @@ -138,16 +138,17 @@ this.DateTimeInputBaseImplWidget = class } generateContent() { /* * Pass the markup through XML parser purely for the reason of loading the localization DTD. * Remove it when migrate to Fluent (bug 1504363). */ const parser = new this.window.DOMParser(); + parser.forceEnableDTD(); let parserDoc = parser.parseFromString( `<!DOCTYPE bindings [ <!ENTITY % datetimeboxDTD SYSTEM "chrome://global/locale/datetimebox.dtd"> %datetimeboxDTD; ]> <div class="datetimebox" xmlns="http://www.w3.org/1999/xhtml" role="none"> <link rel="stylesheet" type="text/css" href="chrome://global/content/bindings/datetimebox.css" /> <div class="datetime-input-box-wrapper" id="input-box-wrapper" role="presentation">
--- a/toolkit/content/widgets/pluginProblem.js +++ b/toolkit/content/widgets/pluginProblem.js @@ -12,16 +12,17 @@ this.PluginProblemWidget = class { this.shadowRoot = shadowRoot; this.element = shadowRoot.host; // ownerGlobal is chrome-only, not accessible to UA Widget script here. this.window = this.element.ownerDocument.defaultView; // eslint-disable-line mozilla/use-ownerGlobal } onsetup() { const parser = new this.window.DOMParser(); + parser.forceEnableDTD(); let parserDoc = parser.parseFromString( ` <!DOCTYPE bindings [ <!ENTITY % pluginproblemDTD SYSTEM "chrome://pluginproblem/locale/pluginproblem.dtd"> <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > %pluginproblemDTD; %globalDTD;
--- a/toolkit/content/widgets/videocontrols.js +++ b/toolkit/content/widgets/videocontrols.js @@ -2541,16 +2541,17 @@ this.VideoControlsImplWidget = class { } generateContent() { /* * Pass the markup through XML parser purely for the reason of loading the localization DTD. * Remove it when migrate to Fluent. */ const parser = new this.window.DOMParser(); + parser.forceEnableDTD(); let parserDoc = parser.parseFromString( `<!DOCTYPE bindings [ <!ENTITY % videocontrolsDTD SYSTEM "chrome://global/locale/videocontrols.dtd"> %videocontrolsDTD; ]> <div class="videocontrols" xmlns="http://www.w3.org/1999/xhtml" role="none"> <link rel="stylesheet" type="text/css" href="chrome://global/skin/media/videocontrols.css" /> <div id="controlsContainer" class="controlsContainer" role="none"> @@ -2788,16 +2789,17 @@ this.NoControlsMobileImplWidget = class } generateContent() { /* * Pass the markup through XML parser purely for the reason of loading the localization DTD. * Remove it when migrate to Fluent. */ const parser = new this.window.DOMParser(); + parser.forceEnableDTD(); let parserDoc = parser.parseFromString( `<!DOCTYPE bindings [ <!ENTITY % videocontrolsDTD SYSTEM "chrome://global/locale/videocontrols.dtd"> %videocontrolsDTD; ]> <div class="videocontrols" xmlns="http://www.w3.org/1999/xhtml" role="none"> <link rel="stylesheet" type="text/css" href="chrome://global/skin/media/videocontrols.css" /> <div id="controlsContainer" class="controlsContainer" role="none" hidden="true"> @@ -2838,16 +2840,17 @@ this.NoControlsPictureInPictureImplWidge destructor() {} generateContent() { /* * Pass the markup through XML parser purely for the reason of loading the localization DTD. * Remove it when migrate to Fluent. */ const parser = new this.window.DOMParser(); + parser.forceEnableDTD(); let parserDoc = parser.parseFromString( `<!DOCTYPE bindings [ <!ENTITY % videocontrolsDTD SYSTEM "chrome://global/locale/videocontrols.dtd"> %videocontrolsDTD; ]> <div class="videocontrols" xmlns="http://www.w3.org/1999/xhtml" role="none"> <link rel="stylesheet" type="text/css" href="chrome://global/skin/media/videocontrols.css" /> <div id="controlsContainer" class="controlsContainer" role="none"> @@ -2975,16 +2978,17 @@ this.NoControlsDesktopImplWidget = class } generateContent() { /* * Pass the markup through XML parser purely for the reason of loading the localization DTD. * Remove it when migrate to Fluent. */ const parser = new this.window.DOMParser(); + parser.forceEnableDTD(); let parserDoc = parser.parseFromString( `<!DOCTYPE bindings [ <!ENTITY % videocontrolsDTD SYSTEM "chrome://global/locale/videocontrols.dtd"> %videocontrolsDTD; ]> <div class="videocontrols" xmlns="http://www.w3.org/1999/xhtml" role="none"> <link rel="stylesheet" type="text/css" href="chrome://global/skin/media/videocontrols.css" /> <div id="controlsContainer" class="controlsContainer" role="none">