diff --git a/src/core/xfa/html_utils.js b/src/core/xfa/html_utils.js
index 7bf13d323..9d1ddc989 100644
--- a/src/core/xfa/html_utils.js
+++ b/src/core/xfa/html_utils.js
@@ -448,6 +448,18 @@ function fixTextIndent(styles) {
}
}
+function setAccess(node, classNames) {
+ switch (node.access) {
+ case "nonInteractive":
+ case "readOnly":
+ classNames.push("xfaReadOnly");
+ break;
+ case "protected":
+ classNames.push("xfaDisabled");
+ break;
+ }
+}
+
function getFonts(family, fontFinder) {
if (family.startsWith("'") || family.startsWith('"')) {
family = family.slice(1, family.length - 1);
@@ -473,6 +485,7 @@ export {
layoutClass,
layoutText,
measureToString,
+ setAccess,
setMinMaxDimensions,
toStyle,
};
diff --git a/src/core/xfa/template.js b/src/core/xfa/template.js
index 0c134100d..a163bf64e 100644
--- a/src/core/xfa/template.js
+++ b/src/core/xfa/template.js
@@ -72,6 +72,7 @@ import {
layoutClass,
layoutText,
measureToString,
+ setAccess,
setMinMaxDimensions,
toStyle,
} from "./html_utils.js";
@@ -2023,8 +2024,11 @@ class ExclGroup extends XFAObject {
const children = [];
const attributes = {
id: this[$uid],
+ class: [],
};
+ setAccess(this, attributes.class);
+
if (!this[$extra]) {
this[$extra] = Object.create(null);
}
@@ -2329,6 +2333,8 @@ class Field extends XFAObject {
class: classNames,
};
+ setAccess(this, classNames);
+
if (this.name) {
attributes.xfaName = this.name;
}
@@ -4171,8 +4177,11 @@ class Subform extends XFAObject {
const children = [];
const attributes = {
id: this[$uid],
+ class: [],
};
+ setAccess(this, attributes.class);
+
if (!this[$extra]) {
this[$extra] = Object.create(null);
}
diff --git a/src/display/xfa_layer.js b/src/display/xfa_layer.js
index 9717eb74e..5b3e16005 100644
--- a/src/display/xfa_layer.js
+++ b/src/display/xfa_layer.js
@@ -181,6 +181,17 @@ class XfaLayer {
childHtml.appendChild(document.createTextNode(child.value));
}
}
+
+ for (const el of rootDiv.querySelectorAll(
+ ".xfaDisabled input, .xfaDisabled textarea"
+ )) {
+ el.setAttribute("disabled", true);
+ }
+ for (const el of rootDiv.querySelectorAll(
+ ".xfaReadOnly input, .xfaReadOnly textarea"
+ )) {
+ el.setAttribute("readOnly", true);
+ }
}
/**
diff --git a/test/pdfs/xfa_bug1716816.pdf.link b/test/pdfs/xfa_bug1716816.pdf.link
new file mode 100644
index 000000000..ad16e60c9
--- /dev/null
+++ b/test/pdfs/xfa_bug1716816.pdf.link
@@ -0,0 +1 @@
+https://bugzilla.mozilla.org/attachment.cgi?id=9227455
diff --git a/test/test_manifest.json b/test/test_manifest.json
index 0cc3b28fe..3afe94ec3 100644
--- a/test/test_manifest.json
+++ b/test/test_manifest.json
@@ -946,6 +946,14 @@
"enableXfa": true,
"type": "eq"
},
+ { "id": "xfa_bug1716816",
+ "file": "pdfs/xfa_bug1716816.pdf",
+ "md5": "3051cd18db7839bc4953df35b52cf3e0",
+ "link": true,
+ "rounds": 1,
+ "enableXfa": true,
+ "type": "eq"
+ },
{ "id": "xfa_bug1716809",
"file": "pdfs/xfa_bug1716809.pdf",
"md5": "7192f9e27e8b84776d107f57cbe353d5",
diff --git a/web/xfa_layer_builder.css b/web/xfa_layer_builder.css
index 7e21fa46a..5dadb1199 100644
--- a/web/xfa_layer_builder.css
+++ b/web/xfa_layer_builder.css
@@ -277,6 +277,13 @@
flex: 1;
}
+.xfaDisabled input,
+.xfaDisabled textarea,
+.xfaReadOnly input,
+.xfaReadOnly textarea {
+ background: initial;
+}
+
@media print {
.xfaTextfield,
.xfaSelect {