From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- dom/html/ConstraintValidation.cpp | 66 + dom/html/ConstraintValidation.h | 48 + dom/html/ElementInternals.cpp | 460 ++ dom/html/ElementInternals.h | 185 + dom/html/HTMLAllCollection.cpp | 195 + dom/html/HTMLAllCollection.h | 90 + dom/html/HTMLAnchorElement.cpp | 226 + dom/html/HTMLAnchorElement.h | 205 + dom/html/HTMLAreaElement.cpp | 128 + dom/html/HTMLAreaElement.h | 175 + dom/html/HTMLAudioElement.cpp | 109 + dom/html/HTMLAudioElement.h | 50 + dom/html/HTMLBRElement.cpp | 77 + dom/html/HTMLBRElement.h | 74 + dom/html/HTMLBodyElement.cpp | 336 + dom/html/HTMLBodyElement.h | 127 + dom/html/HTMLButtonElement.cpp | 413 ++ dom/html/HTMLButtonElement.h | 145 + dom/html/HTMLCanvasElement.cpp | 1367 ++++ dom/html/HTMLCanvasElement.h | 436 ++ dom/html/HTMLDNSPrefetch.cpp | 647 ++ dom/html/HTMLDNSPrefetch.h | 147 + dom/html/HTMLDataElement.cpp | 28 + dom/html/HTMLDataElement.h | 39 + dom/html/HTMLDataListElement.cpp | 37 + dom/html/HTMLDataListElement.h | 56 + dom/html/HTMLDetailsElement.cpp | 137 + dom/html/HTMLDetailsElement.h | 65 + dom/html/HTMLDialogElement.cpp | 207 + dom/html/HTMLDialogElement.h | 69 + dom/html/HTMLDivElement.cpp | 55 + dom/html/HTMLDivElement.h | 49 + dom/html/HTMLElement.cpp | 352 + dom/html/HTMLElement.h | 82 + dom/html/HTMLEmbedElement.cpp | 265 + dom/html/HTMLEmbedElement.h | 142 + dom/html/HTMLFieldSetElement.cpp | 324 + dom/html/HTMLFieldSetElement.h | 141 + dom/html/HTMLFontElement.cpp | 105 + dom/html/HTMLFontElement.h | 54 + dom/html/HTMLFormControlsCollection.cpp | 310 + dom/html/HTMLFormControlsCollection.h | 124 + dom/html/HTMLFormElement.cpp | 2232 ++++++ dom/html/HTMLFormElement.h | 638 ++ dom/html/HTMLFormSubmission.cpp | 888 +++ dom/html/HTMLFormSubmission.h | 292 + dom/html/HTMLFormSubmissionConstants.h | 39 + dom/html/HTMLFrameElement.cpp | 54 + dom/html/HTMLFrameElement.h | 105 + dom/html/HTMLFrameSetElement.cpp | 315 + dom/html/HTMLFrameSetElement.h | 153 + dom/html/HTMLHRElement.cpp | 192 + dom/html/HTMLHRElement.h | 79 + dom/html/HTMLHeadingElement.cpp | 62 + dom/html/HTMLHeadingElement.h | 73 + dom/html/HTMLIFrameElement.cpp | 293 + dom/html/HTMLIFrameElement.h | 212 + dom/html/HTMLImageElement.cpp | 1424 ++++ dom/html/HTMLImageElement.h | 440 ++ dom/html/HTMLInputElement.cpp | 7277 ++++++++++++++++++ dom/html/HTMLInputElement.h | 1668 +++++ dom/html/HTMLLIElement.cpp | 102 + dom/html/HTMLLIElement.h | 56 + dom/html/HTMLLabelElement.cpp | 246 + dom/html/HTMLLabelElement.h | 73 + dom/html/HTMLLegendElement.cpp | 140 + dom/html/HTMLLegendElement.h | 95 + dom/html/HTMLLinkElement.cpp | 701 ++ dom/html/HTMLLinkElement.h | 221 + dom/html/HTMLMapElement.cpp | 44 + dom/html/HTMLMapElement.h | 45 + dom/html/HTMLMarqueeElement.cpp | 174 + dom/html/HTMLMarqueeElement.h | 132 + dom/html/HTMLMediaElement.cpp | 7817 ++++++++++++++++++++ dom/html/HTMLMediaElement.h | 1939 +++++ dom/html/HTMLMenuElement.cpp | 28 + dom/html/HTMLMenuElement.h | 42 + dom/html/HTMLMetaElement.cpp | 178 + dom/html/HTMLMetaElement.h | 74 + dom/html/HTMLMeterElement.cpp | 250 + dom/html/HTMLMeterElement.h | 102 + dom/html/HTMLModElement.cpp | 28 + dom/html/HTMLModElement.h | 42 + dom/html/HTMLObjectElement.cpp | 309 + dom/html/HTMLObjectElement.h | 215 + dom/html/HTMLOptGroupElement.cpp | 115 + dom/html/HTMLOptGroupElement.h | 74 + dom/html/HTMLOptionElement.cpp | 366 + dom/html/HTMLOptionElement.h | 141 + dom/html/HTMLOptionsCollection.cpp | 207 + dom/html/HTMLOptionsCollection.h | 150 + dom/html/HTMLOutputElement.cpp | 154 + dom/html/HTMLOutputElement.h | 103 + dom/html/HTMLParagraphElement.cpp | 61 + dom/html/HTMLParagraphElement.h | 55 + dom/html/HTMLPictureElement.cpp | 79 + dom/html/HTMLPictureElement.h | 40 + dom/html/HTMLPreElement.cpp | 82 + dom/html/HTMLPreElement.h | 53 + dom/html/HTMLProgressElement.cpp | 88 + dom/html/HTMLProgressElement.h | 59 + dom/html/HTMLScriptElement.cpp | 268 + dom/html/HTMLScriptElement.h | 152 + dom/html/HTMLSelectElement.cpp | 1609 ++++ dom/html/HTMLSelectElement.h | 550 ++ dom/html/HTMLSharedElement.cpp | 227 + dom/html/HTMLSharedElement.h | 131 + dom/html/HTMLSharedListElement.cpp | 162 + dom/html/HTMLSharedListElement.h | 66 + dom/html/HTMLSlotElement.cpp | 373 + dom/html/HTMLSlotElement.h | 88 + dom/html/HTMLSourceElement.cpp | 235 + dom/html/HTMLSourceElement.h | 157 + dom/html/HTMLSpanElement.cpp | 28 + dom/html/HTMLSpanElement.h | 30 + dom/html/HTMLStyleElement.cpp | 195 + dom/html/HTMLStyleElement.h | 94 + dom/html/HTMLSummaryElement.cpp | 118 + dom/html/HTMLSummaryElement.h | 55 + dom/html/HTMLTableCaptionElement.cpp | 73 + dom/html/HTMLTableCaptionElement.h | 50 + dom/html/HTMLTableCellElement.cpp | 221 + dom/html/HTMLTableCellElement.h | 128 + dom/html/HTMLTableColElement.cpp | 103 + dom/html/HTMLTableColElement.h | 72 + dom/html/HTMLTableElement.cpp | 1028 +++ dom/html/HTMLTableElement.h | 204 + dom/html/HTMLTableRowElement.cpp | 250 + dom/html/HTMLTableRowElement.h | 93 + dom/html/HTMLTableSectionElement.cpp | 177 + dom/html/HTMLTableSectionElement.h | 77 + dom/html/HTMLTemplateElement.cpp | 65 + dom/html/HTMLTemplateElement.h | 44 + dom/html/HTMLTextAreaElement.cpp | 1192 +++ dom/html/HTMLTextAreaElement.h | 403 + dom/html/HTMLTimeElement.cpp | 30 + dom/html/HTMLTimeElement.h | 40 + dom/html/HTMLTitleElement.cpp | 95 + dom/html/HTMLTitleElement.h | 60 + dom/html/HTMLTrackElement.cpp | 517 ++ dom/html/HTMLTrackElement.h | 137 + dom/html/HTMLUnknownElement.cpp | 26 + dom/html/HTMLUnknownElement.h | 43 + dom/html/HTMLVideoElement.cpp | 682 ++ dom/html/HTMLVideoElement.h | 207 + dom/html/ImageDocument.cpp | 814 ++ dom/html/ImageDocument.h | 157 + dom/html/MediaDocument.cpp | 397 + dom/html/MediaDocument.h | 121 + dom/html/MediaError.cpp | 85 + dom/html/MediaError.h | 48 + dom/html/PlayPromise.cpp | 84 + dom/html/PlayPromise.h | 37 + dom/html/RadioNodeList.cpp | 60 + dom/html/RadioNodeList.h | 44 + dom/html/TextControlElement.h | 243 + dom/html/TextControlState.cpp | 3061 ++++++++ dom/html/TextControlState.h | 549 ++ dom/html/TextInputListener.h | 109 + dom/html/TextTrackManager.cpp | 878 +++ dom/html/TextTrackManager.h | 194 + dom/html/TimeRanges.cpp | 183 + dom/html/TimeRanges.h | 119 + dom/html/ValidityState.cpp | 31 + dom/html/ValidityState.h | 93 + dom/html/VideoDocument.cpp | 156 + dom/html/crashtests/1032654.html | 1 + dom/html/crashtests/1141260.html | 4 + dom/html/crashtests/1228876.html | 21 + dom/html/crashtests/1230110.html | 19 + dom/html/crashtests/1237633.html | 1 + dom/html/crashtests/1281972-1.html | 5 + dom/html/crashtests/1282894.html | 17 + dom/html/crashtests/1290904.html | 37 + dom/html/crashtests/1343886-1.html | 14 + dom/html/crashtests/1343886-2.xml | 3 + dom/html/crashtests/1343886-3.xml | 3 + dom/html/crashtests/1350972.html | 22 + dom/html/crashtests/1386905.html | 13 + dom/html/crashtests/1401726.html | 17 + dom/html/crashtests/1412173.html | 18 + dom/html/crashtests/1429783.html | 19 + dom/html/crashtests/1440523.html | 13 + dom/html/crashtests/1440827.html | 6 + dom/html/crashtests/1547057.html | 11 + dom/html/crashtests/1550524.html | 7 + dom/html/crashtests/1550881-1.html | 13 + dom/html/crashtests/1550881-2.html | 14 + dom/html/crashtests/1667493.html | 13 + dom/html/crashtests/1667493_1.html | 7 + dom/html/crashtests/1680418.html | 17 + dom/html/crashtests/1704660.html | 17 + dom/html/crashtests/1724816.html | 14 + dom/html/crashtests/1785933-inner.html | 28 + dom/html/crashtests/1785933.html | 10 + dom/html/crashtests/1787671.html | 8 + dom/html/crashtests/1789475.html | 10 + dom/html/crashtests/1801380.html | 1 + dom/html/crashtests/257818-1.html | 82 + dom/html/crashtests/285166-1.html | 3 + dom/html/crashtests/294235-1.html | 14 + dom/html/crashtests/307616-1.html | 8 + dom/html/crashtests/324918-1.xhtml | 26 + dom/html/crashtests/338649-1.xhtml | 22 + dom/html/crashtests/339501-1.xhtml | 33 + dom/html/crashtests/339501-2.xhtml | 33 + dom/html/crashtests/378993-1.xhtml | 7 + dom/html/crashtests/382568-1-inner.xhtml | 52 + dom/html/crashtests/382568-1.html | 9 + dom/html/crashtests/383137.xhtml | 13 + dom/html/crashtests/388183-1.html | 8 + dom/html/crashtests/395340-1.html | 28 + dom/html/crashtests/399694-1.html | 20 + dom/html/crashtests/407053.html | 6 + dom/html/crashtests/423371-1.html | 9 + dom/html/crashtests/448564.html | 7 + dom/html/crashtests/451123-1.html | 7 + dom/html/crashtests/453406-1.html | 34 + dom/html/crashtests/464197-1.html | 23 + dom/html/crashtests/468562-1.html | 6 + dom/html/crashtests/468562-2.html | 6 + dom/html/crashtests/494225.html | 10 + dom/html/crashtests/495543.svg | 16 + dom/html/crashtests/495546-1.html | 19 + dom/html/crashtests/504183-1.html | 12 + dom/html/crashtests/515829-1.html | 7 + dom/html/crashtests/515829-2.html | 7 + dom/html/crashtests/570566-1.html | 2 + dom/html/crashtests/571428-1.html | 14 + dom/html/crashtests/580507-1.xhtml | 18 + dom/html/crashtests/590387.html | 8 + dom/html/crashtests/596785-1.html | 9 + dom/html/crashtests/596785-2.html | 9 + dom/html/crashtests/602117.html | 8 + dom/html/crashtests/604807.html | 9 + dom/html/crashtests/605264.html | 8 + dom/html/crashtests/606430-1.html | 31 + dom/html/crashtests/613027.html | 21 + dom/html/crashtests/614279.html | 18 + dom/html/crashtests/614988-1.html | 5 + dom/html/crashtests/616401.html | 8 + dom/html/crashtests/620078-1.html | 20 + dom/html/crashtests/620078-2.html | 6 + dom/html/crashtests/631421.html | 34 + dom/html/crashtests/631421.png | Bin 0 -> 38661 bytes dom/html/crashtests/673853.html | 20 + dom/html/crashtests/682058.xhtml | 11 + dom/html/crashtests/682460.html | 21 + dom/html/crashtests/68912-1.html | 24 + dom/html/crashtests/738744.xhtml | 4 + dom/html/crashtests/741218.json | 1 + dom/html/crashtests/741218.json^headers^ | 1 + dom/html/crashtests/741250.xhtml | 9 + dom/html/crashtests/768344.html | 22 + dom/html/crashtests/795221-1.html | 7 + dom/html/crashtests/795221-2.html | 9 + dom/html/crashtests/795221-3.html | 14 + dom/html/crashtests/795221-4.html | 9 + dom/html/crashtests/795221-5.xml | 6 + dom/html/crashtests/798802-1.html | 18 + dom/html/crashtests/811226.html | 6 + dom/html/crashtests/819745.html | 5 + dom/html/crashtests/828180.html | 5 + dom/html/crashtests/828472.html | 6 + dom/html/crashtests/837033.html | 4 + dom/html/crashtests/838256-1.html | 20 + dom/html/crashtests/862084.html | 9 + dom/html/crashtests/865147.html | 7 + dom/html/crashtests/877910.html | 1 + dom/html/crashtests/903106.html | 3 + dom/html/crashtests/916322-1.html | 10 + dom/html/crashtests/916322-2.html | 10 + dom/html/crashtests/978644.xhtml | 11 + dom/html/crashtests/crashtests.list | 98 + dom/html/input/ButtonInputTypes.h | 73 + dom/html/input/CheckableInputTypes.cpp | 36 + dom/html/input/CheckableInputTypes.h | 55 + dom/html/input/ColorInputType.h | 28 + dom/html/input/DateTimeInputTypes.cpp | 504 ++ dom/html/input/DateTimeInputTypes.h | 159 + dom/html/input/FileInputType.cpp | 26 + dom/html/input/FileInputType.h | 32 + dom/html/input/HiddenInputType.h | 28 + dom/html/input/InputType.cpp | 355 + dom/html/input/InputType.h | 235 + dom/html/input/NumericInputTypes.cpp | 173 + dom/html/input/NumericInputTypes.h | 77 + dom/html/input/SingleLineTextInputTypes.cpp | 290 + dom/html/input/SingleLineTextInputTypes.h | 158 + dom/html/input/moz.build | 36 + dom/html/moz.build | 244 + dom/html/nsBrowserElement.cpp | 57 + dom/html/nsBrowserElement.h | 57 + dom/html/nsDOMStringMap.cpp | 242 + dom/html/nsDOMStringMap.h | 65 + dom/html/nsGenericHTMLElement.cpp | 3568 +++++++++ dom/html/nsGenericHTMLElement.h | 1469 ++++ dom/html/nsGenericHTMLFrameElement.cpp | 359 + dom/html/nsGenericHTMLFrameElement.h | 167 + dom/html/nsHTMLContentSink.cpp | 939 +++ dom/html/nsHTMLDocument.cpp | 747 ++ dom/html/nsHTMLDocument.h | 211 + dom/html/nsIConstraintValidation.cpp | 143 + dom/html/nsIConstraintValidation.h | 111 + dom/html/nsIFormControl.h | 290 + dom/html/nsIHTMLCollection.h | 87 + dom/html/nsIRadioGroupContainer.h | 101 + dom/html/nsIRadioVisitor.h | 48 + dom/html/nsRadioVisitor.cpp | 49 + dom/html/nsRadioVisitor.h | 96 + dom/html/reftests/41464-1-ref.html | 5 + dom/html/reftests/41464-1a.html | 8 + dom/html/reftests/41464-1b.html | 8 + dom/html/reftests/468263-1a.html | 6 + dom/html/reftests/468263-1b.html | 6 + dom/html/reftests/468263-1c.html | 6 + dom/html/reftests/468263-1d.html | 6 + dom/html/reftests/468263-2-alternate-ref.html | 8 + dom/html/reftests/468263-2-ref.html | 10 + dom/html/reftests/468263-2.html | 10 + dom/html/reftests/484200-1-ref.html | 11 + dom/html/reftests/484200-1.html | 11 + dom/html/reftests/485377-ref.html | 3 + dom/html/reftests/485377.html | 3 + dom/html/reftests/52019-1-ref.html | 11 + dom/html/reftests/52019-1.html | 11 + dom/html/reftests/557840-ref.html | 3 + dom/html/reftests/557840.html | 3 + dom/html/reftests/560059-video-dimensions-ref.html | 3 + dom/html/reftests/560059-video-dimensions.html | 3 + dom/html/reftests/573322-no-quirks-ref.html | 28 + dom/html/reftests/573322-no-quirks.html | 28 + dom/html/reftests/573322-quirks-ref.html | 27 + dom/html/reftests/573322-quirks.html | 27 + dom/html/reftests/596455-1a.html | 14 + dom/html/reftests/596455-1b.html | 14 + dom/html/reftests/596455-2a.html | 14 + dom/html/reftests/596455-2b.html | 14 + dom/html/reftests/596455-ref-1.html | 6 + dom/html/reftests/596455-ref-2.html | 6 + dom/html/reftests/610935-ref.html | 12 + dom/html/reftests/610935.html | 11 + dom/html/reftests/649134-1.html | 31 + dom/html/reftests/649134-2-ref.html | 25 + dom/html/reftests/649134-2.html | 31 + dom/html/reftests/649134-ref.html | 13 + dom/html/reftests/741776-1-ref.html | 1 + dom/html/reftests/741776-1.vtt | 1 + dom/html/reftests/82711-1-ref.html | 15 + dom/html/reftests/82711-1.html | 15 + dom/html/reftests/82711-2-ref.html | 15 + dom/html/reftests/82711-2.html | 8 + .../autofocus/autofocus-after-body-focus-ref.html | 7 + .../autofocus/autofocus-after-body-focus.html | 10 + .../autofocus/autofocus-after-load-ref.html | 7 + .../reftests/autofocus/autofocus-after-load.html | 21 + .../autofocus/autofocus-leaves-iframe-ref.html | 17 + .../autofocus/autofocus-leaves-iframe.html | 16 + dom/html/reftests/autofocus/button-create.html | 23 + dom/html/reftests/autofocus/button-load.html | 13 + dom/html/reftests/autofocus/button-ref.html | 7 + dom/html/reftests/autofocus/input-create.html | 23 + dom/html/reftests/autofocus/input-load.html | 13 + dom/html/reftests/autofocus/input-number-ref.html | 17 + dom/html/reftests/autofocus/input-number.html | 26 + dom/html/reftests/autofocus/input-ref.html | 7 + dom/html/reftests/autofocus/input-time-ref.html | 22 + dom/html/reftests/autofocus/input-time.html | 22 + dom/html/reftests/autofocus/reftest.list | 13 + dom/html/reftests/autofocus/select-create.html | 23 + dom/html/reftests/autofocus/select-load.html | 13 + dom/html/reftests/autofocus/select-ref.html | 7 + dom/html/reftests/autofocus/style.css | 10 + dom/html/reftests/autofocus/textarea-create.html | 23 + dom/html/reftests/autofocus/textarea-load.html | 13 + dom/html/reftests/autofocus/textarea-ref.html | 7 + ...dy-frame-margin-remove-other-pres-hint-ref.html | 14 + .../body-frame-margin-remove-other-pres-hint.html | 16 + dom/html/reftests/body-topmargin-dynamic.html | 12 + dom/html/reftests/body-topmargin-ref.html | 7 + dom/html/reftests/bug1106522-1.html | 11 + dom/html/reftests/bug1106522-2.html | 11 + dom/html/reftests/bug1106522-ref.html | 8 + dom/html/reftests/bug1196784-no-srcset.html | 6 + dom/html/reftests/bug1196784-with-srcset.html | 6 + dom/html/reftests/bug1196784.png | Bin 0 -> 294 bytes .../reftests/bug1228601-video-rotated-ref.html | 13 + .../reftests/bug1228601-video-rotation-90.html | 13 + .../bug1423850-canvas-video-rotated-ref.html | 16 + .../bug1423850-canvas-video-rotation-90.html | 16 + dom/html/reftests/bug1512297-ref.html | 7 + dom/html/reftests/bug1512297.html | 14 + dom/html/reftests/bug448564-1_ideal.html | 13 + dom/html/reftests/bug448564-1_malformed.html | 19 + dom/html/reftests/bug448564-1_well-formed.html | 11 + dom/html/reftests/bug448564-4a.html | 10 + dom/html/reftests/bug448564-4b.html | 6 + dom/html/reftests/bug448564_forms.css | 2 + dom/html/reftests/bug502168-1_malformed.html | 10 + dom/html/reftests/bug502168-1_well-formed.html | 9 + dom/html/reftests/bug917595-1-ref.html | 17 + dom/html/reftests/bug917595-exif-rotated.jpg | Bin 0 -> 90700 bytes dom/html/reftests/bug917595-iframe-1.html | 17 + dom/html/reftests/bug917595-pixel-rotated.jpg | Bin 0 -> 91596 bytes dom/html/reftests/bug917595-unrotated.jpg | Bin 0 -> 90864 bytes dom/html/reftests/figure-ref.html | 11 + dom/html/reftests/figure.html | 8 + .../reftests/href-attr-change-restyles-ref.html | 33 + dom/html/reftests/href-attr-change-restyles.html | 48 + dom/html/reftests/image-load-shortcircuit-1.html | 8 + dom/html/reftests/image-load-shortcircuit-2.html | 10 + dom/html/reftests/image-load-shortcircuit-ref.html | 1 + dom/html/reftests/lime100x100.svg | 4 + dom/html/reftests/pass.png | Bin 0 -> 1036 bytes dom/html/reftests/pre-1-ref.html | 22 + dom/html/reftests/pre-1.html | 22 + dom/html/reftests/red.png | Bin 0 -> 82 bytes dom/html/reftests/reftest.list | 75 + .../responsive-image-load-shortcircuit-ref.html | 1 + .../responsive-image-load-shortcircuit.html | 15 + dom/html/reftests/table-border-1-ref.html | 46 + dom/html/reftests/table-border-1.html | 36 + dom/html/reftests/table-border-2-notref.html | 40 + dom/html/reftests/table-border-2-ref.html | 30 + dom/html/reftests/table-border-2.html | 30 + dom/html/reftests/toblob-todataurl/blob.js | 68 + dom/html/reftests/toblob-todataurl/dataurl.js | 56 + .../reftests/toblob-todataurl/images/original.png | Bin 0 -> 50613 bytes dom/html/reftests/toblob-todataurl/images/q0.jpg | Bin 0 -> 2165 bytes dom/html/reftests/toblob-todataurl/images/q100.jpg | Bin 0 -> 54323 bytes dom/html/reftests/toblob-todataurl/images/q25.jpg | Bin 0 -> 3898 bytes dom/html/reftests/toblob-todataurl/images/q50.jpg | Bin 0 -> 4924 bytes dom/html/reftests/toblob-todataurl/images/q75.jpg | Bin 0 -> 6405 bytes dom/html/reftests/toblob-todataurl/images/q92.jpg | Bin 0 -> 13931 bytes .../reftests/toblob-todataurl/quality-0-ref.html | 2 + .../reftests/toblob-todataurl/quality-100-ref.html | 2 + .../reftests/toblob-todataurl/quality-25-ref.html | 2 + .../reftests/toblob-todataurl/quality-50-ref.html | 2 + .../reftests/toblob-todataurl/quality-75-ref.html | 2 + .../reftests/toblob-todataurl/quality-92-ref.html | 2 + dom/html/reftests/toblob-todataurl/reftest.list | 16 + dom/html/reftests/toblob-todataurl/sample.js | 2 + .../toblob-todataurl/toblob-quality-0.html | 10 + .../toblob-todataurl/toblob-quality-100.html | 10 + .../toblob-todataurl/toblob-quality-25.html | 10 + .../toblob-todataurl/toblob-quality-50.html | 10 + .../toblob-todataurl/toblob-quality-75.html | 10 + .../toblob-todataurl/toblob-quality-92.html | 10 + .../toblob-todataurl/toblob-quality-default.html | 7 + .../toblob-todataurl/toblob-quality-undefined.html | 10 + .../toblob-todataurl/todataurl-quality-0.html | 10 + .../toblob-todataurl/todataurl-quality-100.html | 10 + .../toblob-todataurl/todataurl-quality-25.html | 10 + .../toblob-todataurl/todataurl-quality-50.html | 10 + .../toblob-todataurl/todataurl-quality-75.html | 10 + .../toblob-todataurl/todataurl-quality-92.html | 10 + .../todataurl-quality-default.html | 7 + .../todataurl-quality-undefined.html | 10 + dom/html/reftests/video_rotated.mp4 | Bin 0 -> 1543 bytes dom/html/reftests/video_rotation_90.mp4 | Bin 0 -> 1541 bytes dom/html/test/347174transform.xsl | 41 + dom/html/test/347174transformable.xml | 3 + dom/html/test/allowMedia.sjs | 12 + dom/html/test/browser.ini | 37 + dom/html/test/browser_DOMDocElementInserted.js | 23 + dom/html/test/browser_ImageDocument_svg_zoom.js | 38 + dom/html/test/browser_bug1081537.js | 11 + dom/html/test/browser_bug1108547.js | 149 + dom/html/test/browser_bug436200.js | 60 + dom/html/test/browser_bug592641.js | 61 + dom/html/test/browser_containerLoadingContent.js | 130 + .../test/browser_form_post_from_file_to_http.js | 180 + .../test/browser_refresh_after_document_write.js | 52 + dom/html/test/browser_submission_flush.js | 97 + dom/html/test/browser_targetBlankNoOpener.js | 121 + dom/html/test/bug100533_iframe.html | 8 + dom/html/test/bug100533_load.html | 14 + dom/html/test/bug1260704_iframe.html | 38 + dom/html/test/bug1260704_iframe_empty.html | 15 + dom/html/test/bug1292522_iframe.html | 10 + dom/html/test/bug1292522_page.html | 14 + dom/html/test/bug1315146-iframe.html | 4 + dom/html/test/bug1315146-main.html | 15 + dom/html/test/bug196523-subframe.html | 37 + dom/html/test/bug199692-nested-d2.html | 14 + dom/html/test/bug199692-nested.html | 15 + dom/html/test/bug199692-popup.html | 188 + dom/html/test/bug199692-scrolled.html | 34 + dom/html/test/bug242709_iframe.html | 20 + dom/html/test/bug242709_load.html | 11 + dom/html/test/bug277724_iframe1.html | 28 + dom/html/test/bug277724_iframe2.xhtml | 27 + dom/html/test/bug277890_iframe.html | 20 + dom/html/test/bug277890_load.html | 11 + dom/html/test/bug340800_iframe.txt | 4 + dom/html/test/bug369370-popup.png | Bin 0 -> 4073 bytes dom/html/test/bug372098-link-target.html | 7 + dom/html/test/bug436200.html | 12 + dom/html/test/bug441930_iframe.html | 27 + dom/html/test/bug445004-inner.html | 14 + dom/html/test/bug445004-inner.js | 27 + dom/html/test/bug445004-outer-abs.html | 11 + dom/html/test/bug445004-outer-rel.html | 11 + dom/html/test/bug445004-outer-write.html | 11 + dom/html/test/bug446483-iframe.html | 10 + dom/html/test/bug448564-echo.sjs | 6 + dom/html/test/bug448564-iframe-1.html | 16 + dom/html/test/bug448564-iframe-2.html | 16 + dom/html/test/bug448564-iframe-3.html | 16 + dom/html/test/bug448564-submit.js | 6 + dom/html/test/bug499092.html | 6 + dom/html/test/bug499092.xml | 4 + dom/html/test/bug514856_iframe.html | 21 + dom/html/test/bug592641_img.jpg | Bin 0 -> 42018 bytes dom/html/test/bug649134/file_bug649134-1.sjs | 12 + dom/html/test/bug649134/file_bug649134-2.sjs | 12 + dom/html/test/bug649134/index.html | 3 + dom/html/test/chrome.ini | 9 + dom/html/test/dialog/mochitest.ini | 4 + .../test_bug1648877_dialog_fullscreen_denied.html | 52 + dom/html/test/dummy_page.html | 10 + dom/html/test/empty.html | 1 + dom/html/test/file.webm | Bin 0 -> 512 bytes dom/html/test/file_anchor_ping.html | 13 + dom/html/test/file_broadcast_load.html | 16 + dom/html/test/file_bug1108547-1.html | 4 + dom/html/test/file_bug1108547-2.html | 6 + dom/html/test/file_bug1108547-3.html | 5 + dom/html/test/file_bug1166138_1x.png | Bin 0 -> 91 bytes dom/html/test/file_bug1166138_2x.png | Bin 0 -> 100 bytes dom/html/test/file_bug1166138_def.png | Bin 0 -> 85 bytes dom/html/test/file_bug1260704.png | Bin 0 -> 91 bytes dom/html/test/file_bug209275_1.html | 28 + dom/html/test/file_bug209275_2.html | 23 + dom/html/test/file_bug209275_3.html | 23 + dom/html/test/file_bug297761.html | 13 + dom/html/test/file_bug417760.png | Bin 0 -> 1991 bytes dom/html/test/file_bug871161-1.html | 16 + dom/html/test/file_bug871161-2.html | 14 + dom/html/test/file_bug893537.html | 9 + dom/html/test/file_cookiemanager.js | 20 + dom/html/test/file_formSubmission_img.jpg | Bin 0 -> 2711 bytes dom/html/test/file_formSubmission_text.txt | 1 + dom/html/test/file_iframe_sandbox_a_if1.html | 13 + dom/html/test/file_iframe_sandbox_a_if10.html | 12 + dom/html/test/file_iframe_sandbox_a_if11.html | 23 + dom/html/test/file_iframe_sandbox_a_if12.html | 23 + dom/html/test/file_iframe_sandbox_a_if13.html | 13 + dom/html/test/file_iframe_sandbox_a_if14.html | 34 + dom/html/test/file_iframe_sandbox_a_if15.html | 33 + dom/html/test/file_iframe_sandbox_a_if16.html | 25 + dom/html/test/file_iframe_sandbox_a_if17.html | 27 + dom/html/test/file_iframe_sandbox_a_if18.html | 26 + dom/html/test/file_iframe_sandbox_a_if19.html | 21 + dom/html/test/file_iframe_sandbox_a_if2.html | 21 + dom/html/test/file_iframe_sandbox_a_if3.html | 24 + dom/html/test/file_iframe_sandbox_a_if4.html | 30 + dom/html/test/file_iframe_sandbox_a_if5.html | 22 + dom/html/test/file_iframe_sandbox_a_if6.html | 21 + dom/html/test/file_iframe_sandbox_a_if7.html | 20 + dom/html/test/file_iframe_sandbox_a_if8.html | 26 + dom/html/test/file_iframe_sandbox_a_if9.html | 18 + dom/html/test/file_iframe_sandbox_b_if1.html | 11 + dom/html/test/file_iframe_sandbox_b_if2.html | 49 + dom/html/test/file_iframe_sandbox_b_if3.html | 92 + dom/html/test/file_iframe_sandbox_c_if1.html | 35 + dom/html/test/file_iframe_sandbox_c_if2.html | 23 + dom/html/test/file_iframe_sandbox_c_if3.html | 26 + dom/html/test/file_iframe_sandbox_c_if4.html | 36 + dom/html/test/file_iframe_sandbox_c_if5.html | 20 + dom/html/test/file_iframe_sandbox_c_if6.html | 24 + dom/html/test/file_iframe_sandbox_c_if7.html | 27 + dom/html/test/file_iframe_sandbox_c_if8.html | 27 + dom/html/test/file_iframe_sandbox_c_if9.html | 17 + dom/html/test/file_iframe_sandbox_close.html | 3 + dom/html/test/file_iframe_sandbox_d_if1.html | 19 + dom/html/test/file_iframe_sandbox_d_if10.html | 17 + dom/html/test/file_iframe_sandbox_d_if11.html | 30 + dom/html/test/file_iframe_sandbox_d_if12.html | 16 + dom/html/test/file_iframe_sandbox_d_if13.html | 35 + dom/html/test/file_iframe_sandbox_d_if14.html | 35 + dom/html/test/file_iframe_sandbox_d_if15.html | 14 + dom/html/test/file_iframe_sandbox_d_if16.html | 22 + dom/html/test/file_iframe_sandbox_d_if17.html | 24 + dom/html/test/file_iframe_sandbox_d_if18.html | 33 + dom/html/test/file_iframe_sandbox_d_if19.html | 13 + dom/html/test/file_iframe_sandbox_d_if2.html | 28 + dom/html/test/file_iframe_sandbox_d_if20.html | 25 + dom/html/test/file_iframe_sandbox_d_if21.html | 14 + dom/html/test/file_iframe_sandbox_d_if22.html | 25 + dom/html/test/file_iframe_sandbox_d_if23.html | 61 + dom/html/test/file_iframe_sandbox_d_if3.html | 13 + dom/html/test/file_iframe_sandbox_d_if4.html | 20 + dom/html/test/file_iframe_sandbox_d_if5.html | 20 + dom/html/test/file_iframe_sandbox_d_if6.html | 19 + dom/html/test/file_iframe_sandbox_d_if7.html | 20 + dom/html/test/file_iframe_sandbox_d_if8.html | 18 + dom/html/test/file_iframe_sandbox_d_if9.html | 17 + dom/html/test/file_iframe_sandbox_e_if1.html | 20 + dom/html/test/file_iframe_sandbox_e_if10.html | 19 + dom/html/test/file_iframe_sandbox_e_if11.html | 22 + dom/html/test/file_iframe_sandbox_e_if12.html | 19 + dom/html/test/file_iframe_sandbox_e_if13.html | 19 + dom/html/test/file_iframe_sandbox_e_if14.html | 24 + dom/html/test/file_iframe_sandbox_e_if15.html | 17 + dom/html/test/file_iframe_sandbox_e_if16.html | 27 + dom/html/test/file_iframe_sandbox_e_if2.html | 12 + dom/html/test/file_iframe_sandbox_e_if3.html | 11 + dom/html/test/file_iframe_sandbox_e_if4.html | 11 + dom/html/test/file_iframe_sandbox_e_if5.html | 19 + dom/html/test/file_iframe_sandbox_e_if6.html | 20 + dom/html/test/file_iframe_sandbox_e_if7.html | 17 + dom/html/test/file_iframe_sandbox_e_if8.html | 23 + dom/html/test/file_iframe_sandbox_e_if9.html | 19 + dom/html/test/file_iframe_sandbox_fail.js | 4 + dom/html/test/file_iframe_sandbox_form_fail.html | 19 + dom/html/test/file_iframe_sandbox_form_pass.html | 17 + dom/html/test/file_iframe_sandbox_g_if1.html | 60 + dom/html/test/file_iframe_sandbox_h_if1.html | 34 + dom/html/test/file_iframe_sandbox_k_if1.html | 47 + dom/html/test/file_iframe_sandbox_k_if2.html | 50 + dom/html/test/file_iframe_sandbox_k_if3.html | 20 + dom/html/test/file_iframe_sandbox_k_if4.html | 34 + dom/html/test/file_iframe_sandbox_k_if5.html | 33 + dom/html/test/file_iframe_sandbox_k_if6.html | 21 + dom/html/test/file_iframe_sandbox_k_if7.html | 26 + dom/html/test/file_iframe_sandbox_k_if8.html | 36 + dom/html/test/file_iframe_sandbox_k_if9.html | 20 + .../test/file_iframe_sandbox_navigation_fail.html | 17 + .../test/file_iframe_sandbox_navigation_pass.html | 17 + .../test/file_iframe_sandbox_navigation_start.html | 11 + .../test/file_iframe_sandbox_open_window_fail.html | 19 + .../test/file_iframe_sandbox_open_window_pass.html | 25 + dom/html/test/file_iframe_sandbox_pass.js | 4 + dom/html/test/file_iframe_sandbox_redirect.html | 2 + .../file_iframe_sandbox_redirect.html^headers^ | 2 + .../test/file_iframe_sandbox_redirect_target.html | 9 + dom/html/test/file_iframe_sandbox_refresh.html | 2 + .../test/file_iframe_sandbox_refresh.html^headers^ | 1 + .../file_iframe_sandbox_srcdoc_allow_scripts.html | 1 + ...ile_iframe_sandbox_srcdoc_no_allow_scripts.html | 1 + .../file_iframe_sandbox_top_navigation_fail.html | 18 + .../file_iframe_sandbox_top_navigation_pass.html | 20 + .../test/file_iframe_sandbox_window_form_fail.html | 20 + .../test/file_iframe_sandbox_window_form_pass.html | 20 + ...file_iframe_sandbox_window_navigation_fail.html | 20 + ...file_iframe_sandbox_window_navigation_pass.html | 20 + ..._iframe_sandbox_window_top_navigation_fail.html | 24 + ..._iframe_sandbox_window_top_navigation_pass.html | 20 + dom/html/test/file_iframe_sandbox_worker.js | 3 + .../test/file_refresh_after_document_write.html | 15 + dom/html/test/file_script_module.html | 42 + dom/html/test/file_script_nomodule.html | 32 + dom/html/test/file_srcdoc-2.html | 10 + dom/html/test/file_srcdoc.html | 16 + dom/html/test/file_srcdoc_iframe3.html | 1 + dom/html/test/file_window_close_and_open.html | 20 + dom/html/test/file_window_open_close_inner.html | 7 + dom/html/test/file_window_open_close_outer.html | 5 + dom/html/test/formData_test.js | 289 + dom/html/test/formData_worker.js | 23 + dom/html/test/formSubmission_chrome.js | 19 + dom/html/test/form_data_file.bin | 1 + dom/html/test/form_data_file.txt | 1 + dom/html/test/form_submit_server.sjs | 86 + dom/html/test/forms/FAIL.html | 1 + dom/html/test/forms/PASS.html | 1 + dom/html/test/forms/chrome.ini | 5 + dom/html/test/forms/file_double_submit.html | 11 + dom/html/test/forms/file_login_fields.html | 16 + dom/html/test/forms/mochitest.ini | 121 + dom/html/test/forms/save_restore_radio_groups.sjs | 48 + dom/html/test/forms/submit_invalid_file.sjs | 13 + .../test_MozEditableElement_setUserInput.html | 581 ++ dom/html/test/forms/test_autocomplete.html | 137 + dom/html/test/forms/test_autocompleteinfo.html | 177 + dom/html/test/forms/test_bug1039548.html | 55 + dom/html/test/forms/test_bug1283915.html | 67 + dom/html/test/forms/test_bug1286509.html | 49 + .../forms/test_button_attributes_reflection.html | 161 + dom/html/test/forms/test_change_event.html | 286 + dom/html/test/forms/test_datalist_element.html | 118 + dom/html/test/forms/test_double_submit.html | 33 + dom/html/test/forms/test_form_attribute-1.html | 473 ++ dom/html/test/forms/test_form_attribute-2.html | 53 + dom/html/test/forms/test_form_attribute-3.html | 68 + dom/html/test/forms/test_form_attribute-4.html | 48 + .../forms/test_form_attributes_reflection.html | 90 + .../test/forms/test_form_named_getter_dynamic.html | 54 + dom/html/test/forms/test_formaction_attribute.html | 169 + .../test/forms/test_formnovalidate_attribute.html | 125 + .../forms/test_input_attributes_reflection.html | 269 + .../test_input_color_input_change_events.html | 119 + .../forms/test_input_color_picker_datalist.html | 42 + .../forms/test_input_color_picker_initial.html | 78 + .../test/forms/test_input_color_picker_popup.html | 144 + .../test/forms/test_input_color_picker_update.html | 86 + dom/html/test/forms/test_input_date_bad_input.html | 113 + .../test/forms/test_input_date_key_events.html | 270 + .../forms/test_input_datetime_calendar_button.html | 177 + .../forms/test_input_datetime_disabled_focus.html | 42 + .../test/forms/test_input_datetime_focus_blur.html | 64 + .../test_input_datetime_focus_blur_events.html | 93 + .../forms/test_input_datetime_focus_state.html | 79 + .../test/forms/test_input_datetime_hidden.html | 32 + .../test_input_datetime_input_change_events.html | 143 + .../test/forms/test_input_datetime_readonly.html | 20 + ...ime_reset_default_value_input_change_event.html | 122 + .../test/forms/test_input_datetime_tabindex.html | 113 + dom/html/test/forms/test_input_defaultValue.html | 81 + dom/html/test/forms/test_input_email.html | 237 + dom/html/test/forms/test_input_event.html | 409 + dom/html/test/forms/test_input_file_picker.html | 280 + .../test/forms/test_input_hasBeenTypePassword.html | 67 + .../test_input_hasBeenTypePassword_navigation.html | 68 + dom/html/test/forms/test_input_list_attribute.html | 253 + dom/html/test/forms/test_input_number_data.js | 54 + dom/html/test/forms/test_input_number_focus.html | 109 + .../test/forms/test_input_number_key_events.html | 238 + dom/html/test/forms/test_input_number_l10n.html | 77 + .../test/forms/test_input_number_mouse_events.html | 259 + .../forms/test_input_number_placeholder_shown.html | 30 + .../test/forms/test_input_number_rounding.html | 120 + .../test/forms/test_input_number_validation.html | 139 + ..._input_password_click_show_password_button.html | 95 + .../test_input_password_show_password_button.html | 80 + .../test/forms/test_input_radio_indeterminate.html | 109 + .../test/forms/test_input_radio_radiogroup.html | 75 + dom/html/test/forms/test_input_radio_required.html | 31 + .../test/forms/test_input_range_attr_order.html | 48 + .../test/forms/test_input_range_key_events.html | 207 + .../test_input_range_mouse_and_touch_events.html | 227 + dom/html/test/forms/test_input_range_rounding.html | 103 + dom/html/test/forms/test_input_sanitization.html | 585 ++ dom/html/test/forms/test_input_setting_value.html | 619 ++ .../test_input_textarea_set_value_no_scroll.html | 123 + .../test/forms/test_input_time_key_events.html | 221 + .../forms/test_input_time_sec_millisec_field.html | 134 + dom/html/test/forms/test_input_types_pref.html | 77 + .../test/forms/test_input_typing_sanitization.html | 217 + .../forms/test_input_untrusted_key_events.html | 90 + dom/html/test/forms/test_input_url.html | 91 + .../forms/test_interactive_content_in_label.html | 101 + .../forms/test_interactive_content_in_summary.html | 97 + .../test/forms/test_label_control_attribute.html | 100 + dom/html/test/forms/test_label_input_controls.html | 84 + dom/html/test/forms/test_max_attribute.html | 473 ++ dom/html/test/forms/test_maxlength_attribute.html | 129 + dom/html/test/forms/test_meter_element.html | 376 + dom/html/test/forms/test_meter_pseudo-classes.html | 169 + dom/html/test/forms/test_min_attribute.html | 473 ++ dom/html/test/forms/test_minlength_attribute.html | 130 + dom/html/test/forms/test_mozistextfield.html | 111 + dom/html/test/forms/test_novalidate_attribute.html | 85 + dom/html/test/forms/test_option_disabled.html | 123 + .../test/forms/test_option_index_attribute.html | 76 + dom/html/test/forms/test_option_text.html | 57 + dom/html/test/forms/test_output_element.html | 182 + dom/html/test/forms/test_pattern_attribute.html | 324 + .../test_preserving_metadata_between_reloads.html | 84 + dom/html/test/forms/test_progress_element.html | 307 + dom/html/test/forms/test_radio_in_label.html | 54 + dom/html/test/forms/test_radio_radionodelist.html | 57 + .../test_reportValidation_preventDefault.html | 89 + dom/html/test/forms/test_required_attribute.html | 420 ++ .../test/forms/test_restore_form_elements.html | 174 + .../test/forms/test_save_restore_radio_groups.html | 70 + dom/html/test/forms/test_select_change_event.html | 54 + .../test/forms/test_select_input_change_event.html | 122 + .../test/forms/test_select_selectedOptions.html | 119 + dom/html/test/forms/test_select_validation.html | 39 + dom/html/test/forms/test_set_range_text.html | 242 + dom/html/test/forms/test_step_attribute.html | 1060 +++ dom/html/test/forms/test_stepup_stepdown.html | 1137 +++ dom/html/test/forms/test_submit_invalid_file.html | 55 + .../forms/test_textarea_attributes_reflection.html | 104 + dom/html/test/forms/test_validation.html | 343 + .../test/forms/test_validation_not_in_doc.html | 19 + .../test/forms/test_valueasdate_attribute.html | 751 ++ .../test/forms/test_valueasnumber_attribute.html | 858 +++ .../forms/without_selectionchange/mochitest.ini | 5 + .../forms/without_selectionchange/test_select.html | 21 + dom/html/test/head.js | 65 + dom/html/test/image-allow-credentials.png | Bin 0 -> 844 bytes dom/html/test/image-allow-credentials.png^headers^ | 2 + dom/html/test/image.png | Bin 0 -> 268 bytes dom/html/test/image_yellow.png | Bin 0 -> 95 bytes dom/html/test/mochitest.ini | 604 ++ dom/html/test/nnc_lockup.gif | Bin 0 -> 732 bytes dom/html/test/object_bug287465_o1.html | 1 + dom/html/test/object_bug287465_o2.html | 1 + dom/html/test/object_bug556645.html | 1 + dom/html/test/post_action_page.html | 10 + dom/html/test/reflect.js | 1078 +++ dom/html/test/script_fakepath.js | 15 + dom/html/test/simpleFileOpener.js | 37 + dom/html/test/submission_flush.html | 13 + dom/html/test/sw_formSubmission.js | 36 + dom/html/test/test_a_text.html | 44 + dom/html/test/test_allowMedia.html | 97 + .../test/test_anchor_href_cache_invalidation.html | 30 + dom/html/test/test_anchor_ping.html | 300 + dom/html/test/test_base_attributes_reflection.html | 34 + dom/html/test/test_bug1003539.html | 37 + dom/html/test/test_bug100533.html | 47 + dom/html/test/test_bug1013316.html | 46 + dom/html/test/test_bug1045270.html | 46 + dom/html/test/test_bug1089326.html | 108 + dom/html/test/test_bug109445.html | 55 + dom/html/test/test_bug109445.xhtml | 55 + dom/html/test/test_bug1146116.html | 59 + dom/html/test/test_bug1166138.html | 130 + dom/html/test/test_bug1203668.html | 62 + dom/html/test/test_bug1230665.html | 46 + dom/html/test/test_bug1250401.html | 97 + dom/html/test/test_bug1260664.html | 51 + dom/html/test/test_bug1260704.html | 90 + dom/html/test/test_bug1261673.html | 72 + dom/html/test/test_bug1261674-1.html | 77 + dom/html/test/test_bug1261674-2.html | 70 + dom/html/test/test_bug1264157.html | 90 + dom/html/test/test_bug1279218.html | 23 + dom/html/test/test_bug1287321.html | 57 + ...522_same_domain_with_different_port_number.html | 43 + ...t_bug1295719_event_sequence_for_arrow_keys.html | 66 + ..._bug1295719_event_sequence_for_number_keys.html | 65 + dom/html/test/test_bug1297.html | 46 + dom/html/test/test_bug1310865.html | 18 + dom/html/test/test_bug1315146.html | 33 + dom/html/test/test_bug1322678.html | 113 + dom/html/test/test_bug1323815.html | 50 + dom/html/test/test_bug1366.html | 35 + dom/html/test/test_bug1400.html | 42 + dom/html/test/test_bug1414077.html | 50 + dom/html/test/test_bug143220.html | 72 + dom/html/test/test_bug1472426.html | 120 + dom/html/test/test_bug1682.html | 37 + dom/html/test/test_bug1785739.html | 48 + dom/html/test/test_bug182279.html | 35 + dom/html/test/test_bug1823.html | 30 + dom/html/test/test_bug196523.html | 41 + dom/html/test/test_bug199692.html | 21 + dom/html/test/test_bug2082.html | 30 + dom/html/test/test_bug209275.xhtml | 258 + dom/html/test/test_bug237071.html | 28 + dom/html/test/test_bug242709.html | 33 + dom/html/test/test_bug24958.html | 31 + dom/html/test/test_bug255820.html | 99 + dom/html/test/test_bug259332.html | 64 + dom/html/test/test_bug274626.html | 97 + dom/html/test/test_bug277724.html | 141 + dom/html/test/test_bug277890.html | 33 + dom/html/test/test_bug287465.html | 45 + dom/html/test/test_bug295561.html | 86 + dom/html/test/test_bug297761.html | 77 + dom/html/test/test_bug300691-1.html | 120 + dom/html/test/test_bug300691-2.html | 142 + dom/html/test/test_bug300691-3.xhtml | 48 + dom/html/test/test_bug311681.html | 99 + dom/html/test/test_bug311681.xhtml | 102 + dom/html/test/test_bug324378.html | 76 + dom/html/test/test_bug330705-1.html | 41 + dom/html/test/test_bug332246.html | 75 + dom/html/test/test_bug332848.xhtml | 86 + dom/html/test/test_bug332893-1.html | 38 + dom/html/test/test_bug332893-2.html | 53 + dom/html/test/test_bug332893-3.html | 58 + dom/html/test/test_bug332893-4.html | 29 + dom/html/test/test_bug332893-5.html | 29 + dom/html/test/test_bug332893-6.html | 27 + dom/html/test/test_bug332893-7.html | 69 + dom/html/test/test_bug3348.html | 33 + dom/html/test/test_bug340017.xhtml | 27 + dom/html/test/test_bug340800.html | 55 + dom/html/test/test_bug347174.html | 64 + dom/html/test/test_bug347174_write.html | 71 + dom/html/test/test_bug347174_xsl.html | 55 + dom/html/test/test_bug347174_xslp.html | 61 + dom/html/test/test_bug353415-1.html | 42 + dom/html/test/test_bug353415-2.html | 67 + dom/html/test/test_bug359657.html | 40 + dom/html/test/test_bug369370.html | 153 + dom/html/test/test_bug371375.html | 58 + dom/html/test/test_bug372098.html | 68 + dom/html/test/test_bug373589.html | 29 + dom/html/test/test_bug375003-1.html | 156 + dom/html/test/test_bug375003-2.html | 109 + dom/html/test/test_bug377624.html | 25 + dom/html/test/test_bug380383.html | 39 + dom/html/test/test_bug383383.html | 41 + dom/html/test/test_bug383383_2.xhtml | 20 + dom/html/test/test_bug384419.html | 56 + dom/html/test/test_bug386496.html | 53 + dom/html/test/test_bug386728.html | 45 + dom/html/test/test_bug386996.html | 43 + dom/html/test/test_bug388558.html | 76 + dom/html/test/test_bug388746.html | 62 + dom/html/test/test_bug388794.html | 107 + dom/html/test/test_bug389797.html | 248 + dom/html/test/test_bug390975.html | 61 + dom/html/test/test_bug391994.html | 184 + dom/html/test/test_bug394700.html | 49 + dom/html/test/test_bug395107.html | 108 + dom/html/test/test_bug401160.xhtml | 27 + dom/html/test/test_bug402680.html | 50 + dom/html/test/test_bug403868.html | 87 + dom/html/test/test_bug403868.xhtml | 86 + dom/html/test/test_bug405242.html | 35 + dom/html/test/test_bug406596.html | 83 + dom/html/test/test_bug417760.html | 71 + dom/html/test/test_bug421640.html | 56 + dom/html/test/test_bug424698.html | 94 + dom/html/test/test_bug428135.xhtml | 156 + dom/html/test/test_bug430351.html | 523 ++ dom/html/test/test_bug435128.html | 42 + dom/html/test/test_bug441930.html | 29 + dom/html/test/test_bug442801.html | 63 + dom/html/test/test_bug445004.html | 138 + dom/html/test/test_bug446483.html | 47 + dom/html/test/test_bug448166.html | 39 + dom/html/test/test_bug448564.html | 53 + dom/html/test/test_bug456229.html | 30 + dom/html/test/test_bug458037.xhtml | 112 + dom/html/test/test_bug460568.html | 144 + dom/html/test/test_bug463104.html | 25 + dom/html/test/test_bug478251.html | 74 + dom/html/test/test_bug481335.xhtml | 122 + dom/html/test/test_bug481440.html | 30 + dom/html/test/test_bug481647.html | 42 + dom/html/test/test_bug482659.html | 64 + dom/html/test/test_bug486741.html | 43 + dom/html/test/test_bug489532.html | 33 + dom/html/test/test_bug497242.xhtml | 41 + dom/html/test/test_bug499092.html | 43 + dom/html/test/test_bug500885.html | 67 + dom/html/test/test_bug512367.html | 40 + dom/html/test/test_bug514856.html | 61 + dom/html/test/test_bug518122.html | 126 + dom/html/test/test_bug519987.html | 33 + dom/html/test/test_bug523771.html | 106 + dom/html/test/test_bug529819.html | 32 + dom/html/test/test_bug529859.html | 42 + dom/html/test/test_bug535043.html | 90 + dom/html/test/test_bug536891.html | 67 + dom/html/test/test_bug536895.html | 54 + dom/html/test/test_bug546995.html | 40 + dom/html/test/test_bug547850.html | 45 + dom/html/test/test_bug551846.html | 164 + dom/html/test/test_bug555567.html | 42 + dom/html/test/test_bug556645.html | 50 + dom/html/test/test_bug557087-1.html | 125 + dom/html/test/test_bug557087-2.html | 359 + dom/html/test/test_bug557087-3.html | 215 + dom/html/test/test_bug557087-4.html | 90 + dom/html/test/test_bug557087-5.html | 94 + dom/html/test/test_bug557087-6.html | 44 + dom/html/test/test_bug557620.html | 30 + dom/html/test/test_bug558788-1.html | 212 + dom/html/test/test_bug558788-2.html | 174 + dom/html/test/test_bug560112.html | 211 + dom/html/test/test_bug561634.html | 126 + dom/html/test/test_bug561636.html | 99 + dom/html/test/test_bug561640.html | 72 + dom/html/test/test_bug564001.html | 48 + dom/html/test/test_bug566046.html | 200 + dom/html/test/test_bug567938-1.html | 69 + dom/html/test/test_bug567938-2.html | 70 + dom/html/test/test_bug567938-3.html | 70 + dom/html/test/test_bug567938-4.html | 43 + dom/html/test/test_bug569955.html | 37 + dom/html/test/test_bug573969.html | 37 + dom/html/test/test_bug57600.html | 42 + dom/html/test/test_bug579079.html | 40 + dom/html/test/test_bug582412-1.html | 200 + dom/html/test/test_bug582412-2.html | 199 + dom/html/test/test_bug583514.html | 71 + dom/html/test/test_bug583533.html | 81 + dom/html/test/test_bug586763.html | 43 + dom/html/test/test_bug586786.html | 57 + dom/html/test/test_bug587469.html | 41 + dom/html/test/test_bug589.html | 42 + dom/html/test/test_bug590353-1.html | 36 + dom/html/test/test_bug590353-2.html | 79 + dom/html/test/test_bug590363.html | 133 + dom/html/test/test_bug592802.html | 96 + dom/html/test/test_bug593689.html | 50 + dom/html/test/test_bug595429.html | 56 + dom/html/test/test_bug595447.html | 29 + dom/html/test/test_bug595449.html | 95 + dom/html/test/test_bug596350.html | 65 + dom/html/test/test_bug596511.html | 237 + dom/html/test/test_bug598643.html | 80 + dom/html/test/test_bug598833-1.html | 45 + dom/html/test/test_bug600155.html | 44 + dom/html/test/test_bug601030.html | 52 + dom/html/test/test_bug605124-1.html | 99 + dom/html/test/test_bug605124-2.html | 112 + dom/html/test/test_bug605125-1.html | 105 + dom/html/test/test_bug605125-2.html | 149 + dom/html/test/test_bug606817.html | 59 + dom/html/test/test_bug607145.html | 86 + dom/html/test/test_bug610212.html | 42 + dom/html/test/test_bug610687.html | 201 + dom/html/test/test_bug611189.html | 45 + dom/html/test/test_bug612730.html | 51 + dom/html/test/test_bug613019.html | 84 + dom/html/test/test_bug613113.html | 52 + dom/html/test/test_bug613722.html | 32 + dom/html/test/test_bug613979.html | 50 + dom/html/test/test_bug615595.html | Bin 0 -> 2706 bytes dom/html/test/test_bug615833.html | 141 + dom/html/test/test_bug618948.html | 88 + dom/html/test/test_bug619278.html | 56 + dom/html/test/test_bug622558.html | 83 + dom/html/test/test_bug622597.html | 105 + dom/html/test/test_bug623291.html | 46 + dom/html/test/test_bug6296.html | 31 + dom/html/test/test_bug629801.html | 50 + dom/html/test/test_bug633058.html | 66 + dom/html/test/test_bug636336.html | 41 + dom/html/test/test_bug641219.html | 34 + dom/html/test/test_bug643051.html | 55 + dom/html/test/test_bug646157.html | 95 + dom/html/test/test_bug649134.html | 54 + dom/html/test/test_bug651956.html | 48 + dom/html/test/test_bug658746.html | 97 + dom/html/test/test_bug659596.html | 96 + dom/html/test/test_bug659743.xml | 55 + dom/html/test/test_bug660663.html | 30 + dom/html/test/test_bug660959-1.html | 25 + dom/html/test/test_bug660959-2.html | 30 + dom/html/test/test_bug660959-3.html | 28 + dom/html/test/test_bug666200.html | 43 + dom/html/test/test_bug666666.html | 32 + dom/html/test/test_bug669012.html | 44 + dom/html/test/test_bug674558.html | 287 + dom/html/test/test_bug674927.html | 55 + dom/html/test/test_bug677495-1.html | 34 + dom/html/test/test_bug677495.html | 34 + dom/html/test/test_bug677658.html | 41 + dom/html/test/test_bug682886.html | 33 + dom/html/test/test_bug691.html | 62 + dom/html/test/test_bug694.html | 30 + dom/html/test/test_bug694503.html | 75 + dom/html/test/test_bug696.html | 28 + dom/html/test/test_bug717819.html | 36 + dom/html/test/test_bug741266.html | 44 + dom/html/test/test_bug742030.html | 31 + dom/html/test/test_bug742549.html | 47 + dom/html/test/test_bug745685.html | 105 + dom/html/test/test_bug763626.html | 29 + dom/html/test/test_bug765780.html | 46 + dom/html/test/test_bug780993.html | 39 + dom/html/test/test_bug787134.html | 28 + dom/html/test/test_bug797113.html | 39 + dom/html/test/test_bug803677.html | 49 + dom/html/test/test_bug821307.html | 41 + dom/html/test/test_bug827126.html | 28 + dom/html/test/test_bug838582.html | 35 + dom/html/test/test_bug839371.html | 44 + dom/html/test/test_bug839913.html | 14 + dom/html/test/test_bug841466.html | 33 + dom/html/test/test_bug845057.html | 59 + dom/html/test/test_bug869040.html | 36 + dom/html/test/test_bug870787.html | 84 + dom/html/test/test_bug871161.html | 37 + dom/html/test/test_bug874758.html | 31 + dom/html/test/test_bug879319.html | 92 + dom/html/test/test_bug885024.html | 46 + dom/html/test/test_bug893537.html | 45 + dom/html/test/test_bug95530.html | 38 + dom/html/test/test_bug969346.html | 33 + dom/html/test/test_bug982039.html | 46 + dom/html/test/test_change_crossorigin.html | 89 + dom/html/test/test_checked.html | 347 + dom/html/test/test_dir_attributes_reflection.html | 27 + dom/html/test/test_dl_attributes_reflection.html | 27 + dom/html/test/test_document-element-inserted.html | 54 + dom/html/test/test_documentAll.html | 167 + dom/html/test/test_element_prototype.html | 32 + .../test/test_embed_attributes_reflection.html | 57 + dom/html/test/test_external_protocol_iframe.html | 80 + dom/html/test/test_fakepath.html | 40 + .../test/test_filepicker_default_directory.html | 81 + dom/html/test/test_focusshift_button.html | 34 + dom/html/test/test_form-parsing.html | 35 + dom/html/test/test_formData.html | 50 + dom/html/test/test_formSubmission.html | 910 +++ dom/html/test/test_formSubmission2.html | 220 + dom/html/test/test_formelements.html | 68 + dom/html/test/test_fragment_form_pointer.html | 27 + .../test/test_frame_count_with_synthetic_doc.html | 36 + .../test_getElementsByName_after_mutation.html | 51 + dom/html/test/test_hidden.html | 52 + dom/html/test/test_html_attributes_reflection.html | 27 + dom/html/test/test_htmlcollection.html | 55 + dom/html/test/test_iframe_sandbox_general.html | 283 + dom/html/test/test_iframe_sandbox_inheritance.html | 202 + dom/html/test/test_iframe_sandbox_navigation.html | 285 + dom/html/test/test_iframe_sandbox_navigation2.html | 216 + dom/html/test/test_iframe_sandbox_popups.html | 78 + .../test_iframe_sandbox_popups_inheritance.html | 157 + dom/html/test/test_iframe_sandbox_redirect.html | 45 + dom/html/test/test_iframe_sandbox_refresh.html | 101 + dom/html/test/test_iframe_sandbox_same_origin.html | 108 + dom/html/test/test_iframe_sandbox_workers.html | 74 + dom/html/test/test_imageSrcSet.html | 38 + dom/html/test/test_image_clone_load.html | 21 + dom/html/test/test_img_attributes_reflection.html | 103 + dom/html/test/test_input_file_cancel_event.html | 43 + dom/html/test/test_input_files_not_nsIFile.html | 48 + dom/html/test/test_input_lastInteractiveValue.html | 134 + dom/html/test/test_inputmode.html | 132 + dom/html/test/test_li_attributes_reflection.html | 34 + dom/html/test/test_link_attributes_reflection.html | 96 + dom/html/test/test_link_sizes.html | 35 + dom/html/test/test_map_attributes_reflection.html | 27 + dom/html/test/test_meta_attributes_reflection.html | 45 + dom/html/test/test_mod_attributes_reflection.html | 41 + dom/html/test/test_multipleFilePicker.html | 79 + dom/html/test/test_named_options.html | 61 + dom/html/test/test_nested_invalid_fieldsets.html | 47 + dom/html/test/test_nestediframe.html | 56 + dom/html/test/test_non-ascii-cookie.html | 69 + dom/html/test/test_non-ascii-cookie.html^headers^ | 1 + .../test/test_object_attributes_reflection.html | 117 + dom/html/test/test_ol_attributes_reflection.html | 65 + dom/html/test/test_option_defaultSelected.html | 47 + dom/html/test/test_option_selected_state.html | 61 + .../test/test_param_attributes_reflection.html | 45 + dom/html/test/test_plugin.tst | 1 + dom/html/test/test_q_attributes_reflection.html | 32 + .../test/test_restore_from_parser_fragment.html | 59 + dom/html/test/test_rowscollection.html | 69 + dom/html/test/test_script_module.html | 56 + dom/html/test/test_set_input_files.html | 55 + dom/html/test/test_srcdoc-2.html | 57 + dom/html/test/test_srcdoc.html | 118 + .../test/test_style_attributes_reflection.html | 35 + dom/html/test/test_track.html | 62 + dom/html/test/test_ul_attributes_reflection.html | 33 + dom/html/test/test_viewport_resize.html | 44 + dom/html/test/test_window_open_close.html | 53 + dom/html/test/test_window_open_from_closing.html | 43 + 1144 files changed, 124961 insertions(+) create mode 100644 dom/html/ConstraintValidation.cpp create mode 100644 dom/html/ConstraintValidation.h create mode 100644 dom/html/ElementInternals.cpp create mode 100644 dom/html/ElementInternals.h create mode 100644 dom/html/HTMLAllCollection.cpp create mode 100644 dom/html/HTMLAllCollection.h create mode 100644 dom/html/HTMLAnchorElement.cpp create mode 100644 dom/html/HTMLAnchorElement.h create mode 100644 dom/html/HTMLAreaElement.cpp create mode 100644 dom/html/HTMLAreaElement.h create mode 100644 dom/html/HTMLAudioElement.cpp create mode 100644 dom/html/HTMLAudioElement.h create mode 100644 dom/html/HTMLBRElement.cpp create mode 100644 dom/html/HTMLBRElement.h create mode 100644 dom/html/HTMLBodyElement.cpp create mode 100644 dom/html/HTMLBodyElement.h create mode 100644 dom/html/HTMLButtonElement.cpp create mode 100644 dom/html/HTMLButtonElement.h create mode 100644 dom/html/HTMLCanvasElement.cpp create mode 100644 dom/html/HTMLCanvasElement.h create mode 100644 dom/html/HTMLDNSPrefetch.cpp create mode 100644 dom/html/HTMLDNSPrefetch.h create mode 100644 dom/html/HTMLDataElement.cpp create mode 100644 dom/html/HTMLDataElement.h create mode 100644 dom/html/HTMLDataListElement.cpp create mode 100644 dom/html/HTMLDataListElement.h create mode 100644 dom/html/HTMLDetailsElement.cpp create mode 100644 dom/html/HTMLDetailsElement.h create mode 100644 dom/html/HTMLDialogElement.cpp create mode 100644 dom/html/HTMLDialogElement.h create mode 100644 dom/html/HTMLDivElement.cpp create mode 100644 dom/html/HTMLDivElement.h create mode 100644 dom/html/HTMLElement.cpp create mode 100644 dom/html/HTMLElement.h create mode 100644 dom/html/HTMLEmbedElement.cpp create mode 100644 dom/html/HTMLEmbedElement.h create mode 100644 dom/html/HTMLFieldSetElement.cpp create mode 100644 dom/html/HTMLFieldSetElement.h create mode 100644 dom/html/HTMLFontElement.cpp create mode 100644 dom/html/HTMLFontElement.h create mode 100644 dom/html/HTMLFormControlsCollection.cpp create mode 100644 dom/html/HTMLFormControlsCollection.h create mode 100644 dom/html/HTMLFormElement.cpp create mode 100644 dom/html/HTMLFormElement.h create mode 100644 dom/html/HTMLFormSubmission.cpp create mode 100644 dom/html/HTMLFormSubmission.h create mode 100644 dom/html/HTMLFormSubmissionConstants.h create mode 100644 dom/html/HTMLFrameElement.cpp create mode 100644 dom/html/HTMLFrameElement.h create mode 100644 dom/html/HTMLFrameSetElement.cpp create mode 100644 dom/html/HTMLFrameSetElement.h create mode 100644 dom/html/HTMLHRElement.cpp create mode 100644 dom/html/HTMLHRElement.h create mode 100644 dom/html/HTMLHeadingElement.cpp create mode 100644 dom/html/HTMLHeadingElement.h create mode 100644 dom/html/HTMLIFrameElement.cpp create mode 100644 dom/html/HTMLIFrameElement.h create mode 100644 dom/html/HTMLImageElement.cpp create mode 100644 dom/html/HTMLImageElement.h create mode 100644 dom/html/HTMLInputElement.cpp create mode 100644 dom/html/HTMLInputElement.h create mode 100644 dom/html/HTMLLIElement.cpp create mode 100644 dom/html/HTMLLIElement.h create mode 100644 dom/html/HTMLLabelElement.cpp create mode 100644 dom/html/HTMLLabelElement.h create mode 100644 dom/html/HTMLLegendElement.cpp create mode 100644 dom/html/HTMLLegendElement.h create mode 100644 dom/html/HTMLLinkElement.cpp create mode 100644 dom/html/HTMLLinkElement.h create mode 100644 dom/html/HTMLMapElement.cpp create mode 100644 dom/html/HTMLMapElement.h create mode 100644 dom/html/HTMLMarqueeElement.cpp create mode 100644 dom/html/HTMLMarqueeElement.h create mode 100644 dom/html/HTMLMediaElement.cpp create mode 100644 dom/html/HTMLMediaElement.h create mode 100644 dom/html/HTMLMenuElement.cpp create mode 100644 dom/html/HTMLMenuElement.h create mode 100644 dom/html/HTMLMetaElement.cpp create mode 100644 dom/html/HTMLMetaElement.h create mode 100644 dom/html/HTMLMeterElement.cpp create mode 100644 dom/html/HTMLMeterElement.h create mode 100644 dom/html/HTMLModElement.cpp create mode 100644 dom/html/HTMLModElement.h create mode 100644 dom/html/HTMLObjectElement.cpp create mode 100644 dom/html/HTMLObjectElement.h create mode 100644 dom/html/HTMLOptGroupElement.cpp create mode 100644 dom/html/HTMLOptGroupElement.h create mode 100644 dom/html/HTMLOptionElement.cpp create mode 100644 dom/html/HTMLOptionElement.h create mode 100644 dom/html/HTMLOptionsCollection.cpp create mode 100644 dom/html/HTMLOptionsCollection.h create mode 100644 dom/html/HTMLOutputElement.cpp create mode 100644 dom/html/HTMLOutputElement.h create mode 100644 dom/html/HTMLParagraphElement.cpp create mode 100644 dom/html/HTMLParagraphElement.h create mode 100644 dom/html/HTMLPictureElement.cpp create mode 100644 dom/html/HTMLPictureElement.h create mode 100644 dom/html/HTMLPreElement.cpp create mode 100644 dom/html/HTMLPreElement.h create mode 100644 dom/html/HTMLProgressElement.cpp create mode 100644 dom/html/HTMLProgressElement.h create mode 100644 dom/html/HTMLScriptElement.cpp create mode 100644 dom/html/HTMLScriptElement.h create mode 100644 dom/html/HTMLSelectElement.cpp create mode 100644 dom/html/HTMLSelectElement.h create mode 100644 dom/html/HTMLSharedElement.cpp create mode 100644 dom/html/HTMLSharedElement.h create mode 100644 dom/html/HTMLSharedListElement.cpp create mode 100644 dom/html/HTMLSharedListElement.h create mode 100644 dom/html/HTMLSlotElement.cpp create mode 100644 dom/html/HTMLSlotElement.h create mode 100644 dom/html/HTMLSourceElement.cpp create mode 100644 dom/html/HTMLSourceElement.h create mode 100644 dom/html/HTMLSpanElement.cpp create mode 100644 dom/html/HTMLSpanElement.h create mode 100644 dom/html/HTMLStyleElement.cpp create mode 100644 dom/html/HTMLStyleElement.h create mode 100644 dom/html/HTMLSummaryElement.cpp create mode 100644 dom/html/HTMLSummaryElement.h create mode 100644 dom/html/HTMLTableCaptionElement.cpp create mode 100644 dom/html/HTMLTableCaptionElement.h create mode 100644 dom/html/HTMLTableCellElement.cpp create mode 100644 dom/html/HTMLTableCellElement.h create mode 100644 dom/html/HTMLTableColElement.cpp create mode 100644 dom/html/HTMLTableColElement.h create mode 100644 dom/html/HTMLTableElement.cpp create mode 100644 dom/html/HTMLTableElement.h create mode 100644 dom/html/HTMLTableRowElement.cpp create mode 100644 dom/html/HTMLTableRowElement.h create mode 100644 dom/html/HTMLTableSectionElement.cpp create mode 100644 dom/html/HTMLTableSectionElement.h create mode 100644 dom/html/HTMLTemplateElement.cpp create mode 100644 dom/html/HTMLTemplateElement.h create mode 100644 dom/html/HTMLTextAreaElement.cpp create mode 100644 dom/html/HTMLTextAreaElement.h create mode 100644 dom/html/HTMLTimeElement.cpp create mode 100644 dom/html/HTMLTimeElement.h create mode 100644 dom/html/HTMLTitleElement.cpp create mode 100644 dom/html/HTMLTitleElement.h create mode 100644 dom/html/HTMLTrackElement.cpp create mode 100644 dom/html/HTMLTrackElement.h create mode 100644 dom/html/HTMLUnknownElement.cpp create mode 100644 dom/html/HTMLUnknownElement.h create mode 100644 dom/html/HTMLVideoElement.cpp create mode 100644 dom/html/HTMLVideoElement.h create mode 100644 dom/html/ImageDocument.cpp create mode 100644 dom/html/ImageDocument.h create mode 100644 dom/html/MediaDocument.cpp create mode 100644 dom/html/MediaDocument.h create mode 100644 dom/html/MediaError.cpp create mode 100644 dom/html/MediaError.h create mode 100644 dom/html/PlayPromise.cpp create mode 100644 dom/html/PlayPromise.h create mode 100644 dom/html/RadioNodeList.cpp create mode 100644 dom/html/RadioNodeList.h create mode 100644 dom/html/TextControlElement.h create mode 100644 dom/html/TextControlState.cpp create mode 100644 dom/html/TextControlState.h create mode 100644 dom/html/TextInputListener.h create mode 100644 dom/html/TextTrackManager.cpp create mode 100644 dom/html/TextTrackManager.h create mode 100644 dom/html/TimeRanges.cpp create mode 100644 dom/html/TimeRanges.h create mode 100644 dom/html/ValidityState.cpp create mode 100644 dom/html/ValidityState.h create mode 100644 dom/html/VideoDocument.cpp create mode 100644 dom/html/crashtests/1032654.html create mode 100644 dom/html/crashtests/1141260.html create mode 100644 dom/html/crashtests/1228876.html create mode 100644 dom/html/crashtests/1230110.html create mode 100644 dom/html/crashtests/1237633.html create mode 100644 dom/html/crashtests/1281972-1.html create mode 100644 dom/html/crashtests/1282894.html create mode 100644 dom/html/crashtests/1290904.html create mode 100644 dom/html/crashtests/1343886-1.html create mode 100644 dom/html/crashtests/1343886-2.xml create mode 100644 dom/html/crashtests/1343886-3.xml create mode 100644 dom/html/crashtests/1350972.html create mode 100644 dom/html/crashtests/1386905.html create mode 100644 dom/html/crashtests/1401726.html create mode 100644 dom/html/crashtests/1412173.html create mode 100644 dom/html/crashtests/1429783.html create mode 100644 dom/html/crashtests/1440523.html create mode 100644 dom/html/crashtests/1440827.html create mode 100644 dom/html/crashtests/1547057.html create mode 100644 dom/html/crashtests/1550524.html create mode 100644 dom/html/crashtests/1550881-1.html create mode 100644 dom/html/crashtests/1550881-2.html create mode 100644 dom/html/crashtests/1667493.html create mode 100644 dom/html/crashtests/1667493_1.html create mode 100644 dom/html/crashtests/1680418.html create mode 100644 dom/html/crashtests/1704660.html create mode 100644 dom/html/crashtests/1724816.html create mode 100644 dom/html/crashtests/1785933-inner.html create mode 100644 dom/html/crashtests/1785933.html create mode 100644 dom/html/crashtests/1787671.html create mode 100644 dom/html/crashtests/1789475.html create mode 100644 dom/html/crashtests/1801380.html create mode 100644 dom/html/crashtests/257818-1.html create mode 100644 dom/html/crashtests/285166-1.html create mode 100644 dom/html/crashtests/294235-1.html create mode 100644 dom/html/crashtests/307616-1.html create mode 100644 dom/html/crashtests/324918-1.xhtml create mode 100644 dom/html/crashtests/338649-1.xhtml create mode 100644 dom/html/crashtests/339501-1.xhtml create mode 100644 dom/html/crashtests/339501-2.xhtml create mode 100644 dom/html/crashtests/378993-1.xhtml create mode 100644 dom/html/crashtests/382568-1-inner.xhtml create mode 100644 dom/html/crashtests/382568-1.html create mode 100644 dom/html/crashtests/383137.xhtml create mode 100644 dom/html/crashtests/388183-1.html create mode 100644 dom/html/crashtests/395340-1.html create mode 100644 dom/html/crashtests/399694-1.html create mode 100644 dom/html/crashtests/407053.html create mode 100644 dom/html/crashtests/423371-1.html create mode 100644 dom/html/crashtests/448564.html create mode 100644 dom/html/crashtests/451123-1.html create mode 100644 dom/html/crashtests/453406-1.html create mode 100644 dom/html/crashtests/464197-1.html create mode 100644 dom/html/crashtests/468562-1.html create mode 100644 dom/html/crashtests/468562-2.html create mode 100644 dom/html/crashtests/494225.html create mode 100644 dom/html/crashtests/495543.svg create mode 100644 dom/html/crashtests/495546-1.html create mode 100644 dom/html/crashtests/504183-1.html create mode 100644 dom/html/crashtests/515829-1.html create mode 100644 dom/html/crashtests/515829-2.html create mode 100644 dom/html/crashtests/570566-1.html create mode 100644 dom/html/crashtests/571428-1.html create mode 100644 dom/html/crashtests/580507-1.xhtml create mode 100644 dom/html/crashtests/590387.html create mode 100644 dom/html/crashtests/596785-1.html create mode 100644 dom/html/crashtests/596785-2.html create mode 100644 dom/html/crashtests/602117.html create mode 100644 dom/html/crashtests/604807.html create mode 100644 dom/html/crashtests/605264.html create mode 100644 dom/html/crashtests/606430-1.html create mode 100644 dom/html/crashtests/613027.html create mode 100644 dom/html/crashtests/614279.html create mode 100644 dom/html/crashtests/614988-1.html create mode 100644 dom/html/crashtests/616401.html create mode 100644 dom/html/crashtests/620078-1.html create mode 100644 dom/html/crashtests/620078-2.html create mode 100644 dom/html/crashtests/631421.html create mode 100644 dom/html/crashtests/631421.png create mode 100644 dom/html/crashtests/673853.html create mode 100644 dom/html/crashtests/682058.xhtml create mode 100644 dom/html/crashtests/682460.html create mode 100644 dom/html/crashtests/68912-1.html create mode 100644 dom/html/crashtests/738744.xhtml create mode 100644 dom/html/crashtests/741218.json create mode 100644 dom/html/crashtests/741218.json^headers^ create mode 100644 dom/html/crashtests/741250.xhtml create mode 100644 dom/html/crashtests/768344.html create mode 100644 dom/html/crashtests/795221-1.html create mode 100644 dom/html/crashtests/795221-2.html create mode 100644 dom/html/crashtests/795221-3.html create mode 100644 dom/html/crashtests/795221-4.html create mode 100644 dom/html/crashtests/795221-5.xml create mode 100644 dom/html/crashtests/798802-1.html create mode 100644 dom/html/crashtests/811226.html create mode 100644 dom/html/crashtests/819745.html create mode 100644 dom/html/crashtests/828180.html create mode 100644 dom/html/crashtests/828472.html create mode 100644 dom/html/crashtests/837033.html create mode 100644 dom/html/crashtests/838256-1.html create mode 100644 dom/html/crashtests/862084.html create mode 100644 dom/html/crashtests/865147.html create mode 100644 dom/html/crashtests/877910.html create mode 100644 dom/html/crashtests/903106.html create mode 100644 dom/html/crashtests/916322-1.html create mode 100644 dom/html/crashtests/916322-2.html create mode 100644 dom/html/crashtests/978644.xhtml create mode 100644 dom/html/crashtests/crashtests.list create mode 100644 dom/html/input/ButtonInputTypes.h create mode 100644 dom/html/input/CheckableInputTypes.cpp create mode 100644 dom/html/input/CheckableInputTypes.h create mode 100644 dom/html/input/ColorInputType.h create mode 100644 dom/html/input/DateTimeInputTypes.cpp create mode 100644 dom/html/input/DateTimeInputTypes.h create mode 100644 dom/html/input/FileInputType.cpp create mode 100644 dom/html/input/FileInputType.h create mode 100644 dom/html/input/HiddenInputType.h create mode 100644 dom/html/input/InputType.cpp create mode 100644 dom/html/input/InputType.h create mode 100644 dom/html/input/NumericInputTypes.cpp create mode 100644 dom/html/input/NumericInputTypes.h create mode 100644 dom/html/input/SingleLineTextInputTypes.cpp create mode 100644 dom/html/input/SingleLineTextInputTypes.h create mode 100644 dom/html/input/moz.build create mode 100644 dom/html/moz.build create mode 100644 dom/html/nsBrowserElement.cpp create mode 100644 dom/html/nsBrowserElement.h create mode 100644 dom/html/nsDOMStringMap.cpp create mode 100644 dom/html/nsDOMStringMap.h create mode 100644 dom/html/nsGenericHTMLElement.cpp create mode 100644 dom/html/nsGenericHTMLElement.h create mode 100644 dom/html/nsGenericHTMLFrameElement.cpp create mode 100644 dom/html/nsGenericHTMLFrameElement.h create mode 100644 dom/html/nsHTMLContentSink.cpp create mode 100644 dom/html/nsHTMLDocument.cpp create mode 100644 dom/html/nsHTMLDocument.h create mode 100644 dom/html/nsIConstraintValidation.cpp create mode 100644 dom/html/nsIConstraintValidation.h create mode 100644 dom/html/nsIFormControl.h create mode 100644 dom/html/nsIHTMLCollection.h create mode 100644 dom/html/nsIRadioGroupContainer.h create mode 100644 dom/html/nsIRadioVisitor.h create mode 100644 dom/html/nsRadioVisitor.cpp create mode 100644 dom/html/nsRadioVisitor.h create mode 100644 dom/html/reftests/41464-1-ref.html create mode 100644 dom/html/reftests/41464-1a.html create mode 100644 dom/html/reftests/41464-1b.html create mode 100644 dom/html/reftests/468263-1a.html create mode 100644 dom/html/reftests/468263-1b.html create mode 100644 dom/html/reftests/468263-1c.html create mode 100644 dom/html/reftests/468263-1d.html create mode 100644 dom/html/reftests/468263-2-alternate-ref.html create mode 100644 dom/html/reftests/468263-2-ref.html create mode 100644 dom/html/reftests/468263-2.html create mode 100644 dom/html/reftests/484200-1-ref.html create mode 100644 dom/html/reftests/484200-1.html create mode 100644 dom/html/reftests/485377-ref.html create mode 100644 dom/html/reftests/485377.html create mode 100644 dom/html/reftests/52019-1-ref.html create mode 100644 dom/html/reftests/52019-1.html create mode 100644 dom/html/reftests/557840-ref.html create mode 100644 dom/html/reftests/557840.html create mode 100644 dom/html/reftests/560059-video-dimensions-ref.html create mode 100644 dom/html/reftests/560059-video-dimensions.html create mode 100644 dom/html/reftests/573322-no-quirks-ref.html create mode 100644 dom/html/reftests/573322-no-quirks.html create mode 100644 dom/html/reftests/573322-quirks-ref.html create mode 100644 dom/html/reftests/573322-quirks.html create mode 100644 dom/html/reftests/596455-1a.html create mode 100644 dom/html/reftests/596455-1b.html create mode 100644 dom/html/reftests/596455-2a.html create mode 100644 dom/html/reftests/596455-2b.html create mode 100644 dom/html/reftests/596455-ref-1.html create mode 100644 dom/html/reftests/596455-ref-2.html create mode 100644 dom/html/reftests/610935-ref.html create mode 100644 dom/html/reftests/610935.html create mode 100644 dom/html/reftests/649134-1.html create mode 100644 dom/html/reftests/649134-2-ref.html create mode 100644 dom/html/reftests/649134-2.html create mode 100644 dom/html/reftests/649134-ref.html create mode 100644 dom/html/reftests/741776-1-ref.html create mode 100644 dom/html/reftests/741776-1.vtt create mode 100644 dom/html/reftests/82711-1-ref.html create mode 100644 dom/html/reftests/82711-1.html create mode 100644 dom/html/reftests/82711-2-ref.html create mode 100644 dom/html/reftests/82711-2.html create mode 100644 dom/html/reftests/autofocus/autofocus-after-body-focus-ref.html create mode 100644 dom/html/reftests/autofocus/autofocus-after-body-focus.html create mode 100644 dom/html/reftests/autofocus/autofocus-after-load-ref.html create mode 100644 dom/html/reftests/autofocus/autofocus-after-load.html create mode 100644 dom/html/reftests/autofocus/autofocus-leaves-iframe-ref.html create mode 100644 dom/html/reftests/autofocus/autofocus-leaves-iframe.html create mode 100644 dom/html/reftests/autofocus/button-create.html create mode 100644 dom/html/reftests/autofocus/button-load.html create mode 100644 dom/html/reftests/autofocus/button-ref.html create mode 100644 dom/html/reftests/autofocus/input-create.html create mode 100644 dom/html/reftests/autofocus/input-load.html create mode 100644 dom/html/reftests/autofocus/input-number-ref.html create mode 100644 dom/html/reftests/autofocus/input-number.html create mode 100644 dom/html/reftests/autofocus/input-ref.html create mode 100644 dom/html/reftests/autofocus/input-time-ref.html create mode 100644 dom/html/reftests/autofocus/input-time.html create mode 100644 dom/html/reftests/autofocus/reftest.list create mode 100644 dom/html/reftests/autofocus/select-create.html create mode 100644 dom/html/reftests/autofocus/select-load.html create mode 100644 dom/html/reftests/autofocus/select-ref.html create mode 100644 dom/html/reftests/autofocus/style.css create mode 100644 dom/html/reftests/autofocus/textarea-create.html create mode 100644 dom/html/reftests/autofocus/textarea-load.html create mode 100644 dom/html/reftests/autofocus/textarea-ref.html create mode 100644 dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html create mode 100644 dom/html/reftests/body-frame-margin-remove-other-pres-hint.html create mode 100644 dom/html/reftests/body-topmargin-dynamic.html create mode 100644 dom/html/reftests/body-topmargin-ref.html create mode 100644 dom/html/reftests/bug1106522-1.html create mode 100644 dom/html/reftests/bug1106522-2.html create mode 100644 dom/html/reftests/bug1106522-ref.html create mode 100644 dom/html/reftests/bug1196784-no-srcset.html create mode 100644 dom/html/reftests/bug1196784-with-srcset.html create mode 100644 dom/html/reftests/bug1196784.png create mode 100644 dom/html/reftests/bug1228601-video-rotated-ref.html create mode 100644 dom/html/reftests/bug1228601-video-rotation-90.html create mode 100644 dom/html/reftests/bug1423850-canvas-video-rotated-ref.html create mode 100644 dom/html/reftests/bug1423850-canvas-video-rotation-90.html create mode 100644 dom/html/reftests/bug1512297-ref.html create mode 100644 dom/html/reftests/bug1512297.html create mode 100644 dom/html/reftests/bug448564-1_ideal.html create mode 100644 dom/html/reftests/bug448564-1_malformed.html create mode 100644 dom/html/reftests/bug448564-1_well-formed.html create mode 100644 dom/html/reftests/bug448564-4a.html create mode 100644 dom/html/reftests/bug448564-4b.html create mode 100644 dom/html/reftests/bug448564_forms.css create mode 100644 dom/html/reftests/bug502168-1_malformed.html create mode 100644 dom/html/reftests/bug502168-1_well-formed.html create mode 100644 dom/html/reftests/bug917595-1-ref.html create mode 100644 dom/html/reftests/bug917595-exif-rotated.jpg create mode 100644 dom/html/reftests/bug917595-iframe-1.html create mode 100644 dom/html/reftests/bug917595-pixel-rotated.jpg create mode 100644 dom/html/reftests/bug917595-unrotated.jpg create mode 100644 dom/html/reftests/figure-ref.html create mode 100644 dom/html/reftests/figure.html create mode 100644 dom/html/reftests/href-attr-change-restyles-ref.html create mode 100644 dom/html/reftests/href-attr-change-restyles.html create mode 100644 dom/html/reftests/image-load-shortcircuit-1.html create mode 100644 dom/html/reftests/image-load-shortcircuit-2.html create mode 100644 dom/html/reftests/image-load-shortcircuit-ref.html create mode 100644 dom/html/reftests/lime100x100.svg create mode 100644 dom/html/reftests/pass.png create mode 100644 dom/html/reftests/pre-1-ref.html create mode 100644 dom/html/reftests/pre-1.html create mode 100644 dom/html/reftests/red.png create mode 100644 dom/html/reftests/reftest.list create mode 100644 dom/html/reftests/responsive-image-load-shortcircuit-ref.html create mode 100644 dom/html/reftests/responsive-image-load-shortcircuit.html create mode 100644 dom/html/reftests/table-border-1-ref.html create mode 100644 dom/html/reftests/table-border-1.html create mode 100644 dom/html/reftests/table-border-2-notref.html create mode 100644 dom/html/reftests/table-border-2-ref.html create mode 100644 dom/html/reftests/table-border-2.html create mode 100644 dom/html/reftests/toblob-todataurl/blob.js create mode 100644 dom/html/reftests/toblob-todataurl/dataurl.js create mode 100644 dom/html/reftests/toblob-todataurl/images/original.png create mode 100644 dom/html/reftests/toblob-todataurl/images/q0.jpg create mode 100644 dom/html/reftests/toblob-todataurl/images/q100.jpg create mode 100644 dom/html/reftests/toblob-todataurl/images/q25.jpg create mode 100644 dom/html/reftests/toblob-todataurl/images/q50.jpg create mode 100644 dom/html/reftests/toblob-todataurl/images/q75.jpg create mode 100644 dom/html/reftests/toblob-todataurl/images/q92.jpg create mode 100644 dom/html/reftests/toblob-todataurl/quality-0-ref.html create mode 100644 dom/html/reftests/toblob-todataurl/quality-100-ref.html create mode 100644 dom/html/reftests/toblob-todataurl/quality-25-ref.html create mode 100644 dom/html/reftests/toblob-todataurl/quality-50-ref.html create mode 100644 dom/html/reftests/toblob-todataurl/quality-75-ref.html create mode 100644 dom/html/reftests/toblob-todataurl/quality-92-ref.html create mode 100644 dom/html/reftests/toblob-todataurl/reftest.list create mode 100644 dom/html/reftests/toblob-todataurl/sample.js create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-0.html create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-100.html create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-25.html create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-50.html create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-75.html create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-92.html create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-default.html create mode 100644 dom/html/reftests/toblob-todataurl/toblob-quality-undefined.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-0.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-100.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-25.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-50.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-75.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-92.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-default.html create mode 100644 dom/html/reftests/toblob-todataurl/todataurl-quality-undefined.html create mode 100644 dom/html/reftests/video_rotated.mp4 create mode 100644 dom/html/reftests/video_rotation_90.mp4 create mode 100644 dom/html/test/347174transform.xsl create mode 100644 dom/html/test/347174transformable.xml create mode 100644 dom/html/test/allowMedia.sjs create mode 100644 dom/html/test/browser.ini create mode 100644 dom/html/test/browser_DOMDocElementInserted.js create mode 100644 dom/html/test/browser_ImageDocument_svg_zoom.js create mode 100644 dom/html/test/browser_bug1081537.js create mode 100644 dom/html/test/browser_bug1108547.js create mode 100644 dom/html/test/browser_bug436200.js create mode 100644 dom/html/test/browser_bug592641.js create mode 100644 dom/html/test/browser_containerLoadingContent.js create mode 100644 dom/html/test/browser_form_post_from_file_to_http.js create mode 100644 dom/html/test/browser_refresh_after_document_write.js create mode 100644 dom/html/test/browser_submission_flush.js create mode 100644 dom/html/test/browser_targetBlankNoOpener.js create mode 100644 dom/html/test/bug100533_iframe.html create mode 100644 dom/html/test/bug100533_load.html create mode 100644 dom/html/test/bug1260704_iframe.html create mode 100644 dom/html/test/bug1260704_iframe_empty.html create mode 100644 dom/html/test/bug1292522_iframe.html create mode 100644 dom/html/test/bug1292522_page.html create mode 100644 dom/html/test/bug1315146-iframe.html create mode 100644 dom/html/test/bug1315146-main.html create mode 100644 dom/html/test/bug196523-subframe.html create mode 100644 dom/html/test/bug199692-nested-d2.html create mode 100644 dom/html/test/bug199692-nested.html create mode 100644 dom/html/test/bug199692-popup.html create mode 100644 dom/html/test/bug199692-scrolled.html create mode 100644 dom/html/test/bug242709_iframe.html create mode 100644 dom/html/test/bug242709_load.html create mode 100644 dom/html/test/bug277724_iframe1.html create mode 100644 dom/html/test/bug277724_iframe2.xhtml create mode 100644 dom/html/test/bug277890_iframe.html create mode 100644 dom/html/test/bug277890_load.html create mode 100644 dom/html/test/bug340800_iframe.txt create mode 100644 dom/html/test/bug369370-popup.png create mode 100644 dom/html/test/bug372098-link-target.html create mode 100644 dom/html/test/bug436200.html create mode 100644 dom/html/test/bug441930_iframe.html create mode 100644 dom/html/test/bug445004-inner.html create mode 100644 dom/html/test/bug445004-inner.js create mode 100644 dom/html/test/bug445004-outer-abs.html create mode 100644 dom/html/test/bug445004-outer-rel.html create mode 100644 dom/html/test/bug445004-outer-write.html create mode 100644 dom/html/test/bug446483-iframe.html create mode 100644 dom/html/test/bug448564-echo.sjs create mode 100644 dom/html/test/bug448564-iframe-1.html create mode 100644 dom/html/test/bug448564-iframe-2.html create mode 100644 dom/html/test/bug448564-iframe-3.html create mode 100644 dom/html/test/bug448564-submit.js create mode 100644 dom/html/test/bug499092.html create mode 100644 dom/html/test/bug499092.xml create mode 100644 dom/html/test/bug514856_iframe.html create mode 100644 dom/html/test/bug592641_img.jpg create mode 100644 dom/html/test/bug649134/file_bug649134-1.sjs create mode 100644 dom/html/test/bug649134/file_bug649134-2.sjs create mode 100644 dom/html/test/bug649134/index.html create mode 100644 dom/html/test/chrome.ini create mode 100644 dom/html/test/dialog/mochitest.ini create mode 100644 dom/html/test/dialog/test_bug1648877_dialog_fullscreen_denied.html create mode 100644 dom/html/test/dummy_page.html create mode 100644 dom/html/test/empty.html create mode 100644 dom/html/test/file.webm create mode 100644 dom/html/test/file_anchor_ping.html create mode 100644 dom/html/test/file_broadcast_load.html create mode 100644 dom/html/test/file_bug1108547-1.html create mode 100644 dom/html/test/file_bug1108547-2.html create mode 100644 dom/html/test/file_bug1108547-3.html create mode 100644 dom/html/test/file_bug1166138_1x.png create mode 100644 dom/html/test/file_bug1166138_2x.png create mode 100644 dom/html/test/file_bug1166138_def.png create mode 100644 dom/html/test/file_bug1260704.png create mode 100644 dom/html/test/file_bug209275_1.html create mode 100644 dom/html/test/file_bug209275_2.html create mode 100644 dom/html/test/file_bug209275_3.html create mode 100644 dom/html/test/file_bug297761.html create mode 100644 dom/html/test/file_bug417760.png create mode 100644 dom/html/test/file_bug871161-1.html create mode 100644 dom/html/test/file_bug871161-2.html create mode 100644 dom/html/test/file_bug893537.html create mode 100644 dom/html/test/file_cookiemanager.js create mode 100644 dom/html/test/file_formSubmission_img.jpg create mode 100644 dom/html/test/file_formSubmission_text.txt create mode 100644 dom/html/test/file_iframe_sandbox_a_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if10.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if11.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if12.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if13.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if14.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if15.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if16.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if17.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if18.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if19.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if2.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if3.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if4.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if5.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if6.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if7.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if8.html create mode 100644 dom/html/test/file_iframe_sandbox_a_if9.html create mode 100644 dom/html/test/file_iframe_sandbox_b_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_b_if2.html create mode 100644 dom/html/test/file_iframe_sandbox_b_if3.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if2.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if3.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if4.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if5.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if6.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if7.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if8.html create mode 100644 dom/html/test/file_iframe_sandbox_c_if9.html create mode 100644 dom/html/test/file_iframe_sandbox_close.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if10.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if11.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if12.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if13.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if14.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if15.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if16.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if17.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if18.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if19.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if2.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if20.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if21.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if22.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if23.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if3.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if4.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if5.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if6.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if7.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if8.html create mode 100644 dom/html/test/file_iframe_sandbox_d_if9.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if10.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if11.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if12.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if13.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if14.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if15.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if16.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if2.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if3.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if4.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if5.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if6.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if7.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if8.html create mode 100644 dom/html/test/file_iframe_sandbox_e_if9.html create mode 100644 dom/html/test/file_iframe_sandbox_fail.js create mode 100644 dom/html/test/file_iframe_sandbox_form_fail.html create mode 100644 dom/html/test/file_iframe_sandbox_form_pass.html create mode 100644 dom/html/test/file_iframe_sandbox_g_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_h_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if1.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if2.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if3.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if4.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if5.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if6.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if7.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if8.html create mode 100644 dom/html/test/file_iframe_sandbox_k_if9.html create mode 100644 dom/html/test/file_iframe_sandbox_navigation_fail.html create mode 100644 dom/html/test/file_iframe_sandbox_navigation_pass.html create mode 100644 dom/html/test/file_iframe_sandbox_navigation_start.html create mode 100644 dom/html/test/file_iframe_sandbox_open_window_fail.html create mode 100644 dom/html/test/file_iframe_sandbox_open_window_pass.html create mode 100644 dom/html/test/file_iframe_sandbox_pass.js create mode 100644 dom/html/test/file_iframe_sandbox_redirect.html create mode 100644 dom/html/test/file_iframe_sandbox_redirect.html^headers^ create mode 100644 dom/html/test/file_iframe_sandbox_redirect_target.html create mode 100644 dom/html/test/file_iframe_sandbox_refresh.html create mode 100644 dom/html/test/file_iframe_sandbox_refresh.html^headers^ create mode 100644 dom/html/test/file_iframe_sandbox_srcdoc_allow_scripts.html create mode 100644 dom/html/test/file_iframe_sandbox_srcdoc_no_allow_scripts.html create mode 100644 dom/html/test/file_iframe_sandbox_top_navigation_fail.html create mode 100644 dom/html/test/file_iframe_sandbox_top_navigation_pass.html create mode 100644 dom/html/test/file_iframe_sandbox_window_form_fail.html create mode 100644 dom/html/test/file_iframe_sandbox_window_form_pass.html create mode 100644 dom/html/test/file_iframe_sandbox_window_navigation_fail.html create mode 100644 dom/html/test/file_iframe_sandbox_window_navigation_pass.html create mode 100644 dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html create mode 100644 dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html create mode 100644 dom/html/test/file_iframe_sandbox_worker.js create mode 100644 dom/html/test/file_refresh_after_document_write.html create mode 100644 dom/html/test/file_script_module.html create mode 100644 dom/html/test/file_script_nomodule.html create mode 100644 dom/html/test/file_srcdoc-2.html create mode 100644 dom/html/test/file_srcdoc.html create mode 100644 dom/html/test/file_srcdoc_iframe3.html create mode 100644 dom/html/test/file_window_close_and_open.html create mode 100644 dom/html/test/file_window_open_close_inner.html create mode 100644 dom/html/test/file_window_open_close_outer.html create mode 100644 dom/html/test/formData_test.js create mode 100644 dom/html/test/formData_worker.js create mode 100644 dom/html/test/formSubmission_chrome.js create mode 100644 dom/html/test/form_data_file.bin create mode 100644 dom/html/test/form_data_file.txt create mode 100644 dom/html/test/form_submit_server.sjs create mode 100644 dom/html/test/forms/FAIL.html create mode 100644 dom/html/test/forms/PASS.html create mode 100644 dom/html/test/forms/chrome.ini create mode 100644 dom/html/test/forms/file_double_submit.html create mode 100644 dom/html/test/forms/file_login_fields.html create mode 100644 dom/html/test/forms/mochitest.ini create mode 100644 dom/html/test/forms/save_restore_radio_groups.sjs create mode 100644 dom/html/test/forms/submit_invalid_file.sjs create mode 100644 dom/html/test/forms/test_MozEditableElement_setUserInput.html create mode 100644 dom/html/test/forms/test_autocomplete.html create mode 100644 dom/html/test/forms/test_autocompleteinfo.html create mode 100644 dom/html/test/forms/test_bug1039548.html create mode 100644 dom/html/test/forms/test_bug1283915.html create mode 100644 dom/html/test/forms/test_bug1286509.html create mode 100644 dom/html/test/forms/test_button_attributes_reflection.html create mode 100644 dom/html/test/forms/test_change_event.html create mode 100644 dom/html/test/forms/test_datalist_element.html create mode 100644 dom/html/test/forms/test_double_submit.html create mode 100644 dom/html/test/forms/test_form_attribute-1.html create mode 100644 dom/html/test/forms/test_form_attribute-2.html create mode 100644 dom/html/test/forms/test_form_attribute-3.html create mode 100644 dom/html/test/forms/test_form_attribute-4.html create mode 100644 dom/html/test/forms/test_form_attributes_reflection.html create mode 100644 dom/html/test/forms/test_form_named_getter_dynamic.html create mode 100644 dom/html/test/forms/test_formaction_attribute.html create mode 100644 dom/html/test/forms/test_formnovalidate_attribute.html create mode 100644 dom/html/test/forms/test_input_attributes_reflection.html create mode 100644 dom/html/test/forms/test_input_color_input_change_events.html create mode 100644 dom/html/test/forms/test_input_color_picker_datalist.html create mode 100644 dom/html/test/forms/test_input_color_picker_initial.html create mode 100644 dom/html/test/forms/test_input_color_picker_popup.html create mode 100644 dom/html/test/forms/test_input_color_picker_update.html create mode 100644 dom/html/test/forms/test_input_date_bad_input.html create mode 100644 dom/html/test/forms/test_input_date_key_events.html create mode 100644 dom/html/test/forms/test_input_datetime_calendar_button.html create mode 100644 dom/html/test/forms/test_input_datetime_disabled_focus.html create mode 100644 dom/html/test/forms/test_input_datetime_focus_blur.html create mode 100644 dom/html/test/forms/test_input_datetime_focus_blur_events.html create mode 100644 dom/html/test/forms/test_input_datetime_focus_state.html create mode 100644 dom/html/test/forms/test_input_datetime_hidden.html create mode 100644 dom/html/test/forms/test_input_datetime_input_change_events.html create mode 100644 dom/html/test/forms/test_input_datetime_readonly.html create mode 100644 dom/html/test/forms/test_input_datetime_reset_default_value_input_change_event.html create mode 100644 dom/html/test/forms/test_input_datetime_tabindex.html create mode 100644 dom/html/test/forms/test_input_defaultValue.html create mode 100644 dom/html/test/forms/test_input_email.html create mode 100644 dom/html/test/forms/test_input_event.html create mode 100644 dom/html/test/forms/test_input_file_picker.html create mode 100644 dom/html/test/forms/test_input_hasBeenTypePassword.html create mode 100644 dom/html/test/forms/test_input_hasBeenTypePassword_navigation.html create mode 100644 dom/html/test/forms/test_input_list_attribute.html create mode 100644 dom/html/test/forms/test_input_number_data.js create mode 100644 dom/html/test/forms/test_input_number_focus.html create mode 100644 dom/html/test/forms/test_input_number_key_events.html create mode 100644 dom/html/test/forms/test_input_number_l10n.html create mode 100644 dom/html/test/forms/test_input_number_mouse_events.html create mode 100644 dom/html/test/forms/test_input_number_placeholder_shown.html create mode 100644 dom/html/test/forms/test_input_number_rounding.html create mode 100644 dom/html/test/forms/test_input_number_validation.html create mode 100644 dom/html/test/forms/test_input_password_click_show_password_button.html create mode 100644 dom/html/test/forms/test_input_password_show_password_button.html create mode 100644 dom/html/test/forms/test_input_radio_indeterminate.html create mode 100644 dom/html/test/forms/test_input_radio_radiogroup.html create mode 100644 dom/html/test/forms/test_input_radio_required.html create mode 100644 dom/html/test/forms/test_input_range_attr_order.html create mode 100644 dom/html/test/forms/test_input_range_key_events.html create mode 100644 dom/html/test/forms/test_input_range_mouse_and_touch_events.html create mode 100644 dom/html/test/forms/test_input_range_rounding.html create mode 100644 dom/html/test/forms/test_input_sanitization.html create mode 100644 dom/html/test/forms/test_input_setting_value.html create mode 100644 dom/html/test/forms/test_input_textarea_set_value_no_scroll.html create mode 100644 dom/html/test/forms/test_input_time_key_events.html create mode 100644 dom/html/test/forms/test_input_time_sec_millisec_field.html create mode 100644 dom/html/test/forms/test_input_types_pref.html create mode 100644 dom/html/test/forms/test_input_typing_sanitization.html create mode 100644 dom/html/test/forms/test_input_untrusted_key_events.html create mode 100644 dom/html/test/forms/test_input_url.html create mode 100644 dom/html/test/forms/test_interactive_content_in_label.html create mode 100644 dom/html/test/forms/test_interactive_content_in_summary.html create mode 100644 dom/html/test/forms/test_label_control_attribute.html create mode 100644 dom/html/test/forms/test_label_input_controls.html create mode 100644 dom/html/test/forms/test_max_attribute.html create mode 100644 dom/html/test/forms/test_maxlength_attribute.html create mode 100644 dom/html/test/forms/test_meter_element.html create mode 100644 dom/html/test/forms/test_meter_pseudo-classes.html create mode 100644 dom/html/test/forms/test_min_attribute.html create mode 100644 dom/html/test/forms/test_minlength_attribute.html create mode 100644 dom/html/test/forms/test_mozistextfield.html create mode 100644 dom/html/test/forms/test_novalidate_attribute.html create mode 100644 dom/html/test/forms/test_option_disabled.html create mode 100644 dom/html/test/forms/test_option_index_attribute.html create mode 100644 dom/html/test/forms/test_option_text.html create mode 100644 dom/html/test/forms/test_output_element.html create mode 100644 dom/html/test/forms/test_pattern_attribute.html create mode 100644 dom/html/test/forms/test_preserving_metadata_between_reloads.html create mode 100644 dom/html/test/forms/test_progress_element.html create mode 100644 dom/html/test/forms/test_radio_in_label.html create mode 100644 dom/html/test/forms/test_radio_radionodelist.html create mode 100644 dom/html/test/forms/test_reportValidation_preventDefault.html create mode 100644 dom/html/test/forms/test_required_attribute.html create mode 100644 dom/html/test/forms/test_restore_form_elements.html create mode 100644 dom/html/test/forms/test_save_restore_radio_groups.html create mode 100644 dom/html/test/forms/test_select_change_event.html create mode 100644 dom/html/test/forms/test_select_input_change_event.html create mode 100644 dom/html/test/forms/test_select_selectedOptions.html create mode 100644 dom/html/test/forms/test_select_validation.html create mode 100644 dom/html/test/forms/test_set_range_text.html create mode 100644 dom/html/test/forms/test_step_attribute.html create mode 100644 dom/html/test/forms/test_stepup_stepdown.html create mode 100644 dom/html/test/forms/test_submit_invalid_file.html create mode 100644 dom/html/test/forms/test_textarea_attributes_reflection.html create mode 100644 dom/html/test/forms/test_validation.html create mode 100644 dom/html/test/forms/test_validation_not_in_doc.html create mode 100644 dom/html/test/forms/test_valueasdate_attribute.html create mode 100644 dom/html/test/forms/test_valueasnumber_attribute.html create mode 100644 dom/html/test/forms/without_selectionchange/mochitest.ini create mode 100644 dom/html/test/forms/without_selectionchange/test_select.html create mode 100644 dom/html/test/head.js create mode 100644 dom/html/test/image-allow-credentials.png create mode 100644 dom/html/test/image-allow-credentials.png^headers^ create mode 100644 dom/html/test/image.png create mode 100644 dom/html/test/image_yellow.png create mode 100644 dom/html/test/mochitest.ini create mode 100644 dom/html/test/nnc_lockup.gif create mode 100644 dom/html/test/object_bug287465_o1.html create mode 100644 dom/html/test/object_bug287465_o2.html create mode 100644 dom/html/test/object_bug556645.html create mode 100644 dom/html/test/post_action_page.html create mode 100644 dom/html/test/reflect.js create mode 100644 dom/html/test/script_fakepath.js create mode 100644 dom/html/test/simpleFileOpener.js create mode 100644 dom/html/test/submission_flush.html create mode 100644 dom/html/test/sw_formSubmission.js create mode 100644 dom/html/test/test_a_text.html create mode 100644 dom/html/test/test_allowMedia.html create mode 100644 dom/html/test/test_anchor_href_cache_invalidation.html create mode 100644 dom/html/test/test_anchor_ping.html create mode 100644 dom/html/test/test_base_attributes_reflection.html create mode 100644 dom/html/test/test_bug1003539.html create mode 100644 dom/html/test/test_bug100533.html create mode 100644 dom/html/test/test_bug1013316.html create mode 100644 dom/html/test/test_bug1045270.html create mode 100644 dom/html/test/test_bug1089326.html create mode 100644 dom/html/test/test_bug109445.html create mode 100644 dom/html/test/test_bug109445.xhtml create mode 100644 dom/html/test/test_bug1146116.html create mode 100644 dom/html/test/test_bug1166138.html create mode 100644 dom/html/test/test_bug1203668.html create mode 100644 dom/html/test/test_bug1230665.html create mode 100644 dom/html/test/test_bug1250401.html create mode 100644 dom/html/test/test_bug1260664.html create mode 100644 dom/html/test/test_bug1260704.html create mode 100644 dom/html/test/test_bug1261673.html create mode 100644 dom/html/test/test_bug1261674-1.html create mode 100644 dom/html/test/test_bug1261674-2.html create mode 100644 dom/html/test/test_bug1264157.html create mode 100644 dom/html/test/test_bug1279218.html create mode 100644 dom/html/test/test_bug1287321.html create mode 100644 dom/html/test/test_bug1292522_same_domain_with_different_port_number.html create mode 100644 dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html create mode 100644 dom/html/test/test_bug1295719_event_sequence_for_number_keys.html create mode 100644 dom/html/test/test_bug1297.html create mode 100644 dom/html/test/test_bug1310865.html create mode 100644 dom/html/test/test_bug1315146.html create mode 100644 dom/html/test/test_bug1322678.html create mode 100644 dom/html/test/test_bug1323815.html create mode 100644 dom/html/test/test_bug1366.html create mode 100644 dom/html/test/test_bug1400.html create mode 100644 dom/html/test/test_bug1414077.html create mode 100644 dom/html/test/test_bug143220.html create mode 100644 dom/html/test/test_bug1472426.html create mode 100644 dom/html/test/test_bug1682.html create mode 100644 dom/html/test/test_bug1785739.html create mode 100644 dom/html/test/test_bug182279.html create mode 100644 dom/html/test/test_bug1823.html create mode 100644 dom/html/test/test_bug196523.html create mode 100644 dom/html/test/test_bug199692.html create mode 100644 dom/html/test/test_bug2082.html create mode 100644 dom/html/test/test_bug209275.xhtml create mode 100644 dom/html/test/test_bug237071.html create mode 100644 dom/html/test/test_bug242709.html create mode 100644 dom/html/test/test_bug24958.html create mode 100644 dom/html/test/test_bug255820.html create mode 100644 dom/html/test/test_bug259332.html create mode 100644 dom/html/test/test_bug274626.html create mode 100644 dom/html/test/test_bug277724.html create mode 100644 dom/html/test/test_bug277890.html create mode 100644 dom/html/test/test_bug287465.html create mode 100644 dom/html/test/test_bug295561.html create mode 100644 dom/html/test/test_bug297761.html create mode 100644 dom/html/test/test_bug300691-1.html create mode 100644 dom/html/test/test_bug300691-2.html create mode 100644 dom/html/test/test_bug300691-3.xhtml create mode 100644 dom/html/test/test_bug311681.html create mode 100644 dom/html/test/test_bug311681.xhtml create mode 100644 dom/html/test/test_bug324378.html create mode 100644 dom/html/test/test_bug330705-1.html create mode 100644 dom/html/test/test_bug332246.html create mode 100644 dom/html/test/test_bug332848.xhtml create mode 100644 dom/html/test/test_bug332893-1.html create mode 100644 dom/html/test/test_bug332893-2.html create mode 100644 dom/html/test/test_bug332893-3.html create mode 100644 dom/html/test/test_bug332893-4.html create mode 100644 dom/html/test/test_bug332893-5.html create mode 100644 dom/html/test/test_bug332893-6.html create mode 100644 dom/html/test/test_bug332893-7.html create mode 100644 dom/html/test/test_bug3348.html create mode 100644 dom/html/test/test_bug340017.xhtml create mode 100644 dom/html/test/test_bug340800.html create mode 100644 dom/html/test/test_bug347174.html create mode 100644 dom/html/test/test_bug347174_write.html create mode 100644 dom/html/test/test_bug347174_xsl.html create mode 100644 dom/html/test/test_bug347174_xslp.html create mode 100644 dom/html/test/test_bug353415-1.html create mode 100644 dom/html/test/test_bug353415-2.html create mode 100644 dom/html/test/test_bug359657.html create mode 100644 dom/html/test/test_bug369370.html create mode 100644 dom/html/test/test_bug371375.html create mode 100644 dom/html/test/test_bug372098.html create mode 100644 dom/html/test/test_bug373589.html create mode 100644 dom/html/test/test_bug375003-1.html create mode 100644 dom/html/test/test_bug375003-2.html create mode 100644 dom/html/test/test_bug377624.html create mode 100644 dom/html/test/test_bug380383.html create mode 100644 dom/html/test/test_bug383383.html create mode 100644 dom/html/test/test_bug383383_2.xhtml create mode 100644 dom/html/test/test_bug384419.html create mode 100644 dom/html/test/test_bug386496.html create mode 100644 dom/html/test/test_bug386728.html create mode 100644 dom/html/test/test_bug386996.html create mode 100644 dom/html/test/test_bug388558.html create mode 100644 dom/html/test/test_bug388746.html create mode 100644 dom/html/test/test_bug388794.html create mode 100644 dom/html/test/test_bug389797.html create mode 100644 dom/html/test/test_bug390975.html create mode 100644 dom/html/test/test_bug391994.html create mode 100644 dom/html/test/test_bug394700.html create mode 100644 dom/html/test/test_bug395107.html create mode 100644 dom/html/test/test_bug401160.xhtml create mode 100644 dom/html/test/test_bug402680.html create mode 100644 dom/html/test/test_bug403868.html create mode 100644 dom/html/test/test_bug403868.xhtml create mode 100644 dom/html/test/test_bug405242.html create mode 100644 dom/html/test/test_bug406596.html create mode 100644 dom/html/test/test_bug417760.html create mode 100644 dom/html/test/test_bug421640.html create mode 100644 dom/html/test/test_bug424698.html create mode 100644 dom/html/test/test_bug428135.xhtml create mode 100644 dom/html/test/test_bug430351.html create mode 100644 dom/html/test/test_bug435128.html create mode 100644 dom/html/test/test_bug441930.html create mode 100644 dom/html/test/test_bug442801.html create mode 100644 dom/html/test/test_bug445004.html create mode 100644 dom/html/test/test_bug446483.html create mode 100644 dom/html/test/test_bug448166.html create mode 100644 dom/html/test/test_bug448564.html create mode 100644 dom/html/test/test_bug456229.html create mode 100644 dom/html/test/test_bug458037.xhtml create mode 100644 dom/html/test/test_bug460568.html create mode 100644 dom/html/test/test_bug463104.html create mode 100644 dom/html/test/test_bug478251.html create mode 100644 dom/html/test/test_bug481335.xhtml create mode 100644 dom/html/test/test_bug481440.html create mode 100644 dom/html/test/test_bug481647.html create mode 100644 dom/html/test/test_bug482659.html create mode 100644 dom/html/test/test_bug486741.html create mode 100644 dom/html/test/test_bug489532.html create mode 100644 dom/html/test/test_bug497242.xhtml create mode 100644 dom/html/test/test_bug499092.html create mode 100644 dom/html/test/test_bug500885.html create mode 100644 dom/html/test/test_bug512367.html create mode 100644 dom/html/test/test_bug514856.html create mode 100644 dom/html/test/test_bug518122.html create mode 100644 dom/html/test/test_bug519987.html create mode 100644 dom/html/test/test_bug523771.html create mode 100644 dom/html/test/test_bug529819.html create mode 100644 dom/html/test/test_bug529859.html create mode 100644 dom/html/test/test_bug535043.html create mode 100644 dom/html/test/test_bug536891.html create mode 100644 dom/html/test/test_bug536895.html create mode 100644 dom/html/test/test_bug546995.html create mode 100644 dom/html/test/test_bug547850.html create mode 100644 dom/html/test/test_bug551846.html create mode 100644 dom/html/test/test_bug555567.html create mode 100644 dom/html/test/test_bug556645.html create mode 100644 dom/html/test/test_bug557087-1.html create mode 100644 dom/html/test/test_bug557087-2.html create mode 100644 dom/html/test/test_bug557087-3.html create mode 100644 dom/html/test/test_bug557087-4.html create mode 100644 dom/html/test/test_bug557087-5.html create mode 100644 dom/html/test/test_bug557087-6.html create mode 100644 dom/html/test/test_bug557620.html create mode 100644 dom/html/test/test_bug558788-1.html create mode 100644 dom/html/test/test_bug558788-2.html create mode 100644 dom/html/test/test_bug560112.html create mode 100644 dom/html/test/test_bug561634.html create mode 100644 dom/html/test/test_bug561636.html create mode 100644 dom/html/test/test_bug561640.html create mode 100644 dom/html/test/test_bug564001.html create mode 100644 dom/html/test/test_bug566046.html create mode 100644 dom/html/test/test_bug567938-1.html create mode 100644 dom/html/test/test_bug567938-2.html create mode 100644 dom/html/test/test_bug567938-3.html create mode 100644 dom/html/test/test_bug567938-4.html create mode 100644 dom/html/test/test_bug569955.html create mode 100644 dom/html/test/test_bug573969.html create mode 100644 dom/html/test/test_bug57600.html create mode 100644 dom/html/test/test_bug579079.html create mode 100644 dom/html/test/test_bug582412-1.html create mode 100644 dom/html/test/test_bug582412-2.html create mode 100644 dom/html/test/test_bug583514.html create mode 100644 dom/html/test/test_bug583533.html create mode 100644 dom/html/test/test_bug586763.html create mode 100644 dom/html/test/test_bug586786.html create mode 100644 dom/html/test/test_bug587469.html create mode 100644 dom/html/test/test_bug589.html create mode 100644 dom/html/test/test_bug590353-1.html create mode 100644 dom/html/test/test_bug590353-2.html create mode 100644 dom/html/test/test_bug590363.html create mode 100644 dom/html/test/test_bug592802.html create mode 100644 dom/html/test/test_bug593689.html create mode 100644 dom/html/test/test_bug595429.html create mode 100644 dom/html/test/test_bug595447.html create mode 100644 dom/html/test/test_bug595449.html create mode 100644 dom/html/test/test_bug596350.html create mode 100644 dom/html/test/test_bug596511.html create mode 100644 dom/html/test/test_bug598643.html create mode 100644 dom/html/test/test_bug598833-1.html create mode 100644 dom/html/test/test_bug600155.html create mode 100644 dom/html/test/test_bug601030.html create mode 100644 dom/html/test/test_bug605124-1.html create mode 100644 dom/html/test/test_bug605124-2.html create mode 100644 dom/html/test/test_bug605125-1.html create mode 100644 dom/html/test/test_bug605125-2.html create mode 100644 dom/html/test/test_bug606817.html create mode 100644 dom/html/test/test_bug607145.html create mode 100644 dom/html/test/test_bug610212.html create mode 100644 dom/html/test/test_bug610687.html create mode 100644 dom/html/test/test_bug611189.html create mode 100644 dom/html/test/test_bug612730.html create mode 100644 dom/html/test/test_bug613019.html create mode 100644 dom/html/test/test_bug613113.html create mode 100644 dom/html/test/test_bug613722.html create mode 100644 dom/html/test/test_bug613979.html create mode 100644 dom/html/test/test_bug615595.html create mode 100644 dom/html/test/test_bug615833.html create mode 100644 dom/html/test/test_bug618948.html create mode 100644 dom/html/test/test_bug619278.html create mode 100644 dom/html/test/test_bug622558.html create mode 100644 dom/html/test/test_bug622597.html create mode 100644 dom/html/test/test_bug623291.html create mode 100644 dom/html/test/test_bug6296.html create mode 100644 dom/html/test/test_bug629801.html create mode 100644 dom/html/test/test_bug633058.html create mode 100644 dom/html/test/test_bug636336.html create mode 100644 dom/html/test/test_bug641219.html create mode 100644 dom/html/test/test_bug643051.html create mode 100644 dom/html/test/test_bug646157.html create mode 100644 dom/html/test/test_bug649134.html create mode 100644 dom/html/test/test_bug651956.html create mode 100644 dom/html/test/test_bug658746.html create mode 100644 dom/html/test/test_bug659596.html create mode 100644 dom/html/test/test_bug659743.xml create mode 100644 dom/html/test/test_bug660663.html create mode 100644 dom/html/test/test_bug660959-1.html create mode 100644 dom/html/test/test_bug660959-2.html create mode 100644 dom/html/test/test_bug660959-3.html create mode 100644 dom/html/test/test_bug666200.html create mode 100644 dom/html/test/test_bug666666.html create mode 100644 dom/html/test/test_bug669012.html create mode 100644 dom/html/test/test_bug674558.html create mode 100644 dom/html/test/test_bug674927.html create mode 100644 dom/html/test/test_bug677495-1.html create mode 100644 dom/html/test/test_bug677495.html create mode 100644 dom/html/test/test_bug677658.html create mode 100644 dom/html/test/test_bug682886.html create mode 100644 dom/html/test/test_bug691.html create mode 100644 dom/html/test/test_bug694.html create mode 100644 dom/html/test/test_bug694503.html create mode 100644 dom/html/test/test_bug696.html create mode 100644 dom/html/test/test_bug717819.html create mode 100644 dom/html/test/test_bug741266.html create mode 100644 dom/html/test/test_bug742030.html create mode 100644 dom/html/test/test_bug742549.html create mode 100644 dom/html/test/test_bug745685.html create mode 100644 dom/html/test/test_bug763626.html create mode 100644 dom/html/test/test_bug765780.html create mode 100644 dom/html/test/test_bug780993.html create mode 100644 dom/html/test/test_bug787134.html create mode 100644 dom/html/test/test_bug797113.html create mode 100644 dom/html/test/test_bug803677.html create mode 100644 dom/html/test/test_bug821307.html create mode 100644 dom/html/test/test_bug827126.html create mode 100644 dom/html/test/test_bug838582.html create mode 100644 dom/html/test/test_bug839371.html create mode 100644 dom/html/test/test_bug839913.html create mode 100644 dom/html/test/test_bug841466.html create mode 100644 dom/html/test/test_bug845057.html create mode 100644 dom/html/test/test_bug869040.html create mode 100644 dom/html/test/test_bug870787.html create mode 100644 dom/html/test/test_bug871161.html create mode 100644 dom/html/test/test_bug874758.html create mode 100644 dom/html/test/test_bug879319.html create mode 100644 dom/html/test/test_bug885024.html create mode 100644 dom/html/test/test_bug893537.html create mode 100644 dom/html/test/test_bug95530.html create mode 100644 dom/html/test/test_bug969346.html create mode 100644 dom/html/test/test_bug982039.html create mode 100644 dom/html/test/test_change_crossorigin.html create mode 100644 dom/html/test/test_checked.html create mode 100644 dom/html/test/test_dir_attributes_reflection.html create mode 100644 dom/html/test/test_dl_attributes_reflection.html create mode 100644 dom/html/test/test_document-element-inserted.html create mode 100644 dom/html/test/test_documentAll.html create mode 100644 dom/html/test/test_element_prototype.html create mode 100644 dom/html/test/test_embed_attributes_reflection.html create mode 100644 dom/html/test/test_external_protocol_iframe.html create mode 100644 dom/html/test/test_fakepath.html create mode 100644 dom/html/test/test_filepicker_default_directory.html create mode 100644 dom/html/test/test_focusshift_button.html create mode 100644 dom/html/test/test_form-parsing.html create mode 100644 dom/html/test/test_formData.html create mode 100644 dom/html/test/test_formSubmission.html create mode 100644 dom/html/test/test_formSubmission2.html create mode 100644 dom/html/test/test_formelements.html create mode 100644 dom/html/test/test_fragment_form_pointer.html create mode 100644 dom/html/test/test_frame_count_with_synthetic_doc.html create mode 100644 dom/html/test/test_getElementsByName_after_mutation.html create mode 100644 dom/html/test/test_hidden.html create mode 100644 dom/html/test/test_html_attributes_reflection.html create mode 100644 dom/html/test/test_htmlcollection.html create mode 100644 dom/html/test/test_iframe_sandbox_general.html create mode 100644 dom/html/test/test_iframe_sandbox_inheritance.html create mode 100644 dom/html/test/test_iframe_sandbox_navigation.html create mode 100644 dom/html/test/test_iframe_sandbox_navigation2.html create mode 100644 dom/html/test/test_iframe_sandbox_popups.html create mode 100644 dom/html/test/test_iframe_sandbox_popups_inheritance.html create mode 100644 dom/html/test/test_iframe_sandbox_redirect.html create mode 100644 dom/html/test/test_iframe_sandbox_refresh.html create mode 100644 dom/html/test/test_iframe_sandbox_same_origin.html create mode 100644 dom/html/test/test_iframe_sandbox_workers.html create mode 100644 dom/html/test/test_imageSrcSet.html create mode 100644 dom/html/test/test_image_clone_load.html create mode 100644 dom/html/test/test_img_attributes_reflection.html create mode 100644 dom/html/test/test_input_file_cancel_event.html create mode 100644 dom/html/test/test_input_files_not_nsIFile.html create mode 100644 dom/html/test/test_input_lastInteractiveValue.html create mode 100644 dom/html/test/test_inputmode.html create mode 100644 dom/html/test/test_li_attributes_reflection.html create mode 100644 dom/html/test/test_link_attributes_reflection.html create mode 100644 dom/html/test/test_link_sizes.html create mode 100644 dom/html/test/test_map_attributes_reflection.html create mode 100644 dom/html/test/test_meta_attributes_reflection.html create mode 100644 dom/html/test/test_mod_attributes_reflection.html create mode 100644 dom/html/test/test_multipleFilePicker.html create mode 100644 dom/html/test/test_named_options.html create mode 100644 dom/html/test/test_nested_invalid_fieldsets.html create mode 100644 dom/html/test/test_nestediframe.html create mode 100644 dom/html/test/test_non-ascii-cookie.html create mode 100644 dom/html/test/test_non-ascii-cookie.html^headers^ create mode 100644 dom/html/test/test_object_attributes_reflection.html create mode 100644 dom/html/test/test_ol_attributes_reflection.html create mode 100644 dom/html/test/test_option_defaultSelected.html create mode 100644 dom/html/test/test_option_selected_state.html create mode 100644 dom/html/test/test_param_attributes_reflection.html create mode 100644 dom/html/test/test_plugin.tst create mode 100644 dom/html/test/test_q_attributes_reflection.html create mode 100644 dom/html/test/test_restore_from_parser_fragment.html create mode 100644 dom/html/test/test_rowscollection.html create mode 100644 dom/html/test/test_script_module.html create mode 100644 dom/html/test/test_set_input_files.html create mode 100644 dom/html/test/test_srcdoc-2.html create mode 100644 dom/html/test/test_srcdoc.html create mode 100644 dom/html/test/test_style_attributes_reflection.html create mode 100644 dom/html/test/test_track.html create mode 100644 dom/html/test/test_ul_attributes_reflection.html create mode 100644 dom/html/test/test_viewport_resize.html create mode 100644 dom/html/test/test_window_open_close.html create mode 100644 dom/html/test/test_window_open_from_closing.html (limited to 'dom/html') diff --git a/dom/html/ConstraintValidation.cpp b/dom/html/ConstraintValidation.cpp new file mode 100644 index 0000000000..096e401e82 --- /dev/null +++ b/dom/html/ConstraintValidation.cpp @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "ConstraintValidation.h" + +#include "mozilla/ErrorResult.h" +#include "nsAString.h" +#include "nsIContent.h" + +namespace mozilla::dom { + +void ConstraintValidation::GetValidationMessage(nsAString& aValidationMessage, + ErrorResult& aError) { + aValidationMessage.Truncate(); + + if (IsCandidateForConstraintValidation() && !IsValid()) { + if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) { + aValidationMessage.Assign(mCustomValidity); + if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) { + aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage); + } + } else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG); + } else if (GetValidityState(VALIDITY_STATE_TOO_SHORT)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_SHORT); + } else if (GetValidityState(VALIDITY_STATE_VALUE_MISSING)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_VALUE_MISSING); + } else if (GetValidityState(VALIDITY_STATE_TYPE_MISMATCH)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_TYPE_MISMATCH); + } else if (GetValidityState(VALIDITY_STATE_PATTERN_MISMATCH)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH); + } else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_OVERFLOW); + } else if (GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_UNDERFLOW); + } else if (GetValidityState(VALIDITY_STATE_STEP_MISMATCH)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_STEP_MISMATCH); + } else if (GetValidityState(VALIDITY_STATE_BAD_INPUT)) { + GetValidationMessage(aValidationMessage, VALIDITY_STATE_BAD_INPUT); + } else { + // There should not be other validity states. + aError.Throw(NS_ERROR_UNEXPECTED); + return; + } + } else { + aValidationMessage.Truncate(); + } +} + +bool ConstraintValidation::CheckValidity() { + nsCOMPtr content = do_QueryInterface(this); + MOZ_ASSERT(content, "This class should be inherited by HTML elements only!"); + return nsIConstraintValidation::CheckValidity(*content); +} + +ConstraintValidation::ConstraintValidation() : nsIConstraintValidation() {} + +void ConstraintValidation::SetCustomValidity(const nsAString& aError) { + mCustomValidity.Assign(aError); + SetValidityState(VALIDITY_STATE_CUSTOM_ERROR, !mCustomValidity.IsEmpty()); +} + +} // namespace mozilla::dom diff --git a/dom/html/ConstraintValidation.h b/dom/html/ConstraintValidation.h new file mode 100644 index 0000000000..5bd6c89dcb --- /dev/null +++ b/dom/html/ConstraintValidation.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_ConstraintValidition_h___ +#define mozilla_dom_ConstraintValidition_h___ + +#include "nsIConstraintValidation.h" +#include "nsString.h" + +namespace mozilla { +class ErrorResult; + +namespace dom { + +class ConstraintValidation : public nsIConstraintValidation { + public: + // Web IDL binding methods + void GetValidationMessage(nsAString& aValidationMessage, + mozilla::ErrorResult& aError); + bool CheckValidity(); + + protected: + // You can't instantiate an object from that class. + ConstraintValidation(); + + virtual ~ConstraintValidation() = default; + + void SetCustomValidity(const nsAString& aError); + + virtual nsresult GetValidationMessage(nsAString& aValidationMessage, + ValidityStateType aType) { + return NS_OK; + } + + private: + /** + * The string representing the custom error. + */ + nsString mCustomValidity; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_ConstraintValidition_h___ diff --git a/dom/html/ElementInternals.cpp b/dom/html/ElementInternals.cpp new file mode 100644 index 0000000000..62101f2922 --- /dev/null +++ b/dom/html/ElementInternals.cpp @@ -0,0 +1,460 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ + +#include "mozilla/dom/ElementInternals.h" + +#include "mozAutoDocUpdate.h" +#include "mozilla/dom/CustomElementRegistry.h" +#include "mozilla/dom/CustomEvent.h" +#include "mozilla/dom/ElementInternalsBinding.h" +#include "mozilla/dom/FormData.h" +#include "mozilla/dom/HTMLElement.h" +#include "mozilla/dom/HTMLFieldSetElement.h" +#include "mozilla/dom/MutationEventBinding.h" +#include "mozilla/dom/MutationObservers.h" +#include "mozilla/dom/ShadowRoot.h" +#include "mozilla/dom/ValidityState.h" +#include "nsContentUtils.h" +#include "nsDebug.h" +#include "nsGenericHTMLElement.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ElementInternals) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ElementInternals) + tmp->Unlink(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mTarget, mSubmissionValue, mState, mValidity, + mValidationAnchor); + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ElementInternals) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTarget, mSubmissionValue, mState, + mValidity, mValidationAnchor); +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(ElementInternals) +NS_IMPL_CYCLE_COLLECTING_RELEASE(ElementInternals) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ElementInternals) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsIFormControl) + NS_INTERFACE_MAP_ENTRY(nsIConstraintValidation) +NS_INTERFACE_MAP_END + +ElementInternals::ElementInternals(HTMLElement* aTarget) + : nsIFormControl(FormControlType::FormAssociatedCustomElement), + mTarget(aTarget), + mForm(nullptr), + mFieldSet(nullptr) {} + +nsISupports* ElementInternals::GetParentObject() { return ToSupports(mTarget); } + +JSObject* ElementInternals::WrapObject(JSContext* aCx, + JS::Handle aGivenProto) { + return ElementInternals_Binding::Wrap(aCx, this, aGivenProto); +} + +// https://html.spec.whatwg.org/#dom-elementinternals-shadowroot +ShadowRoot* ElementInternals::GetShadowRoot() const { + MOZ_ASSERT(mTarget); + + ShadowRoot* shadowRoot = mTarget->GetShadowRoot(); + if (shadowRoot && !shadowRoot->IsAvailableToElementInternals()) { + return nullptr; + } + + return shadowRoot; +} + +// https://html.spec.whatwg.org/commit-snapshots/912a3fe1f29649ccf8229de56f604b3c07ffd242/#dom-elementinternals-setformvalue +void ElementInternals::SetFormValue( + const Nullable& aValue, + const Optional>& aState, + ErrorResult& aRv) { + MOZ_ASSERT(mTarget); + + /** + * 1. Let element be this's target element. + * 2. If element is not a form-associated custom element, then throw a + * "NotSupportedError" DOMException. + */ + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return; + } + + /** + * 3. Set target element's submission value to value if value is not a + * FormData object, or to a clone of the entry list associated with value + * otherwise. + */ + mSubmissionValue.SetNull(); + if (!aValue.IsNull()) { + const FileOrUSVStringOrFormData& value = aValue.Value(); + OwningFileOrUSVStringOrFormData& owningValue = mSubmissionValue.SetValue(); + if (value.IsFormData()) { + owningValue.SetAsFormData() = value.GetAsFormData().Clone(); + } else if (value.IsFile()) { + owningValue.SetAsFile() = &value.GetAsFile(); + } else { + owningValue.SetAsUSVString() = value.GetAsUSVString(); + } + } + + /** + * 4. If the state argument of the function is omitted, set element's state to + * its submission value. + */ + if (!aState.WasPassed()) { + mState = mSubmissionValue; + return; + } + + /** + * 5. Otherwise, if state is a FormData object, set element's state to clone + * of the entry list associated with state. + * 6. Otherwise, set element's state to state. + */ + mState.SetNull(); + if (!aState.Value().IsNull()) { + const FileOrUSVStringOrFormData& state = aState.Value().Value(); + OwningFileOrUSVStringOrFormData& owningState = mState.SetValue(); + if (state.IsFormData()) { + owningState.SetAsFormData() = state.GetAsFormData().Clone(); + } else if (state.IsFile()) { + owningState.SetAsFile() = &state.GetAsFile(); + } else { + owningState.SetAsUSVString() = state.GetAsUSVString(); + } + } +} + +// https://html.spec.whatwg.org/#dom-elementinternals-form +HTMLFormElement* ElementInternals::GetForm(ErrorResult& aRv) const { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return nullptr; + } + return GetForm(); +} + +// https://html.spec.whatwg.org/commit-snapshots/3ad5159be8f27e110a70cefadcb50fc45ec21b05/#dom-elementinternals-setvalidity +void ElementInternals::SetValidity( + const ValidityStateFlags& aFlags, const Optional& aMessage, + const Optional>& aAnchor, ErrorResult& aRv) { + MOZ_ASSERT(mTarget); + + /** + * 1. Let element be this's target element. + * 2. If element is not a form-associated custom element, then throw a + * "NotSupportedError" DOMException. + */ + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return; + } + + /** + * 3. If flags contains one or more true values and message is not given or is + * the empty string, then throw a TypeError. + */ + if ((aFlags.mBadInput || aFlags.mCustomError || aFlags.mPatternMismatch || + aFlags.mRangeOverflow || aFlags.mRangeUnderflow || + aFlags.mStepMismatch || aFlags.mTooLong || aFlags.mTooShort || + aFlags.mTypeMismatch || aFlags.mValueMissing) && + (!aMessage.WasPassed() || aMessage.Value().IsEmpty())) { + aRv.ThrowTypeError("Need to provide validation message"); + return; + } + + /** + * 4. For each entry flag → value of flags, set element's validity flag with + * the name flag to value. + */ + SetValidityState(VALIDITY_STATE_VALUE_MISSING, aFlags.mValueMissing); + SetValidityState(VALIDITY_STATE_TYPE_MISMATCH, aFlags.mTypeMismatch); + SetValidityState(VALIDITY_STATE_PATTERN_MISMATCH, aFlags.mPatternMismatch); + SetValidityState(VALIDITY_STATE_TOO_LONG, aFlags.mTooLong); + SetValidityState(VALIDITY_STATE_TOO_SHORT, aFlags.mTooShort); + SetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW, aFlags.mRangeUnderflow); + SetValidityState(VALIDITY_STATE_RANGE_OVERFLOW, aFlags.mRangeOverflow); + SetValidityState(VALIDITY_STATE_STEP_MISMATCH, aFlags.mStepMismatch); + SetValidityState(VALIDITY_STATE_BAD_INPUT, aFlags.mBadInput); + SetValidityState(VALIDITY_STATE_CUSTOM_ERROR, aFlags.mCustomError); + mTarget->UpdateState(true); + + /** + * 5. Set element's validation message to the empty string if message is not + * given or all of element's validity flags are false, or to message + * otherwise. + * 6. If element's customError validity flag is true, then set element's + * custom validity error message to element's validation message. + * Otherwise, set element's custom validity error message to the empty + * string. + */ + mValidationMessage = + (!aMessage.WasPassed() || IsValid()) ? EmptyString() : aMessage.Value(); + + /** + * 7. Set element's validation anchor to null if anchor is not given. + * Otherwise, if anchor is not a shadow-including descendant of element, + * then throw a "NotFoundError" DOMException. Otherwise, set element's + * validation anchor to anchor. + */ + nsGenericHTMLElement* anchor = + aAnchor.WasPassed() ? &aAnchor.Value() : nullptr; + // TODO: maybe create something like IsShadowIncludingDescendantOf if there + // are other places also need such check. + if (anchor && (anchor == mTarget || + !anchor->IsShadowIncludingInclusiveDescendantOf(mTarget))) { + aRv.ThrowNotFoundError( + "Validation anchor is not a shadow-including descendant of target" + "element"); + return; + } + mValidationAnchor = anchor; +} + +// https://html.spec.whatwg.org/#dom-elementinternals-willvalidate +bool ElementInternals::GetWillValidate(ErrorResult& aRv) const { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return false; + } + return WillValidate(); +} + +// https://html.spec.whatwg.org/#dom-elementinternals-validity +ValidityState* ElementInternals::GetValidity(ErrorResult& aRv) { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return nullptr; + } + return Validity(); +} + +// https://html.spec.whatwg.org/#dom-elementinternals-validationmessage +void ElementInternals::GetValidationMessage(nsAString& aValidationMessage, + ErrorResult& aRv) const { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return; + } + aValidationMessage = mValidationMessage; +} + +// https://html.spec.whatwg.org/#dom-elementinternals-checkvalidity +bool ElementInternals::CheckValidity(ErrorResult& aRv) { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return false; + } + return nsIConstraintValidation::CheckValidity(*mTarget); +} + +// https://html.spec.whatwg.org/#dom-elementinternals-reportvalidity +bool ElementInternals::ReportValidity(ErrorResult& aRv) { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return false; + } + + bool defaultAction = true; + if (nsIConstraintValidation::CheckValidity(*mTarget, &defaultAction)) { + return true; + } + + if (!defaultAction) { + return false; + } + + AutoTArray, 1> invalidElements; + invalidElements.AppendElement(mTarget); + + AutoJSAPI jsapi; + if (!jsapi.Init(mTarget->GetOwnerGlobal())) { + return false; + } + JS::Rooted detail(jsapi.cx()); + if (!ToJSValue(jsapi.cx(), invalidElements, &detail)) { + return false; + } + + mTarget->UpdateState(true); + + RefPtr event = + NS_NewDOMCustomEvent(mTarget->OwnerDoc(), nullptr, nullptr); + event->InitCustomEvent(jsapi.cx(), u"MozInvalidForm"_ns, + /* CanBubble */ true, + /* Cancelable */ true, detail); + event->SetTrusted(true); + event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true; + mTarget->DispatchEvent(*event); + + return false; +} + +// https://html.spec.whatwg.org/#dom-elementinternals-labels +already_AddRefed ElementInternals::GetLabels( + ErrorResult& aRv) const { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return nullptr; + } + return mTarget->Labels(); +} + +nsGenericHTMLElement* ElementInternals::GetValidationAnchor( + ErrorResult& aRv) const { + MOZ_ASSERT(mTarget); + + if (!mTarget->IsFormAssociatedElement()) { + aRv.ThrowNotSupportedError( + "Target element is not a form-associated custom element"); + return nullptr; + } + return mValidationAnchor; +} + +void ElementInternals::SetForm(HTMLFormElement* aForm) { mForm = aForm; } + +void ElementInternals::ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) { + if (mTarget) { + mTarget->ClearForm(aRemoveFromForm, aUnbindOrDelete); + } +} + +NS_IMETHODIMP ElementInternals::Reset() { + if (mTarget) { + MOZ_ASSERT(mTarget->IsFormAssociatedElement()); + nsContentUtils::EnqueueLifecycleCallback(ElementCallbackType::eFormReset, + mTarget, {}); + } + return NS_OK; +} + +NS_IMETHODIMP ElementInternals::SubmitNamesValues(FormData* aFormData) { + if (!mTarget) { + return NS_ERROR_UNEXPECTED; + } + + MOZ_ASSERT(mTarget->IsFormAssociatedElement()); + + // https://html.spec.whatwg.org/#face-entry-construction + if (!mSubmissionValue.IsNull()) { + if (mSubmissionValue.Value().IsFormData()) { + aFormData->Append(mSubmissionValue.Value().GetAsFormData()); + return NS_OK; + } + + // Get the name + nsAutoString name; + if (!mTarget->GetAttr(nsGkAtoms::name, name) || name.IsEmpty()) { + return NS_OK; + } + + if (mSubmissionValue.Value().IsUSVString()) { + return aFormData->AddNameValuePair( + name, mSubmissionValue.Value().GetAsUSVString()); + } + + return aFormData->AddNameBlobPair(name, + mSubmissionValue.Value().GetAsFile()); + } + return NS_OK; +} + +void ElementInternals::UpdateFormOwner() { + if (mTarget) { + mTarget->UpdateFormOwner(); + } +} + +void ElementInternals::UpdateBarredFromConstraintValidation() { + if (mTarget) { + MOZ_ASSERT(mTarget->IsFormAssociatedElement()); + SetBarredFromConstraintValidation( + mTarget->HasAttr(nsGkAtoms::readonly) || + mTarget->HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) || + mTarget->IsDisabled()); + } +} + +void ElementInternals::Unlink() { + if (mForm) { + // Don't notify, since we're being destroyed in any case. + ClearForm(true, true); + MOZ_DIAGNOSTIC_ASSERT(!mForm); + } + if (mFieldSet) { + mFieldSet->RemoveElement(mTarget); + mFieldSet = nullptr; + } +} + +void ElementInternals::GetAttr(const nsAtom* aName, nsAString& aResult) const { + MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in"); + + const nsAttrValue* val = mAttrs.GetAttr(aName); + if (val) { + val->ToString(aResult); + return; + } + SetDOMStringToNull(aResult); +} + +nsresult ElementInternals::SetAttr(nsAtom* aName, const nsAString& aValue) { + Document* document = mTarget->GetComposedDoc(); + mozAutoDocUpdate updateBatch(document, true); + + uint8_t modType = mAttrs.HasAttr(kNameSpaceID_None, aName) + ? MutationEvent_Binding::MODIFICATION + : MutationEvent_Binding::ADDITION; + + MutationObservers::NotifyARIAAttributeDefaultWillChange(mTarget, aName, + modType); + + bool attrHadValue; + nsAttrValue attrValue(aValue); + nsresult rs = mAttrs.SetAndSwapAttr(aName, attrValue, &attrHadValue); + nsMutationGuard::DidMutate(); + + MutationObservers::NotifyARIAAttributeDefaultChanged(mTarget, aName, modType); + + mTarget->UpdateState(true); + + return rs; +} + +DocGroup* ElementInternals::GetDocGroup() { + return mTarget->OwnerDoc()->GetDocGroup(); +} + +} // namespace mozilla::dom diff --git a/dom/html/ElementInternals.h b/dom/html/ElementInternals.h new file mode 100644 index 0000000000..4f0008421c --- /dev/null +++ b/dom/html/ElementInternals.h @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ + +#ifndef mozilla_dom_ElementInternals_h +#define mozilla_dom_ElementInternals_h + +#include "js/TypeDecls.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/ElementInternalsBinding.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIConstraintValidation.h" +#include "nsIFormControl.h" +#include "nsWrapperCache.h" +#include "AttrArray.h" +#include "nsGkAtoms.h" + +#define ARIA_REFLECT_ATTR(method, attr) \ + void Get##method(nsAString& aValue) const { \ + GetAttr(nsGkAtoms::attr, aValue); \ + } \ + void Set##method(const nsAString& aValue, ErrorResult& aResult) { \ + aResult = ErrorResult(SetAttr(nsGkAtoms::attr, aValue)); \ + } + +class nsINodeList; +class nsGenericHTMLElement; + +namespace mozilla::dom { + +class DocGroup; +class HTMLElement; +class HTMLFieldSetElement; +class HTMLFormElement; +class ShadowRoot; +class ValidityState; + +class ElementInternals final : public nsIFormControl, + public nsIConstraintValidation, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS_AMBIGUOUS(ElementInternals, + nsIFormControl) + + explicit ElementInternals(HTMLElement* aTarget); + + nsISupports* GetParentObject(); + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + // WebIDL + ShadowRoot* GetShadowRoot() const; + void SetFormValue(const Nullable& aValue, + const Optional>& aState, + ErrorResult& aRv); + mozilla::dom::HTMLFormElement* GetForm(ErrorResult& aRv) const; + void SetValidity(const ValidityStateFlags& aFlags, + const Optional& aMessage, + const Optional>& aAnchor, + ErrorResult& aRv); + bool GetWillValidate(ErrorResult& aRv) const; + ValidityState* GetValidity(ErrorResult& aRv); + void GetValidationMessage(nsAString& aValidationMessage, + ErrorResult& aRv) const; + bool CheckValidity(ErrorResult& aRv); + bool ReportValidity(ErrorResult& aRv); + already_AddRefed GetLabels(ErrorResult& aRv) const; + nsGenericHTMLElement* GetValidationAnchor(ErrorResult& aRv) const; + + // nsIFormControl + mozilla::dom::HTMLFieldSetElement* GetFieldSet() override { + return mFieldSet; + } + mozilla::dom::HTMLFormElement* GetForm() const override { return mForm; } + void SetForm(mozilla::dom::HTMLFormElement* aForm) override; + void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override; + NS_IMETHOD Reset() override; + NS_IMETHOD SubmitNamesValues(mozilla::dom::FormData* aFormData) override; + bool AllowDrop() override { return true; } + + void SetFieldSet(mozilla::dom::HTMLFieldSetElement* aFieldSet) { + mFieldSet = aFieldSet; + } + + void UpdateFormOwner(); + void UpdateBarredFromConstraintValidation(); + + void Unlink(); + + // AccessibilityRole + ARIA_REFLECT_ATTR(Role, role) + + // AriaAttributes + ARIA_REFLECT_ATTR(AriaAtomic, aria_atomic) + ARIA_REFLECT_ATTR(AriaAutoComplete, aria_autocomplete) + ARIA_REFLECT_ATTR(AriaBusy, aria_busy) + ARIA_REFLECT_ATTR(AriaChecked, aria_checked) + ARIA_REFLECT_ATTR(AriaColCount, aria_colcount) + ARIA_REFLECT_ATTR(AriaColIndex, aria_colindex) + ARIA_REFLECT_ATTR(AriaColIndexText, aria_colindextext) + ARIA_REFLECT_ATTR(AriaColSpan, aria_colspan) + ARIA_REFLECT_ATTR(AriaCurrent, aria_current) + ARIA_REFLECT_ATTR(AriaDescription, aria_description) + ARIA_REFLECT_ATTR(AriaDisabled, aria_disabled) + ARIA_REFLECT_ATTR(AriaExpanded, aria_expanded) + ARIA_REFLECT_ATTR(AriaHasPopup, aria_haspopup) + ARIA_REFLECT_ATTR(AriaHidden, aria_hidden) + ARIA_REFLECT_ATTR(AriaInvalid, aria_invalid) + ARIA_REFLECT_ATTR(AriaKeyShortcuts, aria_keyshortcuts) + ARIA_REFLECT_ATTR(AriaLabel, aria_label) + ARIA_REFLECT_ATTR(AriaLevel, aria_level) + ARIA_REFLECT_ATTR(AriaLive, aria_live) + ARIA_REFLECT_ATTR(AriaModal, aria_modal) + ARIA_REFLECT_ATTR(AriaMultiLine, aria_multiline) + ARIA_REFLECT_ATTR(AriaMultiSelectable, aria_multiselectable) + ARIA_REFLECT_ATTR(AriaOrientation, aria_orientation) + ARIA_REFLECT_ATTR(AriaPlaceholder, aria_placeholder) + ARIA_REFLECT_ATTR(AriaPosInSet, aria_posinset) + ARIA_REFLECT_ATTR(AriaPressed, aria_pressed) + ARIA_REFLECT_ATTR(AriaReadOnly, aria_readonly) + ARIA_REFLECT_ATTR(AriaRelevant, aria_relevant) + ARIA_REFLECT_ATTR(AriaRequired, aria_required) + ARIA_REFLECT_ATTR(AriaRoleDescription, aria_roledescription) + ARIA_REFLECT_ATTR(AriaRowCount, aria_rowcount) + ARIA_REFLECT_ATTR(AriaRowIndex, aria_rowindex) + ARIA_REFLECT_ATTR(AriaRowIndexText, aria_rowindextext) + ARIA_REFLECT_ATTR(AriaRowSpan, aria_rowspan) + ARIA_REFLECT_ATTR(AriaSelected, aria_selected) + ARIA_REFLECT_ATTR(AriaSetSize, aria_setsize) + ARIA_REFLECT_ATTR(AriaSort, aria_sort) + ARIA_REFLECT_ATTR(AriaValueMax, aria_valuemax) + ARIA_REFLECT_ATTR(AriaValueMin, aria_valuemin) + ARIA_REFLECT_ATTR(AriaValueNow, aria_valuenow) + ARIA_REFLECT_ATTR(AriaValueText, aria_valuetext) + + void GetAttr(const nsAtom* aName, nsAString& aResult) const; + + nsresult SetAttr(nsAtom* aName, const nsAString& aValue); + + const AttrArray& GetAttrs() const { return mAttrs; } + + DocGroup* GetDocGroup(); + + private: + ~ElementInternals() = default; + + // It's a target element which is a custom element. + RefPtr mTarget; + + // The form that contains the target element. + // It's safe to use raw pointer because it will be reset via + // CustomElementData::Unlink when mTarget is released or unlinked. + HTMLFormElement* mForm; + + // This is a pointer to the target element's closest fieldset parent if any. + // It's safe to use raw pointer because it will be reset via + // CustomElementData::Unlink when mTarget is released or unlinked. + HTMLFieldSetElement* mFieldSet; + + // https://html.spec.whatwg.org/#face-submission-value + Nullable mSubmissionValue; + + // https://html.spec.whatwg.org/#face-state + // TODO: Bug 1734841 - Figure out how to support form restoration or + // autocomplete for form-associated custom element + Nullable mState; + + // https://html.spec.whatwg.org/#face-validation-message + nsString mValidationMessage; + + // https://html.spec.whatwg.org/#face-validation-anchor + RefPtr mValidationAnchor; + + AttrArray mAttrs; +}; + +} // namespace mozilla::dom + +#undef ARIA_REFLECT_ATTR + +#endif // mozilla_dom_ElementInternals_h diff --git a/dom/html/HTMLAllCollection.cpp b/dom/html/HTMLAllCollection.cpp new file mode 100644 index 0000000000..b26c96b3c2 --- /dev/null +++ b/dom/html/HTMLAllCollection.cpp @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/HTMLAllCollection.h" + +#include "jsfriendapi.h" +#include "mozilla/dom/HTMLAllCollectionBinding.h" +#include "mozilla/dom/Nullable.h" +#include "mozilla/dom/Element.h" +#include "nsContentList.h" +#include "nsGenericHTMLElement.h" + +namespace mozilla::dom { + +HTMLAllCollection::HTMLAllCollection(mozilla::dom::Document* aDocument) + : mDocument(aDocument) { + MOZ_ASSERT(mDocument); +} + +HTMLAllCollection::~HTMLAllCollection() = default; + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(HTMLAllCollection, mDocument, mCollection, + mNamedMap) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(HTMLAllCollection) +NS_IMPL_CYCLE_COLLECTING_RELEASE(HTMLAllCollection) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLAllCollection) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +nsINode* HTMLAllCollection::GetParentObject() const { return mDocument; } + +uint32_t HTMLAllCollection::Length() { return Collection()->Length(true); } + +Element* HTMLAllCollection::Item(uint32_t aIndex) { + nsIContent* item = Collection()->Item(aIndex); + return item ? item->AsElement() : nullptr; +} + +void HTMLAllCollection::Item(const Optional& aNameOrIndex, + Nullable& aResult) { + if (!aNameOrIndex.WasPassed()) { + aResult.SetNull(); + return; + } + + const nsAString& nameOrIndex = aNameOrIndex.Value(); + uint32_t indexVal; + if (js::StringIsArrayIndex(nameOrIndex.BeginReading(), nameOrIndex.Length(), + &indexVal)) { + Element* element = Item(indexVal); + if (element) { + aResult.SetValue().SetAsElement() = element; + } else { + aResult.SetNull(); + } + return; + } + + NamedItem(nameOrIndex, aResult); +} + +nsContentList* HTMLAllCollection::Collection() { + if (!mCollection) { + Document* document = mDocument; + mCollection = document->GetElementsByTagName(u"*"_ns); + MOZ_ASSERT(mCollection); + } + return mCollection; +} + +static bool IsAllNamedElement(nsIContent* aContent) { + return aContent->IsAnyOfHTMLElements( + nsGkAtoms::a, nsGkAtoms::button, nsGkAtoms::embed, nsGkAtoms::form, + nsGkAtoms::iframe, nsGkAtoms::img, nsGkAtoms::input, nsGkAtoms::map, + nsGkAtoms::meta, nsGkAtoms::object, nsGkAtoms::select, + nsGkAtoms::textarea, nsGkAtoms::frame, nsGkAtoms::frameset); +} + +static bool DocAllResultMatch(Element* aElement, int32_t aNamespaceID, + nsAtom* aAtom, void* aData) { + if (aElement->GetID() == aAtom) { + return true; + } + + nsGenericHTMLElement* elm = nsGenericHTMLElement::FromNode(aElement); + if (!elm) { + return false; + } + + if (!IsAllNamedElement(elm)) { + return false; + } + + const nsAttrValue* val = elm->GetParsedAttr(nsGkAtoms::name); + return val && val->Type() == nsAttrValue::eAtom && + val->GetAtomValue() == aAtom; +} + +nsContentList* HTMLAllCollection::GetDocumentAllList(const nsAString& aID) { + return mNamedMap + .LookupOrInsertWith(aID, + [this, &aID] { + RefPtr id = NS_Atomize(aID); + return new nsContentList(mDocument, + DocAllResultMatch, nullptr, + nullptr, true, id); + }) + .get(); +} + +void HTMLAllCollection::NamedGetter( + const nsAString& aID, bool& aFound, + Nullable& aResult) { + if (aID.IsEmpty()) { + aFound = false; + aResult.SetNull(); + return; + } + + nsContentList* docAllList = GetDocumentAllList(aID); + if (!docAllList) { + aFound = false; + aResult.SetNull(); + return; + } + + // Check if there are more than 1 entries. Do this by getting the second one + // rather than the length since getting the length always requires walking + // the entire document. + if (docAllList->Item(1, true)) { + aFound = true; + aResult.SetValue().SetAsHTMLCollection() = docAllList; + return; + } + + // There's only 0 or 1 items. Return the first one or null. + if (nsIContent* node = docAllList->Item(0, true)) { + aFound = true; + aResult.SetValue().SetAsElement() = node->AsElement(); + return; + } + + aFound = false; + aResult.SetNull(); +} + +void HTMLAllCollection::GetSupportedNames(nsTArray& aNames) { + // XXXbz this is very similar to nsContentList::GetSupportedNames, + // but has to check IsAllNamedElement for the name case. + AutoTArray atoms; + for (uint32_t i = 0; i < Length(); ++i) { + nsIContent* content = Item(i); + if (content->HasID()) { + nsAtom* id = content->GetID(); + MOZ_ASSERT(id != nsGkAtoms::_empty, "Empty ids don't get atomized"); + if (!atoms.Contains(id)) { + atoms.AppendElement(id); + } + } + + nsGenericHTMLElement* el = nsGenericHTMLElement::FromNode(content); + if (el) { + // Note: nsINode::HasName means the name is exposed on the document, + // which is false for options, so we don't check it here. + const nsAttrValue* val = el->GetParsedAttr(nsGkAtoms::name); + if (val && val->Type() == nsAttrValue::eAtom && + IsAllNamedElement(content)) { + nsAtom* name = val->GetAtomValue(); + MOZ_ASSERT(name != nsGkAtoms::_empty, "Empty names don't get atomized"); + if (!atoms.Contains(name)) { + atoms.AppendElement(name); + } + } + } + } + + uint32_t atomsLen = atoms.Length(); + nsString* names = aNames.AppendElements(atomsLen); + for (uint32_t i = 0; i < atomsLen; ++i) { + atoms[i]->ToString(names[i]); + } +} + +JSObject* HTMLAllCollection::WrapObject(JSContext* aCx, + JS::Handle aGivenProto) { + return HTMLAllCollection_Binding::Wrap(aCx, this, aGivenProto); +} + +} // namespace mozilla::dom diff --git a/dom/html/HTMLAllCollection.h b/dom/html/HTMLAllCollection.h new file mode 100644 index 0000000000..6179951175 --- /dev/null +++ b/dom/html/HTMLAllCollection.h @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_HTMLAllCollection_h +#define mozilla_dom_HTMLAllCollection_h + +#include "mozilla/dom/Document.h" +#include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" +#include "nsRefPtrHashtable.h" +#include "nsWrapperCache.h" + +#include + +class nsContentList; +class nsINode; + +namespace mozilla::dom { + +class Document; +class Element; +class OwningHTMLCollectionOrElement; +template +struct Nullable; +template +class Optional; + +class HTMLAllCollection final : public nsISupports, public nsWrapperCache { + ~HTMLAllCollection(); + + public: + explicit HTMLAllCollection(mozilla::dom::Document* aDocument); + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(HTMLAllCollection) + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + nsINode* GetParentObject() const; + + uint32_t Length(); + Element* IndexedGetter(uint32_t aIndex, bool& aFound) { + Element* result = Item(aIndex); + aFound = !!result; + return result; + } + + void NamedItem(const nsAString& aName, + Nullable& aResult) { + bool found = false; + NamedGetter(aName, found, aResult); + } + void NamedGetter(const nsAString& aName, bool& aFound, + Nullable& aResult); + void GetSupportedNames(nsTArray& aNames); + + void Item(const Optional& aNameOrIndex, + Nullable& aResult); + + void LegacyCall(JS::Handle, + const Optional& aNameOrIndex, + Nullable& aResult) { + Item(aNameOrIndex, aResult); + } + + private: + nsContentList* Collection(); + + /** + * Returns the HTMLCollection for document.all[aID], or null if there isn't + * one. + */ + nsContentList* GetDocumentAllList(const nsAString& aID); + + /** + * Helper for indexed getter and spec Item() method. + */ + Element* Item(uint32_t aIndex); + + RefPtr mDocument; + RefPtr mCollection; + nsRefPtrHashtable mNamedMap; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_HTMLAllCollection_h diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp new file mode 100644 index 0000000000..c2eb118ec2 --- /dev/null +++ b/dom/html/HTMLAnchorElement.cpp @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/HTMLAnchorElement.h" + +#include "mozilla/dom/BindContext.h" +#include "mozilla/dom/HTMLAnchorElementBinding.h" +#include "mozilla/dom/HTMLDNSPrefetch.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/MemoryReporting.h" +#include "nsCOMPtr.h" +#include "nsContentUtils.h" +#include "nsGkAtoms.h" +#include "nsAttrValueOrString.h" +#include "mozilla/dom/Document.h" +#include "nsPresContext.h" +#include "nsIURI.h" +#include "nsWindowSizes.h" + +NS_IMPL_NS_NEW_HTML_ELEMENT(Anchor) + +namespace mozilla::dom { + +HTMLAnchorElement::~HTMLAnchorElement() { + SupportsDNSPrefetch::Destroyed(*this); +} + +bool HTMLAnchorElement::IsInteractiveHTMLContent() const { + return HasAttr(kNameSpaceID_None, nsGkAtoms::href) || + nsGenericHTMLElement::IsInteractiveHTMLContent(); +} + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement, + nsGenericHTMLElement, Link) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement, nsGenericHTMLElement, + mRelList) + +NS_IMPL_ELEMENT_CLONE(HTMLAnchorElement) + +JSObject* HTMLAnchorElement::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + return HTMLAnchorElement_Binding::Wrap(aCx, this, aGivenProto); +} + +int32_t HTMLAnchorElement::TabIndexDefault() { return 0; } + +bool HTMLAnchorElement::Draggable() const { + // links can be dragged as long as there is an href and the + // draggable attribute isn't false + if (!HasAttr(kNameSpaceID_None, nsGkAtoms::href)) { + // no href, so just use the same behavior as other elements + return nsGenericHTMLElement::Draggable(); + } + + return !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable, + nsGkAtoms::_false, eIgnoreCase); +} + +nsresult HTMLAnchorElement::BindToTree(BindContext& aContext, + nsINode& aParent) { + Link::ResetLinkState(false, Link::ElementHasHref()); + + nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent); + NS_ENSURE_SUCCESS(rv, rv); + + // Prefetch links + if (IsInComposedDoc()) { + aContext.OwnerDoc().RegisterPendingLinkUpdate(this); + TryDNSPrefetch(*this); + } + + return rv; +} + +void HTMLAnchorElement::UnbindFromTree(bool aNullParent) { + // Cancel any DNS prefetches + // Note: Must come before ResetLinkState. If called after, it will recreate + // mCachedURI based on data that is invalid - due to a call to Link::GetURI() + // via GetURIForDNSPrefetch(). + CancelDNSPrefetch(*this); + + // Without removing the link state we risk a dangling pointer + // in the mStyledLinks hashtable + Link::ResetLinkState(false, Link::ElementHasHref()); + + nsGenericHTMLElement::UnbindFromTree(aNullParent); +} + +bool HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex) { + if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, + aTabIndex)) { + return true; + } + + // cannot focus links if there is no link handler + if (!OwnerDoc()->LinkHandlingEnabled()) { + *aIsFocusable = false; + return false; + } + + // Links that are in an editable region should never be focusable, even if + // they are in a contenteditable="false" region. + if (nsContentUtils::IsNodeInEditableRegion(this)) { + if (aTabIndex) { + *aTabIndex = -1; + } + + *aIsFocusable = false; + + return true; + } + + if (GetTabIndexAttrValue().isNothing()) { + // check whether we're actually a link + if (!IsLink()) { + // Not tabbable or focusable without href (bug 17605), unless + // forced to be via presence of nonnegative tabindex attribute + if (aTabIndex) { + *aTabIndex = -1; + } + + *aIsFocusable = false; + + return false; + } + } + + if (aTabIndex && (sTabFocusModel & eTabFocus_linksMask) == 0) { + *aTabIndex = -1; + } + + *aIsFocusable = true; + + return false; +} + +void HTMLAnchorElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { + GetEventTargetParentForAnchors(aVisitor); +} + +nsresult HTMLAnchorElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { + return PostHandleEventForAnchors(aVisitor); +} + +void HTMLAnchorElement::GetLinkTarget(nsAString& aTarget) { + GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget); + if (aTarget.IsEmpty()) { + GetBaseTarget(aTarget); + } +} + +void HTMLAnchorElement::GetTarget(nsAString& aValue) const { + if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) { + GetBaseTarget(aValue); + } +} + +nsDOMTokenList* HTMLAnchorElement::RelList() { + if (!mRelList) { + mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues); + } + return mRelList; +} + +void HTMLAnchorElement::GetText(nsAString& aText, + mozilla::ErrorResult& aRv) const { + if (NS_WARN_IF( + !nsContentUtils::GetNodeTextContent(this, true, aText, fallible))) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + } +} + +void HTMLAnchorElement::SetText(const nsAString& aText, ErrorResult& aRv) { + aRv = nsContentUtils::SetNodeTextContent(this, aText, false); +} + +already_AddRefed HTMLAnchorElement::GetHrefURI() const { + if (nsCOMPtr uri = GetCachedURI()) { + return uri.forget(); + } + return GetHrefURIForAnchors(); +} + +void HTMLAnchorElement::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, bool aNotify) { + if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::href) { + CancelDNSPrefetch(*this); + } + return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue, + aNotify); +} + +void HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::href) { + Link::ResetLinkState(aNotify, !!aValue); + if (aValue && IsInComposedDoc()) { + TryDNSPrefetch(*this); + } + } + } + + return nsGenericHTMLElement::AfterSetAttr( + aNamespaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); +} + +ElementState HTMLAnchorElement::IntrinsicState() const { + return Link::LinkState() | nsGenericHTMLElement::IntrinsicState(); +} + +void HTMLAnchorElement::AddSizeOfExcludingThis(nsWindowSizes& aSizes, + size_t* aNodeSize) const { + nsGenericHTMLElement::AddSizeOfExcludingThis(aSizes, aNodeSize); + *aNodeSize += Link::SizeOfExcludingThis(aSizes.mState); +} + +} // namespace mozilla::dom diff --git a/dom/html/HTMLAnchorElement.h b/dom/html/HTMLAnchorElement.h new file mode 100644 index 0000000000..ce202829c6 --- /dev/null +++ b/dom/html/HTMLAnchorElement.h @@ -0,0 +1,205 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_HTMLAnchorElement_h +#define mozilla_dom_HTMLAnchorElement_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/AnchorAreaFormRelValues.h" +#include "mozilla/dom/Link.h" +#include "mozilla/dom/HTMLDNSPrefetch.h" +#include "nsGenericHTMLElement.h" +#include "nsDOMTokenList.h" + +namespace mozilla { +class EventChainPostVisitor; +class EventChainPreVisitor; +namespace dom { + +class HTMLAnchorElement final : public nsGenericHTMLElement, + public Link, + public SupportsDNSPrefetch, + public AnchorAreaFormRelValues { + public: + using Element::GetText; + + explicit HTMLAnchorElement( + already_AddRefed&& aNodeInfo) + : nsGenericHTMLElement(std::move(aNodeInfo)), Link(this) {} + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // CC + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAnchorElement, + nsGenericHTMLElement) + + NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLAnchorElement, a); + + int32_t TabIndexDefault() override; + bool Draggable() const override; + + // Element + bool IsInteractiveHTMLContent() const override; + + // DOM memory reporter participant + NS_DECL_ADDSIZEOFEXCLUDINGTHIS + + nsresult BindToTree(BindContext&, nsINode& aParent) override; + void UnbindFromTree(bool aNullParent = true) override; + bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex) override; + + void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; + MOZ_CAN_RUN_SCRIPT + nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; + + void GetLinkTarget(nsAString& aTarget) override; + already_AddRefed GetHrefURI() const override; + + void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, bool aNotify) override; + void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, bool aNotify) override; + + nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; + + ElementState IntrinsicState() const override; + + // WebIDL API + + void GetHref(nsAString& aValue) const { + GetURIAttr(nsGkAtoms::href, nullptr, aValue); + } + void SetHref(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::href, aValue, rv); + } + void GetTarget(nsAString& aValue) const; + void SetTarget(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::target, aValue, rv); + } + void GetDownload(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::download, aValue); + } + void SetDownload(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::download, aValue, rv); + } + void GetPing(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::ping, aValue); + } + void SetPing(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::ping, aValue, rv); + } + void GetRel(DOMString& aValue) const { GetHTMLAttr(nsGkAtoms::rel, aValue); } + void SetRel(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::rel, aValue, rv); + } + void SetReferrerPolicy(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::referrerpolicy, aValue, rv); + } + void GetReferrerPolicy(DOMString& aPolicy) const { + GetEnumAttr(nsGkAtoms::referrerpolicy, "", aPolicy); + } + nsDOMTokenList* RelList(); + void GetHreflang(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::hreflang, aValue); + } + void SetHreflang(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::hreflang, aValue, rv); + } + // Needed for docshell + void GetType(nsAString& aValue) const { + GetHTMLAttr(nsGkAtoms::type, aValue); + } + void GetType(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::type, aValue); + } + void SetType(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::type, aValue, rv); + } + void GetText(nsAString& aText, mozilla::ErrorResult& aRv) const; + void SetText(const nsAString& aText, mozilla::ErrorResult& aRv); + + // Link::GetOrigin is OK for us + + // Link::GetProtocol is OK for us + // Link::SetProtocol is OK for us + + // Link::GetUsername is OK for us + // Link::SetUsername is OK for us + + // Link::GetPassword is OK for us + // Link::SetPassword is OK for us + + // Link::Link::GetHost is OK for us + // Link::Link::SetHost is OK for us + + // Link::Link::GetHostname is OK for us + // Link::Link::SetHostname is OK for us + + // Link::Link::GetPort is OK for us + // Link::Link::SetPort is OK for us + + // Link::Link::GetPathname is OK for us + // Link::Link::SetPathname is OK for us + + // Link::Link::GetSearch is OK for us + // Link::Link::SetSearch is OK for us + + // Link::Link::GetHash is OK for us + // Link::Link::SetHash is OK for us + + void GetCoords(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::coords, aValue); + } + void SetCoords(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::coords, aValue, rv); + } + void GetCharset(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::charset, aValue); + } + void SetCharset(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::charset, aValue, rv); + } + void GetName(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::name, aValue); + } + void GetName(nsAString& aValue) const { + GetHTMLAttr(nsGkAtoms::name, aValue); + } + void SetName(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::name, aValue, rv); + } + void GetRev(DOMString& aValue) const { GetHTMLAttr(nsGkAtoms::rev, aValue); } + void SetRev(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::rev, aValue, rv); + } + void GetShape(DOMString& aValue) const { + GetHTMLAttr(nsGkAtoms::shape, aValue); + } + void SetShape(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::shape, aValue, rv); + } + void Stringify(nsAString& aResult) const { GetHref(aResult); } + void ToString(nsAString& aSource) const { GetHref(aSource); } + + void NodeInfoChanged(Document* aOldDoc) final { + ClearHasPendingLinkUpdate(); + nsGenericHTMLElement::NodeInfoChanged(aOldDoc); + } + + protected: + virtual ~HTMLAnchorElement(); + + JSObject* WrapNode(JSContext*, JS::Handle aGivenProto) override; + RefPtr mRelList; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_HTMLAnchorElement_h diff --git a/dom/html/HTMLAreaElement.cpp b/dom/html/HTMLAreaElement.cpp new file mode 100644 index 0000000000..b3d83d4b41 --- /dev/null +++ b/dom/html/HTMLAreaElement.cpp @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/HTMLAreaElement.h" + +#include "mozilla/Attributes.h" +#include "mozilla/dom/BindContext.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/HTMLAnchorElement.h" +#include "mozilla/dom/HTMLAreaElementBinding.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/MemoryReporting.h" +#include "nsWindowSizes.h" + +NS_IMPL_NS_NEW_HTML_ELEMENT(Area) + +namespace mozilla::dom { + +HTMLAreaElement::HTMLAreaElement( + already_AddRefed&& aNodeInfo) + : nsGenericHTMLElement(std::move(aNodeInfo)), Link(this) {} + +HTMLAreaElement::~HTMLAreaElement() = default; + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLAreaElement, + nsGenericHTMLElement, Link) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLAreaElement, nsGenericHTMLElement, + mRelList) + +NS_IMPL_ELEMENT_CLONE(HTMLAreaElement) + +int32_t HTMLAreaElement::TabIndexDefault() { return 0; } + +void HTMLAreaElement::GetTarget(DOMString& aValue) { + if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) { + GetBaseTarget(aValue); + } +} + +void HTMLAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { + GetEventTargetParentForAnchors(aVisitor); +} + +nsresult HTMLAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { + return PostHandleEventForAnchors(aVisitor); +} + +void HTMLAreaElement::GetLinkTarget(nsAString& aTarget) { + GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget); + if (aTarget.IsEmpty()) { + GetBaseTarget(aTarget); + } +} + +nsDOMTokenList* HTMLAreaElement::RelList() { + if (!mRelList) { + mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues); + } + return mRelList; +} + +nsresult HTMLAreaElement::BindToTree(BindContext& aContext, nsINode& aParent) { + Link::ResetLinkState(false, Link::ElementHasHref()); + nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent); + NS_ENSURE_SUCCESS(rv, rv); + + if (IsInComposedDoc()) { + aContext.OwnerDoc().RegisterPendingLinkUpdate(this); + } + return rv; +} + +void HTMLAreaElement::UnbindFromTree(bool aNullParent) { + // Without removing the link state we risk a dangling pointer + // in the mStyledLinks hashtable + Link::ResetLinkState(false, Link::ElementHasHref()); + + nsGenericHTMLElement::UnbindFromTree(aNullParent); +} + +void HTMLAreaElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) { + if (aNamespaceID == kNameSpaceID_None) { + // This must happen after the attribute is set. We will need the updated + // attribute value because notifying the document that content states have + // changed will call IntrinsicState, which will try to get updated + // information about the visitedness from Link. + if (aName == nsGkAtoms::href) { + Link::ResetLinkState(aNotify, !!aValue); + } + } + + return nsGenericHTMLElement::AfterSetAttr( + aNamespaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); +} + +void HTMLAreaElement::ToString(nsAString& aSource) { GetHref(aSource); } + +already_AddRefed HTMLAreaElement::GetHrefURI() const { + if (nsCOMPtr uri = GetCachedURI()) { + return uri.forget(); + } + return GetHrefURIForAnchors(); +} + +ElementState HTMLAreaElement::IntrinsicState() const { + return Link::LinkState() | nsGenericHTMLElement::IntrinsicState(); +} + +void HTMLAreaElement::AddSizeOfExcludingThis(nsWindowSizes& aSizes, + size_t* aNodeSize) const { + nsGenericHTMLElement::AddSizeOfExcludingThis(aSizes, aNodeSize); + *aNodeSize += Link::SizeOfExcludingThis(aSizes.mState); +} + +JSObject* HTMLAreaElement::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + return HTMLAreaElement_Binding::Wrap(aCx, this, aGivenProto); +} + +} // namespace mozilla::dom diff --git a/dom/html/HTMLAreaElement.h b/dom/html/HTMLAreaElement.h new file mode 100644 index 0000000000..3b393ca137 --- /dev/null +++ b/dom/html/HTMLAreaElement.h @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_HTMLAreaElement_h +#define mozilla_dom_HTMLAreaElement_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/AnchorAreaFormRelValues.h" +#include "mozilla/dom/Link.h" +#include "nsGenericHTMLElement.h" +#include "nsGkAtoms.h" + +namespace mozilla { +class EventChainPostVisitor; +class EventChainPreVisitor; +namespace dom { + +class HTMLAreaElement final : public nsGenericHTMLElement, + public Link, + public AnchorAreaFormRelValues { + public: + explicit HTMLAreaElement( + already_AddRefed&& aNodeInfo); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // CC + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAreaElement, + nsGenericHTMLElement) + + NS_DECL_ADDSIZEOFEXCLUDINGTHIS + + NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLAreaElement, area) + + virtual int32_t TabIndexDefault() override; + + void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; + MOZ_CAN_RUN_SCRIPT + nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; + + void GetLinkTarget(nsAString& aTarget) override; + already_AddRefed GetHrefURI() const override; + + virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; + virtual void UnbindFromTree(bool aNullParent = true) override; + + virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; + + virtual ElementState IntrinsicState() const override; + + // WebIDL + void GetAlt(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::alt, aValue); } + void SetAlt(const nsAString& aAlt, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::alt, aAlt, aError); + } + + void GetCoords(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::coords, aValue); } + void SetCoords(const nsAString& aCoords, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::coords, aCoords, aError); + } + + // argument type nsAString for HTMLImageMapAccessible + void GetShape(nsAString& aValue) { GetHTMLAttr(nsGkAtoms::shape, aValue); } + void SetShape(const nsAString& aShape, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::shape, aShape, aError); + } + + // argument type nsAString for nsContextMenuInfo + void GetHref(nsAString& aValue) { + GetURIAttr(nsGkAtoms::href, nullptr, aValue); + } + void SetHref(const nsAString& aHref, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::href, aHref, aError); + } + + void GetTarget(DOMString& aValue); + void SetTarget(const nsAString& aTarget, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::target, aTarget, aError); + } + + void GetDownload(DOMString& aValue) { + GetHTMLAttr(nsGkAtoms::download, aValue); + } + void SetDownload(const nsAString& aDownload, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::download, aDownload, aError); + } + + void GetPing(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::ping, aValue); } + + void SetPing(const nsAString& aPing, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::ping, aPing, aError); + } + + void GetRel(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::rel, aValue); } + + void SetRel(const nsAString& aRel, ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::rel, aRel, aError); + } + nsDOMTokenList* RelList(); + + void SetReferrerPolicy(const nsAString& aValue, mozilla::ErrorResult& rv) { + SetHTMLAttr(nsGkAtoms::referrerpolicy, aValue, rv); + } + void GetReferrerPolicy(nsAString& aReferrer) { + GetEnumAttr(nsGkAtoms::referrerpolicy, "", aReferrer); + } + + // The Link::GetOrigin is OK for us + + // Link::Link::GetProtocol is OK for us + // Link::Link::SetProtocol is OK for us + + // The Link::GetUsername is OK for us + // The Link::SetUsername is OK for us + + // The Link::GetPassword is OK for us + // The Link::SetPassword is OK for us + + // Link::Link::GetHost is OK for us + // Link::Link::SetHost is OK for us + + // Link::Link::GetHostname is OK for us + // Link::Link::SetHostname is OK for us + + // Link::Link::GetPort is OK for us + // Link::Link::SetPort is OK for us + + // Link::Link::GetPathname is OK for us + // Link::Link::SetPathname is OK for us + + // Link::Link::GetSearch is OK for us + // Link::Link::SetSearch is OK for us + + // Link::Link::GetHash is OK for us + // Link::Link::SetHash is OK for us + + // The Link::GetSearchParams is OK for us + + bool NoHref() const { return GetBoolAttr(nsGkAtoms::nohref); } + + void SetNoHref(bool aValue, ErrorResult& aError) { + SetHTMLBoolAttr(nsGkAtoms::nohref, aValue, aError); + } + + void ToString(nsAString& aSource); + void Stringify(nsAString& aResult) { GetHref(aResult); } + + void NodeInfoChanged(Document* aOldDoc) final { + ClearHasPendingLinkUpdate(); + nsGenericHTMLElement::NodeInfoChanged(aOldDoc); + } + + protected: + virtual ~HTMLAreaElement(); + + virtual JSObject* WrapNode(JSContext* aCx, + JS::Handle aGivenProto) override; + + virtual void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) override; + + RefPtr mRelList; +}; + +} // namespace dom +} // namespace mozilla + +#endif /* mozilla_dom_HTMLAreaElement_h */ diff --git a/dom/html/HTMLAudioElement.cpp b/dom/html/HTMLAudioElement.cpp new file mode 100644 index 0000000000..bf92f00411 --- /dev/null +++ b/dom/html/HTMLAudioElement.cpp @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/HTMLAudioElement.h" +#include "mozilla/dom/HTMLAudioElementBinding.h" +#include "nsError.h" +#include "nsGenericHTMLElement.h" +#include "nsGkAtoms.h" +#include "mozilla/dom/Document.h" +#include "jsfriendapi.h" +#include "nsContentUtils.h" +#include "nsJSUtils.h" +#include "AudioSampleFormat.h" +#include +#include "nsComponentManagerUtils.h" +#include "nsIHttpChannel.h" +#include "mozilla/dom/TimeRanges.h" +#include "AudioStream.h" + +nsGenericHTMLElement* NS_NewHTMLAudioElement( + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser) { + RefPtr nodeInfo(aNodeInfo); + auto* nim = nodeInfo->NodeInfoManager(); + mozilla::dom::HTMLAudioElement* element = + new (nim) mozilla::dom::HTMLAudioElement(nodeInfo.forget()); + element->Init(); + return element; +} + +namespace mozilla::dom { + +nsresult HTMLAudioElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, + nsINode** aResult) const { + *aResult = nullptr; + RefPtr ni(aNodeInfo); + auto* nim = ni->NodeInfoManager(); + HTMLAudioElement* it = new (nim) HTMLAudioElement(ni.forget()); + it->Init(); + nsCOMPtr kungFuDeathGrip = it; + nsresult rv = const_cast(this)->CopyInnerTo(it); + if (NS_SUCCEEDED(rv)) { + kungFuDeathGrip.swap(*aResult); + } + return rv; +} + +HTMLAudioElement::HTMLAudioElement(already_AddRefed&& aNodeInfo) + : HTMLMediaElement(std::move(aNodeInfo)) { + DecoderDoctorLogger::LogConstruction(this); +} + +HTMLAudioElement::~HTMLAudioElement() { + DecoderDoctorLogger::LogDestruction(this); +} + +bool HTMLAudioElement::IsInteractiveHTMLContent() const { + return HasAttr(kNameSpaceID_None, nsGkAtoms::controls) || + HTMLMediaElement::IsInteractiveHTMLContent(); +} + +already_AddRefed HTMLAudioElement::Audio( + const GlobalObject& aGlobal, const Optional& aSrc, + ErrorResult& aRv) { + nsCOMPtr win = do_QueryInterface(aGlobal.GetAsSupports()); + Document* doc; + if (!win || !(doc = win->GetExtantDoc())) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr nodeInfo = doc->NodeInfoManager()->GetNodeInfo( + nsGkAtoms::audio, nullptr, kNameSpaceID_XHTML, ELEMENT_NODE); + + RefPtr audio = + static_cast(NS_NewHTMLAudioElement(nodeInfo.forget())); + audio->SetHTMLAttr(nsGkAtoms::preload, u"auto"_ns, aRv); + if (aRv.Failed()) { + return nullptr; + } + + if (aSrc.WasPassed()) { + audio->SetSrc(aSrc.Value(), aRv); + } + + return audio.forget(); +} + +nsresult HTMLAudioElement::SetAcceptHeader(nsIHttpChannel* aChannel) { + nsAutoCString value( + "audio/webm," + "audio/ogg," + "audio/wav," + "audio/*;q=0.9," + "application/ogg;q=0.7," + "video/*;q=0.6,*/*;q=0.5"); + + return aChannel->SetRequestHeader("Accept"_ns, value, false); +} + +JSObject* HTMLAudioElement::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + return HTMLAudioElement_Binding::Wrap(aCx, this, aGivenProto); +} + +} // namespace mozilla::dom diff --git a/dom/html/HTMLAudioElement.h b/dom/html/HTMLAudioElement.h new file mode 100644 index 0000000000..75f7105c6f --- /dev/null +++ b/dom/html/HTMLAudioElement.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ +#ifndef mozilla_dom_HTMLAudioElement_h +#define mozilla_dom_HTMLAudioElement_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/HTMLMediaElement.h" +#include "mozilla/dom/TypedArray.h" + +typedef uint16_t nsMediaNetworkState; +typedef uint16_t nsMediaReadyState; + +namespace mozilla::dom { + +class HTMLAudioElement final : public HTMLMediaElement { + public: + typedef mozilla::dom::NodeInfo NodeInfo; + + NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLAudioElement, audio) + + explicit HTMLAudioElement(already_AddRefed&& aNodeInfo); + + // Element + virtual bool IsInteractiveHTMLContent() const override; + + // nsIDOMHTMLMediaElement + using HTMLMediaElement::GetPaused; + + virtual nsresult Clone(NodeInfo*, nsINode** aResult) const override; + virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) override; + + // WebIDL + + static already_AddRefed Audio( + const GlobalObject& aGlobal, const Optional& aSrc, + ErrorResult& aRv); + + protected: + virtual ~HTMLAudioElement(); + + virtual JSObject* WrapNode(JSContext* aCx, + JS::Handle aGivenProto) override; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_HTMLAudioElement_h diff --git a/dom/html/HTMLBRElement.cpp b/dom/html/HTMLBRElement.cpp new file mode 100644 index 0000000000..dd930f81cb --- /dev/null +++ b/dom/html/HTMLBRElement.cpp @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/HTMLBRElement.h" +#include "mozilla/dom/HTMLBRElementBinding.h" +#include "mozilla/MappedDeclarations.h" +#include "nsAttrValueInlines.h" +#include "nsStyleConsts.h" +#include "nsMappedAttributes.h" + +NS_IMPL_NS_NEW_HTML_ELEMENT(BR) + +namespace mozilla::dom { + +HTMLBRElement::HTMLBRElement( + already_AddRefed&& aNodeInfo) + : nsGenericHTMLElement(std::move(aNodeInfo)) {} + +HTMLBRElement::~HTMLBRElement() = default; + +NS_IMPL_ELEMENT_CLONE(HTMLBRElement) + +static const nsAttrValue::EnumTable kClearTable[] = { + {"left", StyleClear::Left}, + {"right", StyleClear::Right}, + {"all", StyleClear::Both}, + {"both", StyleClear::Both}, + {nullptr, 0}}; + +bool HTMLBRElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) { + if (aAttribute == nsGkAtoms::clear && aNamespaceID == kNameSpaceID_None) { + return aResult.ParseEnumValue(aValue, kClearTable, false); + } + + return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, + aMaybeScriptedPrincipal, aResult); +} + +void HTMLBRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes, + MappedDeclarations& aDecls) { + if (!aDecls.PropertyIsSet(eCSSProperty_clear)) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::clear); + if (value && value->Type() == nsAttrValue::eEnum) + aDecls.SetKeywordValue(eCSSProperty_clear, value->GetEnumValue()); + } + nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls); +} + +NS_IMETHODIMP_(bool) +HTMLBRElement::IsAttributeMapped(const nsAtom* aAttribute) const { + static const MappedAttributeEntry attributes[] = {{nsGkAtoms::clear}, + {nullptr}}; + + static const MappedAttributeEntry* const map[] = { + attributes, + sCommonAttributeMap, + }; + + return FindAttributeDependence(aAttribute, map); +} + +nsMapRuleToAttributesFunc HTMLBRElement::GetAttributeMappingFunction() const { + return &MapAttributesIntoRule; +} + +JSObject* HTMLBRElement::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + return HTMLBRElement_Binding::Wrap(aCx, this, aGivenProto); +} + +} // namespace mozilla::dom diff --git a/dom/html/HTMLBRElement.h b/dom/html/HTMLBRElement.h new file mode 100644 index 0000000000..e8aa735157 --- /dev/null +++ b/dom/html/HTMLBRElement.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_HTMLBRElement_h +#define mozilla_dom_HTMLBRElement_h + +#include "mozilla/Attributes.h" +#include "nsGenericHTMLElement.h" +#include "nsGkAtoms.h" + +namespace mozilla::dom { + +#define BR_ELEMENT_FLAG_BIT(n_) \ + NODE_FLAG_BIT(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) + +// BR element specific bits +enum { + // NS_PADDING_FOR_EMPTY_EDITOR is set if the
element is created by + // editor for placing caret at proper position in empty editor. + NS_PADDING_FOR_EMPTY_EDITOR = BR_ELEMENT_FLAG_BIT(0), + + // NS_PADDING_FOR_EMPTY_LAST_LINE is set if the
element is created by + // editor for placing caret at proper position for making empty last line + // in a block or diff --git a/dom/html/crashtests/1350972.html b/dom/html/crashtests/1350972.html new file mode 100644 index 0000000000..7af7f9e174 --- /dev/null +++ b/dom/html/crashtests/1350972.html @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/dom/html/crashtests/1386905.html b/dom/html/crashtests/1386905.html new file mode 100644 index 0000000000..6ecc59e23b --- /dev/null +++ b/dom/html/crashtests/1386905.html @@ -0,0 +1,13 @@ + + + + + + diff --git a/dom/html/crashtests/1401726.html b/dom/html/crashtests/1401726.html new file mode 100644 index 0000000000..bf4b4918ab --- /dev/null +++ b/dom/html/crashtests/1401726.html @@ -0,0 +1,17 @@ + + + + + + diff --git a/dom/html/crashtests/1412173.html b/dom/html/crashtests/1412173.html new file mode 100644 index 0000000000..6989260cc7 --- /dev/null +++ b/dom/html/crashtests/1412173.html @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/dom/html/crashtests/1429783.html b/dom/html/crashtests/1429783.html new file mode 100644 index 0000000000..211f9e7ee2 --- /dev/null +++ b/dom/html/crashtests/1429783.html @@ -0,0 +1,19 @@ + + + + + + diff --git a/dom/html/crashtests/1440523.html b/dom/html/crashtests/1440523.html new file mode 100644 index 0000000000..11ce699781 --- /dev/null +++ b/dom/html/crashtests/1440523.html @@ -0,0 +1,13 @@ + + + + + diff --git a/dom/html/crashtests/1440827.html b/dom/html/crashtests/1440827.html new file mode 100644 index 0000000000..ee204212ff --- /dev/null +++ b/dom/html/crashtests/1440827.html @@ -0,0 +1,6 @@ + + + +> + + diff --git a/dom/html/crashtests/1547057.html b/dom/html/crashtests/1547057.html new file mode 100644 index 0000000000..89f48b5344 --- /dev/null +++ b/dom/html/crashtests/1547057.html @@ -0,0 +1,11 @@ + + + + + diff --git a/dom/html/crashtests/1550524.html b/dom/html/crashtests/1550524.html new file mode 100644 index 0000000000..1b41f527dc --- /dev/null +++ b/dom/html/crashtests/1550524.html @@ -0,0 +1,7 @@ + + diff --git a/dom/html/crashtests/1550881-1.html b/dom/html/crashtests/1550881-1.html new file mode 100644 index 0000000000..b9d73df957 --- /dev/null +++ b/dom/html/crashtests/1550881-1.html @@ -0,0 +1,13 @@ + + + diff --git a/dom/html/crashtests/1550881-2.html b/dom/html/crashtests/1550881-2.html new file mode 100644 index 0000000000..97bf5ef350 --- /dev/null +++ b/dom/html/crashtests/1550881-2.html @@ -0,0 +1,14 @@ + + + diff --git a/dom/html/crashtests/1667493.html b/dom/html/crashtests/1667493.html new file mode 100644 index 0000000000..d7cf6c6174 --- /dev/null +++ b/dom/html/crashtests/1667493.html @@ -0,0 +1,13 @@ + + + + + + diff --git a/dom/html/crashtests/1667493_1.html b/dom/html/crashtests/1667493_1.html new file mode 100644 index 0000000000..9b1a5fc047 --- /dev/null +++ b/dom/html/crashtests/1667493_1.html @@ -0,0 +1,7 @@ + + diff --git a/dom/html/crashtests/1680418.html b/dom/html/crashtests/1680418.html new file mode 100644 index 0000000000..ccebe0ed33 --- /dev/null +++ b/dom/html/crashtests/1680418.html @@ -0,0 +1,17 @@ + + + + + + + diff --git a/dom/html/crashtests/1704660.html b/dom/html/crashtests/1704660.html new file mode 100644 index 0000000000..01497975df --- /dev/null +++ b/dom/html/crashtests/1704660.html @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/dom/html/crashtests/1724816.html b/dom/html/crashtests/1724816.html new file mode 100644 index 0000000000..9264a5225f --- /dev/null +++ b/dom/html/crashtests/1724816.html @@ -0,0 +1,14 @@ + +
a
+ +a diff --git a/dom/html/crashtests/1785933-inner.html b/dom/html/crashtests/1785933-inner.html new file mode 100644 index 0000000000..8c97da8a8e --- /dev/null +++ b/dom/html/crashtests/1785933-inner.html @@ -0,0 +1,28 @@ + + + + + diff --git a/dom/html/crashtests/1785933.html b/dom/html/crashtests/1785933.html new file mode 100644 index 0000000000..e73395faea --- /dev/null +++ b/dom/html/crashtests/1785933.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/dom/html/crashtests/1787671.html b/dom/html/crashtests/1787671.html new file mode 100644 index 0000000000..5f891386af --- /dev/null +++ b/dom/html/crashtests/1787671.html @@ -0,0 +1,8 @@ + + + diff --git a/dom/html/crashtests/1789475.html b/dom/html/crashtests/1789475.html new file mode 100644 index 0000000000..f12924a742 --- /dev/null +++ b/dom/html/crashtests/1789475.html @@ -0,0 +1,10 @@ + + diff --git a/dom/html/crashtests/1801380.html b/dom/html/crashtests/1801380.html new file mode 100644 index 0000000000..f4ce3e109f --- /dev/null +++ b/dom/html/crashtests/1801380.html @@ -0,0 +1 @@ + diff --git a/dom/html/crashtests/257818-1.html b/dom/html/crashtests/257818-1.html new file mode 100644 index 0000000000..27929fd793 --- /dev/null +++ b/dom/html/crashtests/257818-1.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + diff --git a/dom/html/crashtests/285166-1.html b/dom/html/crashtests/285166-1.html new file mode 100644 index 0000000000..8a73d7d74e --- /dev/null +++ b/dom/html/crashtests/285166-1.html @@ -0,0 +1,3 @@ + diff --git a/dom/html/crashtests/294235-1.html b/dom/html/crashtests/294235-1.html new file mode 100644 index 0000000000..00eed38f4e --- /dev/null +++ b/dom/html/crashtests/294235-1.html @@ -0,0 +1,14 @@ + + + bug 294235 + + + +
+ + diff --git a/dom/html/crashtests/307616-1.html b/dom/html/crashtests/307616-1.html new file mode 100644 index 0000000000..8f28ddd6e8 --- /dev/null +++ b/dom/html/crashtests/307616-1.html @@ -0,0 +1,8 @@ + +Testcase for assertion + + + + + + \ No newline at end of file diff --git a/dom/html/crashtests/324918-1.xhtml b/dom/html/crashtests/324918-1.xhtml new file mode 100644 index 0000000000..921714cff3 --- /dev/null +++ b/dom/html/crashtests/324918-1.xhtml @@ -0,0 +1,26 @@ + + + + + + +
+ + + + + diff --git a/dom/html/crashtests/338649-1.xhtml b/dom/html/crashtests/338649-1.xhtml new file mode 100644 index 0000000000..b0bf3186fc --- /dev/null +++ b/dom/html/crashtests/338649-1.xhtml @@ -0,0 +1,22 @@ + + +ASSERTION: Options collection broken + + + + +
+ + + +
+ + + \ No newline at end of file diff --git a/dom/html/crashtests/339501-1.xhtml b/dom/html/crashtests/339501-1.xhtml new file mode 100644 index 0000000000..1a231ee645 --- /dev/null +++ b/dom/html/crashtests/339501-1.xhtml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/dom/html/crashtests/339501-2.xhtml b/dom/html/crashtests/339501-2.xhtml new file mode 100644 index 0000000000..6a1835fb71 --- /dev/null +++ b/dom/html/crashtests/339501-2.xhtml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/dom/html/crashtests/378993-1.xhtml b/dom/html/crashtests/378993-1.xhtml new file mode 100644 index 0000000000..99cbb01dae --- /dev/null +++ b/dom/html/crashtests/378993-1.xhtml @@ -0,0 +1,7 @@ + + + + + diff --git a/dom/html/crashtests/382568-1-inner.xhtml b/dom/html/crashtests/382568-1-inner.xhtml new file mode 100644 index 0000000000..67d7427582 --- /dev/null +++ b/dom/html/crashtests/382568-1-inner.xhtml @@ -0,0 +1,52 @@ + + + +Test + + + + +

TestCase for unsafe mutable events from textarea

+

Please wait for 3 seconds after document was loaded, +if your browser is vulnerable, it may stop responding +to keyboard and mouse event +and most likely it will eventually crash (may take a +while for debug builds).

+

+ +

+ diff --git a/dom/html/crashtests/382568-1.html b/dom/html/crashtests/382568-1.html new file mode 100644 index 0000000000..c10c71fd14 --- /dev/null +++ b/dom/html/crashtests/382568-1.html @@ -0,0 +1,9 @@ + + + + + + + diff --git a/dom/html/crashtests/383137.xhtml b/dom/html/crashtests/383137.xhtml new file mode 100644 index 0000000000..87d853c035 --- /dev/null +++ b/dom/html/crashtests/383137.xhtml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/dom/html/crashtests/388183-1.html b/dom/html/crashtests/388183-1.html new file mode 100644 index 0000000000..fcca410e93 --- /dev/null +++ b/dom/html/crashtests/388183-1.html @@ -0,0 +1,8 @@ + + + + + +
+ + diff --git a/dom/html/crashtests/395340-1.html b/dom/html/crashtests/395340-1.html new file mode 100644 index 0000000000..ddbccfe968 --- /dev/null +++ b/dom/html/crashtests/395340-1.html @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/dom/html/crashtests/399694-1.html b/dom/html/crashtests/399694-1.html new file mode 100644 index 0000000000..e6db2342b5 --- /dev/null +++ b/dom/html/crashtests/399694-1.html @@ -0,0 +1,20 @@ + + + + + + +
+ + + diff --git a/dom/html/crashtests/407053.html b/dom/html/crashtests/407053.html new file mode 100644 index 0000000000..b80a231722 --- /dev/null +++ b/dom/html/crashtests/407053.html @@ -0,0 +1,6 @@ + + + +
+ + diff --git a/dom/html/crashtests/423371-1.html b/dom/html/crashtests/423371-1.html new file mode 100644 index 0000000000..0069cf95db --- /dev/null +++ b/dom/html/crashtests/423371-1.html @@ -0,0 +1,9 @@ + + + +
hello
+ + + diff --git a/dom/html/crashtests/448564.html b/dom/html/crashtests/448564.html new file mode 100644 index 0000000000..f31830afa1 --- /dev/null +++ b/dom/html/crashtests/448564.html @@ -0,0 +1,7 @@ + +
a
+ + +
+ + diff --git a/dom/html/crashtests/451123-1.html b/dom/html/crashtests/451123-1.html new file mode 100644 index 0000000000..abf23c1e73 --- /dev/null +++ b/dom/html/crashtests/451123-1.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/html/crashtests/453406-1.html b/dom/html/crashtests/453406-1.html new file mode 100644 index 0000000000..bf75686553 --- /dev/null +++ b/dom/html/crashtests/453406-1.html @@ -0,0 +1,34 @@ + + + + + + + diff --git a/dom/html/crashtests/464197-1.html b/dom/html/crashtests/464197-1.html new file mode 100644 index 0000000000..785686023e --- /dev/null +++ b/dom/html/crashtests/464197-1.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/dom/html/crashtests/468562-1.html b/dom/html/crashtests/468562-1.html new file mode 100644 index 0000000000..81123fe2ea --- /dev/null +++ b/dom/html/crashtests/468562-1.html @@ -0,0 +1,6 @@ + + + +
+ + diff --git a/dom/html/crashtests/468562-2.html b/dom/html/crashtests/468562-2.html new file mode 100644 index 0000000000..e0db5cd974 --- /dev/null +++ b/dom/html/crashtests/468562-2.html @@ -0,0 +1,6 @@ + + + +
+ + diff --git a/dom/html/crashtests/494225.html b/dom/html/crashtests/494225.html new file mode 100644 index 0000000000..a78051d2a1 --- /dev/null +++ b/dom/html/crashtests/494225.html @@ -0,0 +1,10 @@ + + diff --git a/dom/html/crashtests/495543.svg b/dom/html/crashtests/495543.svg new file mode 100644 index 0000000000..b795796ad4 --- /dev/null +++ b/dom/html/crashtests/495543.svg @@ -0,0 +1,16 @@ + + + + diff --git a/dom/html/crashtests/495546-1.html b/dom/html/crashtests/495546-1.html new file mode 100644 index 0000000000..0547b98674 --- /dev/null +++ b/dom/html/crashtests/495546-1.html @@ -0,0 +1,19 @@ + + + + + + + diff --git a/dom/html/crashtests/504183-1.html b/dom/html/crashtests/504183-1.html new file mode 100644 index 0000000000..e44db41520 --- /dev/null +++ b/dom/html/crashtests/504183-1.html @@ -0,0 +1,12 @@ + + + + diff --git a/dom/html/crashtests/515829-1.html b/dom/html/crashtests/515829-1.html new file mode 100644 index 0000000000..e2fc655c01 --- /dev/null +++ b/dom/html/crashtests/515829-1.html @@ -0,0 +1,7 @@ + + + + +
+ + diff --git a/dom/html/crashtests/515829-2.html b/dom/html/crashtests/515829-2.html new file mode 100644 index 0000000000..6de6d5986c --- /dev/null +++ b/dom/html/crashtests/515829-2.html @@ -0,0 +1,7 @@ + + + + +
+ + diff --git a/dom/html/crashtests/570566-1.html b/dom/html/crashtests/570566-1.html new file mode 100644 index 0000000000..70ec003a68 --- /dev/null +++ b/dom/html/crashtests/570566-1.html @@ -0,0 +1,2 @@ + + diff --git a/dom/html/crashtests/571428-1.html b/dom/html/crashtests/571428-1.html new file mode 100644 index 0000000000..ae2b960cac --- /dev/null +++ b/dom/html/crashtests/571428-1.html @@ -0,0 +1,14 @@ + + + + + + + diff --git a/dom/html/crashtests/580507-1.xhtml b/dom/html/crashtests/580507-1.xhtml new file mode 100644 index 0000000000..eff3fb255d --- /dev/null +++ b/dom/html/crashtests/580507-1.xhtml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/dom/html/crashtests/590387.html b/dom/html/crashtests/590387.html new file mode 100644 index 0000000000..50cd05ac9e --- /dev/null +++ b/dom/html/crashtests/590387.html @@ -0,0 +1,8 @@ + + + + + + diff --git a/dom/html/crashtests/596785-1.html b/dom/html/crashtests/596785-1.html new file mode 100644 index 0000000000..5d830628b0 --- /dev/null +++ b/dom/html/crashtests/596785-1.html @@ -0,0 +1,9 @@ + + + +
+ +
+ + diff --git a/dom/html/crashtests/596785-2.html b/dom/html/crashtests/596785-2.html new file mode 100644 index 0000000000..18cfe2788d --- /dev/null +++ b/dom/html/crashtests/596785-2.html @@ -0,0 +1,9 @@ + + + +
+ +
+ + diff --git a/dom/html/crashtests/602117.html b/dom/html/crashtests/602117.html new file mode 100644 index 0000000000..0d1818b2a9 --- /dev/null +++ b/dom/html/crashtests/602117.html @@ -0,0 +1,8 @@ + + + + diff --git a/dom/html/crashtests/604807.html b/dom/html/crashtests/604807.html new file mode 100644 index 0000000000..bec4012e5c --- /dev/null +++ b/dom/html/crashtests/604807.html @@ -0,0 +1,9 @@ + + diff --git a/dom/html/crashtests/605264.html b/dom/html/crashtests/605264.html new file mode 100644 index 0000000000..782720a9d6 --- /dev/null +++ b/dom/html/crashtests/605264.html @@ -0,0 +1,8 @@ + + diff --git a/dom/html/crashtests/606430-1.html b/dom/html/crashtests/606430-1.html new file mode 100644 index 0000000000..c347e3c9f1 --- /dev/null +++ b/dom/html/crashtests/606430-1.html @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/dom/html/crashtests/613027.html b/dom/html/crashtests/613027.html new file mode 100644 index 0000000000..a866860f10 --- /dev/null +++ b/dom/html/crashtests/613027.html @@ -0,0 +1,21 @@ + + + + + + + diff --git a/dom/html/crashtests/614279.html b/dom/html/crashtests/614279.html new file mode 100644 index 0000000000..ff1c505167 --- /dev/null +++ b/dom/html/crashtests/614279.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/dom/html/crashtests/614988-1.html b/dom/html/crashtests/614988-1.html new file mode 100644 index 0000000000..931f83ac73 --- /dev/null +++ b/dom/html/crashtests/614988-1.html @@ -0,0 +1,5 @@ + + + +
+ diff --git a/dom/html/crashtests/616401.html b/dom/html/crashtests/616401.html new file mode 100644 index 0000000000..eb5a0bcf4c --- /dev/null +++ b/dom/html/crashtests/616401.html @@ -0,0 +1,8 @@ + + diff --git a/dom/html/crashtests/620078-1.html b/dom/html/crashtests/620078-1.html new file mode 100644 index 0000000000..39462706c1 --- /dev/null +++ b/dom/html/crashtests/620078-1.html @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/dom/html/crashtests/620078-2.html b/dom/html/crashtests/620078-2.html new file mode 100644 index 0000000000..1be23fa1f2 --- /dev/null +++ b/dom/html/crashtests/620078-2.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/dom/html/crashtests/631421.html b/dom/html/crashtests/631421.html new file mode 100644 index 0000000000..e4a7b9192b --- /dev/null +++ b/dom/html/crashtests/631421.html @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/dom/html/crashtests/631421.png b/dom/html/crashtests/631421.png new file mode 100644 index 0000000000..ef350c4678 Binary files /dev/null and b/dom/html/crashtests/631421.png differ diff --git a/dom/html/crashtests/673853.html b/dom/html/crashtests/673853.html new file mode 100644 index 0000000000..1325fa9ed6 --- /dev/null +++ b/dom/html/crashtests/673853.html @@ -0,0 +1,20 @@ + + + + + + + diff --git a/dom/html/crashtests/682058.xhtml b/dom/html/crashtests/682058.xhtml new file mode 100644 index 0000000000..95e7da98fc --- /dev/null +++ b/dom/html/crashtests/682058.xhtml @@ -0,0 +1,11 @@ + + + + + + diff --git a/dom/html/crashtests/682460.html b/dom/html/crashtests/682460.html new file mode 100644 index 0000000000..91306be71d --- /dev/null +++ b/dom/html/crashtests/682460.html @@ -0,0 +1,21 @@ + + + + + + +
+ + diff --git a/dom/html/crashtests/68912-1.html b/dom/html/crashtests/68912-1.html new file mode 100644 index 0000000000..bdd2ab4614 --- /dev/null +++ b/dom/html/crashtests/68912-1.html @@ -0,0 +1,24 @@ + + +Crash TR.cells = null + + + + +

+This test case creates a TR element then tries to assign to the cells property +

+

+Crash +

+ + + diff --git a/dom/html/crashtests/738744.xhtml b/dom/html/crashtests/738744.xhtml new file mode 100644 index 0000000000..7f91d0149b --- /dev/null +++ b/dom/html/crashtests/738744.xhtml @@ -0,0 +1,4 @@ + +
+ + diff --git a/dom/html/crashtests/741218.json b/dom/html/crashtests/741218.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/dom/html/crashtests/741218.json @@ -0,0 +1 @@ +{} diff --git a/dom/html/crashtests/741218.json^headers^ b/dom/html/crashtests/741218.json^headers^ new file mode 100644 index 0000000000..7b5e82d4b7 --- /dev/null +++ b/dom/html/crashtests/741218.json^headers^ @@ -0,0 +1 @@ +Content-Type: application/json diff --git a/dom/html/crashtests/741250.xhtml b/dom/html/crashtests/741250.xhtml new file mode 100644 index 0000000000..e18a9409fe --- /dev/null +++ b/dom/html/crashtests/741250.xhtml @@ -0,0 +1,9 @@ + +
+ + diff --git a/dom/html/crashtests/768344.html b/dom/html/crashtests/768344.html new file mode 100644 index 0000000000..4830e6674d --- /dev/null +++ b/dom/html/crashtests/768344.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/dom/html/crashtests/795221-1.html b/dom/html/crashtests/795221-1.html new file mode 100644 index 0000000000..70e400bed9 --- /dev/null +++ b/dom/html/crashtests/795221-1.html @@ -0,0 +1,7 @@ + + + diff --git a/dom/html/crashtests/795221-2.html b/dom/html/crashtests/795221-2.html new file mode 100644 index 0000000000..fc2aa7d506 --- /dev/null +++ b/dom/html/crashtests/795221-2.html @@ -0,0 +1,9 @@ + + + diff --git a/dom/html/crashtests/795221-3.html b/dom/html/crashtests/795221-3.html new file mode 100644 index 0000000000..93348af0bd --- /dev/null +++ b/dom/html/crashtests/795221-3.html @@ -0,0 +1,14 @@ + + + diff --git a/dom/html/crashtests/795221-4.html b/dom/html/crashtests/795221-4.html new file mode 100644 index 0000000000..476dd34672 --- /dev/null +++ b/dom/html/crashtests/795221-4.html @@ -0,0 +1,9 @@ + + + + + diff --git a/dom/html/crashtests/795221-5.xml b/dom/html/crashtests/795221-5.xml new file mode 100644 index 0000000000..286dcff0d4 --- /dev/null +++ b/dom/html/crashtests/795221-5.xml @@ -0,0 +1,6 @@ + + + + diff --git a/dom/html/crashtests/798802-1.html b/dom/html/crashtests/798802-1.html new file mode 100644 index 0000000000..92ab50fd87 --- /dev/null +++ b/dom/html/crashtests/798802-1.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/dom/html/crashtests/811226.html b/dom/html/crashtests/811226.html new file mode 100644 index 0000000000..990ef9af53 --- /dev/null +++ b/dom/html/crashtests/811226.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/dom/html/crashtests/819745.html b/dom/html/crashtests/819745.html new file mode 100644 index 0000000000..389e6b8c13 --- /dev/null +++ b/dom/html/crashtests/819745.html @@ -0,0 +1,5 @@ + + + diff --git a/dom/html/crashtests/828180.html b/dom/html/crashtests/828180.html new file mode 100644 index 0000000000..055c8a34ba --- /dev/null +++ b/dom/html/crashtests/828180.html @@ -0,0 +1,5 @@ + diff --git a/dom/html/crashtests/828472.html b/dom/html/crashtests/828472.html new file mode 100644 index 0000000000..59ce4d280b --- /dev/null +++ b/dom/html/crashtests/828472.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/dom/html/crashtests/837033.html b/dom/html/crashtests/837033.html new file mode 100644 index 0000000000..772d24014c --- /dev/null +++ b/dom/html/crashtests/837033.html @@ -0,0 +1,4 @@ + + + + diff --git a/dom/html/crashtests/838256-1.html b/dom/html/crashtests/838256-1.html new file mode 100644 index 0000000000..e1cdc588e8 --- /dev/null +++ b/dom/html/crashtests/838256-1.html @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/dom/html/crashtests/862084.html b/dom/html/crashtests/862084.html new file mode 100644 index 0000000000..d6d04f74de --- /dev/null +++ b/dom/html/crashtests/862084.html @@ -0,0 +1,9 @@ + + + diff --git a/dom/html/crashtests/865147.html b/dom/html/crashtests/865147.html new file mode 100644 index 0000000000..841cf8b6d8 --- /dev/null +++ b/dom/html/crashtests/865147.html @@ -0,0 +1,7 @@ + + + diff --git a/dom/html/crashtests/877910.html b/dom/html/crashtests/877910.html new file mode 100644 index 0000000000..d454c4478b --- /dev/null +++ b/dom/html/crashtests/877910.html @@ -0,0 +1 @@ + + + + + diff --git a/dom/html/crashtests/crashtests.list b/dom/html/crashtests/crashtests.list new file mode 100644 index 0000000000..915b00ac5a --- /dev/null +++ b/dom/html/crashtests/crashtests.list @@ -0,0 +1,98 @@ +load 68912-1.html +load 257818-1.html +load 285166-1.html +load 294235-1.html +load 307616-1.html +load 324918-1.xhtml +load 338649-1.xhtml +load 339501-1.xhtml +load 339501-2.xhtml +load 378993-1.xhtml +load 382568-1.html +load 383137.xhtml +load 388183-1.html +load 395340-1.html +load 399694-1.html +load 407053.html +load 423371-1.html +load 448564.html +load 451123-1.html +load 453406-1.html +load 464197-1.html +load 468562-1.html +load 468562-2.html +load 494225.html +load 495543.svg +load 495546-1.html +load 504183-1.html +load 515829-1.html +load 515829-2.html +load 570566-1.html +load 571428-1.html +load 580507-1.xhtml +load 590387.html +load 596785-1.html +load 596785-2.html +load 602117.html +load 604807.html +load 605264.html +load 606430-1.html +load 613027.html +load 614279.html +load 614988-1.html +load 620078-1.html +load 620078-2.html +load 631421.html +load 673853.html +load 682058.xhtml +load 682460.html +load 738744.xhtml +load 741218.json +load 741250.xhtml +load 768344.html +load 795221-1.html +load 795221-2.html +load 795221-3.html +load 795221-4.html +load 795221-5.xml +load 811226.html +load 819745.html +load 828180.html +load 828472.html +load 837033.html +load 838256-1.html +load 862084.html +load 865147.html +load 877910.html +load 903106.html +load 916322-1.html +load 916322-2.html +load 978644.xhtml +load 1032654.html +load 1141260.html +load 1228876.html +load 1230110.html +load 1237633.html +load 1281972-1.html +load 1282894.html +load 1290904.html +load 1343886-1.html +load 1343886-2.xml +load 1343886-3.xml +load 1350972.html +load 1386905.html +asserts(0-4) load 1401726.html +load 1412173.html +load 1440523.html +load 1547057.html +load 1550524.html +load 1550881-1.html +load 1550881-2.html +skip-if(Android) pref(dom.disable_open_during_load,false) load 1667493.html +load 1680418.html +load 1704660.html +load 1724816.html +load 1785933.html +load 1787671.html +load 1789475.html +load 1801380.html diff --git a/dom/html/input/ButtonInputTypes.h b/dom/html/input/ButtonInputTypes.h new file mode 100644 index 0000000000..e891db00e0 --- /dev/null +++ b/dom/html/input/ButtonInputTypes.h @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_ButtonInputTypes_h__ +#define mozilla_dom_ButtonInputTypes_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +class ButtonInputTypeBase : public InputType { + public: + ~ButtonInputTypeBase() override = default; + + protected: + explicit ButtonInputTypeBase(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} +}; + +// input type=button +class ButtonInputType : public ButtonInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) ButtonInputType(aInputElement); + } + + private: + explicit ButtonInputType(HTMLInputElement* aInputElement) + : ButtonInputTypeBase(aInputElement) {} +}; + +// input type=image +class ImageInputType : public ButtonInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) ImageInputType(aInputElement); + } + + private: + explicit ImageInputType(HTMLInputElement* aInputElement) + : ButtonInputTypeBase(aInputElement) {} +}; + +// input type=reset +class ResetInputType : public ButtonInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) ResetInputType(aInputElement); + } + + private: + explicit ResetInputType(HTMLInputElement* aInputElement) + : ButtonInputTypeBase(aInputElement) {} +}; + +// input type=submit +class SubmitInputType : public ButtonInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) SubmitInputType(aInputElement); + } + + private: + explicit SubmitInputType(HTMLInputElement* aInputElement) + : ButtonInputTypeBase(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_ButtonInputTypes_h__ */ diff --git a/dom/html/input/CheckableInputTypes.cpp b/dom/html/input/CheckableInputTypes.cpp new file mode 100644 index 0000000000..f9d4d69d19 --- /dev/null +++ b/dom/html/input/CheckableInputTypes.cpp @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/CheckableInputTypes.h" + +#include "mozilla/dom/HTMLInputElement.h" + +using namespace mozilla; +using namespace mozilla::dom; + +/* input type=checkbox */ + +bool CheckboxInputType::IsValueMissing() const { + if (!mInputElement->IsRequired()) { + return false; + } + + return !mInputElement->Checked(); +} + +nsresult CheckboxInputType::GetValueMissingMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationCheckboxMissing", + mInputElement->OwnerDoc(), aMessage); +} + +/* input type=radio */ + +nsresult RadioInputType::GetValueMissingMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationRadioMissing", + mInputElement->OwnerDoc(), aMessage); +} diff --git a/dom/html/input/CheckableInputTypes.h b/dom/html/input/CheckableInputTypes.h new file mode 100644 index 0000000000..98c673685b --- /dev/null +++ b/dom/html/input/CheckableInputTypes.h @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_CheckableInputTypes_h__ +#define mozilla_dom_CheckableInputTypes_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +class CheckableInputTypeBase : public InputType { + public: + ~CheckableInputTypeBase() override = default; + + protected: + explicit CheckableInputTypeBase(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} +}; + +// input type=checkbox +class CheckboxInputType : public CheckableInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) CheckboxInputType(aInputElement); + } + + bool IsValueMissing() const override; + + nsresult GetValueMissingMessage(nsAString& aMessage) override; + + private: + explicit CheckboxInputType(HTMLInputElement* aInputElement) + : CheckableInputTypeBase(aInputElement) {} +}; + +// input type=radio +class RadioInputType : public CheckableInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) RadioInputType(aInputElement); + } + + nsresult GetValueMissingMessage(nsAString& aMessage) override; + + private: + explicit RadioInputType(HTMLInputElement* aInputElement) + : CheckableInputTypeBase(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_CheckableInputTypes_h__ */ diff --git a/dom/html/input/ColorInputType.h b/dom/html/input/ColorInputType.h new file mode 100644 index 0000000000..b6749849b7 --- /dev/null +++ b/dom/html/input/ColorInputType.h @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_ColorInputType_h__ +#define mozilla_dom_ColorInputType_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +// input type=color +class ColorInputType : public InputType { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) ColorInputType(aInputElement); + } + + private: + explicit ColorInputType(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_ColorInputType_h__ */ diff --git a/dom/html/input/DateTimeInputTypes.cpp b/dom/html/input/DateTimeInputTypes.cpp new file mode 100644 index 0000000000..c113d07718 --- /dev/null +++ b/dom/html/input/DateTimeInputTypes.cpp @@ -0,0 +1,504 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/DateTimeInputTypes.h" + +#include "js/Date.h" +#include "mozilla/AsyncEventDispatcher.h" +#include "mozilla/StaticPrefs_dom.h" +#include "mozilla/dom/HTMLInputElement.h" +#include "mozilla/dom/ShadowRoot.h" +#include "nsDOMTokenList.h" + +namespace mozilla::dom { + +const double DateTimeInputTypeBase::kMinimumYear = 1; +const double DateTimeInputTypeBase::kMaximumYear = 275760; +const double DateTimeInputTypeBase::kMaximumMonthInMaximumYear = 9; +const double DateTimeInputTypeBase::kMaximumWeekInMaximumYear = 37; +const double DateTimeInputTypeBase::kMsPerDay = 24 * 60 * 60 * 1000; + +bool DateTimeInputTypeBase::IsMutable() const { + return !mInputElement->IsDisabled() && + !mInputElement->HasAttr(nsGkAtoms::readonly); +} + +bool DateTimeInputTypeBase::IsValueMissing() const { + if (!mInputElement->IsRequired()) { + return false; + } + + if (!IsMutable()) { + return false; + } + + return IsValueEmpty(); +} + +bool DateTimeInputTypeBase::IsRangeOverflow() const { + Decimal maximum = mInputElement->GetMaximum(); + if (maximum.isNaN()) { + return false; + } + + Decimal value = mInputElement->GetValueAsDecimal(); + if (value.isNaN()) { + return false; + } + + return value > maximum; +} + +bool DateTimeInputTypeBase::IsRangeUnderflow() const { + Decimal minimum = mInputElement->GetMinimum(); + if (minimum.isNaN()) { + return false; + } + + Decimal value = mInputElement->GetValueAsDecimal(); + if (value.isNaN()) { + return false; + } + + return value < minimum; +} + +bool DateTimeInputTypeBase::HasStepMismatch() const { + Decimal value = mInputElement->GetValueAsDecimal(); + return mInputElement->ValueIsStepMismatch(value); +} + +bool DateTimeInputTypeBase::HasBadInput() const { + ShadowRoot* shadow = mInputElement->GetShadowRoot(); + if (!shadow) { + return false; + } + + Element* editWrapperElement = shadow->GetElementById(u"edit-wrapper"_ns); + if (!editWrapperElement) { + return false; + } + + bool allEmpty = true; + // Empty field does not imply bad input, but incomplete field does. + for (Element* child = editWrapperElement->GetFirstElementChild(); child; + child = child->GetNextElementSibling()) { + if (!child->ClassList()->Contains(u"datetime-edit-field"_ns)) { + continue; + } + nsAutoString value; + child->GetAttr(nsGkAtoms::value, value); + if (!value.IsEmpty()) { + allEmpty = false; + break; + } + } + + // If some fields are available but input element's value is empty implies it + // has been sanitized. + return !allEmpty && IsValueEmpty(); +} + +nsresult DateTimeInputTypeBase::GetRangeOverflowMessage(nsAString& aMessage) { + nsAutoString maxStr; + mInputElement->GetAttr(nsGkAtoms::max, maxStr); + + return nsContentUtils::FormatMaybeLocalizedString( + aMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationDateTimeRangeOverflow", mInputElement->OwnerDoc(), maxStr); +} + +nsresult DateTimeInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) { + nsAutoString minStr; + mInputElement->GetAttr(nsGkAtoms::min, minStr); + + return nsContentUtils::FormatMaybeLocalizedString( + aMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationDateTimeRangeUnderflow", mInputElement->OwnerDoc(), + minStr); +} + +void DateTimeInputTypeBase::MinMaxStepAttrChanged() { + if (Element* dateTimeBoxElement = mInputElement->GetDateTimeBoxElement()) { + AsyncEventDispatcher::RunDOMEventWhenSafe( + *dateTimeBoxElement, u"MozNotifyMinMaxStepAttrChanged"_ns, + CanBubble::eNo, ChromeOnlyDispatch::eNo); + } +} + +bool DateTimeInputTypeBase::GetTimeFromMs(double aValue, uint16_t* aHours, + uint16_t* aMinutes, + uint16_t* aSeconds, + uint16_t* aMilliseconds) const { + MOZ_ASSERT(aValue >= 0 && aValue < kMsPerDay, + "aValue must be milliseconds within a day!"); + + uint32_t value = floor(aValue); + + *aMilliseconds = value % 1000; + value /= 1000; + + *aSeconds = value % 60; + value /= 60; + + *aMinutes = value % 60; + value /= 60; + + *aHours = value; + + return true; +} + +// input type=date + +nsresult DateInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidDate", + mInputElement->OwnerDoc(), aMessage); +} + +bool DateInputType::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + uint32_t year, month, day; + if (!ParseDate(aValue, &year, &month, &day)) { + return false; + } + + JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day)); + if (!time.isValid()) { + return false; + } + + aResultValue = Decimal::fromDouble(time.toDouble()); + return true; +} + +bool DateInputType::ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + + // The specs (and our JS APIs) require |aValue| to be truncated. + aValue = aValue.floor(); + + double year = JS::YearFromTime(aValue.toDouble()); + double month = JS::MonthFromTime(aValue.toDouble()); + double day = JS::DayFromTime(aValue.toDouble()); + + if (std::isnan(year) || std::isnan(month) || std::isnan(day)) { + return false; + } + + aResultString.AppendPrintf("%04.0f-%02.0f-%02.0f", year, month + 1, day); + return true; +} + +// input type=time + +nsresult TimeInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidTime", + mInputElement->OwnerDoc(), aMessage); +} + +bool TimeInputType::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + uint32_t milliseconds; + if (!ParseTime(aValue, &milliseconds)) { + return false; + } + + aResultValue = Decimal(int32_t(milliseconds)); + return true; +} + +bool TimeInputType::ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + + aValue = aValue.floor(); + // Per spec, we need to truncate |aValue| and we should only represent + // times inside a day [00:00, 24:00[, which means that we should do a + // modulo on |aValue| using the number of milliseconds in a day (86400000). + uint32_t value = + NS_floorModulo(aValue, Decimal::fromDouble(kMsPerDay)).toDouble(); + + uint16_t milliseconds, seconds, minutes, hours; + if (!GetTimeFromMs(value, &hours, &minutes, &seconds, &milliseconds)) { + return false; + } + + if (milliseconds != 0) { + aResultString.AppendPrintf("%02d:%02d:%02d.%03d", hours, minutes, seconds, + milliseconds); + } else if (seconds != 0) { + aResultString.AppendPrintf("%02d:%02d:%02d", hours, minutes, seconds); + } else { + aResultString.AppendPrintf("%02d:%02d", hours, minutes); + } + + return true; +} + +bool TimeInputType::HasReversedRange() const { + mozilla::Decimal maximum = mInputElement->GetMaximum(); + if (maximum.isNaN()) { + return false; + } + + mozilla::Decimal minimum = mInputElement->GetMinimum(); + if (minimum.isNaN()) { + return false; + } + + return maximum < minimum; +} + +bool TimeInputType::IsReversedRangeUnderflowAndOverflow() const { + mozilla::Decimal maximum = mInputElement->GetMaximum(); + mozilla::Decimal minimum = mInputElement->GetMinimum(); + mozilla::Decimal value = mInputElement->GetValueAsDecimal(); + + MOZ_ASSERT(HasReversedRange(), "Must have reserved range."); + + if (value.isNaN()) { + return false; + } + + // When an element has a reversed range, and the value is more than the + // maximum and less than the minimum the element is simultaneously suffering + // from an underflow and suffering from an overflow. + return value > maximum && value < minimum; +} + +bool TimeInputType::IsRangeOverflow() const { + return HasReversedRange() ? IsReversedRangeUnderflowAndOverflow() + : DateTimeInputTypeBase::IsRangeOverflow(); +} + +bool TimeInputType::IsRangeUnderflow() const { + return HasReversedRange() ? IsReversedRangeUnderflowAndOverflow() + : DateTimeInputTypeBase::IsRangeUnderflow(); +} + +nsresult TimeInputType::GetReversedRangeUnderflowAndOverflowMessage( + nsAString& aMessage) { + nsAutoString maxStr; + mInputElement->GetAttr(nsGkAtoms::max, maxStr); + + nsAutoString minStr; + mInputElement->GetAttr(nsGkAtoms::min, minStr); + + return nsContentUtils::FormatMaybeLocalizedString( + aMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationTimeReversedRangeUnderflowAndOverflow", + mInputElement->OwnerDoc(), minStr, maxStr); +} + +nsresult TimeInputType::GetRangeOverflowMessage(nsAString& aMessage) { + return HasReversedRange() + ? GetReversedRangeUnderflowAndOverflowMessage(aMessage) + : DateTimeInputTypeBase::GetRangeOverflowMessage(aMessage); +} + +nsresult TimeInputType::GetRangeUnderflowMessage(nsAString& aMessage) { + return HasReversedRange() + ? GetReversedRangeUnderflowAndOverflowMessage(aMessage) + : DateTimeInputTypeBase::GetRangeUnderflowMessage(aMessage); +} + +// input type=week + +nsresult WeekInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidWeek", + mInputElement->OwnerDoc(), aMessage); +} + +bool WeekInputType::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + uint32_t year, week; + if (!ParseWeek(aValue, &year, &week)) { + return false; + } + + if (year < kMinimumYear || year > kMaximumYear) { + return false; + } + + // Maximum week is 275760-W37, the week of 275760-09-13. + if (year == kMaximumYear && week > kMaximumWeekInMaximumYear) { + return false; + } + + double days = DaysSinceEpochFromWeek(year, week); + aResultValue = Decimal::fromDouble(days * kMsPerDay); + return true; +} + +bool WeekInputType::ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + + aValue = aValue.floor(); + + // Based on ISO 8601 date. + double year = JS::YearFromTime(aValue.toDouble()); + double month = JS::MonthFromTime(aValue.toDouble()); + double day = JS::DayFromTime(aValue.toDouble()); + // Adding 1 since day starts from 0. + double dayInYear = JS::DayWithinYear(aValue.toDouble(), year) + 1; + + // Adding 1 since month starts from 0. + uint32_t isoWeekday = DayOfWeek(year, month + 1, day, true); + // Target on Wednesday since ISO 8601 states that week 1 is the week + // with the first Thursday of that year. + uint32_t week = (dayInYear - isoWeekday + 10) / 7; + + if (week < 1) { + year--; + if (year < 1) { + return false; + } + week = MaximumWeekInYear(year); + } else if (week > MaximumWeekInYear(year)) { + year++; + if (year > kMaximumYear || + (year == kMaximumYear && week > kMaximumWeekInMaximumYear)) { + return false; + } + week = 1; + } + + aResultString.AppendPrintf("%04.0f-W%02d", year, week); + return true; +} + +// input type=month + +nsresult MonthInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidMonth", + mInputElement->OwnerDoc(), aMessage); +} + +bool MonthInputType::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + uint32_t year, month; + if (!ParseMonth(aValue, &year, &month)) { + return false; + } + + if (year < kMinimumYear || year > kMaximumYear) { + return false; + } + + // Maximum valid month is 275760-09. + if (year == kMaximumYear && month > kMaximumMonthInMaximumYear) { + return false; + } + + int32_t months = MonthsSinceJan1970(year, month); + aResultValue = Decimal(int32_t(months)); + return true; +} + +bool MonthInputType::ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + + aValue = aValue.floor(); + + double month = NS_floorModulo(aValue, Decimal(12)).toDouble(); + month = (month < 0 ? month + 12 : month); + + double year = 1970 + (aValue.toDouble() - month) / 12; + + // Maximum valid month is 275760-09. + if (year < kMinimumYear || year > kMaximumYear) { + return false; + } + + if (year == kMaximumYear && month > 8) { + return false; + } + + aResultString.AppendPrintf("%04.0f-%02.0f", year, month + 1); + return true; +} + +// input type=datetime-local + +nsresult DateTimeLocalInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidDateTime", + mInputElement->OwnerDoc(), aMessage); +} + +bool DateTimeLocalInputType::ConvertStringToNumber( + nsAString& aValue, Decimal& aResultValue) const { + uint32_t year, month, day, timeInMs; + if (!ParseDateTimeLocal(aValue, &year, &month, &day, &timeInMs)) { + return false; + } + + JS::ClippedTime time = + JS::TimeClip(JS::MakeDate(year, month - 1, day, timeInMs)); + if (!time.isValid()) { + return false; + } + + aResultValue = Decimal::fromDouble(time.toDouble()); + return true; +} + +bool DateTimeLocalInputType::ConvertNumberToString( + Decimal aValue, nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + + aValue = aValue.floor(); + + uint32_t timeValue = + NS_floorModulo(aValue, Decimal::fromDouble(kMsPerDay)).toDouble(); + + uint16_t milliseconds, seconds, minutes, hours; + if (!GetTimeFromMs(timeValue, &hours, &minutes, &seconds, &milliseconds)) { + return false; + } + + double year = JS::YearFromTime(aValue.toDouble()); + double month = JS::MonthFromTime(aValue.toDouble()); + double day = JS::DayFromTime(aValue.toDouble()); + + if (std::isnan(year) || std::isnan(month) || std::isnan(day)) { + return false; + } + + if (milliseconds != 0) { + aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d:%02d.%03d", year, + month + 1, day, hours, minutes, seconds, + milliseconds); + } else if (seconds != 0) { + aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d:%02d", year, + month + 1, day, hours, minutes, seconds); + } else { + aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d", year, + month + 1, day, hours, minutes); + } + + return true; +} + +} // namespace mozilla::dom diff --git a/dom/html/input/DateTimeInputTypes.h b/dom/html/input/DateTimeInputTypes.h new file mode 100644 index 0000000000..fc46ef4606 --- /dev/null +++ b/dom/html/input/DateTimeInputTypes.h @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_DateTimeInputTypes_h__ +#define mozilla_dom_DateTimeInputTypes_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +class DateTimeInputTypeBase : public InputType { + public: + ~DateTimeInputTypeBase() override = default; + + bool IsValueMissing() const override; + bool IsRangeOverflow() const override; + bool IsRangeUnderflow() const override; + bool HasStepMismatch() const override; + bool HasBadInput() const override; + + nsresult GetRangeOverflowMessage(nsAString& aMessage) override; + nsresult GetRangeUnderflowMessage(nsAString& aMessage) override; + + void MinMaxStepAttrChanged() override; + + protected: + explicit DateTimeInputTypeBase(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} + + bool IsMutable() const override; + + nsresult GetBadInputMessage(nsAString& aMessage) override = 0; + + /** + * This method converts aValue (milliseconds within a day) to hours, minutes, + * seconds and milliseconds. + */ + bool GetTimeFromMs(double aValue, uint16_t* aHours, uint16_t* aMinutes, + uint16_t* aSeconds, uint16_t* aMilliseconds) const; + + // Minimum year limited by HTML standard, year >= 1. + static const double kMinimumYear; + // Maximum year limited by ECMAScript date object range, year <= 275760. + static const double kMaximumYear; + // Maximum valid month is 275760-09. + static const double kMaximumMonthInMaximumYear; + // Maximum valid week is 275760-W37. + static const double kMaximumWeekInMaximumYear; + // Milliseconds in a day. + static const double kMsPerDay; +}; + +// input type=date +class DateInputType : public DateTimeInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) DateInputType(aInputElement); + } + + nsresult GetBadInputMessage(nsAString& aMessage) override; + + bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const override; + bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const override; + + private: + explicit DateInputType(HTMLInputElement* aInputElement) + : DateTimeInputTypeBase(aInputElement) {} +}; + +// input type=time +class TimeInputType : public DateTimeInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) TimeInputType(aInputElement); + } + + nsresult GetBadInputMessage(nsAString& aMessage) override; + + bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const override; + bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const override; + bool IsRangeOverflow() const override; + bool IsRangeUnderflow() const override; + nsresult GetRangeOverflowMessage(nsAString& aMessage) override; + nsresult GetRangeUnderflowMessage(nsAString& aMessage) override; + + private: + explicit TimeInputType(HTMLInputElement* aInputElement) + : DateTimeInputTypeBase(aInputElement) {} + + // https://html.spec.whatwg.org/multipage/input.html#has-a-reversed-range + bool HasReversedRange() const; + bool IsReversedRangeUnderflowAndOverflow() const; + nsresult GetReversedRangeUnderflowAndOverflowMessage(nsAString& aMessage); +}; + +// input type=week +class WeekInputType : public DateTimeInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) WeekInputType(aInputElement); + } + + nsresult GetBadInputMessage(nsAString& aMessage) override; + bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const override; + bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const override; + + private: + explicit WeekInputType(HTMLInputElement* aInputElement) + : DateTimeInputTypeBase(aInputElement) {} +}; + +// input type=month +class MonthInputType : public DateTimeInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) MonthInputType(aInputElement); + } + + nsresult GetBadInputMessage(nsAString& aMessage) override; + bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const override; + bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const override; + + private: + explicit MonthInputType(HTMLInputElement* aInputElement) + : DateTimeInputTypeBase(aInputElement) {} +}; + +// input type=datetime-local +class DateTimeLocalInputType : public DateTimeInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) DateTimeLocalInputType(aInputElement); + } + + nsresult GetBadInputMessage(nsAString& aMessage) override; + bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const override; + bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const override; + + private: + explicit DateTimeLocalInputType(HTMLInputElement* aInputElement) + : DateTimeInputTypeBase(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_DateTimeInputTypes_h__ */ diff --git a/dom/html/input/FileInputType.cpp b/dom/html/input/FileInputType.cpp new file mode 100644 index 0000000000..ed14aaa48d --- /dev/null +++ b/dom/html/input/FileInputType.cpp @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/FileInputType.h" + +#include "mozilla/dom/HTMLInputElement.h" + +using namespace mozilla; +using namespace mozilla::dom; + +bool FileInputType::IsValueMissing() const { + if (!mInputElement->IsRequired()) { + return false; + } + + return mInputElement->GetFilesOrDirectoriesInternal().IsEmpty(); +} + +nsresult FileInputType::GetValueMissingMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationFileMissing", + mInputElement->OwnerDoc(), aMessage); +} diff --git a/dom/html/input/FileInputType.h b/dom/html/input/FileInputType.h new file mode 100644 index 0000000000..870ef93136 --- /dev/null +++ b/dom/html/input/FileInputType.h @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_FileInputType_h__ +#define mozilla_dom_FileInputType_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +// input type=file +class FileInputType : public InputType { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) FileInputType(aInputElement); + } + + bool IsValueMissing() const override; + + nsresult GetValueMissingMessage(nsAString& aMessage) override; + + private: + explicit FileInputType(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_FileInputType_h__ */ diff --git a/dom/html/input/HiddenInputType.h b/dom/html/input/HiddenInputType.h new file mode 100644 index 0000000000..ac7c9c571a --- /dev/null +++ b/dom/html/input/HiddenInputType.h @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_HiddenInputType_h__ +#define mozilla_dom_HiddenInputType_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +// input type=hidden +class HiddenInputType : public InputType { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) HiddenInputType(aInputElement); + } + + private: + explicit HiddenInputType(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_HiddenInputType_h__ */ diff --git a/dom/html/input/InputType.cpp b/dom/html/input/InputType.cpp new file mode 100644 index 0000000000..8a596681b6 --- /dev/null +++ b/dom/html/input/InputType.cpp @@ -0,0 +1,355 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/InputType.h" + +#include "mozilla/Assertions.h" +#include "mozilla/Likely.h" +#include "nsIFormControl.h" +#include "mozilla/dom/ButtonInputTypes.h" +#include "mozilla/dom/CheckableInputTypes.h" +#include "mozilla/dom/ColorInputType.h" +#include "mozilla/dom/DateTimeInputTypes.h" +#include "mozilla/dom/FileInputType.h" +#include "mozilla/dom/HiddenInputType.h" +#include "mozilla/dom/HTMLInputElement.h" +#include "mozilla/dom/NumericInputTypes.h" +#include "mozilla/dom/SingleLineTextInputTypes.h" + +#include "nsContentUtils.h" + +using namespace mozilla; +using namespace mozilla::dom; + +const Decimal InputType::kStepAny = Decimal(0); + +/* static */ UniquePtr InputType::Create( + HTMLInputElement* aInputElement, FormControlType aType, void* aMemory) { + UniquePtr inputType; + switch (aType) { + // Single line text + case FormControlType::InputText: + inputType.reset(TextInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputTel: + inputType.reset(TelInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputEmail: + inputType.reset(EmailInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputSearch: + inputType.reset(SearchInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputPassword: + inputType.reset(PasswordInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputUrl: + inputType.reset(URLInputType::Create(aInputElement, aMemory)); + break; + // Button + case FormControlType::InputButton: + inputType.reset(ButtonInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputSubmit: + inputType.reset(SubmitInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputImage: + inputType.reset(ImageInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputReset: + inputType.reset(ResetInputType::Create(aInputElement, aMemory)); + break; + // Checkable + case FormControlType::InputCheckbox: + inputType.reset(CheckboxInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputRadio: + inputType.reset(RadioInputType::Create(aInputElement, aMemory)); + break; + // Numeric + case FormControlType::InputNumber: + inputType.reset(NumberInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputRange: + inputType.reset(RangeInputType::Create(aInputElement, aMemory)); + break; + // DateTime + case FormControlType::InputDate: + inputType.reset(DateInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputTime: + inputType.reset(TimeInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputMonth: + inputType.reset(MonthInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputWeek: + inputType.reset(WeekInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputDatetimeLocal: + inputType.reset(DateTimeLocalInputType::Create(aInputElement, aMemory)); + break; + // Others + case FormControlType::InputColor: + inputType.reset(ColorInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputFile: + inputType.reset(FileInputType::Create(aInputElement, aMemory)); + break; + case FormControlType::InputHidden: + inputType.reset(HiddenInputType::Create(aInputElement, aMemory)); + break; + default: + inputType.reset(TextInputType::Create(aInputElement, aMemory)); + } + + return inputType; +} + +bool InputType::IsMutable() const { return !mInputElement->IsDisabled(); } + +bool InputType::IsValueEmpty() const { return mInputElement->IsValueEmpty(); } + +void InputType::GetNonFileValueInternal(nsAString& aValue) const { + return mInputElement->GetNonFileValueInternal(aValue); +} + +nsresult InputType::SetValueInternal(const nsAString& aValue, + const ValueSetterOptions& aOptions) { + RefPtr inputElement(mInputElement); + return inputElement->SetValueInternal(aValue, aOptions); +} + +nsIFrame* InputType::GetPrimaryFrame() const { + return mInputElement->GetPrimaryFrame(); +} + +void InputType::DropReference() { + // Drop our (non ref-counted) reference. + mInputElement = nullptr; +} + +bool InputType::IsTooLong() const { return false; } + +bool InputType::IsTooShort() const { return false; } + +bool InputType::IsValueMissing() const { return false; } + +bool InputType::HasTypeMismatch() const { return false; } + +Maybe InputType::HasPatternMismatch() const { return Some(false); } + +bool InputType::IsRangeOverflow() const { return false; } + +bool InputType::IsRangeUnderflow() const { return false; } + +bool InputType::HasStepMismatch() const { return false; } + +bool InputType::HasBadInput() const { return false; } + +nsresult InputType::GetValidationMessage( + nsAString& aValidationMessage, + nsIConstraintValidation::ValidityStateType aType) { + aValidationMessage.Truncate(); + + switch (aType) { + case nsIConstraintValidation::VALIDITY_STATE_TOO_LONG: { + int32_t maxLength = mInputElement->MaxLength(); + int32_t textLength = mInputElement->InputTextLength(CallerType::System); + nsAutoString strMaxLength; + nsAutoString strTextLength; + + strMaxLength.AppendInt(maxLength); + strTextLength.AppendInt(textLength); + + return nsContentUtils::FormatMaybeLocalizedString( + aValidationMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationTextTooLong", mInputElement->OwnerDoc(), strMaxLength, + strTextLength); + } + case nsIConstraintValidation::VALIDITY_STATE_TOO_SHORT: { + int32_t minLength = mInputElement->MinLength(); + int32_t textLength = mInputElement->InputTextLength(CallerType::System); + nsAutoString strMinLength; + nsAutoString strTextLength; + + strMinLength.AppendInt(minLength); + strTextLength.AppendInt(textLength); + + return nsContentUtils::FormatMaybeLocalizedString( + aValidationMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationTextTooShort", mInputElement->OwnerDoc(), strMinLength, + strTextLength); + } + case nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING: + return GetValueMissingMessage(aValidationMessage); + case nsIConstraintValidation::VALIDITY_STATE_TYPE_MISMATCH: { + return GetTypeMismatchMessage(aValidationMessage); + } + case nsIConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH: { + nsAutoString title; + mInputElement->GetAttr(nsGkAtoms::title, title); + + if (title.IsEmpty()) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationPatternMismatch", + mInputElement->OwnerDoc(), aValidationMessage); + } + + if (title.Length() > + nsIConstraintValidation::sContentSpecifiedMaxLengthMessage) { + title.Truncate( + nsIConstraintValidation::sContentSpecifiedMaxLengthMessage); + } + return nsContentUtils::FormatMaybeLocalizedString( + aValidationMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationPatternMismatchWithTitle", mInputElement->OwnerDoc(), + title); + } + case nsIConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW: + return GetRangeOverflowMessage(aValidationMessage); + case nsIConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW: + return GetRangeUnderflowMessage(aValidationMessage); + case nsIConstraintValidation::VALIDITY_STATE_STEP_MISMATCH: { + Decimal value = mInputElement->GetValueAsDecimal(); + if (MOZ_UNLIKELY(NS_WARN_IF(value.isNaN()))) { + // TODO(bug 1651070): This should ideally never happen, but we don't + // deal with lang changes correctly, so it could. + return GetBadInputMessage(aValidationMessage); + } + + Decimal step = mInputElement->GetStep(); + MOZ_ASSERT(step != kStepAny && step > Decimal(0)); + + Decimal stepBase = mInputElement->GetStepBase(); + + Decimal valueLow = value - NS_floorModulo(value - stepBase, step); + Decimal valueHigh = value + step - NS_floorModulo(value - stepBase, step); + + Decimal maximum = mInputElement->GetMaximum(); + + if (maximum.isNaN() || valueHigh <= maximum) { + nsAutoString valueLowStr, valueHighStr; + ConvertNumberToString(valueLow, valueLowStr); + ConvertNumberToString(valueHigh, valueHighStr); + + if (valueLowStr.Equals(valueHighStr)) { + return nsContentUtils::FormatMaybeLocalizedString( + aValidationMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationStepMismatchOneValue", mInputElement->OwnerDoc(), + valueLowStr); + } + return nsContentUtils::FormatMaybeLocalizedString( + aValidationMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationStepMismatch", mInputElement->OwnerDoc(), + valueLowStr, valueHighStr); + } + + nsAutoString valueLowStr; + ConvertNumberToString(valueLow, valueLowStr); + + return nsContentUtils::FormatMaybeLocalizedString( + aValidationMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationStepMismatchOneValue", mInputElement->OwnerDoc(), + valueLowStr); + } + case nsIConstraintValidation::VALIDITY_STATE_BAD_INPUT: + return GetBadInputMessage(aValidationMessage); + default: + MOZ_ASSERT_UNREACHABLE("Unknown validity state"); + return NS_ERROR_UNEXPECTED; + } +} + +nsresult InputType::GetValueMissingMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationValueMissing", + mInputElement->OwnerDoc(), aMessage); +} + +nsresult InputType::GetTypeMismatchMessage(nsAString& aMessage) { + return NS_ERROR_UNEXPECTED; +} + +nsresult InputType::GetRangeOverflowMessage(nsAString& aMessage) { + return NS_ERROR_UNEXPECTED; +} + +nsresult InputType::GetRangeUnderflowMessage(nsAString& aMessage) { + return NS_ERROR_UNEXPECTED; +} + +nsresult InputType::GetBadInputMessage(nsAString& aMessage) { + return NS_ERROR_UNEXPECTED; +} + +bool InputType::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + NS_WARNING("InputType::ConvertStringToNumber called"); + + return false; +} + +bool InputType::ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const { + NS_WARNING("InputType::ConvertNumberToString called"); + + return false; +} + +bool InputType::ParseDate(const nsAString& aValue, uint32_t* aYear, + uint32_t* aMonth, uint32_t* aDay) const { + // TODO: move this function and implementation to DateTimeInpuTypeBase when + // refactoring is completed. Now we can only call HTMLInputElement::ParseDate + // from here, since the method is protected and only InputType is a friend + // class. + return mInputElement->ParseDate(aValue, aYear, aMonth, aDay); +} + +bool InputType::ParseTime(const nsAString& aValue, uint32_t* aResult) const { + // see comment in InputType::ParseDate(). + return HTMLInputElement::ParseTime(aValue, aResult); +} + +bool InputType::ParseMonth(const nsAString& aValue, uint32_t* aYear, + uint32_t* aMonth) const { + // see comment in InputType::ParseDate(). + return mInputElement->ParseMonth(aValue, aYear, aMonth); +} + +bool InputType::ParseWeek(const nsAString& aValue, uint32_t* aYear, + uint32_t* aWeek) const { + // see comment in InputType::ParseDate(). + return mInputElement->ParseWeek(aValue, aYear, aWeek); +} + +bool InputType::ParseDateTimeLocal(const nsAString& aValue, uint32_t* aYear, + uint32_t* aMonth, uint32_t* aDay, + uint32_t* aTime) const { + // see comment in InputType::ParseDate(). + return mInputElement->ParseDateTimeLocal(aValue, aYear, aMonth, aDay, aTime); +} + +int32_t InputType::MonthsSinceJan1970(uint32_t aYear, uint32_t aMonth) const { + // see comment in InputType::ParseDate(). + return mInputElement->MonthsSinceJan1970(aYear, aMonth); +} + +double InputType::DaysSinceEpochFromWeek(uint32_t aYear, uint32_t aWeek) const { + // see comment in InputType::ParseDate(). + return mInputElement->DaysSinceEpochFromWeek(aYear, aWeek); +} + +uint32_t InputType::DayOfWeek(uint32_t aYear, uint32_t aMonth, uint32_t aDay, + bool isoWeek) const { + // see comment in InputType::ParseDate(). + return mInputElement->DayOfWeek(aYear, aMonth, aDay, isoWeek); +} + +uint32_t InputType::MaximumWeekInYear(uint32_t aYear) const { + // see comment in InputType::ParseDate(). + return mInputElement->MaximumWeekInYear(aYear); +} diff --git a/dom/html/input/InputType.h b/dom/html/input/InputType.h new file mode 100644 index 0000000000..a4853e09b2 --- /dev/null +++ b/dom/html/input/InputType.h @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_InputType_h__ +#define mozilla_dom_InputType_h__ + +#include +#include "mozilla/Decimal.h" +#include "mozilla/Maybe.h" +#include "mozilla/TextControlState.h" +#include "mozilla/UniquePtr.h" +#include "nsIConstraintValidation.h" +#include "nsString.h" +#include "nsError.h" + +// This must come outside of any namespace, or else it won't overload with the +// double based version in nsMathUtils.h +inline mozilla::Decimal NS_floorModulo(mozilla::Decimal x, mozilla::Decimal y) { + return (x - y * (x / y).floor()); +} + +class nsIFrame; + +namespace mozilla::dom { +class HTMLInputElement; + +/** + * A common superclass for different types of a HTMLInputElement. + */ +class InputType { + public: + using ValueSetterOption = TextControlState::ValueSetterOption; + using ValueSetterOptions = TextControlState::ValueSetterOptions; + + // Custom deleter for UniquePtr to avoid freeing memory + // pre-allocated for InputType, but we still need to call the destructor + // explictly. + struct DoNotDelete { + void operator()(InputType* p) { p->~InputType(); } + }; + + static UniquePtr Create( + HTMLInputElement* aInputElement, FormControlType, void* aMemory); + + virtual ~InputType() = default; + + // Float value returned by GetStep() when the step attribute is set to 'any'. + static const Decimal kStepAny; + + /** + * Drop the reference to the input element. + */ + void DropReference(); + + virtual bool MinAndMaxLengthApply() const { return false; } + virtual bool IsTooLong() const; + virtual bool IsTooShort() const; + virtual bool IsValueMissing() const; + virtual bool HasTypeMismatch() const; + // May return Nothing() if the JS engine failed to evaluate the regex. + virtual Maybe HasPatternMismatch() const; + virtual bool IsRangeOverflow() const; + virtual bool IsRangeUnderflow() const; + virtual bool HasStepMismatch() const; + virtual bool HasBadInput() const; + + nsresult GetValidationMessage( + nsAString& aValidationMessage, + nsIConstraintValidation::ValidityStateType aType); + virtual nsresult GetValueMissingMessage(nsAString& aMessage); + virtual nsresult GetTypeMismatchMessage(nsAString& aMessage); + virtual nsresult GetRangeOverflowMessage(nsAString& aMessage); + virtual nsresult GetRangeUnderflowMessage(nsAString& aMessage); + virtual nsresult GetBadInputMessage(nsAString& aMessage); + + MOZ_CAN_RUN_SCRIPT virtual void MinMaxStepAttrChanged() {} + + /** + * Convert a string to a Decimal number in a type specific way, + * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#concept-input-value-string-number + * ie parse a date string to a timestamp if type=date, + * or parse a number string to its value if type=number. + * @param aValue the string to be parsed. + * @param aResultValue the number as a Decimal. + * @result whether the parsing was successful. + */ + virtual bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const; + + /** + * Convert a Decimal to a string in a type specific way, ie convert a + * timestamp to a date string if type=date or append the number string + * representing the value if type=number. + * + * @param aValue the Decimal to be converted + * @param aResultString [out] the string representing the Decimal + * @return whether the function succeeded, it will fail if the current input's + * type is not supported or the number can't be converted to a string + * as expected by the type. + */ + virtual bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const; + + protected: + explicit InputType(HTMLInputElement* aInputElement) + : mInputElement(aInputElement) {} + + /** + * Get the mutable state of the element. + * When the element isn't mutable (immutable), the value or checkedness + * should not be changed by the user. + * + * See: + * https://html.spec.whatwg.org/multipage/forms.html#the-input-element:concept-fe-mutable + */ + virtual bool IsMutable() const; + + /** + * Returns whether the input element's current value is the empty string. + * This only makes sense for some input types; does NOT make sense for file + * inputs. + * + * @return whether the input element's current value is the empty string. + */ + bool IsValueEmpty() const; + + // A getter for callers that know we're not dealing with a file input, so they + // don't have to think about the caller type. + void GetNonFileValueInternal(nsAString& aValue) const; + + /** + * Setting the input element's value. + * + * @param aValue String to set. + * @param aOptions See TextControlState::ValueSetterOption. + */ + MOZ_CAN_RUN_SCRIPT nsresult + SetValueInternal(const nsAString& aValue, const ValueSetterOptions& aOptions); + + /** + * Get the primary frame for the input element. + */ + nsIFrame* GetPrimaryFrame() const; + + /** + * Parse a date string of the form yyyy-mm-dd + * + * @param aValue the string to be parsed. + * @return the date in aYear, aMonth, aDay. + * @return whether the parsing was successful. + */ + bool ParseDate(const nsAString& aValue, uint32_t* aYear, uint32_t* aMonth, + uint32_t* aDay) const; + + /** + * Returns the time expressed in milliseconds of |aValue| being parsed as a + * time following the HTML specifications: + * https://html.spec.whatwg.org/multipage/infrastructure.html#parse-a-time-string + * + * Note: |aResult| can be null. + * + * @param aValue the string to be parsed. + * @param aResult the time expressed in milliseconds representing the time + * [out] + * @return whether the parsing was successful. + */ + bool ParseTime(const nsAString& aValue, uint32_t* aResult) const; + + /** + * Parse a month string of the form yyyy-mm + * + * @param the string to be parsed. + * @return the year and month in aYear and aMonth. + * @return whether the parsing was successful. + */ + bool ParseMonth(const nsAString& aValue, uint32_t* aYear, + uint32_t* aMonth) const; + + /** + * Parse a week string of the form yyyy-Www + * + * @param the string to be parsed. + * @return the year and week in aYear and aWeek. + * @return whether the parsing was successful. + */ + bool ParseWeek(const nsAString& aValue, uint32_t* aYear, + uint32_t* aWeek) const; + + /** + * Parse a datetime-local string of the form yyyy-mm-ddThh:mm[:ss.s] or + * yyyy-mm-dd hh:mm[:ss.s], where fractions of seconds can be 1 to 3 digits. + * + * @param the string to be parsed. + * @return the date in aYear, aMonth, aDay and time expressed in milliseconds + * in aTime. + * @return whether the parsing was successful. + */ + bool ParseDateTimeLocal(const nsAString& aValue, uint32_t* aYear, + uint32_t* aMonth, uint32_t* aDay, + uint32_t* aTime) const; + + /** + * This methods returns the number of months between January 1970 and the + * given year and month. + */ + int32_t MonthsSinceJan1970(uint32_t aYear, uint32_t aMonth) const; + + /** + * This methods returns the number of days since epoch for a given year and + * week. + */ + double DaysSinceEpochFromWeek(uint32_t aYear, uint32_t aWeek) const; + + /** + * This methods returns the day of the week given a date. If @isoWeek is true, + * 7=Sunday, otherwise, 0=Sunday. + */ + uint32_t DayOfWeek(uint32_t aYear, uint32_t aMonth, uint32_t aDay, + bool isoWeek) const; + + /** + * This methods returns the maximum number of week in a given year, the + * result is either 52 or 53. + */ + uint32_t MaximumWeekInYear(uint32_t aYear) const; + + HTMLInputElement* mInputElement; +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_InputType_h__ */ diff --git a/dom/html/input/NumericInputTypes.cpp b/dom/html/input/NumericInputTypes.cpp new file mode 100644 index 0000000000..54811ddb9d --- /dev/null +++ b/dom/html/input/NumericInputTypes.cpp @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/NumericInputTypes.h" + +#include "mozilla/TextControlState.h" +#include "mozilla/dom/HTMLInputElement.h" +#include "ICUUtils.h" + +using namespace mozilla; +using namespace mozilla::dom; + +bool NumericInputTypeBase::IsRangeOverflow() const { + Decimal maximum = mInputElement->GetMaximum(); + if (maximum.isNaN()) { + return false; + } + + Decimal value = mInputElement->GetValueAsDecimal(); + if (value.isNaN()) { + return false; + } + + return value > maximum; +} + +bool NumericInputTypeBase::IsRangeUnderflow() const { + Decimal minimum = mInputElement->GetMinimum(); + if (minimum.isNaN()) { + return false; + } + + Decimal value = mInputElement->GetValueAsDecimal(); + if (value.isNaN()) { + return false; + } + + return value < minimum; +} + +bool NumericInputTypeBase::HasStepMismatch() const { + Decimal value = mInputElement->GetValueAsDecimal(); + return mInputElement->ValueIsStepMismatch(value); +} + +nsresult NumericInputTypeBase::GetRangeOverflowMessage(nsAString& aMessage) { + // We want to show the value as parsed when it's a number + Decimal maximum = mInputElement->GetMaximum(); + MOZ_ASSERT(!maximum.isNaN()); + + nsAutoString maxStr; + char buf[32]; + DebugOnly ok = maximum.toString(buf, ArrayLength(buf)); + maxStr.AssignASCII(buf); + MOZ_ASSERT(ok, "buf not big enough"); + + return nsContentUtils::FormatMaybeLocalizedString( + aMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationNumberRangeOverflow", mInputElement->OwnerDoc(), maxStr); +} + +nsresult NumericInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) { + Decimal minimum = mInputElement->GetMinimum(); + MOZ_ASSERT(!minimum.isNaN()); + + nsAutoString minStr; + char buf[32]; + DebugOnly ok = minimum.toString(buf, ArrayLength(buf)); + minStr.AssignASCII(buf); + MOZ_ASSERT(ok, "buf not big enough"); + + return nsContentUtils::FormatMaybeLocalizedString( + aMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationNumberRangeUnderflow", mInputElement->OwnerDoc(), minStr); +} + +bool NumericInputTypeBase::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + aResultValue = HTMLInputElement::StringToDecimal(aValue); + return aResultValue.isFinite(); +} + +bool NumericInputTypeBase::ConvertNumberToString( + Decimal aValue, nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + + char buf[32]; + bool ok = aValue.toString(buf, ArrayLength(buf)); + aResultString.AssignASCII(buf); + MOZ_ASSERT(ok, "buf not big enough"); + + return ok; +} + +/* input type=number */ + +bool NumberInputType::IsValueMissing() const { + if (!mInputElement->IsRequired()) { + return false; + } + + if (!IsMutable()) { + return false; + } + + return IsValueEmpty(); +} + +bool NumberInputType::HasBadInput() const { + nsAutoString value; + GetNonFileValueInternal(value); + return !value.IsEmpty() && mInputElement->GetValueAsDecimal().isNaN(); +} + +bool NumberInputType::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + ICUUtils::LanguageTagIterForContent langTagIter(mInputElement); + aResultValue = + Decimal::fromDouble(ICUUtils::ParseNumber(aValue, langTagIter)); + if (aResultValue.isFinite()) { + return true; + } + return NumericInputTypeBase::ConvertStringToNumber(aValue, aResultValue); +} + +bool NumberInputType::ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + ICUUtils::LanguageTagIterForContent langTagIter(mInputElement); + ICUUtils::LocalizeNumber(aValue.toDouble(), langTagIter, aResultString); + return true; +} + +nsresult NumberInputType::GetValueMissingMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationBadInputNumber", + mInputElement->OwnerDoc(), aMessage); +} + +nsresult NumberInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationBadInputNumber", + mInputElement->OwnerDoc(), aMessage); +} + +bool NumberInputType::IsMutable() const { + return !mInputElement->IsDisabled() && + !mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly); +} + +/* input type=range */ +void RangeInputType::MinMaxStepAttrChanged() { + // The value may need to change when @min/max/step changes since the value may + // have been invalid and can now change to a valid value, or vice versa. For + // example, consider: . The valid + // range is 0 to 1 while the nearest valid steps are -1 and 2 (the max value + // having prevented there being a valid step in range). Changing @max to/from + // 1 and a number greater than on equal to 3 should change whether we have a + // step mismatch or not. + // The value may also need to change between a value that results in a step + // mismatch and a value that results in overflow. For example, if @max in the + // example above were to change from 1 to -1. + nsAutoString value; + GetNonFileValueInternal(value); + SetValueInternal(value, TextControlState::ValueSetterOption::ByInternalAPI); +} diff --git a/dom/html/input/NumericInputTypes.h b/dom/html/input/NumericInputTypes.h new file mode 100644 index 0000000000..0c23bb74e7 --- /dev/null +++ b/dom/html/input/NumericInputTypes.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_NumericInputTypes_h__ +#define mozilla_dom_NumericInputTypes_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +class NumericInputTypeBase : public InputType { + public: + ~NumericInputTypeBase() override = default; + + bool IsRangeOverflow() const override; + bool IsRangeUnderflow() const override; + bool HasStepMismatch() const override; + + nsresult GetRangeOverflowMessage(nsAString& aMessage) override; + nsresult GetRangeUnderflowMessage(nsAString& aMessage) override; + + bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const override; + bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const override; + + protected: + explicit NumericInputTypeBase(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} +}; + +// input type=number +class NumberInputType final : public NumericInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) NumberInputType(aInputElement); + } + + bool IsValueMissing() const override; + bool HasBadInput() const override; + + nsresult GetValueMissingMessage(nsAString& aMessage) override; + nsresult GetBadInputMessage(nsAString& aMessage) override; + + bool ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const override; + bool ConvertNumberToString(Decimal aValue, + nsAString& aResultString) const override; + + protected: + bool IsMutable() const override; + + private: + explicit NumberInputType(HTMLInputElement* aInputElement) + : NumericInputTypeBase(aInputElement) {} +}; + +// input type=range +class RangeInputType : public NumericInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) RangeInputType(aInputElement); + } + + MOZ_CAN_RUN_SCRIPT void MinMaxStepAttrChanged() override; + + private: + explicit RangeInputType(HTMLInputElement* aInputElement) + : NumericInputTypeBase(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_NumericInputTypes_h__ */ diff --git a/dom/html/input/SingleLineTextInputTypes.cpp b/dom/html/input/SingleLineTextInputTypes.cpp new file mode 100644 index 0000000000..2222ed8a56 --- /dev/null +++ b/dom/html/input/SingleLineTextInputTypes.cpp @@ -0,0 +1,290 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/SingleLineTextInputTypes.h" + +#include "mozilla/dom/HTMLInputElement.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/TextUtils.h" +#include "HTMLSplitOnSpacesTokenizer.h" +#include "nsContentUtils.h" +#include "nsCRTGlue.h" +#include "nsIIDNService.h" +#include "nsIIOService.h" +#include "nsNetCID.h" +#include "nsNetUtil.h" + +using namespace mozilla; +using namespace mozilla::dom; + +bool SingleLineTextInputTypeBase::IsMutable() const { + return !mInputElement->IsDisabled() && + !mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly); +} + +bool SingleLineTextInputTypeBase::IsTooLong() const { + int32_t maxLength = mInputElement->MaxLength(); + + // Maxlength of -1 means attribute isn't set or parsing error. + if (maxLength == -1) { + return false; + } + + int32_t textLength = mInputElement->InputTextLength(CallerType::System); + + return textLength > maxLength; +} + +bool SingleLineTextInputTypeBase::IsTooShort() const { + int32_t minLength = mInputElement->MinLength(); + + // Minlength of -1 means attribute isn't set or parsing error. + if (minLength == -1) { + return false; + } + + int32_t textLength = mInputElement->InputTextLength(CallerType::System); + + return textLength && textLength < minLength; +} + +bool SingleLineTextInputTypeBase::IsValueMissing() const { + if (!mInputElement->IsRequired()) { + return false; + } + + if (!IsMutable()) { + return false; + } + + return IsValueEmpty(); +} + +Maybe SingleLineTextInputTypeBase::HasPatternMismatch() const { + if (!mInputElement->HasPatternAttribute()) { + return Some(false); + } + + nsAutoString pattern; + if (!mInputElement->GetAttr(kNameSpaceID_None, nsGkAtoms::pattern, pattern)) { + return Some(false); + } + + nsAutoString value; + GetNonFileValueInternal(value); + + if (value.IsEmpty()) { + return Some(false); + } + + Document* doc = mInputElement->OwnerDoc(); + Maybe result = nsContentUtils::IsPatternMatching( + value, pattern, doc, + mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)); + return result ? Some(!*result) : Nothing(); +} + +/* input type=url */ + +bool URLInputType::HasTypeMismatch() const { + nsAutoString value; + GetNonFileValueInternal(value); + + if (value.IsEmpty()) { + return false; + } + + /** + * TODO: + * The URL is not checked as the HTML5 specifications want it to be because + * there is no code to check for a valid URI/IRI according to 3986 and 3987 + * RFC's at the moment, see bug 561586. + * + * RFC 3987 (IRI) implementation: bug 42899 + * + * HTML5 specifications: + * http://dev.w3.org/html5/spec/infrastructure.html#valid-url + */ + nsCOMPtr ioService = do_GetIOService(); + nsCOMPtr uri; + + return !NS_SUCCEEDED(ioService->NewURI(NS_ConvertUTF16toUTF8(value), nullptr, + nullptr, getter_AddRefs(uri))); +} + +nsresult URLInputType::GetTypeMismatchMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidURL", + mInputElement->OwnerDoc(), aMessage); +} + +/* input type=email */ + +bool EmailInputType::HasTypeMismatch() const { + nsAutoString value; + GetNonFileValueInternal(value); + + if (value.IsEmpty()) { + return false; + } + + return mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) + ? !IsValidEmailAddressList(value) + : !IsValidEmailAddress(value); +} + +bool EmailInputType::HasBadInput() const { + // With regards to suffering from bad input the spec says that only the + // punycode conversion works, so we don't care whether the email address is + // valid or not here. (If the email address is invalid then we will be + // suffering from a type mismatch.) + nsAutoString value; + nsAutoCString unused; + uint32_t unused2; + GetNonFileValueInternal(value); + HTMLSplitOnSpacesTokenizer tokenizer(value, ','); + while (tokenizer.hasMoreTokens()) { + if (!PunycodeEncodeEmailAddress(tokenizer.nextToken(), unused, &unused2)) { + return true; + } + } + return false; +} + +nsresult EmailInputType::GetTypeMismatchMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidEmail", + mInputElement->OwnerDoc(), aMessage); +} + +nsresult EmailInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidEmail", + mInputElement->OwnerDoc(), aMessage); +} + +/* static */ +bool EmailInputType::IsValidEmailAddressList(const nsAString& aValue) { + HTMLSplitOnSpacesTokenizer tokenizer(aValue, ','); + + while (tokenizer.hasMoreTokens()) { + if (!IsValidEmailAddress(tokenizer.nextToken())) { + return false; + } + } + + return !tokenizer.separatorAfterCurrentToken(); +} + +/* static */ +bool EmailInputType::IsValidEmailAddress(const nsAString& aValue) { + // Email addresses can't be empty and can't end with a '.' or '-'. + if (aValue.IsEmpty() || aValue.Last() == '.' || aValue.Last() == '-') { + return false; + } + + uint32_t atPos; + nsAutoCString value; + if (!PunycodeEncodeEmailAddress(aValue, value, &atPos) || + atPos == (uint32_t)kNotFound || atPos == 0 || + atPos == value.Length() - 1) { + // Could not encode, or "@" was not found, or it was at the start or end + // of the input - in all cases, not a valid email address. + return false; + } + + uint32_t length = value.Length(); + uint32_t i = 0; + + // Parsing the username. + for (; i < atPos; ++i) { + char16_t c = value[i]; + + // The username characters have to be in this list to be valid. + if (!(IsAsciiAlpha(c) || IsAsciiDigit(c) || c == '.' || c == '!' || + c == '#' || c == '$' || c == '%' || c == '&' || c == '\'' || + c == '*' || c == '+' || c == '-' || c == '/' || c == '=' || + c == '?' || c == '^' || c == '_' || c == '`' || c == '{' || + c == '|' || c == '}' || c == '~')) { + return false; + } + } + + // Skip the '@'. + ++i; + + // The domain name can't begin with a dot or a dash. + if (value[i] == '.' || value[i] == '-') { + return false; + } + + // Parsing the domain name. + for (; i < length; ++i) { + char16_t c = value[i]; + + if (c == '.') { + // A dot can't follow a dot or a dash. + if (value[i - 1] == '.' || value[i - 1] == '-') { + return false; + } + } else if (c == '-') { + // A dash can't follow a dot. + if (value[i - 1] == '.') { + return false; + } + } else if (!(IsAsciiAlpha(c) || IsAsciiDigit(c) || c == '-')) { + // The domain characters have to be in this list to be valid. + return false; + } + } + + return true; +} + +/* static */ +bool EmailInputType::PunycodeEncodeEmailAddress(const nsAString& aEmail, + nsAutoCString& aEncodedEmail, + uint32_t* aIndexOfAt) { + nsAutoCString value = NS_ConvertUTF16toUTF8(aEmail); + *aIndexOfAt = (uint32_t)value.FindChar('@'); + + if (*aIndexOfAt == (uint32_t)kNotFound || *aIndexOfAt == value.Length() - 1) { + aEncodedEmail = value; + return true; + } + + nsCOMPtr idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID); + if (!idnSrv) { + NS_ERROR("nsIIDNService isn't present!"); + return false; + } + + uint32_t indexOfDomain = *aIndexOfAt + 1; + + const nsDependentCSubstring domain = Substring(value, indexOfDomain); + bool ace; + if (NS_SUCCEEDED(idnSrv->IsACE(domain, &ace)) && !ace) { + nsAutoCString domainACE; + if (NS_FAILED(idnSrv->ConvertUTF8toACE(domain, domainACE))) { + return false; + } + + // Bug 1788115 removed the 63 character limit from the + // IDNService::ConvertUTF8toACE so we check for that limit here as required + // by the spec: https://html.spec.whatwg.org/#valid-e-mail-address + nsCCharSeparatedTokenizer tokenizer(domainACE, '.'); + while (tokenizer.hasMoreTokens()) { + if (tokenizer.nextToken().Length() > 63) { + return false; + } + } + + value.Replace(indexOfDomain, domain.Length(), domainACE); + } + + aEncodedEmail = value; + return true; +} diff --git a/dom/html/input/SingleLineTextInputTypes.h b/dom/html/input/SingleLineTextInputTypes.h new file mode 100644 index 0000000000..afacc917a3 --- /dev/null +++ b/dom/html/input/SingleLineTextInputTypes.h @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_SingleLineTextInputTypes_h__ +#define mozilla_dom_SingleLineTextInputTypes_h__ + +#include "mozilla/dom/InputType.h" + +namespace mozilla::dom { + +class SingleLineTextInputTypeBase : public InputType { + public: + ~SingleLineTextInputTypeBase() override = default; + + bool MinAndMaxLengthApply() const final { return true; } + bool IsTooLong() const final; + bool IsTooShort() const final; + bool IsValueMissing() const final; + // Can return Nothing() if the JS engine failed to evaluate the pattern. + Maybe HasPatternMismatch() const final; + + protected: + explicit SingleLineTextInputTypeBase(HTMLInputElement* aInputElement) + : InputType(aInputElement) {} + + bool IsMutable() const override; +}; + +// input type=text +class TextInputType : public SingleLineTextInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) TextInputType(aInputElement); + } + + private: + explicit TextInputType(HTMLInputElement* aInputElement) + : SingleLineTextInputTypeBase(aInputElement) {} +}; + +// input type=search +class SearchInputType : public SingleLineTextInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) SearchInputType(aInputElement); + } + + private: + explicit SearchInputType(HTMLInputElement* aInputElement) + : SingleLineTextInputTypeBase(aInputElement) {} +}; + +// input type=tel +class TelInputType : public SingleLineTextInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) TelInputType(aInputElement); + } + + private: + explicit TelInputType(HTMLInputElement* aInputElement) + : SingleLineTextInputTypeBase(aInputElement) {} +}; + +// input type=url +class URLInputType : public SingleLineTextInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) URLInputType(aInputElement); + } + + bool HasTypeMismatch() const override; + + nsresult GetTypeMismatchMessage(nsAString& aMessage) override; + + private: + explicit URLInputType(HTMLInputElement* aInputElement) + : SingleLineTextInputTypeBase(aInputElement) {} +}; + +// input type=email +class EmailInputType : public SingleLineTextInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) EmailInputType(aInputElement); + } + + bool HasTypeMismatch() const override; + bool HasBadInput() const override; + + nsresult GetTypeMismatchMessage(nsAString& aMessage) override; + nsresult GetBadInputMessage(nsAString& aMessage) override; + + private: + explicit EmailInputType(HTMLInputElement* aInputElement) + : SingleLineTextInputTypeBase(aInputElement) {} + + /** + * This helper method returns true if aValue is a valid email address. + * This is following the HTML5 specification: + * http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address + * + * @param aValue the email address to check. + * @result whether the given string is a valid email address. + */ + static bool IsValidEmailAddress(const nsAString& aValue); + + /** + * This helper method returns true if aValue is a valid email address list. + * Email address list is a list of email address separated by comas (,) which + * can be surrounded by space charecters. + * This is following the HTML5 specification: + * http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address-list + * + * @param aValue the email address list to check. + * @result whether the given string is a valid email address list. + */ + static bool IsValidEmailAddressList(const nsAString& aValue); + + /** + * Takes aEmail and attempts to convert everything after the first "@" + * character (if anything) to punycode before returning the complete result + * via the aEncodedEmail out-param. The aIndexOfAt out-param is set to the + * index of the "@" character. + * + * If no "@" is found in aEmail, aEncodedEmail is simply set to aEmail and + * the aIndexOfAt out-param is set to kNotFound. + * + * Returns true in all cases unless an attempt to punycode encode fails. If + * false is returned, aEncodedEmail has not been set. + * + * This function exists because ConvertUTF8toACE() splits on ".", meaning that + * for 'user.name@sld.tld' it would treat "name@sld" as a label. We want to + * encode the domain part only. + */ + static bool PunycodeEncodeEmailAddress(const nsAString& aEmail, + nsAutoCString& aEncodedEmail, + uint32_t* aIndexOfAt); +}; + +// input type=password +class PasswordInputType : public SingleLineTextInputTypeBase { + public: + static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) { + return new (aMemory) PasswordInputType(aInputElement); + } + + private: + explicit PasswordInputType(HTMLInputElement* aInputElement) + : SingleLineTextInputTypeBase(aInputElement) {} +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_SingleLineTextInputTypes_h__ */ diff --git a/dom/html/input/moz.build b/dom/html/input/moz.build new file mode 100644 index 0000000000..fa468f11e7 --- /dev/null +++ b/dom/html/input/moz.build @@ -0,0 +1,36 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# 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/. + +EXPORTS.mozilla.dom += [ + "ButtonInputTypes.h", + "CheckableInputTypes.h", + "ColorInputType.h", + "DateTimeInputTypes.h", + "FileInputType.h", + "HiddenInputType.h", + "InputType.h", + "NumericInputTypes.h", + "SingleLineTextInputTypes.h", +] + +UNIFIED_SOURCES += [ + "CheckableInputTypes.cpp", + "DateTimeInputTypes.cpp", + "FileInputType.cpp", + "InputType.cpp", + "NumericInputTypes.cpp", + "SingleLineTextInputTypes.cpp", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +LOCAL_INCLUDES += [ + "/dom/base", + "/dom/html", + "/layout/forms", +] + +FINAL_LIBRARY = "xul" diff --git a/dom/html/moz.build b/dom/html/moz.build new file mode 100644 index 0000000000..1dc679dce3 --- /dev/null +++ b/dom/html/moz.build @@ -0,0 +1,244 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# 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", "DOM: Core & HTML") + +DIRS += ["input"] + +MOCHITEST_MANIFESTS += [ + "test/dialog/mochitest.ini", + "test/forms/mochitest.ini", + "test/forms/without_selectionchange/mochitest.ini", + "test/mochitest.ini", +] + +MOCHITEST_CHROME_MANIFESTS += [ + "test/chrome.ini", + "test/forms/chrome.ini", +] + +BROWSER_CHROME_MANIFESTS += ["test/browser.ini"] + +EXPORTS += [ + "nsGenericHTMLElement.h", + "nsGenericHTMLFrameElement.h", + "nsHTMLDocument.h", + "nsIConstraintValidation.h", + "nsIFormControl.h", + "nsIHTMLCollection.h", + "nsIRadioGroupContainer.h", + "nsIRadioVisitor.h", +] + +EXPORTS.mozilla += [ + "TextControlElement.h", + "TextControlState.h", + "TextInputListener.h", +] + +EXPORTS.mozilla.dom += [ + "ConstraintValidation.h", + "ElementInternals.h", + "HTMLAllCollection.h", + "HTMLAnchorElement.h", + "HTMLAreaElement.h", + "HTMLAudioElement.h", + "HTMLBodyElement.h", + "HTMLBRElement.h", + "HTMLButtonElement.h", + "HTMLCanvasElement.h", + "HTMLDataElement.h", + "HTMLDataListElement.h", + "HTMLDetailsElement.h", + "HTMLDialogElement.h", + "HTMLDivElement.h", + "HTMLDNSPrefetch.h", + "HTMLElement.h", + "HTMLEmbedElement.h", + "HTMLFieldSetElement.h", + "HTMLFontElement.h", + "HTMLFormControlsCollection.h", + "HTMLFormElement.h", + "HTMLFormSubmission.h", + "HTMLFrameElement.h", + "HTMLFrameSetElement.h", + "HTMLHeadingElement.h", + "HTMLHRElement.h", + "HTMLIFrameElement.h", + "HTMLImageElement.h", + "HTMLInputElement.h", + "HTMLLabelElement.h", + "HTMLLegendElement.h", + "HTMLLIElement.h", + "HTMLLinkElement.h", + "HTMLMapElement.h", + "HTMLMarqueeElement.h", + "HTMLMediaElement.h", + "HTMLMenuElement.h", + "HTMLMetaElement.h", + "HTMLMeterElement.h", + "HTMLModElement.h", + "HTMLObjectElement.h", + "HTMLOptGroupElement.h", + "HTMLOptionElement.h", + "HTMLOptionsCollection.h", + "HTMLOutputElement.h", + "HTMLParagraphElement.h", + "HTMLPictureElement.h", + "HTMLPreElement.h", + "HTMLProgressElement.h", + "HTMLScriptElement.h", + "HTMLSelectElement.h", + "HTMLSharedElement.h", + "HTMLSharedListElement.h", + "HTMLSlotElement.h", + "HTMLSourceElement.h", + "HTMLSpanElement.h", + "HTMLStyleElement.h", + "HTMLSummaryElement.h", + "HTMLTableCaptionElement.h", + "HTMLTableCellElement.h", + "HTMLTableColElement.h", + "HTMLTableElement.h", + "HTMLTableRowElement.h", + "HTMLTableSectionElement.h", + "HTMLTemplateElement.h", + "HTMLTextAreaElement.h", + "HTMLTimeElement.h", + "HTMLTitleElement.h", + "HTMLTrackElement.h", + "HTMLUnknownElement.h", + "HTMLVideoElement.h", + "ImageDocument.h", + "MediaDocument.h", + "MediaError.h", + "nsBrowserElement.h", + "PlayPromise.h", + "RadioNodeList.h", + "TextTrackManager.h", + "TimeRanges.h", + "ValidityState.h", +] + +UNIFIED_SOURCES += [ + "ConstraintValidation.cpp", + "ElementInternals.cpp", + "HTMLAllCollection.cpp", + "HTMLAnchorElement.cpp", + "HTMLAreaElement.cpp", + "HTMLAudioElement.cpp", + "HTMLBodyElement.cpp", + "HTMLBRElement.cpp", + "HTMLButtonElement.cpp", + "HTMLCanvasElement.cpp", + "HTMLDataElement.cpp", + "HTMLDataListElement.cpp", + "HTMLDetailsElement.cpp", + "HTMLDialogElement.cpp", + "HTMLDivElement.cpp", + "HTMLDNSPrefetch.cpp", + "HTMLElement.cpp", + "HTMLEmbedElement.cpp", + "HTMLFieldSetElement.cpp", + "HTMLFontElement.cpp", + "HTMLFormControlsCollection.cpp", + "HTMLFormElement.cpp", + "HTMLFormSubmission.cpp", + "HTMLFrameElement.cpp", + "HTMLFrameSetElement.cpp", + "HTMLHeadingElement.cpp", + "HTMLHRElement.cpp", + "HTMLIFrameElement.cpp", + "HTMLImageElement.cpp", + "HTMLInputElement.cpp", + "HTMLLabelElement.cpp", + "HTMLLegendElement.cpp", + "HTMLLIElement.cpp", + "HTMLLinkElement.cpp", + "HTMLMapElement.cpp", + "HTMLMarqueeElement.cpp", + "HTMLMediaElement.cpp", + "HTMLMenuElement.cpp", + "HTMLMetaElement.cpp", + "HTMLMeterElement.cpp", + "HTMLModElement.cpp", + "HTMLObjectElement.cpp", + "HTMLOptGroupElement.cpp", + "HTMLOptionElement.cpp", + "HTMLOptionsCollection.cpp", + "HTMLOutputElement.cpp", + "HTMLParagraphElement.cpp", + "HTMLPictureElement.cpp", + "HTMLPreElement.cpp", + "HTMLProgressElement.cpp", + "HTMLScriptElement.cpp", + "HTMLSelectElement.cpp", + "HTMLSharedElement.cpp", + "HTMLSharedListElement.cpp", + "HTMLSlotElement.cpp", + "HTMLSourceElement.cpp", + "HTMLSpanElement.cpp", + "HTMLStyleElement.cpp", + "HTMLSummaryElement.cpp", + "HTMLTableCaptionElement.cpp", + "HTMLTableCellElement.cpp", + "HTMLTableColElement.cpp", + "HTMLTableElement.cpp", + "HTMLTableRowElement.cpp", + "HTMLTableSectionElement.cpp", + "HTMLTemplateElement.cpp", + "HTMLTextAreaElement.cpp", + "HTMLTimeElement.cpp", + "HTMLTitleElement.cpp", + "HTMLTrackElement.cpp", + "HTMLUnknownElement.cpp", + "HTMLVideoElement.cpp", + "ImageDocument.cpp", + "MediaDocument.cpp", + "MediaError.cpp", + "nsBrowserElement.cpp", + "nsDOMStringMap.cpp", + "nsGenericHTMLElement.cpp", + "nsGenericHTMLFrameElement.cpp", + "nsHTMLContentSink.cpp", + "nsHTMLDocument.cpp", + "nsIConstraintValidation.cpp", + "nsRadioVisitor.cpp", + "PlayPromise.cpp", + "RadioNodeList.cpp", + "TextControlState.cpp", + "TextTrackManager.cpp", + "TimeRanges.cpp", + "ValidityState.cpp", + "VideoDocument.cpp", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +LOCAL_INCLUDES += [ + "/caps", + "/docshell/base", + "/dom/base", + "/dom/canvas", + "/dom/html/input", + "/dom/media", + "/dom/security", + "/dom/xul", + "/image", + "/layout/forms", + "/layout/generic", + "/layout/style", + "/layout/tables", + "/layout/xul", + "/netwerk/base", + "/parser/htmlparser", +] + +FINAL_LIBRARY = "xul" + +if CONFIG["MOZ_ANDROID_HLS_SUPPORT"]: + DEFINES["MOZ_ANDROID_HLS_SUPPORT"] = True diff --git a/dom/html/nsBrowserElement.cpp b/dom/html/nsBrowserElement.cpp new file mode 100644 index 0000000000..69284e77ab --- /dev/null +++ b/dom/html/nsBrowserElement.cpp @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "nsBrowserElement.h" + +#include "mozilla/Preferences.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/dom/ToJSValue.h" + +#include "nsComponentManagerUtils.h" +#include "nsFrameLoader.h" +#include "nsINode.h" + +#include "js/Wrapper.h" + +using namespace mozilla::dom; + +namespace mozilla { + +bool nsBrowserElement::IsBrowserElementOrThrow(ErrorResult& aRv) { + if (mBrowserElementAPI) { + return true; + } + aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR); + return false; +} + +void nsBrowserElement::InitBrowserElementAPI() { + RefPtr frameLoader = GetFrameLoader(); + NS_ENSURE_TRUE_VOID(frameLoader); + + if (!frameLoader->OwnerIsMozBrowserFrame()) { + return; + } + + if (!mBrowserElementAPI) { + mBrowserElementAPI = + do_CreateInstance("@mozilla.org/dom/browser-element-api;1"); + if (NS_WARN_IF(!mBrowserElementAPI)) { + return; + } + } + mBrowserElementAPI->SetFrameLoader(frameLoader); +} + +void nsBrowserElement::DestroyBrowserElementFrameScripts() { + if (!mBrowserElementAPI) { + return; + } + mBrowserElementAPI->DestroyFrameScripts(); +} + +} // namespace mozilla diff --git a/dom/html/nsBrowserElement.h b/dom/html/nsBrowserElement.h new file mode 100644 index 0000000000..c81529de33 --- /dev/null +++ b/dom/html/nsBrowserElement.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef nsBrowserElement_h +#define nsBrowserElement_h + +#include "mozilla/dom/BindingDeclarations.h" + +#include "nsCOMPtr.h" +#include "nsIBrowserElementAPI.h" + +class nsFrameLoader; + +namespace mozilla { + +namespace dom { +class Promise; +} // namespace dom + +class ErrorResult; + +/** + * A helper class for browser-element frames + */ +class nsBrowserElement { + public: + nsBrowserElement() = default; + virtual ~nsBrowserElement() = default; + + void SendMouseEvent(const nsAString& aType, uint32_t aX, uint32_t aY, + uint32_t aButton, uint32_t aClickCount, + uint32_t aModifiers, ErrorResult& aRv); + void GoBack(ErrorResult& aRv); + void GoForward(ErrorResult& aRv); + void Reload(bool aHardReload, ErrorResult& aRv); + void Stop(ErrorResult& aRv); + + already_AddRefed GetCanGoBack(ErrorResult& aRv); + already_AddRefed GetCanGoForward(ErrorResult& aRv); + + protected: + virtual already_AddRefed GetFrameLoader() = 0; + + void InitBrowserElementAPI(); + void DestroyBrowserElementFrameScripts(); + nsCOMPtr mBrowserElementAPI; + + private: + bool IsBrowserElementOrThrow(ErrorResult& aRv); +}; + +} // namespace mozilla + +#endif // nsBrowserElement_h diff --git a/dom/html/nsDOMStringMap.cpp b/dom/html/nsDOMStringMap.cpp new file mode 100644 index 0000000000..0f2171ed79 --- /dev/null +++ b/dom/html/nsDOMStringMap.cpp @@ -0,0 +1,242 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "nsDOMStringMap.h" + +#include "jsapi.h" +#include "nsError.h" +#include "nsGenericHTMLElement.h" +#include "nsContentUtils.h" +#include "mozilla/dom/DOMStringMapBinding.h" +#include "mozilla/dom/MutationEventBinding.h" + +using namespace mozilla; +using namespace mozilla::dom; + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(nsDOMStringMap) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStringMap) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER + // Check that mElement exists in case the unlink code is run more than once. + if (tmp->mElement) { + // Call back to element to null out weak reference to this object. + tmp->mElement->ClearDataset(); + tmp->mElement->RemoveMutationObserver(tmp); + tmp->mElement = nullptr; + } + tmp->mExpandoAndGeneration.OwnerUnlinked(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStringMap) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsIMutationObserver) + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMStringMap) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMStringMap) + +nsDOMStringMap::nsDOMStringMap(Element* aElement) + : mElement(aElement), mRemovingProp(false) { + mElement->AddMutationObserver(this); +} + +nsDOMStringMap::~nsDOMStringMap() { + // Check if element still exists, may have been unlinked by cycle collector. + if (mElement) { + // Call back to element to null out weak reference to this object. + mElement->ClearDataset(); + mElement->RemoveMutationObserver(this); + } +} + +DocGroup* nsDOMStringMap::GetDocGroup() const { + return mElement ? mElement->GetDocGroup() : nullptr; +} + +/* virtual */ +JSObject* nsDOMStringMap::WrapObject(JSContext* cx, + JS::Handle aGivenProto) { + return DOMStringMap_Binding::Wrap(cx, this, aGivenProto); +} + +void nsDOMStringMap::NamedGetter(const nsAString& aProp, bool& found, + DOMString& aResult) const { + nsAutoString attr; + + if (!DataPropToAttr(aProp, attr)) { + found = false; + return; + } + + found = mElement->GetAttr(attr, aResult); +} + +void nsDOMStringMap::NamedSetter(const nsAString& aProp, + const nsAString& aValue, ErrorResult& rv) { + nsAutoString attr; + if (!DataPropToAttr(aProp, attr)) { + rv.Throw(NS_ERROR_DOM_SYNTAX_ERR); + return; + } + + nsresult res = nsContentUtils::CheckQName(attr, false); + if (NS_FAILED(res)) { + rv.Throw(res); + return; + } + + RefPtr attrAtom = NS_Atomize(attr); + MOZ_ASSERT(attrAtom, "Should be infallible"); + + res = mElement->SetAttr(kNameSpaceID_None, attrAtom, aValue, true); + if (NS_FAILED(res)) { + rv.Throw(res); + } +} + +void nsDOMStringMap::NamedDeleter(const nsAString& aProp, bool& found) { + // Currently removing property, attribute is already removed. + if (mRemovingProp) { + found = false; + return; + } + + nsAutoString attr; + if (!DataPropToAttr(aProp, attr)) { + found = false; + return; + } + + RefPtr attrAtom = NS_Atomize(attr); + MOZ_ASSERT(attrAtom, "Should be infallible"); + + found = mElement->HasAttr(kNameSpaceID_None, attrAtom); + + if (found) { + mRemovingProp = true; + mElement->UnsetAttr(kNameSpaceID_None, attrAtom, true); + mRemovingProp = false; + } +} + +void nsDOMStringMap::GetSupportedNames(nsTArray& aNames) { + uint32_t attrCount = mElement->GetAttrCount(); + + // Iterate through all the attributes and add property + // names corresponding to data attributes to return array. + for (uint32_t i = 0; i < attrCount; ++i) { + const nsAttrName* attrName = mElement->GetAttrNameAt(i); + // Skip the ones that are not in the null namespace + if (attrName->NamespaceID() != kNameSpaceID_None) { + continue; + } + + nsAutoString prop; + if (!AttrToDataProp(nsDependentAtomString(attrName->LocalName()), prop)) { + continue; + } + + aNames.AppendElement(prop); + } +} + +/** + * Converts a dataset property name to the corresponding data attribute name. + * (ex. aBigFish to data-a-big-fish). + */ +bool nsDOMStringMap::DataPropToAttr(const nsAString& aProp, + nsAutoString& aResult) { + // aResult is an autostring, so don't worry about setting its capacity: + // SetCapacity is slow even when it's a no-op and we already have enough + // storage there for most cases, probably. + aResult.AppendLiteral("data-"); + + // Iterate property by character to form attribute name. + // Return syntax error if there is a sequence of "-" followed by a character + // in the range "a" to "z". + // Replace capital characters with "-" followed by lower case character. + // Otherwise, simply append character to attribute name. + const char16_t* start = aProp.BeginReading(); + const char16_t* end = aProp.EndReading(); + const char16_t* cur = start; + for (; cur < end; ++cur) { + const char16_t* next = cur + 1; + if (char16_t('-') == *cur && next < end && char16_t('a') <= *next && + *next <= char16_t('z')) { + // Syntax error if character following "-" is in range "a" to "z". + return false; + } + + if (char16_t('A') <= *cur && *cur <= char16_t('Z')) { + // Append the characters in the range [start, cur) + aResult.Append(start, cur - start); + // Uncamel-case characters in the range of "A" to "Z". + aResult.Append(char16_t('-')); + aResult.Append(*cur - 'A' + 'a'); + start = next; // We've already appended the thing at *cur + } + } + + aResult.Append(start, cur - start); + + return true; +} + +/** + * Converts a data attribute name to the corresponding dataset property name. + * (ex. data-a-big-fish to aBigFish). + */ +bool nsDOMStringMap::AttrToDataProp(const nsAString& aAttr, + nsAutoString& aResult) { + // If the attribute name does not begin with "data-" then it can not be + // a data attribute. + if (!StringBeginsWith(aAttr, u"data-"_ns)) { + return false; + } + + // Start reading attribute from first character after "data-". + const char16_t* cur = aAttr.BeginReading() + 5; + const char16_t* end = aAttr.EndReading(); + + // Don't try to mess with aResult's capacity: the probably-no-op SetCapacity() + // call is not that fast. + + // Iterate through attrName by character to form property name. + // If there is a sequence of "-" followed by a character in the range "a" to + // "z" then replace with upper case letter. + // Otherwise append character to property name. + for (; cur < end; ++cur) { + const char16_t* next = cur + 1; + if (char16_t('-') == *cur && next < end && char16_t('a') <= *next && + *next <= char16_t('z')) { + // Upper case the lower case letters that follow a "-". + aResult.Append(*next - 'a' + 'A'); + // Consume character to account for "-" character. + ++cur; + } else { + // Simply append character if camel case is not necessary. + aResult.Append(*cur); + } + } + + return true; +} + +void nsDOMStringMap::AttributeChanged(Element* aElement, int32_t aNameSpaceID, + nsAtom* aAttribute, int32_t aModType, + const nsAttrValue* aOldValue) { + if ((aModType == MutationEvent_Binding::ADDITION || + aModType == MutationEvent_Binding::REMOVAL) && + aNameSpaceID == kNameSpaceID_None && + StringBeginsWith(nsDependentAtomString(aAttribute), u"data-"_ns)) { + ++mExpandoAndGeneration.generation; + } +} diff --git a/dom/html/nsDOMStringMap.h b/dom/html/nsDOMStringMap.h new file mode 100644 index 0000000000..a5b3a20832 --- /dev/null +++ b/dom/html/nsDOMStringMap.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef nsDOMStringMap_h +#define nsDOMStringMap_h + +#include "nsCycleCollectionParticipant.h" +#include "nsStubMutationObserver.h" +#include "nsTArray.h" +#include "nsString.h" +#include "nsWrapperCache.h" +#include "js/friend/DOMProxy.h" // JS::ExpandoAndGeneration +#include "js/RootingAPI.h" // JS::Handle + +// XXX Avoid including this here by moving function bodies to the cpp file +#include "mozilla/dom/Element.h" + +namespace mozilla { +class ErrorResult; +namespace dom { +class DOMString; +class DocGroup; +} // namespace dom +} // namespace mozilla + +class nsDOMStringMap : public nsStubMutationObserver, public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(nsDOMStringMap) + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + + nsINode* GetParentObject() { return mElement; } + + mozilla::dom::DocGroup* GetDocGroup() const; + + explicit nsDOMStringMap(mozilla::dom::Element* aElement); + + // WebIDL API + virtual JSObject* WrapObject(JSContext* cx, + JS::Handle aGivenProto) override; + void NamedGetter(const nsAString& aProp, bool& found, + mozilla::dom::DOMString& aResult) const; + void NamedSetter(const nsAString& aProp, const nsAString& aValue, + mozilla::ErrorResult& rv); + void NamedDeleter(const nsAString& aProp, bool& found); + void GetSupportedNames(nsTArray& aNames); + + JS::ExpandoAndGeneration mExpandoAndGeneration; + + private: + virtual ~nsDOMStringMap(); + + protected: + RefPtr mElement; + // Flag to guard against infinite recursion. + bool mRemovingProp; + static bool DataPropToAttr(const nsAString& aProp, nsAutoString& aResult); + static bool AttrToDataProp(const nsAString& aAttr, nsAutoString& aResult); +}; + +#endif diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp new file mode 100644 index 0000000000..c49a896f90 --- /dev/null +++ b/dom/html/nsGenericHTMLElement.cpp @@ -0,0 +1,3568 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/ArrayUtils.h" +#include "mozilla/DeclarationBlock.h" +#include "mozilla/EditorBase.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/EventListenerManager.h" +#include "mozilla/EventStateManager.h" +#include "mozilla/HTMLEditor.h" +#include "mozilla/IMEContentObserver.h" +#include "mozilla/IMEStateManager.h" +#include "mozilla/MappedDeclarations.h" +#include "mozilla/Maybe.h" +#include "mozilla/Likely.h" +#include "mozilla/MouseEvents.h" +#include "mozilla/PresShell.h" +#include "mozilla/TextEditor.h" +#include "mozilla/TextEvents.h" +#include "mozilla/StaticPrefs_html5.h" +#include "mozilla/StaticPrefs_layout.h" +#include "mozilla/StaticPrefs_accessibility.h" + +#include "nscore.h" +#include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" +#include "nsCOMPtr.h" +#include "nsAtom.h" +#include "nsQueryObject.h" +#include "nsIContentInlines.h" +#include "mozilla/dom/BindContext.h" +#include "mozilla/dom/Document.h" +#include "nsMappedAttributes.h" +#include "nsHTMLStyleSheet.h" +#include "nsPIDOMWindow.h" +#include "nsEscape.h" +#include "nsIFrameInlines.h" +#include "nsIScrollableFrame.h" +#include "nsView.h" +#include "nsViewManager.h" +#include "nsIWidget.h" +#include "nsRange.h" +#include "nsPresContext.h" +#include "nsNameSpaceManager.h" +#include "nsError.h" +#include "nsIPrincipal.h" +#include "nsContainerFrame.h" +#include "nsStyleUtil.h" +#include "ReferrerInfo.h" + +#include "mozilla/PresState.h" +#include "nsILayoutHistoryState.h" + +#include "nsHTMLParts.h" +#include "nsContentUtils.h" +#include "mozilla/dom/DirectionalityUtils.h" +#include "mozilla/dom/DocumentOrShadowRoot.h" +#include "nsString.h" +#include "nsUnicharUtils.h" +#include "nsGkAtoms.h" +#include "nsDOMCSSDeclaration.h" +#include "nsITextControlFrame.h" +#include "nsIFormControl.h" +#include "mozilla/dom/HTMLFormElement.h" +#include "nsFocusManager.h" + +#include "mozilla/InternalMutationEvent.h" +#include "nsDOMStringMap.h" +#include "nsDOMString.h" + +#include "nsLayoutUtils.h" +#include "mozAutoDocUpdate.h" +#include "nsHtml5Module.h" +#include "mozilla/dom/DocumentInlines.h" +#include "mozilla/dom/ElementInlines.h" +#include "HTMLFieldSetElement.h" +#include "nsTextNode.h" +#include "HTMLBRElement.h" +#include "nsDOMMutationObserver.h" +#include "mozilla/Preferences.h" +#include "mozilla/dom/FromParser.h" +#include "mozilla/dom/Link.h" +#include "mozilla/BloomFilter.h" +#include "mozilla/dom/ScriptLoader.h" + +#include "nsVariant.h" +#include "nsDOMTokenList.h" +#include "nsThreadUtils.h" +#include "nsTextFragment.h" +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/MouseEventBinding.h" +#include "mozilla/dom/ToggleEvent.h" +#include "mozilla/dom/TouchEvent.h" +#include "mozilla/ErrorResult.h" +#include "nsHTMLDocument.h" +#include "nsGlobalWindow.h" +#include "mozilla/dom/HTMLBodyElement.h" +#include "imgIContainer.h" +#include "nsComputedDOMStyle.h" +#include "mozilla/dom/HTMLDialogElement.h" +#include "mozilla/dom/HTMLLabelElement.h" +#include "mozilla/dom/HTMLInputElement.h" +#include "mozilla/dom/CustomElementRegistry.h" +#include "mozilla/dom/ElementBinding.h" +#include "mozilla/dom/ElementInternals.h" + +using namespace mozilla; +using namespace mozilla::dom; + +static const uint8_t NS_INPUTMODE_NONE = 1; +static const uint8_t NS_INPUTMODE_TEXT = 2; +static const uint8_t NS_INPUTMODE_TEL = 3; +static const uint8_t NS_INPUTMODE_URL = 4; +static const uint8_t NS_INPUTMODE_EMAIL = 5; +static const uint8_t NS_INPUTMODE_NUMERIC = 6; +static const uint8_t NS_INPUTMODE_DECIMAL = 7; +static const uint8_t NS_INPUTMODE_SEARCH = 8; + +static const nsAttrValue::EnumTable kInputmodeTable[] = { + {"none", NS_INPUTMODE_NONE}, + {"text", NS_INPUTMODE_TEXT}, + {"tel", NS_INPUTMODE_TEL}, + {"url", NS_INPUTMODE_URL}, + {"email", NS_INPUTMODE_EMAIL}, + {"numeric", NS_INPUTMODE_NUMERIC}, + {"decimal", NS_INPUTMODE_DECIMAL}, + {"search", NS_INPUTMODE_SEARCH}, + {nullptr, 0}}; + +static const uint8_t NS_ENTERKEYHINT_ENTER = 1; +static const uint8_t NS_ENTERKEYHINT_DONE = 2; +static const uint8_t NS_ENTERKEYHINT_GO = 3; +static const uint8_t NS_ENTERKEYHINT_NEXT = 4; +static const uint8_t NS_ENTERKEYHINT_PREVIOUS = 5; +static const uint8_t NS_ENTERKEYHINT_SEARCH = 6; +static const uint8_t NS_ENTERKEYHINT_SEND = 7; + +static const nsAttrValue::EnumTable kEnterKeyHintTable[] = { + {"enter", NS_ENTERKEYHINT_ENTER}, + {"done", NS_ENTERKEYHINT_DONE}, + {"go", NS_ENTERKEYHINT_GO}, + {"next", NS_ENTERKEYHINT_NEXT}, + {"previous", NS_ENTERKEYHINT_PREVIOUS}, + {"search", NS_ENTERKEYHINT_SEARCH}, + {"send", NS_ENTERKEYHINT_SEND}, + {nullptr, 0}}; + +static const uint8_t NS_AUTOCAPITALIZE_NONE = 1; +static const uint8_t NS_AUTOCAPITALIZE_SENTENCES = 2; +static const uint8_t NS_AUTOCAPITALIZE_WORDS = 3; +static const uint8_t NS_AUTOCAPITALIZE_CHARACTERS = 4; + +static const nsAttrValue::EnumTable kAutocapitalizeTable[] = { + {"none", NS_AUTOCAPITALIZE_NONE}, + {"sentences", NS_AUTOCAPITALIZE_SENTENCES}, + {"words", NS_AUTOCAPITALIZE_WORDS}, + {"characters", NS_AUTOCAPITALIZE_CHARACTERS}, + {"off", NS_AUTOCAPITALIZE_NONE}, + {"on", NS_AUTOCAPITALIZE_SENTENCES}, + {"", 0}, + {nullptr, 0}}; + +static const nsAttrValue::EnumTable* kDefaultAutocapitalize = + &kAutocapitalizeTable[1]; + +nsresult nsGenericHTMLElement::CopyInnerTo(Element* aDst) { + MOZ_ASSERT(!aDst->GetUncomposedDoc(), + "Should not CopyInnerTo an Element in a document"); + + auto reparse = aDst->OwnerDoc() == OwnerDoc() ? ReparseAttributes::No + : ReparseAttributes::Yes; + nsresult rv = Element::CopyInnerTo(aDst, reparse); + NS_ENSURE_SUCCESS(rv, rv); + + // cloning a node must retain its internal nonce slot + nsString* nonce = static_cast(GetProperty(nsGkAtoms::nonce)); + if (nonce) { + static_cast(aDst)->SetNonce(*nonce); + } + return NS_OK; +} + +static const nsAttrValue::EnumTable kDirTable[] = { + {"ltr", eDir_LTR}, {"rtl", eDir_RTL}, {"auto", eDir_Auto}, {nullptr, 0}}; + +namespace { +// See . +enum class PopoverAttributeKeyword : uint8_t { Auto, EmptyString, Manual }; + +static const char* kPopoverAttributeValueAuto = "auto"; +static const char* kPopoverAttributeValueEmptyString = ""; +static const char* kPopoverAttributeValueManual = "manual"; + +static const nsAttrValue::EnumTable kPopoverTable[] = { + {kPopoverAttributeValueAuto, PopoverAttributeKeyword::Auto}, + {kPopoverAttributeValueEmptyString, PopoverAttributeKeyword::EmptyString}, + {kPopoverAttributeValueManual, PopoverAttributeKeyword::Manual}, + {nullptr, 0}}; + +// See . +static const nsAttrValue::EnumTable* kPopoverTableInvalidValueDefault = + &kPopoverTable[2]; +} // namespace + +void nsGenericHTMLElement::AddToNameTable(nsAtom* aName) { + MOZ_ASSERT(HasName(), "Node doesn't have name?"); + Document* doc = GetUncomposedDoc(); + if (doc && !IsInNativeAnonymousSubtree()) { + doc->AddToNameTable(this, aName); + } +} + +void nsGenericHTMLElement::RemoveFromNameTable() { + if (HasName() && CanHaveName(NodeInfo()->NameAtom())) { + if (Document* doc = GetUncomposedDoc()) { + doc->RemoveFromNameTable(this, + GetParsedAttr(nsGkAtoms::name)->GetAtomValue()); + } + } +} + +void nsGenericHTMLElement::GetAccessKeyLabel(nsString& aLabel) { + nsAutoString suffix; + GetAccessKey(suffix); + if (!suffix.IsEmpty()) { + EventStateManager::GetAccessKeyLabelPrefix(this, aLabel); + aLabel.Append(suffix); + } +} + +static bool IsOffsetParent(nsIFrame* aFrame) { + LayoutFrameType frameType = aFrame->Type(); + + if (frameType == LayoutFrameType::TableCell || + frameType == LayoutFrameType::Table) { + // Per the IDL for Element, only td, th, and table are acceptable + // offsetParents apart from body or positioned elements; we need to check + // the content type as well as the frame type so we ignore anonymous tables + // created by an element with display: table-cell with no actual table + nsIContent* content = aFrame->GetContent(); + + return content->IsAnyOfHTMLElements(nsGkAtoms::table, nsGkAtoms::td, + nsGkAtoms::th); + } + return false; +} + +struct OffsetResult { + Element* mParent = nullptr; + CSSIntRect mRect; +}; + +static OffsetResult GetUnretargetedOffsetsFor(const Element& aElement) { + nsIFrame* frame = aElement.GetPrimaryFrame(); + if (!frame) { + return {}; + } + + nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(frame); + + nsIFrame* parent = frame->GetParent(); + nsPoint origin(0, 0); + + nsIContent* offsetParent = nullptr; + Element* docElement = aElement.GetComposedDoc()->GetRootElement(); + nsIContent* content = frame->GetContent(); + + if (content && + (content->IsHTMLElement(nsGkAtoms::body) || content == docElement)) { + parent = frame; + } else { + const bool isPositioned = styleFrame->IsAbsPosContainingBlock(); + const bool isAbsolutelyPositioned = frame->IsAbsolutelyPositioned(); + origin += frame->GetPositionIgnoringScrolling(); + + for (; parent; parent = parent->GetParent()) { + content = parent->GetContent(); + + // Stop at the first ancestor that is positioned. + if (parent->IsAbsPosContainingBlock()) { + offsetParent = content; + break; + } + + // Add the parent's origin to our own to get to the + // right coordinate system. + const bool isOffsetParent = !isPositioned && IsOffsetParent(parent); + if (!isOffsetParent) { + origin += parent->GetPositionIgnoringScrolling(); + } + + if (content) { + // If we've hit the document element, break here. + if (content == docElement) { + break; + } + + // Break if the ancestor frame type makes it suitable as offset parent + // and this element is *not* positioned or if we found the body element. + if (isOffsetParent || content->IsHTMLElement(nsGkAtoms::body)) { + offsetParent = content; + break; + } + } + } + + if (isAbsolutelyPositioned && !offsetParent) { + // If this element is absolutely positioned, but we don't have + // an offset parent it means this element is an absolutely + // positioned child that's not nested inside another positioned + // element, in this case the element's frame's parent is the + // frame for the HTML element so we fail to find the body in the + // parent chain. We want the offset parent in this case to be + // the body, so we just get the body element from the document. + // + // We use GetBodyElement() here, not GetBody(), because we don't want to + // end up with framesets here. + offsetParent = aElement.GetComposedDoc()->GetBodyElement(); + } + } + + // Make the position relative to the padding edge. + if (parent) { + const nsStyleBorder* border = parent->StyleBorder(); + origin.x -= border->GetComputedBorderWidth(eSideLeft); + origin.y -= border->GetComputedBorderWidth(eSideTop); + } + + // Get the union of all rectangles in this and continuation frames. + // It doesn't really matter what we use as aRelativeTo here, since + // we only care about the size. We just have to use something non-null. + nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, frame); + rcFrame.MoveTo(origin); + return {Element::FromNodeOrNull(offsetParent), + CSSIntRect::FromAppUnitsRounded(rcFrame)}; +} + +static bool ShouldBeRetargeted(const Element& aReferenceElement, + const Element& aElementToMaybeRetarget) { + ShadowRoot* shadow = aElementToMaybeRetarget.GetContainingShadow(); + if (!shadow) { + return false; + } + for (ShadowRoot* scope = aReferenceElement.GetContainingShadow(); scope; + scope = scope->Host()->GetContainingShadow()) { + if (scope == shadow) { + return false; + } + } + + return true; +} + +Element* nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect) { + aRect = CSSIntRect(); + + if (!GetPrimaryFrame(FlushType::Layout)) { + return nullptr; + } + + OffsetResult thisResult = GetUnretargetedOffsetsFor(*this); + aRect = thisResult.mRect; + + Element* parent = thisResult.mParent; + while (parent && ShouldBeRetargeted(*this, *parent)) { + OffsetResult result = GetUnretargetedOffsetsFor(*parent); + aRect += result.mRect.TopLeft(); + parent = result.mParent; + } + + return parent; +} + +bool nsGenericHTMLElement::Spellcheck() { + // Has the state has been explicitly set? + nsIContent* node; + for (node = this; node; node = node->GetParent()) { + if (node->IsHTMLElement()) { + static Element::AttrValuesArray strings[] = {nsGkAtoms::_true, + nsGkAtoms::_false, nullptr}; + switch (node->AsElement()->FindAttrValueIn( + kNameSpaceID_None, nsGkAtoms::spellcheck, strings, eCaseMatters)) { + case 0: // spellcheck = "true" + return true; + case 1: // spellcheck = "false" + return false; + } + } + } + + // contenteditable/designMode are spellchecked by default + if (IsEditable()) { + return true; + } + + // Is this a chrome element? + if (nsContentUtils::IsChromeDoc(OwnerDoc())) { + return false; // Not spellchecked by default + } + + // Anything else that's not a form control is not spellchecked by default + nsCOMPtr formControl = do_QueryObject(this); + if (!formControl) { + return false; // Not spellchecked by default + } + + // Is this a multiline plaintext input? + auto controlType = formControl->ControlType(); + if (controlType == FormControlType::Textarea) { + return true; // Spellchecked by default + } + + // Is this anything other than an input text? + // Other inputs are not spellchecked. + if (controlType != FormControlType::InputText) { + return false; // Not spellchecked by default + } + + // Does the user want input text spellchecked by default? + // NOTE: Do not reflect a pref value of 0 back to the DOM getter. + // The web page should not know if the user has disabled spellchecking. + // We'll catch this in the editor itself. + int32_t spellcheckLevel = Preferences::GetInt("layout.spellcheckDefault", 1); + return spellcheckLevel == 2; // "Spellcheck multi- and single-line" +} + +bool nsGenericHTMLElement::InNavQuirksMode(Document* aDoc) { + return aDoc && aDoc->GetCompatibilityMode() == eCompatibility_NavQuirks; +} + +void nsGenericHTMLElement::UpdateEditableState(bool aNotify) { + // XXX Should we do this only when in a document? + ContentEditableTristate value = GetContentEditableValue(); + if (value != eInherit) { + DoSetEditableFlag(!!value, aNotify); + return; + } + + nsStyledElement::UpdateEditableState(aNotify); +} + +ElementState nsGenericHTMLElement::IntrinsicState() const { + ElementState state = nsGenericHTMLElementBase::IntrinsicState(); + + if (GetDirectionality() == eDir_RTL) { + state |= ElementState::RTL; + state &= ~ElementState::LTR; + } else { // at least for HTML, directionality is exclusively LTR or RTL + NS_ASSERTION(GetDirectionality() == eDir_LTR, + "HTML element's directionality must be either RTL or LTR"); + state |= ElementState::LTR; + state &= ~ElementState::RTL; + } + + return state; +} + +nsresult nsGenericHTMLElement::BindToTree(BindContext& aContext, + nsINode& aParent) { + nsresult rv = nsGenericHTMLElementBase::BindToTree(aContext, aParent); + NS_ENSURE_SUCCESS(rv, rv); + + if (IsInComposedDoc()) { + RegUnRegAccessKey(true); + } + + if (IsInUncomposedDoc()) { + if (HasName() && CanHaveName(NodeInfo()->NameAtom())) { + aContext.OwnerDoc().AddToNameTable( + this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue()); + } + } + + if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue && + IsInComposedDoc()) { + aContext.OwnerDoc().ChangeContentEditableCount(this, +1); + } + + // Hide any nonce from the DOM, but keep the internal value of the + // nonce by copying and resetting the internal nonce value. + if (HasFlag(NODE_HAS_NONCE_AND_HEADER_CSP) && IsInComposedDoc() && + OwnerDoc()->GetBrowsingContext()) { + nsContentUtils::AddScriptRunner(NS_NewRunnableFunction( + "nsGenericHTMLElement::ResetNonce::Runnable", + [self = RefPtr(this)]() { + nsAutoString nonce; + self->GetNonce(nonce); + self->SetAttr(kNameSpaceID_None, nsGkAtoms::nonce, u""_ns, true); + self->SetNonce(nonce); + })); + } + + // We need to consider a labels element is moved to another subtree + // with different root, it needs to update labels list and its root + // as well. + nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); + if (slots && slots->mLabelsList) { + slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); + } + + return rv; +} + +void nsGenericHTMLElement::UnbindFromTree(bool aNullParent) { + if (IsInComposedDoc()) { + // https://html.spec.whatwg.org/#dom-trees:hide-popover-algorithm + // If removedNode's popover attribute is not in the no popover state, then + // run the hide popover algorithm given removedNode, false, false, and + // false. + if (GetPopoverData()) { + HidePopoverWithoutRunningScript(); + } + RegUnRegAccessKey(false); + } + + RemoveFromNameTable(); + + if (GetContentEditableValue() == eTrue) { + Document* doc = GetComposedDoc(); + if (doc) { + doc->ChangeContentEditableCount(this, -1); + } + } + + nsStyledElement::UnbindFromTree(aNullParent); + + // Invalidate .labels list. It will be repopulated when used the next time. + nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); + if (slots && slots->mLabelsList) { + slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); + } +} + +HTMLFormElement* nsGenericHTMLElement::FindAncestorForm( + HTMLFormElement* aCurrentForm) { + NS_ASSERTION(!HasAttr(kNameSpaceID_None, nsGkAtoms::form) || + IsHTMLElement(nsGkAtoms::img), + "FindAncestorForm should not be called if @form is set!"); + if (IsInNativeAnonymousSubtree()) { + return nullptr; + } + + nsIContent* content = this; + while (content) { + // If the current ancestor is a form, return it as our form + if (content->IsHTMLElement(nsGkAtoms::form)) { +#ifdef DEBUG + if (!nsContentUtils::IsInSameAnonymousTree(this, content)) { + // It's possible that we started unbinding at |content| or + // some ancestor of it, and |content| and |this| used to all be + // anonymous. Check for this the hard way. + for (nsIContent* child = this; child != content; + child = child->GetParent()) { + NS_ASSERTION(child->ComputeIndexInParentContent().isSome(), + "Walked too far?"); + } + } +#endif + return static_cast(content); + } + + nsIContent* prevContent = content; + content = prevContent->GetParent(); + + if (!content && aCurrentForm) { + // We got to the root of the subtree we're in, and we're being removed + // from the DOM (the only time we get into this method with a non-null + // aCurrentForm). Check whether aCurrentForm is in the same subtree. If + // it is, we want to return aCurrentForm, since this case means that + // we're one of those inputs-in-a-table that have a hacked mForm pointer + // and a subtree containing both us and the form got removed from the + // DOM. + if (aCurrentForm->IsInclusiveDescendantOf(prevContent)) { + return aCurrentForm; + } + } + } + + return nullptr; +} + +bool nsGenericHTMLElement::CheckHandleEventForAnchorsPreconditions( + EventChainVisitor& aVisitor) { + MOZ_ASSERT(nsCOMPtr(do_QueryObject(this)), + "should be called only when |this| implements |Link|"); + // When disconnected, only
should navigate away per + // https://html.spec.whatwg.org/#cannot-navigate + return IsInComposedDoc() || IsHTMLElement(nsGkAtoms::a); +} + +void nsGenericHTMLElement::GetEventTargetParentForAnchors( + EventChainPreVisitor& aVisitor) { + nsGenericHTMLElementBase::GetEventTargetParent(aVisitor); + + if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) { + return; + } + + GetEventTargetParentForLinks(aVisitor); +} + +nsresult nsGenericHTMLElement::PostHandleEventForAnchors( + EventChainPostVisitor& aVisitor) { + if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) { + return NS_OK; + } + + return PostHandleEventForLinks(aVisitor); +} + +bool nsGenericHTMLElement::IsHTMLLink(nsIURI** aURI) const { + MOZ_ASSERT(aURI, "Must provide aURI out param"); + + *aURI = GetHrefURIForAnchors().take(); + // We promise out param is non-null if we return true, so base rv on it + return *aURI != nullptr; +} + +already_AddRefed nsGenericHTMLElement::GetHrefURIForAnchors() const { + // This is used by the three Link implementations and + // nsHTMLStyleElement. + + // Get href= attribute (relative URI). + + // We use the nsAttrValue's copy of the URI string to avoid copying. + nsCOMPtr uri; + GetURIAttr(nsGkAtoms::href, nullptr, getter_AddRefs(uri)); + + return uri.forget(); +} + +void nsGenericHTMLElement::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, + bool aNotify) { + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::accesskey) { + // Have to unregister before clearing flag. See UnregAccessKey + RegUnRegAccessKey(false); + if (!aValue) { + UnsetFlags(NODE_HAS_ACCESSKEY); + } + } else if (aName == nsGkAtoms::name) { + // Have to do this before clearing flag. See RemoveFromNameTable + RemoveFromNameTable(); + if (!aValue || aValue->IsEmptyString()) { + ClearHasName(); + } + } else if (aName == nsGkAtoms::contenteditable) { + if (aValue) { + // Set this before the attribute is set so that any subclass code that + // runs before the attribute is set won't think we're missing a + // contenteditable attr when we actually have one. + SetMayHaveContentEditableAttr(); + } + } + if (!aValue && IsEventAttributeName(aName)) { + if (EventListenerManager* manager = GetExistingListenerManager()) { + manager->RemoveEventHandler(GetEventNameForAttr(aName)); + } + } + } + + return nsGenericHTMLElementBase::BeforeSetAttr(aNamespaceID, aName, aValue, + aNotify); +} + +namespace { +constexpr PopoverAttributeState ToPopoverAttributeState( + PopoverAttributeKeyword aPopoverAttributeKeyword) { + // See . + switch (aPopoverAttributeKeyword) { + case PopoverAttributeKeyword::Auto: + return PopoverAttributeState::Auto; + case PopoverAttributeKeyword::EmptyString: + return PopoverAttributeState::Auto; + case PopoverAttributeKeyword::Manual: + return PopoverAttributeState::Manual; + default: { + MOZ_ASSERT_UNREACHABLE(); + return PopoverAttributeState::None; + } + } +} +} // namespace + +void nsGenericHTMLElement::AfterSetPopoverAttr() { + const nsAttrValue* newValue = GetParsedAttr(nsGkAtoms::popover); + + const PopoverAttributeState newState = [&newValue]() { + if (newValue) { + MOZ_ASSERT(newValue->Type() == nsAttrValue::eEnum); + const auto popoverAttributeKeyword = + static_cast(newValue->GetEnumValue()); + return ToPopoverAttributeState(popoverAttributeKeyword); + } + + // The missing value default is the no popover state, see + // . + return PopoverAttributeState::None; + }(); + + const PopoverAttributeState oldState = GetPopoverAttributeState(); + + if (newState != oldState) { + EnsurePopoverData().SetPopoverAttributeState(newState); + + HidePopoverInternal(/* aFocusPreviousElement = */ true, + /* aFireEvents = */ true, IgnoreErrors()); + + // In case `HidePopoverInternal` changed the state, keep the corresponding + // changes and don't overwrite anything here. + if (newState == GetPopoverAttributeState()) { + if (newState == PopoverAttributeState::None) { + // `HidePopoverInternal` above didn't remove the element from the top + // layer, because in that call, the element's popover attribute state + // was already `None`. Revisit this, when the spec is corrected + // (bug 1835811). + OwnerDoc()->RemovePopoverFromTopLayer(*this); + + ClearPopoverData(); + RemoveStates(ElementState::POPOVER_OPEN); + } else { + // TODO: what if `HidePopoverInternal` called `ShowPopup()`? + PopoverPseudoStateUpdate(false, true); + } + } + } +} + +void nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { + if (aNamespaceID == kNameSpaceID_None) { + if (IsEventAttributeName(aName) && aValue) { + MOZ_ASSERT(aValue->Type() == nsAttrValue::eString, + "Expected string value for script body"); + SetEventHandler(GetEventNameForAttr(aName), aValue->GetStringValue()); + } else if (aNotify && aName == nsGkAtoms::spellcheck) { + SyncEditorsOnSubtree(this); + } else if (aName == nsGkAtoms::popover && + StaticPrefs::dom_element_popover_enabled()) { + nsContentUtils::AddScriptRunner( + NewRunnableMethod("nsGenericHTMLElement::AfterSetPopoverAttr", this, + &nsGenericHTMLElement::AfterSetPopoverAttr)); + } else if (aName == nsGkAtoms::dir) { + Directionality dir = eDir_LTR; + // A boolean tracking whether we need to recompute our directionality. + // This needs to happen after we update our internal "dir" attribute + // state but before we call SetDirectionalityOnDescendants. + bool recomputeDirectionality = false; + // We don't want to have to keep getting the "dir" attribute in + // IntrinsicState, so we manually recompute our dir-related event states + // here and send the relevant update notifications. + ElementState dirStates; + if (aValue && aValue->Type() == nsAttrValue::eEnum) { + SetHasValidDir(); + dirStates |= ElementState::HAS_DIR_ATTR; + Directionality dirValue = (Directionality)aValue->GetEnumValue(); + if (dirValue == eDir_Auto) { + dirStates |= ElementState::HAS_DIR_ATTR_LIKE_AUTO; + } else { + dir = dirValue; + SetDirectionality(dir, aNotify); + if (dirValue == eDir_LTR) { + dirStates |= ElementState::HAS_DIR_ATTR_LTR; + } else { + MOZ_ASSERT(dirValue == eDir_RTL); + dirStates |= ElementState::HAS_DIR_ATTR_RTL; + } + } + } else { + if (aValue) { + // We have a value, just not a valid one. + dirStates |= ElementState::HAS_DIR_ATTR; + } + ClearHasValidDir(); + if (NodeInfo()->Equals(nsGkAtoms::bdi)) { + dirStates |= ElementState::HAS_DIR_ATTR_LIKE_AUTO; + } else { + recomputeDirectionality = true; + } + } + // Now figure out what's changed about our dir states. + ElementState oldDirStates = State() & ElementState::DIR_ATTR_STATES; + ElementState changedStates = dirStates ^ oldDirStates; + ToggleStates(changedStates, aNotify); + if (recomputeDirectionality) { + dir = RecomputeDirectionality(this, aNotify); + } + SetDirectionalityOnDescendants(this, dir, aNotify); + } else if (aName == nsGkAtoms::contenteditable) { + int32_t editableCountDelta = 0; + if (aOldValue && (aOldValue->Equals(u"true"_ns, eIgnoreCase) || + aOldValue->Equals(u""_ns, eIgnoreCase))) { + editableCountDelta = -1; + } + if (aValue && (aValue->Equals(u"true"_ns, eIgnoreCase) || + aValue->Equals(u""_ns, eIgnoreCase))) { + ++editableCountDelta; + } + ChangeEditableState(editableCountDelta); + } else if (aName == nsGkAtoms::accesskey) { + if (aValue && !aValue->Equals(u""_ns, eIgnoreCase)) { + SetFlags(NODE_HAS_ACCESSKEY); + RegUnRegAccessKey(true); + } + } else if (aName == nsGkAtoms::inert && + StaticPrefs::html5_inert_enabled()) { + if (aValue) { + AddStates(ElementState::INERT); + } else { + RemoveStates(ElementState::INERT); + } + } else if (aName == nsGkAtoms::name) { + if (aValue && !aValue->Equals(u""_ns, eIgnoreCase)) { + // This may not be quite right because we can have subclass code run + // before here. But in practice subclasses don't care about this flag, + // and in particular selector matching does not care. Otherwise we'd + // want to handle it like we handle id attributes (in PreIdMaybeChange + // and PostIdMaybeChange). + SetHasName(); + if (CanHaveName(NodeInfo()->NameAtom())) { + AddToNameTable(aValue->GetAtomValue()); + } + } + } else if ((aName == nsGkAtoms::inputmode && + StaticPrefs::dom_forms_inputmode()) || + (aName == nsGkAtoms::enterkeyhint && + StaticPrefs::dom_forms_enterkeyhint())) { + nsPIDOMWindowOuter* window = OwnerDoc()->GetWindow(); + if (window && window->GetFocusedElement() == this) { + if (IMEContentObserver* observer = + IMEStateManager::GetActiveContentObserver()) { + if (const nsPresContext* presContext = + GetPresContext(eForComposedDoc)) { + if (observer->IsManaging(*presContext, this)) { + if (RefPtr editor = + nsContentUtils::GetActiveEditor(window)) { + IMEState newState; + editor->GetPreferredIMEState(&newState); + OwningNonNull kungFuDeathGrip(*this); + IMEStateManager::UpdateIMEState( + newState, kungFuDeathGrip, *editor, + {IMEStateManager::UpdateIMEStateOption::ForceUpdate, + IMEStateManager::UpdateIMEStateOption:: + DontCommitComposition}); + } + } + } + } + } + } + + // The nonce will be copied over to an internal slot and cleared from the + // Element within BindToTree to avoid CSS Selector nonce exfiltration if + // the CSP list contains a header-delivered CSP. + if (nsGkAtoms::nonce == aName) { + if (aValue) { + SetNonce(aValue->GetStringValue()); + if (OwnerDoc()->GetHasCSPDeliveredThroughHeader()) { + SetFlags(NODE_HAS_NONCE_AND_HEADER_CSP); + } + } else { + RemoveNonce(); + } + } + } + + return nsGenericHTMLElementBase::AfterSetAttr( + aNamespaceID, aName, aValue, aOldValue, aMaybeScriptedPrincipal, aNotify); +} + +EventListenerManager* nsGenericHTMLElement::GetEventListenerManagerForAttr( + nsAtom* aAttrName, bool* aDefer) { + // Attributes on the body and frameset tags get set on the global object + if ((mNodeInfo->Equals(nsGkAtoms::body) || + mNodeInfo->Equals(nsGkAtoms::frameset)) && + // We only forward some event attributes from body/frameset to window + (0 +#define EVENT(name_, id_, type_, struct_) /* nothing */ +#define FORWARDED_EVENT(name_, id_, type_, struct_) \ + || nsGkAtoms::on##name_ == aAttrName +#define WINDOW_EVENT FORWARDED_EVENT +#include "mozilla/EventNameList.h" // IWYU pragma: keep +#undef WINDOW_EVENT +#undef FORWARDED_EVENT +#undef EVENT + )) { + nsPIDOMWindowInner* win; + + // If we have a document, and it has a window, add the event + // listener on the window (the inner window). If not, proceed as + // normal. + // XXXbz sXBL/XBL2 issue: should we instead use GetComposedDoc() here, + // override BindToTree for those classes and munge event listeners there? + Document* document = OwnerDoc(); + + *aDefer = false; + if ((win = document->GetInnerWindow())) { + nsCOMPtr piTarget(do_QueryInterface(win)); + + return piTarget->GetOrCreateListenerManager(); + } + + return nullptr; + } + + return nsGenericHTMLElementBase::GetEventListenerManagerForAttr(aAttrName, + aDefer); +} + +#define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */ +#define FORWARDED_EVENT(name_, id_, type_, struct_) \ + EventHandlerNonNull* nsGenericHTMLElement::GetOn##name_() { \ + if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) { \ + /* XXXbz note to self: add tests for this! */ \ + if (nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow()) { \ + nsGlobalWindowInner* globalWin = nsGlobalWindowInner::Cast(win); \ + return globalWin->GetOn##name_(); \ + } \ + return nullptr; \ + } \ + \ + return nsINode::GetOn##name_(); \ + } \ + void nsGenericHTMLElement::SetOn##name_(EventHandlerNonNull* handler) { \ + if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) { \ + nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow(); \ + if (!win) { \ + return; \ + } \ + \ + nsGlobalWindowInner* globalWin = nsGlobalWindowInner::Cast(win); \ + return globalWin->SetOn##name_(handler); \ + } \ + \ + return nsINode::SetOn##name_(handler); \ + } +#define ERROR_EVENT(name_, id_, type_, struct_) \ + already_AddRefed nsGenericHTMLElement::GetOn##name_() { \ + if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) { \ + /* XXXbz note to self: add tests for this! */ \ + if (nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow()) { \ + nsGlobalWindowInner* globalWin = nsGlobalWindowInner::Cast(win); \ + OnErrorEventHandlerNonNull* errorHandler = globalWin->GetOn##name_(); \ + if (errorHandler) { \ + RefPtr handler = \ + new EventHandlerNonNull(errorHandler); \ + return handler.forget(); \ + } \ + } \ + return nullptr; \ + } \ + \ + RefPtr handler = nsINode::GetOn##name_(); \ + return handler.forget(); \ + } \ + void nsGenericHTMLElement::SetOn##name_(EventHandlerNonNull* handler) { \ + if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) { \ + nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow(); \ + if (!win) { \ + return; \ + } \ + \ + nsGlobalWindowInner* globalWin = nsGlobalWindowInner::Cast(win); \ + RefPtr errorHandler; \ + if (handler) { \ + errorHandler = new OnErrorEventHandlerNonNull(handler); \ + } \ + return globalWin->SetOn##name_(errorHandler); \ + } \ + \ + return nsINode::SetOn##name_(handler); \ + } +#include "mozilla/EventNameList.h" // IWYU pragma: keep +#undef ERROR_EVENT +#undef FORWARDED_EVENT +#undef EVENT + +void nsGenericHTMLElement::GetBaseTarget(nsAString& aBaseTarget) const { + OwnerDoc()->GetBaseTarget(aBaseTarget); +} + +//---------------------------------------------------------------------- + +bool nsGenericHTMLElement::ParseAttribute(int32_t aNamespaceID, + nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) { + if (aNamespaceID == kNameSpaceID_None) { + if (aAttribute == nsGkAtoms::dir) { + return aResult.ParseEnumValue(aValue, kDirTable, false); + } + + if (aAttribute == nsGkAtoms::popover && + StaticPrefs::dom_element_popover_enabled()) { + return aResult.ParseEnumValue(aValue, kPopoverTable, false, + kPopoverTableInvalidValueDefault); + } + + if (aAttribute == nsGkAtoms::tabindex) { + return aResult.ParseIntValue(aValue); + } + + if (aAttribute == nsGkAtoms::referrerpolicy) { + return ParseReferrerAttribute(aValue, aResult); + } + + if (aAttribute == nsGkAtoms::name) { + // Store name as an atom. name="" means that the element has no name, + // not that it has an empty string as the name. + if (aValue.IsEmpty()) { + return false; + } + aResult.ParseAtom(aValue); + return true; + } + + if (aAttribute == nsGkAtoms::contenteditable || + aAttribute == nsGkAtoms::translate) { + aResult.ParseAtom(aValue); + return true; + } + + if (aAttribute == nsGkAtoms::rel) { + aResult.ParseAtomArray(aValue); + return true; + } + + if (aAttribute == nsGkAtoms::inputmode) { + return aResult.ParseEnumValue(aValue, kInputmodeTable, false); + } + + if (aAttribute == nsGkAtoms::enterkeyhint) { + return aResult.ParseEnumValue(aValue, kEnterKeyHintTable, false); + } + + if (aAttribute == nsGkAtoms::autocapitalize) { + return aResult.ParseEnumValue(aValue, kAutocapitalizeTable, false); + } + } + + return nsGenericHTMLElementBase::ParseAttribute( + aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult); +} + +bool nsGenericHTMLElement::ParseBackgroundAttribute(int32_t aNamespaceID, + nsAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) { + if (aNamespaceID == kNameSpaceID_None && + aAttribute == nsGkAtoms::background && !aValue.IsEmpty()) { + // Resolve url to an absolute url + Document* doc = OwnerDoc(); + nsCOMPtr uri; + nsresult rv = nsContentUtils::NewURIWithDocumentCharset( + getter_AddRefs(uri), aValue, doc, GetBaseURI()); + if (NS_FAILED(rv)) { + return false; + } + aResult.SetTo(uri, &aValue); + return true; + } + + return false; +} + +bool nsGenericHTMLElement::IsAttributeMapped(const nsAtom* aAttribute) const { + static const MappedAttributeEntry* const map[] = {sCommonAttributeMap}; + + return FindAttributeDependence(aAttribute, map); +} + +nsMapRuleToAttributesFunc nsGenericHTMLElement::GetAttributeMappingFunction() + const { + return &MapCommonAttributesInto; +} + +nsIFormControlFrame* nsGenericHTMLElement::GetFormControlFrame( + bool aFlushFrames) { + auto flushType = aFlushFrames ? FlushType::Frames : FlushType::None; + nsIFrame* frame = GetPrimaryFrame(flushType); + if (!frame) { + return nullptr; + } + + if (nsIFormControlFrame* f = do_QueryFrame(frame)) { + return f; + } + + // If we have generated content, the primary frame will be a wrapper frame... + // Our real frame will be in its child list. + // + // FIXME(emilio): I don't think that's true... See bug 155957 for test-cases + // though, we should figure out whether this is still needed. + for (nsIFrame* kid : frame->PrincipalChildList()) { + if (nsIFormControlFrame* f = do_QueryFrame(kid)) { + return f; + } + } + + return nullptr; +} + +static const nsAttrValue::EnumTable kDivAlignTable[] = { + {"left", StyleTextAlign::MozLeft}, + {"right", StyleTextAlign::MozRight}, + {"center", StyleTextAlign::MozCenter}, + {"middle", StyleTextAlign::MozCenter}, + {"justify", StyleTextAlign::Justify}, + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kFrameborderTable[] = { + {"yes", FrameBorderProperty::Yes}, + {"no", FrameBorderProperty::No}, + {"1", FrameBorderProperty::One}, + {"0", FrameBorderProperty::Zero}, + {nullptr, 0}}; + +// TODO(emilio): Nobody uses the parsed attribute here. +static const nsAttrValue::EnumTable kScrollingTable[] = { + {"yes", ScrollingAttribute::Yes}, + {"no", ScrollingAttribute::No}, + {"on", ScrollingAttribute::On}, + {"off", ScrollingAttribute::Off}, + {"scroll", ScrollingAttribute::Scroll}, + {"noscroll", ScrollingAttribute::Noscroll}, + {"auto", ScrollingAttribute::Auto}, + {nullptr, 0}}; + +static const nsAttrValue::EnumTable kTableVAlignTable[] = { + {"top", StyleVerticalAlignKeyword::Top}, + {"middle", StyleVerticalAlignKeyword::Middle}, + {"bottom", StyleVerticalAlignKeyword::Bottom}, + {"baseline", StyleVerticalAlignKeyword::Baseline}, + {nullptr, 0}}; + +bool nsGenericHTMLElement::ParseAlignValue(const nsAString& aString, + nsAttrValue& aResult) { + static const nsAttrValue::EnumTable kAlignTable[] = { + {"left", StyleTextAlign::Left}, + {"right", StyleTextAlign::Right}, + + {"top", StyleVerticalAlignKeyword::Top}, + {"middle", StyleVerticalAlignKeyword::MozMiddleWithBaseline}, + + // Intentionally not bottom. + {"bottom", StyleVerticalAlignKeyword::Baseline}, + + {"center", StyleVerticalAlignKeyword::MozMiddleWithBaseline}, + {"baseline", StyleVerticalAlignKeyword::Baseline}, + + {"texttop", StyleVerticalAlignKeyword::TextTop}, + {"absmiddle", StyleVerticalAlignKeyword::Middle}, + {"abscenter", StyleVerticalAlignKeyword::Middle}, + {"absbottom", StyleVerticalAlignKeyword::Bottom}, + {nullptr, 0}}; + + static_assert(uint8_t(StyleTextAlign::Left) != + uint8_t(StyleVerticalAlignKeyword::Top) && + uint8_t(StyleTextAlign::Left) != + uint8_t(StyleVerticalAlignKeyword::MozMiddleWithBaseline) && + uint8_t(StyleTextAlign::Left) != + uint8_t(StyleVerticalAlignKeyword::Baseline) && + uint8_t(StyleTextAlign::Left) != + uint8_t(StyleVerticalAlignKeyword::TextTop) && + uint8_t(StyleTextAlign::Left) != + uint8_t(StyleVerticalAlignKeyword::Middle) && + uint8_t(StyleTextAlign::Left) != + uint8_t(StyleVerticalAlignKeyword::Bottom)); + + static_assert(uint8_t(StyleTextAlign::Right) != + uint8_t(StyleVerticalAlignKeyword::Top) && + uint8_t(StyleTextAlign::Right) != + uint8_t(StyleVerticalAlignKeyword::MozMiddleWithBaseline) && + uint8_t(StyleTextAlign::Right) != + uint8_t(StyleVerticalAlignKeyword::Baseline) && + uint8_t(StyleTextAlign::Right) != + uint8_t(StyleVerticalAlignKeyword::TextTop) && + uint8_t(StyleTextAlign::Right) != + uint8_t(StyleVerticalAlignKeyword::Middle) && + uint8_t(StyleTextAlign::Right) != + uint8_t(StyleVerticalAlignKeyword::Bottom)); + + return aResult.ParseEnumValue(aString, kAlignTable, false); +} + +//---------------------------------------- + +static const nsAttrValue::EnumTable kTableHAlignTable[] = { + {"left", StyleTextAlign::Left}, {"right", StyleTextAlign::Right}, + {"center", StyleTextAlign::Center}, {"char", StyleTextAlign::Char}, + {"justify", StyleTextAlign::Justify}, {nullptr, 0}}; + +bool nsGenericHTMLElement::ParseTableHAlignValue(const nsAString& aString, + nsAttrValue& aResult) { + return aResult.ParseEnumValue(aString, kTableHAlignTable, false); +} + +//---------------------------------------- + +// This table is used for td, th, tr, col, thead, tbody and tfoot. +static const nsAttrValue::EnumTable kTableCellHAlignTable[] = { + {"left", StyleTextAlign::MozLeft}, + {"right", StyleTextAlign::MozRight}, + {"center", StyleTextAlign::MozCenter}, + {"char", StyleTextAlign::Char}, + {"justify", StyleTextAlign::Justify}, + {"middle", StyleTextAlign::MozCenter}, + {"absmiddle", StyleTextAlign::Center}, + {nullptr, 0}}; + +bool nsGenericHTMLElement::ParseTableCellHAlignValue(const nsAString& aString, + nsAttrValue& aResult) { + return aResult.ParseEnumValue(aString, kTableCellHAlignTable, false); +} + +//---------------------------------------- + +bool nsGenericHTMLElement::ParseTableVAlignValue(const nsAString& aString, + nsAttrValue& aResult) { + return aResult.ParseEnumValue(aString, kTableVAlignTable, false); +} + +bool nsGenericHTMLElement::ParseDivAlignValue(const nsAString& aString, + nsAttrValue& aResult) { + return aResult.ParseEnumValue(aString, kDivAlignTable, false); +} + +bool nsGenericHTMLElement::ParseImageAttribute(nsAtom* aAttribute, + const nsAString& aString, + nsAttrValue& aResult) { + if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height || + aAttribute == nsGkAtoms::hspace || aAttribute == nsGkAtoms::vspace) { + return aResult.ParseHTMLDimension(aString); + } + if (aAttribute == nsGkAtoms::border) { + return aResult.ParseNonNegativeIntValue(aString); + } + return false; +} + +bool nsGenericHTMLElement::ParseReferrerAttribute(const nsAString& aString, + nsAttrValue& aResult) { + using mozilla::dom::ReferrerInfo; + static const nsAttrValue::EnumTable kReferrerPolicyTable[] = { + {ReferrerInfo::ReferrerPolicyToString(ReferrerPolicy::No_referrer), + static_cast(ReferrerPolicy::No_referrer)}, + {ReferrerInfo::ReferrerPolicyToString(ReferrerPolicy::Origin), + static_cast(ReferrerPolicy::Origin)}, + {ReferrerInfo::ReferrerPolicyToString( + ReferrerPolicy::Origin_when_cross_origin), + static_cast(ReferrerPolicy::Origin_when_cross_origin)}, + {ReferrerInfo::ReferrerPolicyToString( + ReferrerPolicy::No_referrer_when_downgrade), + static_cast(ReferrerPolicy::No_referrer_when_downgrade)}, + {ReferrerInfo::ReferrerPolicyToString(ReferrerPolicy::Unsafe_url), + static_cast(ReferrerPolicy::Unsafe_url)}, + {ReferrerInfo::ReferrerPolicyToString(ReferrerPolicy::Strict_origin), + static_cast(ReferrerPolicy::Strict_origin)}, + {ReferrerInfo::ReferrerPolicyToString(ReferrerPolicy::Same_origin), + static_cast(ReferrerPolicy::Same_origin)}, + {ReferrerInfo::ReferrerPolicyToString( + ReferrerPolicy::Strict_origin_when_cross_origin), + static_cast(ReferrerPolicy::Strict_origin_when_cross_origin)}, + {nullptr, ReferrerPolicy::_empty}}; + return aResult.ParseEnumValue(aString, kReferrerPolicyTable, false); +} + +bool nsGenericHTMLElement::ParseFrameborderValue(const nsAString& aString, + nsAttrValue& aResult) { + return aResult.ParseEnumValue(aString, kFrameborderTable, false); +} + +bool nsGenericHTMLElement::ParseScrollingValue(const nsAString& aString, + nsAttrValue& aResult) { + return aResult.ParseEnumValue(aString, kScrollingTable, false); +} + +static inline void MapLangAttributeInto(const nsMappedAttributes* aAttributes, + MappedDeclarations& aDecls) { + const nsAttrValue* langValue = aAttributes->GetAttr(nsGkAtoms::lang); + if (!langValue) { + return; + } + MOZ_ASSERT(langValue->Type() == nsAttrValue::eAtom); + aDecls.SetIdentAtomValueIfUnset(eCSSProperty__x_lang, + langValue->GetAtomValue()); + if (!aDecls.PropertyIsSet(eCSSProperty_text_emphasis_position)) { + const nsAtom* lang = langValue->GetAtomValue(); + if (nsStyleUtil::MatchesLanguagePrefix(lang, u"zh")) { + aDecls.SetKeywordValue(eCSSProperty_text_emphasis_position, + StyleTextEmphasisPosition::UNDER.bits); + } else if (nsStyleUtil::MatchesLanguagePrefix(lang, u"ja") || + nsStyleUtil::MatchesLanguagePrefix(lang, u"mn")) { + // This branch is currently no part of the spec. + // See bug 1040668 comment 69 and comment 75. + aDecls.SetKeywordValue(eCSSProperty_text_emphasis_position, + StyleTextEmphasisPosition::OVER.bits); + } + } +} + +/** + * Handle attributes common to all html elements + */ +void nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + if (!aDecls.PropertyIsSet(eCSSProperty__moz_user_modify)) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::contenteditable); + if (value) { + if (value->Equals(nsGkAtoms::_empty, eCaseMatters) || + value->Equals(nsGkAtoms::_true, eIgnoreCase)) { + aDecls.SetKeywordValue(eCSSProperty__moz_user_modify, + StyleUserModify::ReadWrite); + } else if (value->Equals(nsGkAtoms::_false, eIgnoreCase)) { + aDecls.SetKeywordValue(eCSSProperty__moz_user_modify, + StyleUserModify::ReadOnly); + } + } + } + + MapLangAttributeInto(aAttributes, aDecls); +} + +void nsGenericHTMLElement::MapCommonAttributesInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + MapCommonAttributesIntoExceptHidden(aAttributes, aDecls); + + if (!aDecls.PropertyIsSet(eCSSProperty_display)) { + if (aAttributes->IndexOfAttr(nsGkAtoms::hidden) >= 0) { + aDecls.SetKeywordValue(eCSSProperty_display, StyleDisplay::None); + } + } +} + +/* static */ +const nsGenericHTMLElement::MappedAttributeEntry + nsGenericHTMLElement::sCommonAttributeMap[] = {{nsGkAtoms::contenteditable}, + {nsGkAtoms::lang}, + {nsGkAtoms::hidden}, + {nullptr}}; + +/* static */ +const Element::MappedAttributeEntry + nsGenericHTMLElement::sImageMarginSizeAttributeMap[] = {{nsGkAtoms::width}, + {nsGkAtoms::height}, + {nsGkAtoms::hspace}, + {nsGkAtoms::vspace}, + {nullptr}}; + +/* static */ +const Element::MappedAttributeEntry + nsGenericHTMLElement::sImageAlignAttributeMap[] = {{nsGkAtoms::align}, + {nullptr}}; + +/* static */ +const Element::MappedAttributeEntry + nsGenericHTMLElement::sDivAlignAttributeMap[] = {{nsGkAtoms::align}, + {nullptr}}; + +/* static */ +const Element::MappedAttributeEntry + nsGenericHTMLElement::sImageBorderAttributeMap[] = {{nsGkAtoms::border}, + {nullptr}}; + +/* static */ +const Element::MappedAttributeEntry + nsGenericHTMLElement::sBackgroundAttributeMap[] = { + {nsGkAtoms::background}, {nsGkAtoms::bgcolor}, {nullptr}}; + +/* static */ +const Element::MappedAttributeEntry + nsGenericHTMLElement::sBackgroundColorAttributeMap[] = { + {nsGkAtoms::bgcolor}, {nullptr}}; + +void nsGenericHTMLElement::MapImageAlignAttributeInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align); + if (value && value->Type() == nsAttrValue::eEnum) { + int32_t align = value->GetEnumValue(); + if (!aDecls.PropertyIsSet(eCSSProperty_float)) { + if (align == uint8_t(StyleTextAlign::Left)) { + aDecls.SetKeywordValue(eCSSProperty_float, StyleFloat::Left); + } else if (align == uint8_t(StyleTextAlign::Right)) { + aDecls.SetKeywordValue(eCSSProperty_float, StyleFloat::Right); + } + } + if (!aDecls.PropertyIsSet(eCSSProperty_vertical_align)) { + switch (align) { + case uint8_t(StyleTextAlign::Left): + case uint8_t(StyleTextAlign::Right): + break; + default: + aDecls.SetKeywordValue(eCSSProperty_vertical_align, align); + break; + } + } + } +} + +void nsGenericHTMLElement::MapDivAlignAttributeInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + if (!aDecls.PropertyIsSet(eCSSProperty_text_align)) { + // align: enum + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align); + if (value && value->Type() == nsAttrValue::eEnum) + aDecls.SetKeywordValue(eCSSProperty_text_align, value->GetEnumValue()); + } +} + +void nsGenericHTMLElement::MapVAlignAttributeInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + if (!aDecls.PropertyIsSet(eCSSProperty_vertical_align)) { + // align: enum + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign); + if (value && value->Type() == nsAttrValue::eEnum) + aDecls.SetKeywordValue(eCSSProperty_vertical_align, + value->GetEnumValue()); + } +} + +static void MapDimensionAttributeInto(MappedDeclarations& aDecls, + nsCSSPropertyID aProp, + const nsAttrValue& aValue) { + MOZ_ASSERT(!aDecls.PropertyIsSet(aProp), + "Why mapping the same property twice?"); + if (aValue.Type() == nsAttrValue::eInteger) { + return aDecls.SetPixelValue(aProp, aValue.GetIntegerValue()); + } + if (aValue.Type() == nsAttrValue::ePercent) { + return aDecls.SetPercentValue(aProp, aValue.GetPercentValue()); + } + if (aValue.Type() == nsAttrValue::eDoubleValue) { + return aDecls.SetPixelValue(aProp, aValue.GetDoubleValue()); + } +} + +void nsGenericHTMLElement::MapImageMarginAttributeInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + const nsAttrValue* value; + + // hspace: value + value = aAttributes->GetAttr(nsGkAtoms::hspace); + if (value) { + MapDimensionAttributeInto(aDecls, eCSSProperty_margin_left, *value); + MapDimensionAttributeInto(aDecls, eCSSProperty_margin_right, *value); + } + + // vspace: value + value = aAttributes->GetAttr(nsGkAtoms::vspace); + if (value) { + MapDimensionAttributeInto(aDecls, eCSSProperty_margin_top, *value); + MapDimensionAttributeInto(aDecls, eCSSProperty_margin_bottom, *value); + } +} + +void nsGenericHTMLElement::MapWidthAttributeInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + if (const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width)) { + MapDimensionAttributeInto(aDecls, eCSSProperty_width, *value); + } +} + +void nsGenericHTMLElement::MapHeightAttributeInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + if (const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height)) { + MapDimensionAttributeInto(aDecls, eCSSProperty_height, *value); + } +} + +static void DoMapAspectRatio(const nsAttrValue& aWidth, + const nsAttrValue& aHeight, + MappedDeclarations& aDecls) { + Maybe w; + if (aWidth.Type() == nsAttrValue::eInteger) { + w.emplace(aWidth.GetIntegerValue()); + } else if (aWidth.Type() == nsAttrValue::eDoubleValue) { + w.emplace(aWidth.GetDoubleValue()); + } + + Maybe h; + if (aHeight.Type() == nsAttrValue::eInteger) { + h.emplace(aHeight.GetIntegerValue()); + } else if (aHeight.Type() == nsAttrValue::eDoubleValue) { + h.emplace(aHeight.GetDoubleValue()); + } + + if (w && h) { + aDecls.SetAspectRatio(*w, *h); + } +} + +void nsGenericHTMLElement::MapImageSizeAttributesInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls, + MapAspectRatio aMapAspectRatio) { + auto* width = aAttributes->GetAttr(nsGkAtoms::width); + auto* height = aAttributes->GetAttr(nsGkAtoms::height); + if (width) { + MapDimensionAttributeInto(aDecls, eCSSProperty_width, *width); + } + if (height) { + MapDimensionAttributeInto(aDecls, eCSSProperty_height, *height); + } + if (aMapAspectRatio == MapAspectRatio::Yes && width && height) { + DoMapAspectRatio(*width, *height, aDecls); + } +} + +void nsGenericHTMLElement::MapPictureSourceSizeAttributesInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + const auto* width = aAttributes->GetAttr(nsGkAtoms::width); + const auto* height = aAttributes->GetAttr(nsGkAtoms::height); + if (!width && !height) { + return; + } + + // We should set the missing property values with auto value to make sure it + // overrides the declaraion created by the presentation attributes of + // HTMLImageElement. This can make sure we compute the ratio-dependent axis + // size properly by the natural aspect-ratio of the image. + // + // Note: The spec doesn't specify this, so we follow the implementation in + // other browsers. + // Spec issue: https://github.com/whatwg/html/issues/8178. + if (width) { + MapDimensionAttributeInto(aDecls, eCSSProperty_width, *width); + } else { + aDecls.SetAutoValue(eCSSProperty_width); + } + + if (height) { + MapDimensionAttributeInto(aDecls, eCSSProperty_height, *height); + } else { + aDecls.SetAutoValue(eCSSProperty_height); + } + + if (width && height) { + DoMapAspectRatio(*width, *height, aDecls); + } else { + aDecls.SetAutoValue(eCSSProperty_aspect_ratio); + } +} + +void nsGenericHTMLElement::MapAspectRatioInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + auto* width = aAttributes->GetAttr(nsGkAtoms::width); + auto* height = aAttributes->GetAttr(nsGkAtoms::height); + if (width && height) { + DoMapAspectRatio(*width, *height, aDecls); + } +} + +void nsGenericHTMLElement::MapImageBorderAttributeInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + // border: pixels + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::border); + if (!value) return; + + nscoord val = 0; + if (value->Type() == nsAttrValue::eInteger) val = value->GetIntegerValue(); + + aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)val); + aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)val); + aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)val); + aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)val); + + aDecls.SetKeywordValueIfUnset(eCSSProperty_border_top_style, + StyleBorderStyle::Solid); + aDecls.SetKeywordValueIfUnset(eCSSProperty_border_right_style, + StyleBorderStyle::Solid); + aDecls.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style, + StyleBorderStyle::Solid); + aDecls.SetKeywordValueIfUnset(eCSSProperty_border_left_style, + StyleBorderStyle::Solid); + + aDecls.SetCurrentColorIfUnset(eCSSProperty_border_top_color); + aDecls.SetCurrentColorIfUnset(eCSSProperty_border_right_color); + aDecls.SetCurrentColorIfUnset(eCSSProperty_border_bottom_color); + aDecls.SetCurrentColorIfUnset(eCSSProperty_border_left_color); +} + +void nsGenericHTMLElement::MapBackgroundInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + if (!aDecls.PropertyIsSet(eCSSProperty_background_image)) { + // background + nsAttrValue* value = + const_cast(aAttributes->GetAttr(nsGkAtoms::background)); + if (value) { + aDecls.SetBackgroundImage(*value); + } + } +} + +void nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes, + MappedDeclarations& aDecls) { + if (!aDecls.PropertyIsSet(eCSSProperty_background_color)) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor); + nscolor color; + if (value && value->GetColorValue(color)) { + aDecls.SetColorValue(eCSSProperty_background_color, color); + } + } +} + +void nsGenericHTMLElement::MapBackgroundAttributesInto( + const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) { + MapBackgroundInto(aAttributes, aDecls); + MapBGColorInto(aAttributes, aDecls); +} + +//---------------------------------------------------------------------- + +int32_t nsGenericHTMLElement::GetIntAttr(nsAtom* aAttr, + int32_t aDefault) const { + const nsAttrValue* attrVal = mAttrs.GetAttr(aAttr); + if (attrVal && attrVal->Type() == nsAttrValue::eInteger) { + return attrVal->GetIntegerValue(); + } + return aDefault; +} + +nsresult nsGenericHTMLElement::SetIntAttr(nsAtom* aAttr, int32_t aValue) { + nsAutoString value; + value.AppendInt(aValue); + + return SetAttr(kNameSpaceID_None, aAttr, value, true); +} + +uint32_t nsGenericHTMLElement::GetUnsignedIntAttr(nsAtom* aAttr, + uint32_t aDefault) const { + const nsAttrValue* attrVal = mAttrs.GetAttr(aAttr); + if (!attrVal || attrVal->Type() != nsAttrValue::eInteger) { + return aDefault; + } + + return attrVal->GetIntegerValue(); +} + +uint32_t nsGenericHTMLElement::GetDimensionAttrAsUnsignedInt( + nsAtom* aAttr, uint32_t aDefault) const { + const nsAttrValue* attrVal = mAttrs.GetAttr(aAttr); + if (!attrVal) { + return aDefault; + } + + if (attrVal->Type() == nsAttrValue::eInteger) { + return attrVal->GetIntegerValue(); + } + + if (attrVal->Type() == nsAttrValue::ePercent) { + // This is a nasty hack. When we parsed the value, we stored it as an + // ePercent, not eInteger, because there was a '%' after it in the string. + // But the spec says to basically re-parse the string as an integer. + // Luckily, we can just return the value we have stored. But + // GetPercentValue() divides it by 100, so we need to multiply it back. + return uint32_t(attrVal->GetPercentValue() * 100.0f); + } + + if (attrVal->Type() == nsAttrValue::eDoubleValue) { + return uint32_t(attrVal->GetDoubleValue()); + } + + // Unfortunately, the set of values that are valid dimensions is not a + // superset of values that are valid unsigned ints. In particular "+100" is + // not a valid dimension, but should parse as the unsigned int "100". So if + // we got here and we don't have a valid dimension value, just try re-parsing + // the string we have as an integer. + nsAutoString val; + attrVal->ToString(val); + nsContentUtils::ParseHTMLIntegerResultFlags result; + int32_t parsedInt = nsContentUtils::ParseHTMLInteger(val, &result); + if ((result & nsContentUtils::eParseHTMLInteger_Error) || parsedInt < 0) { + return aDefault; + } + + return parsedInt; +} + +void nsGenericHTMLElement::GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, + nsAString& aResult) const { + nsCOMPtr uri; + bool hadAttr = GetURIAttr(aAttr, aBaseAttr, getter_AddRefs(uri)); + if (!hadAttr) { + aResult.Truncate(); + return; + } + + if (!uri) { + // Just return the attr value + GetAttr(kNameSpaceID_None, aAttr, aResult); + return; + } + + nsAutoCString spec; + uri->GetSpec(spec); + CopyUTF8toUTF16(spec, aResult); +} + +bool nsGenericHTMLElement::GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, + nsIURI** aURI) const { + *aURI = nullptr; + + const nsAttrValue* attr = mAttrs.GetAttr(aAttr); + if (!attr) { + return false; + } + + nsCOMPtr baseURI = GetBaseURI(); + + if (aBaseAttr) { + nsAutoString baseAttrValue; + if (GetAttr(kNameSpaceID_None, aBaseAttr, baseAttrValue)) { + nsCOMPtr baseAttrURI; + nsresult rv = nsContentUtils::NewURIWithDocumentCharset( + getter_AddRefs(baseAttrURI), baseAttrValue, OwnerDoc(), baseURI); + if (NS_FAILED(rv)) { + return true; + } + baseURI.swap(baseAttrURI); + } + } + + // Don't care about return value. If it fails, we still want to + // return true, and *aURI will be null. + nsContentUtils::NewURIWithDocumentCharset(aURI, attr->GetStringValue(), + OwnerDoc(), baseURI); + return true; +} + +bool nsGenericHTMLElement::IsLabelable() const { + return IsAnyOfHTMLElements(nsGkAtoms::progress, nsGkAtoms::meter); +} + +/* static */ +bool nsGenericHTMLElement::MatchLabelsElement(Element* aElement, + int32_t aNamespaceID, + nsAtom* aAtom, void* aData) { + HTMLLabelElement* element = HTMLLabelElement::FromNode(aElement); + return element && element->GetControl() == aData; +} + +already_AddRefed nsGenericHTMLElement::Labels() { + MOZ_ASSERT(IsLabelable(), + "Labels() only allow labelable elements to use it."); + nsExtendedDOMSlots* slots = ExtendedDOMSlots(); + + if (!slots->mLabelsList) { + slots->mLabelsList = + new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement, nullptr, this); + } + + RefPtr labels = slots->mLabelsList; + return labels.forget(); +} + +// static +bool nsGenericHTMLElement::LegacyTouchAPIEnabled(JSContext* aCx, + JSObject* aGlobal) { + return TouchEvent::LegacyAPIEnabled(aCx, aGlobal); +} + +bool nsGenericHTMLElement::IsFormControlDefaultFocusable( + bool aWithMouse) const { + if (!aWithMouse) { + return true; + } + switch (StaticPrefs::accessibility_mouse_focuses_formcontrol()) { + case 0: + return false; + case 1: + return true; + default: + return !IsInChromeDocument(); + } +} + +//---------------------------------------------------------------------- + +nsGenericHTMLFormElement::nsGenericHTMLFormElement( + already_AddRefed&& aNodeInfo) + : nsGenericHTMLElement(std::move(aNodeInfo)) { + // We should add the ElementState::ENABLED bit here as needed, but + // that depends on our type, which is not initialized yet. So we + // have to do this in subclasses. +} + +void nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm, + bool aUnbindOrDelete) { + MOZ_ASSERT(IsFormAssociatedElement()); + + HTMLFormElement* form = GetFormInternal(); + NS_ASSERTION((form != nullptr) == HasFlag(ADDED_TO_FORM), + "Form control should have had flag set correctly"); + + if (!form) { + return; + } + + if (aRemoveFromForm) { + nsAutoString nameVal, idVal; + GetAttr(nsGkAtoms::name, nameVal); + GetAttr(nsGkAtoms::id, idVal); + + form->RemoveElement(this, true); + + if (!nameVal.IsEmpty()) { + form->RemoveElementFromTable(this, nameVal); + } + + if (!idVal.IsEmpty()) { + form->RemoveElementFromTable(this, idVal); + } + } + + UnsetFlags(ADDED_TO_FORM); + SetFormInternal(nullptr, false); + AfterClearForm(aUnbindOrDelete); + UpdateState(true); +} + +nsresult nsGenericHTMLFormElement::BindToTree(BindContext& aContext, + nsINode& aParent) { + nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent); + NS_ENSURE_SUCCESS(rv, rv); + + if (IsFormAssociatedElement()) { + // If @form is set, the element *has* to be in a composed document, + // otherwise it wouldn't be possible to find an element with the + // corresponding id. If @form isn't set, the element *has* to have a parent, + // otherwise it wouldn't be possible to find a form ancestor. We should not + // call UpdateFormOwner if none of these conditions are fulfilled. + if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ? IsInComposedDoc() + : aParent.IsContent()) { + UpdateFormOwner(true, nullptr); + } + } + + // Set parent fieldset which should be used for the disabled state. + UpdateFieldSet(false); + + return NS_OK; +} + +void nsGenericHTMLFormElement::UnbindFromTree(bool aNullParent) { + if (IsFormAssociatedElement()) { + if (HTMLFormElement* form = GetFormInternal()) { + // Might need to unset form + if (aNullParent) { + // No more parent means no more form + ClearForm(true, true); + } else { + // Recheck whether we should still have an form. + if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) || + !FindAncestorForm(form)) { + ClearForm(true, true); + } else { + UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT); + } + } + + if (!GetFormInternal()) { + // Our novalidate state might have changed + UpdateState(false); + } + } + + // We have to remove the form id observer if there was one. + // We will re-add one later if needed (during bind to tree). + if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None, + nsGkAtoms::form)) { + RemoveFormIdObserver(); + } + } + + nsGenericHTMLElement::UnbindFromTree(aNullParent); + + // The element might not have a fieldset anymore. + UpdateFieldSet(false); +} + +void nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, + nsAtom* aName, + const nsAttrValue* aValue, + bool aNotify) { + if (aNameSpaceID == kNameSpaceID_None && IsFormAssociatedElement()) { + nsAutoString tmp; + HTMLFormElement* form = GetFormInternal(); + + // remove the control from the hashtable as needed + + if (form && (aName == nsGkAtoms::name || aName == nsGkAtoms::id)) { + GetAttr(kNameSpaceID_None, aName, tmp); + + if (!tmp.IsEmpty()) { + form->RemoveElementFromTable(this, tmp); + } + } + + if (form && aName == nsGkAtoms::type) { + GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp); + + if (!tmp.IsEmpty()) { + form->RemoveElementFromTable(this, tmp); + } + + GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp); + + if (!tmp.IsEmpty()) { + form->RemoveElementFromTable(this, tmp); + } + + form->RemoveElement(this, false); + } + + if (aName == nsGkAtoms::form) { + // If @form isn't set or set to the empty string, there were no observer + // so we don't have to remove it. + if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None, + nsGkAtoms::form)) { + // The current form id observer is no longer needed. + // A new one may be added in AfterSetAttr. + RemoveFormIdObserver(); + } + } + } + + return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName, aValue, + aNotify); +} + +void nsGenericHTMLFormElement::AfterSetAttr( + int32_t aNameSpaceID, nsAtom* aName, const nsAttrValue* aValue, + const nsAttrValue* aOldValue, nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { + if (aNameSpaceID == kNameSpaceID_None && IsFormAssociatedElement()) { + HTMLFormElement* form = GetFormInternal(); + + // add the control to the hashtable as needed + if (form && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) && + aValue && !aValue->IsEmptyString()) { + MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom, + "Expected atom value for name/id"); + form->AddElementToTable(this, + nsDependentAtomString(aValue->GetAtomValue())); + } + + if (form && aName == nsGkAtoms::type) { + nsAutoString tmp; + + GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp); + + if (!tmp.IsEmpty()) { + form->AddElementToTable(this, tmp); + } + + GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp); + + if (!tmp.IsEmpty()) { + form->AddElementToTable(this, tmp); + } + + form->AddElement(this, false, aNotify); + } + + if (aName == nsGkAtoms::form) { + // We need a new form id observer. + DocumentOrShadowRoot* docOrShadow = + GetUncomposedDocOrConnectedShadowRoot(); + if (docOrShadow) { + Element* formIdElement = nullptr; + if (aValue && !aValue->IsEmptyString()) { + formIdElement = AddFormIdObserver(); + } + + // Because we have a new @form value (or no more @form), we have to + // update our form owner. + UpdateFormOwner(false, formIdElement); + } + } + } + + return nsGenericHTMLElement::AfterSetAttr( + aNameSpaceID, aName, aValue, aOldValue, aMaybeScriptedPrincipal, aNotify); +} + +void nsGenericHTMLFormElement::ForgetFieldSet(nsIContent* aFieldset) { + MOZ_DIAGNOSTIC_ASSERT(IsFormAssociatedElement()); + if (GetFieldSetInternal() == aFieldset) { + SetFieldSetInternal(nullptr); + } +} + +Element* nsGenericHTMLFormElement::AddFormIdObserver() { + MOZ_ASSERT(IsFormAssociatedElement()); + + nsAutoString formId; + DocumentOrShadowRoot* docOrShadow = GetUncomposedDocOrConnectedShadowRoot(); + GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId); + NS_ASSERTION(!formId.IsEmpty(), + "@form value should not be the empty string!"); + RefPtr atom = NS_Atomize(formId); + + return docOrShadow->AddIDTargetObserver(atom, FormIdUpdated, this, false); +} + +void nsGenericHTMLFormElement::RemoveFormIdObserver() { + MOZ_ASSERT(IsFormAssociatedElement()); + + DocumentOrShadowRoot* docOrShadow = GetUncomposedDocOrConnectedShadowRoot(); + if (!docOrShadow) { + return; + } + + nsAutoString formId; + GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId); + NS_ASSERTION(!formId.IsEmpty(), + "@form value should not be the empty string!"); + RefPtr atom = NS_Atomize(formId); + + docOrShadow->RemoveIDTargetObserver(atom, FormIdUpdated, this, false); +} + +/* static */ +bool nsGenericHTMLFormElement::FormIdUpdated(Element* aOldElement, + Element* aNewElement, + void* aData) { + nsGenericHTMLFormElement* element = + static_cast(aData); + + NS_ASSERTION(element->IsHTMLElement(), "aData should be an HTML element"); + + element->UpdateFormOwner(false, aNewElement); + + return true; +} + +bool nsGenericHTMLFormElement::IsElementDisabledForEvents(WidgetEvent* aEvent, + nsIFrame* aFrame) { + MOZ_ASSERT(aEvent); + + // Allow dispatch of CustomEvent and untrusted Events. + if (!aEvent->IsTrusted()) { + return false; + } + + switch (aEvent->mMessage) { + case eAnimationStart: + case eAnimationEnd: + case eAnimationIteration: + case eAnimationCancel: + case eFormChange: + case eMouseMove: + case eMouseOver: + case eMouseOut: + case eMouseEnter: + case eMouseLeave: + case ePointerMove: + case ePointerOver: + case ePointerOut: + case ePointerEnter: + case ePointerLeave: + case eTransitionCancel: + case eTransitionEnd: + case eTransitionRun: + case eTransitionStart: + case eWheel: + case eLegacyMouseLineOrPageScroll: + case eLegacyMousePixelScroll: + return false; + case eFocus: + case eBlur: + case eFocusIn: + case eFocusOut: + case eKeyPress: + case eKeyUp: + case eKeyDown: + if (StaticPrefs::dom_forms_always_allow_key_and_focus_events_enabled()) { + return false; + } + [[fallthrough]]; + case ePointerDown: + case ePointerUp: + case ePointerCancel: + case ePointerGotCapture: + case ePointerLostCapture: + if (StaticPrefs::dom_forms_always_allow_pointer_events_enabled()) { + return false; + } + [[fallthrough]]; + default: + break; + } + + if (aEvent->mSpecifiedEventType == nsGkAtoms::oninput) { + return false; + } + + // FIXME(emilio): This poking at the style of the frame is slightly bogus + // unless we flush before every event, which we don't really want to do. + if (aFrame && aFrame->StyleUI()->UserInput() == StyleUserInput::None) { + return true; + } + + return IsDisabled(); +} + +void nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree, + Element* aFormIdElement) { + MOZ_ASSERT(IsFormAssociatedElement()); + MOZ_ASSERT(!aBindToTree || !aFormIdElement, + "aFormIdElement shouldn't be set if aBindToTree is true!"); + + bool needStateUpdate = false; + if (!aBindToTree) { + HTMLFormElement* form = GetFormInternal(); + needStateUpdate = form && form->IsDefaultSubmitElement(this); + ClearForm(true, false); + } + + // We have to get form again since the above ClearForm() call might update the + // form value. + HTMLFormElement* oldForm = GetFormInternal(); + if (!oldForm) { + // If @form is set, we have to use that to find the form. + nsAutoString formId; + if (GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId)) { + if (!formId.IsEmpty()) { + Element* element = nullptr; + + if (aBindToTree) { + element = AddFormIdObserver(); + } else { + element = aFormIdElement; + } + + NS_ASSERTION(!IsInComposedDoc() || + element == GetUncomposedDocOrConnectedShadowRoot() + ->GetElementById(formId), + "element should be equals to the current element " + "associated with the id in @form!"); + + if (element && element->IsHTMLElement(nsGkAtoms::form) && + nsContentUtils::IsInSameAnonymousTree(this, element)) { + SetFormInternal(static_cast(element), aBindToTree); + } + } + } else { + // We now have a parent, so we may have picked up an ancestor form. Search + // for it. Note that if form is already set we don't want to do this, + // because that means someone (probably the content sink) has already set + // it to the right value. Also note that even if being bound here didn't + // change our parent, we still need to search, since our parent chain + // probably changed _somewhere_. + SetFormInternal(FindAncestorForm(), aBindToTree); + } + } + + HTMLFormElement* form = GetFormInternal(); + if (form && !HasFlag(ADDED_TO_FORM)) { + // Now we need to add ourselves to the form + nsAutoString nameVal, idVal; + GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal); + GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal); + + SetFlags(ADDED_TO_FORM); + + // Notify only if we just found this form. + form->AddElement(this, true, oldForm == nullptr); + + if (!nameVal.IsEmpty()) { + form->AddElementToTable(this, nameVal); + } + + if (!idVal.IsEmpty()) { + form->AddElementToTable(this, idVal); + } + } + + if (form != oldForm || needStateUpdate) { + UpdateState(true); + } +} + +void nsGenericHTMLFormElement::UpdateFieldSet(bool aNotify) { + if (IsInNativeAnonymousSubtree() || !IsFormAssociatedElement()) { + MOZ_ASSERT_IF(IsFormAssociatedElement(), !GetFieldSetInternal()); + return; + } + + nsIContent* parent = nullptr; + nsIContent* prev = nullptr; + HTMLFieldSetElement* fieldset = GetFieldSetInternal(); + + for (parent = GetParent(); parent; + prev = parent, parent = parent->GetParent()) { + HTMLFieldSetElement* parentFieldset = HTMLFieldSetElement::FromNode(parent); + if (parentFieldset && (!prev || parentFieldset->GetFirstLegend() != prev)) { + if (fieldset == parentFieldset) { + // We already have the right fieldset; + return; + } + + if (fieldset) { + fieldset->RemoveElement(this); + } + SetFieldSetInternal(parentFieldset); + parentFieldset->AddElement(this); + + // The disabled state may have changed + FieldSetDisabledChanged(aNotify); + return; + } + } + + // No fieldset found. + if (fieldset) { + fieldset->RemoveElement(this); + SetFieldSetInternal(nullptr); + // The disabled state may have changed + FieldSetDisabledChanged(aNotify); + } +} + +void nsGenericHTMLFormElement::UpdateDisabledState(bool aNotify) { + if (!CanBeDisabled()) { + return; + } + + HTMLFieldSetElement* fieldset = GetFieldSetInternal(); + const bool isDisabled = + HasAttr(nsGkAtoms::disabled) || (fieldset && fieldset->IsDisabled()); + + const ElementState disabledStates = + isDisabled ? ElementState::DISABLED : ElementState::ENABLED; + + ElementState oldDisabledStates = State() & ElementState::DISABLED_STATES; + ElementState changedStates = disabledStates ^ oldDisabledStates; + + if (!changedStates.IsEmpty()) { + ToggleStates(changedStates, aNotify); + if (DoesReadOnlyApply()) { + // :disabled influences :read-only / :read-write. + UpdateState(aNotify); + } + } +} + +void nsGenericHTMLFormElement::FieldSetDisabledChanged(bool aNotify) { + UpdateDisabledState(aNotify); +} + +//---------------------------------------------------------------------- + +void nsGenericHTMLElement::Click(CallerType aCallerType) { + if (IsDisabled() || HandlingClick()) { + return; + } + + // Strong in case the event kills it + nsCOMPtr doc = GetComposedDoc(); + + RefPtr context; + if (doc) { + context = doc->GetPresContext(); + } + + SetHandlingClick(); + + // Mark this event trusted if Click() is called from system code. + WidgetMouseEvent event(aCallerType == CallerType::System, eMouseClick, + nullptr, WidgetMouseEvent::eReal); + event.mFlags.mIsPositionless = true; + event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_UNKNOWN; + + EventDispatcher::Dispatch(static_cast(this), context, &event); + + ClearHandlingClick(); +} + +bool nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex) { + if (ShadowRoot* root = GetShadowRoot()) { + if (root->DelegatesFocus()) { + *aIsFocusable = false; + return true; + } + } + + Document* doc = GetComposedDoc(); + if (!doc || IsInDesignMode()) { + // In designMode documents we only allow focusing the document. + if (aTabIndex) { + *aTabIndex = -1; + } + + *aIsFocusable = false; + + return true; + } + + int32_t tabIndex = TabIndex(); + bool disabled = false; + bool disallowOverridingFocusability = true; + Maybe attrVal = GetTabIndexAttrValue(); + + if (IsEditableRoot()) { + // Editable roots should always be focusable. + disallowOverridingFocusability = true; + + // Ignore the disabled attribute in editable contentEditable/designMode + // roots. + if (attrVal.isNothing()) { + // The default value for tabindex should be 0 for editable + // contentEditable roots. + tabIndex = 0; + } + } else { + disallowOverridingFocusability = false; + + // Just check for disabled attribute on form controls + disabled = IsDisabled(); + if (disabled) { + tabIndex = -1; + } + } + + if (aTabIndex) { + *aTabIndex = tabIndex; + } + + // If a tabindex is specified at all, or the default tabindex is 0, we're + // focusable + *aIsFocusable = (tabIndex >= 0 || (!disabled && attrVal.isSome())); + + return disallowOverridingFocusability; +} + +Result nsGenericHTMLElement::PerformAccesskey( + bool aKeyCausesActivation, bool aIsTrustedEvent) { + RefPtr presContext = GetPresContext(eForComposedDoc); + if (!presContext) { + return Err(NS_ERROR_UNEXPECTED); + } + + // It's hard to say what HTML4 wants us to do in all cases. + bool focused = true; + if (RefPtr fm = nsFocusManager::GetFocusManager()) { + fm->SetFocus(this, nsIFocusManager::FLAG_BYKEY); + + // Return true if the element became the current focus within its window. + nsPIDOMWindowOuter* window = OwnerDoc()->GetWindow(); + focused = window && window->GetFocusedElement() == this; + } + + if (aKeyCausesActivation) { + // Click on it if the users prefs indicate to do so. + AutoHandlingUserInputStatePusher userInputStatePusher(aIsTrustedEvent); + AutoPopupStatePusher popupStatePusher( + aIsTrustedEvent ? PopupBlocker::openAllowed : PopupBlocker::openAbused); + DispatchSimulatedClick(this, aIsTrustedEvent, presContext); + return focused; + } + + // If the accesskey won't cause the activation and the focus isn't changed, + // either. Return error so EventStateManager would try to find next element + // to handle the accesskey. + return focused ? Result{focused} : Err(NS_ERROR_ABORT); +} + +void nsGenericHTMLElement::HandleKeyboardActivation( + EventChainPostVisitor& aVisitor) { + MOZ_ASSERT(aVisitor.mEvent->HasKeyEventMessage()); + MOZ_ASSERT(aVisitor.mEvent->IsTrusted()); + + // If focused element is different from this element, it may be editable. + // In that case, associated editor for the element should handle the keyboard + // instead. Therefore, if this is not the focused element, we should not + // handle the event here. Note that this element may be an editing host, + // i.e., focused and editable. In the case, keyboard events should be + // handled by the focused element instead of associated editor because + // Chrome handles the case so. For compatibility with Chrome, we follow them. + if (nsFocusManager::GetFocusedElementStatic() != this) { + return; + } + + const auto message = aVisitor.mEvent->mMessage; + const WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent(); + if (nsEventStatus_eIgnore != aVisitor.mEventStatus) { + if (message == eKeyUp && keyEvent->mKeyCode == NS_VK_SPACE) { + // Unset the flag even if the event is default-prevented or something. + UnsetFlags(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD); + } + return; + } + + bool shouldActivate = false; + switch (message) { + case eKeyDown: + if (keyEvent->ShouldWorkAsSpaceKey()) { + SetFlags(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD); + } + return; + case eKeyPress: + shouldActivate = keyEvent->mKeyCode == NS_VK_RETURN; + if (keyEvent->ShouldWorkAsSpaceKey()) { + // Consume 'space' key to prevent scrolling the page down. + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; + } + break; + case eKeyUp: + shouldActivate = keyEvent->ShouldWorkAsSpaceKey() && + HasFlag(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD); + if (shouldActivate) { + UnsetFlags(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD); + } + break; + default: + MOZ_ASSERT_UNREACHABLE("why didn't we bail out earlier?"); + break; + } + + if (!shouldActivate) { + return; + } + + RefPtr presContext = aVisitor.mPresContext; + DispatchSimulatedClick(this, aVisitor.mEvent->IsTrusted(), presContext); + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; +} + +nsresult nsGenericHTMLElement::DispatchSimulatedClick( + nsGenericHTMLElement* aElement, bool aIsTrusted, + nsPresContext* aPresContext) { + WidgetMouseEvent event(aIsTrusted, eMouseClick, nullptr, + WidgetMouseEvent::eReal); + event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_KEYBOARD; + event.mFlags.mIsPositionless = true; + // TODO: Bug 1506441 + return EventDispatcher::Dispatch(MOZ_KnownLive(ToSupports(aElement)), + aPresContext, &event); +} + +already_AddRefed nsGenericHTMLElement::GetAssociatedEditor() { + // If contenteditable is ever implemented, it might need to do something + // different here? + + RefPtr textEditor = GetTextEditorInternal(); + return textEditor.forget(); +} + +// static +void nsGenericHTMLElement::SyncEditorsOnSubtree(nsIContent* content) { + /* Sync this node */ + nsGenericHTMLElement* element = FromNode(content); + if (element) { + if (RefPtr editorBase = element->GetAssociatedEditor()) { + editorBase->SyncRealTimeSpell(); + } + } + + /* Sync all children */ + for (nsIContent* child = content->GetFirstChild(); child; + child = child->GetNextSibling()) { + SyncEditorsOnSubtree(child); + } +} + +bool nsGenericHTMLElement::IsEditableRoot() const { + if (!IsInComposedDoc()) { + return false; + } + + if (IsInDesignMode()) { + return false; + } + + if (GetContentEditableValue() != eTrue) { + return false; + } + + nsIContent* parent = GetParent(); + + return !parent || !parent->HasFlag(NODE_IS_EDITABLE); +} + +static void MakeContentDescendantsEditable(nsIContent* aContent) { + // If aContent is not an element, we just need to update its + // internal editable state and don't need to notify anyone about + // that. For elements, we need to send a ElementStateChanged + // notification. + if (!aContent->IsElement()) { + aContent->UpdateEditableState(false); + return; + } + + Element* element = aContent->AsElement(); + + element->UpdateEditableState(true); + + for (nsIContent* child = aContent->GetFirstChild(); child; + child = child->GetNextSibling()) { + if (!child->IsElement() || + !child->AsElement()->HasAttr(kNameSpaceID_None, + nsGkAtoms::contenteditable)) { + MakeContentDescendantsEditable(child); + } + } +} + +void nsGenericHTMLElement::ChangeEditableState(int32_t aChange) { + Document* document = GetComposedDoc(); + if (!document) { + return; + } + + Document::EditingState previousEditingState = Document::EditingState::eOff; + if (aChange != 0) { + document->ChangeContentEditableCount(this, aChange); + previousEditingState = document->GetEditingState(); + } + + // MakeContentDescendantsEditable is going to call ElementStateChanged for + // this element and all descendants if editable state has changed. + // We might as well wrap it all in one script blocker. + nsAutoScriptBlocker scriptBlocker; + MakeContentDescendantsEditable(this); + + // If the document already had contenteditable and JS adds new + // contenteditable, that might cause changing editing host to current editing + // host's ancestor. In such case, HTMLEditor needs to know that + // synchronously to update selection limitter. + // Additionally, elements in shadow DOM is not editable in the normal cases, + // but if its content has `contenteditable`, only in it can be ediable. + // So we don't need to notify HTMLEditor of this change only when we're not + // in shadow DOM and the composed document is in design mode. + if (IsInDesignMode() && !IsInShadowTree() && aChange > 0 && + previousEditingState == Document::EditingState::eContentEditable) { + if (HTMLEditor* htmlEditor = + nsContentUtils::GetHTMLEditor(document->GetPresContext())) { + htmlEditor->NotifyEditingHostMaybeChanged(); + } + } +} + +//---------------------------------------------------------------------- + +nsGenericHTMLFormControlElement::nsGenericHTMLFormControlElement( + already_AddRefed&& aNodeInfo, FormControlType aType) + : nsGenericHTMLFormElement(std::move(aNodeInfo)), + nsIFormControl(aType), + mForm(nullptr), + mFieldSet(nullptr) {} + +nsGenericHTMLFormControlElement::~nsGenericHTMLFormControlElement() { + if (mFieldSet) { + mFieldSet->RemoveElement(this); + } + + // Check that this element doesn't know anything about its form at this point. + NS_ASSERTION(!mForm, "mForm should be null at this point!"); +} + +NS_IMPL_ISUPPORTS_INHERITED(nsGenericHTMLFormControlElement, + nsGenericHTMLFormElement, nsIFormControl) + +nsINode* nsGenericHTMLFormControlElement::GetScopeChainParent() const { + return mForm ? mForm : nsGenericHTMLElement::GetScopeChainParent(); +} + +void nsGenericHTMLFormControlElement::SaveSubtreeState() { + SaveState(); + + nsGenericHTMLFormElement::SaveSubtreeState(); +} + +nsIContent::IMEState nsGenericHTMLFormControlElement::GetDesiredIMEState() { + TextEditor* textEditor = GetTextEditorInternal(); + if (!textEditor) { + return nsGenericHTMLFormElement::GetDesiredIMEState(); + } + IMEState state; + nsresult rv = textEditor->GetPreferredIMEState(&state); + if (NS_FAILED(rv)) { + return nsGenericHTMLFormElement::GetDesiredIMEState(); + } + return state; +} + +void nsGenericHTMLFormControlElement::UnbindFromTree(bool aNullParent) { + // Save state before doing anything + SaveState(); + nsGenericHTMLFormElement::UnbindFromTree(aNullParent); +} + +void nsGenericHTMLFormControlElement::GetAutocapitalize( + nsAString& aValue) const { + if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None, + nsGkAtoms::autocapitalize)) { + nsGenericHTMLFormElement::GetAutocapitalize(aValue); + return; + } + + if (mForm && IsAutocapitalizeInheriting()) { + mForm->GetAutocapitalize(aValue); + } +} + +bool nsGenericHTMLFormControlElement::IsHTMLFocusable(bool aWithMouse, + bool* aIsFocusable, + int32_t* aTabIndex) { + if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, + aTabIndex)) { + return true; + } + + *aIsFocusable = *aIsFocusable && IsFormControlDefaultFocusable(aWithMouse); + return false; +} + +void nsGenericHTMLFormControlElement::GetEventTargetParent( + EventChainPreVisitor& aVisitor) { + if (aVisitor.mEvent->IsTrusted() && (aVisitor.mEvent->mMessage == eFocus || + aVisitor.mEvent->mMessage == eBlur)) { + // We have to handle focus/blur event to change focus states in + // PreHandleEvent to prevent it breaks event target chain creation. + aVisitor.mWantsPreHandleEvent = true; + } + nsGenericHTMLFormElement::GetEventTargetParent(aVisitor); +} + +nsresult nsGenericHTMLFormControlElement::PreHandleEvent( + EventChainVisitor& aVisitor) { + if (aVisitor.mEvent->IsTrusted()) { + switch (aVisitor.mEvent->mMessage) { + case eFocus: { + // Check to see if focus has bubbled up from a form control's + // child textfield or button. If that's the case, don't focus + // this parent file control -- leave focus on the child. + nsIFormControlFrame* formControlFrame = GetFormControlFrame(true); + if (formControlFrame && + aVisitor.mEvent->mOriginalTarget == static_cast(this)) { + formControlFrame->SetFocus(true, true); + } + break; + } + case eBlur: { + nsIFormControlFrame* formControlFrame = GetFormControlFrame(true); + if (formControlFrame) { + formControlFrame->SetFocus(false, false); + } + break; + } + default: + break; + } + } + return nsGenericHTMLFormElement::PreHandleEvent(aVisitor); +} + +HTMLFieldSetElement* nsGenericHTMLFormControlElement::GetFieldSet() { + return GetFieldSetInternal(); +} + +void nsGenericHTMLFormControlElement::SetForm(HTMLFormElement* aForm) { + MOZ_ASSERT(aForm, "Don't pass null here"); + NS_ASSERTION(!mForm, + "We don't support switching from one non-null form to another."); + + SetFormInternal(aForm, false); +} + +void nsGenericHTMLFormControlElement::ClearForm(bool aRemoveFromForm, + bool aUnbindOrDelete) { + nsGenericHTMLFormElement::ClearForm(aRemoveFromForm, aUnbindOrDelete); +} + +ElementState nsGenericHTMLFormControlElement::IntrinsicState() const { + // If you add attribute-dependent states here, you need to add them to + // AfterSetAttr too. And add them to AfterSetAttr for all subclasses that + // implement IntrinsicState() and are affected by that attribute. + ElementState state = nsGenericHTMLFormElement::IntrinsicState(); + + if (mForm && mForm->IsDefaultSubmitElement(this)) { + NS_ASSERTION(IsSubmitControl(), + "Default submit element that isn't a submit control."); + // We are the default submit element (:default) + state |= ElementState::DEFAULT; + } + + // Make the text controls read-write + if (!state.HasState(ElementState::READWRITE) && DoesReadOnlyApply()) { + if (!GetBoolAttr(nsGkAtoms::readonly) && !IsDisabled()) { + state |= ElementState::READWRITE; + state &= ~ElementState::READONLY; + } + } + + return state; +} + +bool nsGenericHTMLFormControlElement::IsLabelable() const { + auto type = ControlType(); + return (IsInputElement(type) && type != FormControlType::InputHidden) || + IsButtonElement(type) || type == FormControlType::Output || + type == FormControlType::Select || type == FormControlType::Textarea; +} + +bool nsGenericHTMLFormControlElement::CanBeDisabled() const { + auto type = ControlType(); + // It's easier to test the types that _cannot_ be disabled + return type != FormControlType::Object && type != FormControlType::Output; +} + +bool nsGenericHTMLFormControlElement::DoesReadOnlyApply() const { + auto type = ControlType(); + if (!IsInputElement(type) && type != FormControlType::Textarea) { + return false; + } + + switch (type) { + case FormControlType::InputHidden: + case FormControlType::InputButton: + case FormControlType::InputImage: + case FormControlType::InputReset: + case FormControlType::InputSubmit: + case FormControlType::InputRadio: + case FormControlType::InputFile: + case FormControlType::InputCheckbox: + case FormControlType::InputRange: + case FormControlType::InputColor: + return false; +#ifdef DEBUG + case FormControlType::Textarea: + case FormControlType::InputText: + case FormControlType::InputPassword: + case FormControlType::InputSearch: + case FormControlType::InputTel: + case FormControlType::InputEmail: + case FormControlType::InputUrl: + case FormControlType::InputNumber: + case FormControlType::InputDate: + case FormControlType::InputTime: + case FormControlType::InputMonth: + case FormControlType::InputWeek: + case FormControlType::InputDatetimeLocal: + return true; + default: + MOZ_ASSERT_UNREACHABLE("Unexpected input type in DoesReadOnlyApply()"); + return true; +#else // DEBUG + default: + return true; +#endif // DEBUG + } +} + +void nsGenericHTMLFormControlElement::SetFormInternal(HTMLFormElement* aForm, + bool aBindToTree) { + if (aForm) { + BeforeSetForm(aForm, aBindToTree); + } + + // keep a *weak* ref to the form here + mForm = aForm; +} + +HTMLFormElement* nsGenericHTMLFormControlElement::GetFormInternal() const { + return mForm; +} + +HTMLFieldSetElement* nsGenericHTMLFormControlElement::GetFieldSetInternal() + const { + return mFieldSet; +} + +void nsGenericHTMLFormControlElement::SetFieldSetInternal( + HTMLFieldSetElement* aFieldset) { + mFieldSet = aFieldset; +} + +void nsGenericHTMLFormControlElement::UpdateRequiredState(bool aIsRequired, + bool aNotify) { +#ifdef DEBUG + auto type = ControlType(); +#endif + MOZ_ASSERT(IsInputElement(type) || type == FormControlType::Select || + type == FormControlType::Textarea, + "This should be called only on types that @required applies"); + +#ifdef DEBUG + if (HTMLInputElement* input = HTMLInputElement::FromNode(this)) { + MOZ_ASSERT( + input->DoesRequiredApply(), + "This should be called only on input types that @required applies"); + } +#endif + + ElementState requiredStates; + if (aIsRequired) { + requiredStates |= ElementState::REQUIRED; + } else { + requiredStates |= ElementState::OPTIONAL_; + } + + ElementState oldRequiredStates = State() & ElementState::REQUIRED_STATES; + ElementState changedStates = requiredStates ^ oldRequiredStates; + + if (!changedStates.IsEmpty()) { + ToggleStates(changedStates, aNotify); + } +} + +bool nsGenericHTMLFormControlElement::IsAutocapitalizeInheriting() const { + auto type = ControlType(); + return IsInputElement(type) || IsButtonElement(type) || + type == FormControlType::Fieldset || type == FormControlType::Output || + type == FormControlType::Select || type == FormControlType::Textarea; +} + +//---------------------------------------------------------------------- + +static const nsAttrValue::EnumTable kPopoverTargetActionTable[] = { + {"toggle", PopoverTargetAction::Toggle}, + {"show", PopoverTargetAction::Show}, + {"hide", PopoverTargetAction::Hide}, + {nullptr, 0}}; + +static const nsAttrValue::EnumTable* kPopoverTargetActionDefault = + &kPopoverTargetActionTable[0]; + +nsGenericHTMLFormControlElementWithState:: + nsGenericHTMLFormControlElementWithState( + already_AddRefed&& aNodeInfo, + FromParser aFromParser, FormControlType aType) + : nsGenericHTMLFormControlElement(std::move(aNodeInfo), aType), + mControlNumber(!!(aFromParser & FROM_PARSER_NETWORK) + ? OwnerDoc()->GetNextControlNumber() + : -1) { + mStateKey.SetIsVoid(true); +} + +bool nsGenericHTMLFormControlElementWithState::ParseAttribute( + int32_t aNamespaceID, nsAtom* aAttribute, const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, nsAttrValue& aResult) { + if (aNamespaceID == kNameSpaceID_None && + StaticPrefs::dom_element_popover_enabled()) { + if (aAttribute == nsGkAtoms::popovertargetaction) { + return aResult.ParseEnumValue(aValue, kPopoverTargetActionTable, false, + kPopoverTargetActionDefault); + } + if (aAttribute == nsGkAtoms::popovertarget) { + aResult.ParseAtom(aValue); + return true; + } + } + + return nsGenericHTMLFormControlElement::ParseAttribute( + aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult); +} + +mozilla::dom::Element* +nsGenericHTMLFormControlElementWithState::GetPopoverTargetElement() const { + return GetAttrAssociatedElement(nsGkAtoms::popovertarget); +} + +void nsGenericHTMLFormControlElementWithState::SetPopoverTargetElement( + mozilla::dom::Element* aElement) { + ExplicitlySetAttrElement(nsGkAtoms::popovertarget, aElement); +} + +void nsGenericHTMLFormControlElementWithState::HandlePopoverTargetAction() { + RefPtr target = GetEffectivePopoverTargetElement(); + if (!target) { + return; + } + + const nsAttrValue* value = GetParsedAttr(nsGkAtoms::popovertargetaction); + if (!value) { + return; + } + + auto action = static_cast(value->GetEnumValue()); + bool canHide = action == PopoverTargetAction::Hide || + action == PopoverTargetAction::Toggle; + bool canShow = action == PopoverTargetAction::Show || + action == PopoverTargetAction::Toggle; + + if (canHide && target->IsPopoverOpen()) { + target->HidePopover(IgnoreErrors()); + } else if (canShow && !target->IsPopoverOpen()) { + target->GetPopoverData()->SetInvoker(this); + target->ShowPopover(IgnoreErrors()); + } +} + +void nsGenericHTMLFormControlElementWithState::GenerateStateKey() { + // Keep the key if already computed + if (!mStateKey.IsVoid()) { + return; + } + + Document* doc = GetUncomposedDoc(); + if (!doc) { + mStateKey.Truncate(); + return; + } + + // Generate the state key + nsContentUtils::GenerateStateKey(this, doc, mStateKey); + + // If the state key is blank, this is anonymous content or for whatever + // reason we are not supposed to save/restore state: keep it as such. + if (!mStateKey.IsEmpty()) { + // Add something unique to content so layout doesn't muck us up. + mStateKey += "-C"; + } +} + +PresState* nsGenericHTMLFormControlElementWithState::GetPrimaryPresState() { + if (mStateKey.IsEmpty()) { + return nullptr; + } + + nsCOMPtr history = GetLayoutHistory(false); + + if (!history) { + return nullptr; + } + + // Get the pres state for this key, if it doesn't exist, create one. + PresState* result = history->GetState(mStateKey); + if (!result) { + UniquePtr newState = NewPresState(); + result = newState.get(); + history->AddState(mStateKey, std::move(newState)); + } + + return result; +} + +already_AddRefed +nsGenericHTMLFormControlElementWithState::GetLayoutHistory(bool aRead) { + nsCOMPtr doc = GetUncomposedDoc(); + if (!doc) { + return nullptr; + } + + // + // Get the history + // + nsCOMPtr history = doc->GetLayoutHistoryState(); + if (!history) { + return nullptr; + } + + if (aRead && !history->HasStates()) { + return nullptr; + } + + return history.forget(); +} + +bool nsGenericHTMLFormControlElementWithState::RestoreFormControlState() { + MOZ_ASSERT(!mStateKey.IsVoid(), + "GenerateStateKey must already have been called"); + + if (mStateKey.IsEmpty()) { + return false; + } + + nsCOMPtr history = GetLayoutHistory(true); + if (!history) { + return false; + } + + // Get the pres state for this key + PresState* state = history->GetState(mStateKey); + if (state) { + bool result = RestoreState(state); + history->RemoveState(mStateKey); + return result; + } + + return false; +} + +void nsGenericHTMLFormControlElementWithState::NodeInfoChanged( + Document* aOldDoc) { + nsGenericHTMLFormControlElement::NodeInfoChanged(aOldDoc); + + // We need to regenerate the state key now we're in a new document. Clearing + // mControlNumber means we stop considering this control to be parser + // inserted, and we'll generate a state key based on its position in the + // document rather than the order it was inserted into the document. + mControlNumber = -1; + mStateKey.SetIsVoid(true); +} + +void nsGenericHTMLFormControlElementWithState::GetFormAction(nsString& aValue) { + auto type = ControlType(); + if (!IsInputElement(type) && !IsButtonElement(type)) { + return; + } + + if (!GetAttr(kNameSpaceID_None, nsGkAtoms::formaction, aValue) || + aValue.IsEmpty()) { + Document* document = OwnerDoc(); + nsIURI* docURI = document->GetDocumentURI(); + if (docURI) { + nsAutoCString spec; + nsresult rv = docURI->GetSpec(spec); + if (NS_FAILED(rv)) { + return; + } + + CopyUTF8toUTF16(spec, aValue); + } + } else { + GetURIAttr(nsGkAtoms::formaction, nullptr, aValue); + } +} + +bool nsGenericHTMLElement::IsEventAttributeNameInternal(nsAtom* aName) { + return nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML); +} + +/** + * Construct a URI from a string, as an element.src attribute + * would be set to. Helper for the media elements. + */ +nsresult nsGenericHTMLElement::NewURIFromString(const nsAString& aURISpec, + nsIURI** aURI) { + NS_ENSURE_ARG_POINTER(aURI); + + *aURI = nullptr; + + nsCOMPtr doc = OwnerDoc(); + + nsresult rv = nsContentUtils::NewURIWithDocumentCharset(aURI, aURISpec, doc, + GetBaseURI()); + NS_ENSURE_SUCCESS(rv, rv); + + bool equal; + if (aURISpec.IsEmpty() && doc->GetDocumentURI() && + NS_SUCCEEDED(doc->GetDocumentURI()->Equals(*aURI, &equal)) && equal) { + // Assume an element can't point to a fragment of its embedding + // document. Fail here instead of returning the recursive URI + // and waiting for the subsequent load to fail. + NS_RELEASE(*aURI); + return NS_ERROR_DOM_INVALID_STATE_ERR; + } + + return NS_OK; +} + +void nsGenericHTMLElement::GetInnerText(mozilla::dom::DOMString& aValue, + mozilla::ErrorResult& aError) { + // innerText depends on layout. For example, white space processing is + // something that happens during reflow and which must be reflected by + // innerText. So for: + // + //
A B C
+ // + // innerText should give "A B C". + // + // The approach taken here to avoid the expense of reflow is to flush style + // and then see whether it's necessary to flush layout afterwards. Flushing + // layout can be skipped if we can detect that the element or its descendants + // are not dirty. + + // Obtain the composed doc to handle elements in Shadow DOM. + Document* doc = GetComposedDoc(); + if (doc) { + doc->FlushPendingNotifications(FlushType::Style); + } + + // Elements with `display: content` will not have a frame. To handle Shadow + // DOM, walk the flattened tree looking for parent frame. + nsIFrame* frame = GetPrimaryFrame(); + if (IsDisplayContents()) { + for (Element* parent = GetFlattenedTreeParentElement(); parent; + parent = parent->GetFlattenedTreeParentElement()) { + frame = parent->GetPrimaryFrame(); + if (frame) { + break; + } + } + } + + // Check for dirty reflow roots in the subtree from targetFrame; this requires + // a reflow flush. + bool dirty = frame && frame->PresShell()->FrameIsAncestorOfDirtyRoot(frame); + + // The way we do that is by checking whether the element has either of the two + // dirty bits (NS_FRAME_IS_DIRTY or NS_FRAME_HAS_DIRTY_DESCENDANTS) or if any + // ancestor has NS_FRAME_IS_DIRTY. We need to check for NS_FRAME_IS_DIRTY on + // ancestors since that is something that implies NS_FRAME_IS_DIRTY on all + // descendants. + dirty |= frame && frame->HasAnyStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); + while (!dirty && frame) { + dirty |= frame->HasAnyStateBits(NS_FRAME_IS_DIRTY); + frame = frame->GetInFlowParent(); + } + + // Flush layout if we determined a reflow is required. + if (dirty && doc) { + doc->FlushPendingNotifications(FlushType::Layout); + } + + if (!IsRendered()) { + GetTextContentInternal(aValue, aError); + } else { + nsRange::GetInnerTextNoFlush(aValue, aError, this); + } +} + +static already_AddRefed TextToNode(const nsAString& aString, + nsNodeInfoManager* aNim) { + nsString str; + const char16_t* s = aString.BeginReading(); + const char16_t* end = aString.EndReading(); + RefPtr fragment; + while (true) { + if (s != end && *s == '\r' && s + 1 != end && s[1] == '\n') { + // a \r\n pair should only generate one
, so just skip the \r + ++s; + } + if (s == end || *s == '\r' || *s == '\n') { + if (!str.IsEmpty()) { + RefPtr textContent = new (aNim) nsTextNode(aNim); + textContent->SetText(str, true); + if (!fragment) { + if (s == end) { + return textContent.forget(); + } + fragment = new (aNim) DocumentFragment(aNim); + } + fragment->AppendChildTo(textContent, true, IgnoreErrors()); + } + if (s == end) { + break; + } + str.Truncate(); + RefPtr ni = aNim->GetNodeInfo( + nsGkAtoms::br, nullptr, kNameSpaceID_XHTML, nsINode::ELEMENT_NODE); + auto* nim = ni->NodeInfoManager(); + RefPtr br = new (nim) HTMLBRElement(ni.forget()); + if (!fragment) { + if (s + 1 == end) { + return br.forget(); + } + fragment = new (aNim) DocumentFragment(aNim); + } + fragment->AppendChildTo(br, true, IgnoreErrors()); + } else { + str.Append(*s); + } + ++s; + } + return fragment.forget(); +} + +void nsGenericHTMLElement::SetInnerText(const nsAString& aValue) { + RefPtr node = TextToNode(aValue, NodeInfo()->NodeInfoManager()); + ReplaceChildren(node, IgnoreErrors()); +} + +// https://html.spec.whatwg.org/#merge-with-the-next-text-node +static void MergeWithNextTextNode(Text& aText, ErrorResult& aRv) { + RefPtr nextSibling = Text::FromNodeOrNull(aText.GetNextSibling()); + if (!nextSibling) { + return; + } + nsAutoString data; + nextSibling->GetData(data); + aText.AppendData(data, aRv); + nextSibling->Remove(); +} + +// https://html.spec.whatwg.org/#dom-outertext +void nsGenericHTMLElement::SetOuterText(const nsAString& aValue, + ErrorResult& aRv) { + nsCOMPtr parent = GetParentNode(); + if (!parent) { + return aRv.ThrowNoModificationAllowedError("Element has no parent"); + } + + RefPtr next = GetNextSibling(); + RefPtr previous = GetPreviousSibling(); + + // Batch possible DOMSubtreeModified events. + mozAutoSubtreeModified subtree(OwnerDoc(), nullptr); + + nsNodeInfoManager* nim = NodeInfo()->NodeInfoManager(); + RefPtr node = TextToNode(aValue, nim); + if (!node) { + // This doesn't match the spec, see + // https://github.com/whatwg/html/issues/7508 + node = new (nim) nsTextNode(nim); + } + parent->ReplaceChild(*node, *this, aRv); + if (aRv.Failed()) { + return; + } + + if (next) { + if (RefPtr text = Text::FromNodeOrNull(next->GetPreviousSibling())) { + MergeWithNextTextNode(*text, aRv); + if (aRv.Failed()) { + return; + } + } + } + if (auto* text = Text::FromNodeOrNull(previous)) { + MergeWithNextTextNode(*text, aRv); + } +} + +// This should be true when `:open` should match. +bool nsGenericHTMLElement::PopoverOpen() const { + if (PopoverData* popoverData = GetPopoverData()) { + return popoverData->GetPopoverVisibilityState() == + PopoverVisibilityState::Showing; + } + return false; +} + +// https://html.spec.whatwg.org/#check-popover-validity +bool nsGenericHTMLElement::CheckPopoverValidity( + PopoverVisibilityState aExpectedState, Document* aExpectedDocument, + ErrorResult& aRv) { + const PopoverData* data = GetPopoverData(); + if (!data || + data->GetPopoverAttributeState() == PopoverAttributeState::None) { + MOZ_ASSERT(!HasAttr(nsGkAtoms::popover)); + aRv.ThrowNotSupportedError("Element is in the no popover state"); + return false; + } + + MOZ_ASSERT(HasAttr(nsGkAtoms::popover)); + + if (data->GetPopoverVisibilityState() != aExpectedState) { + return false; + } + + if (!IsInComposedDoc()) { + aRv.ThrowInvalidStateError("Element is not connected"); + return false; + } + + if (aExpectedDocument && aExpectedDocument != OwnerDoc()) { + aRv.ThrowInvalidStateError("Element is moved to other document"); + return false; + } + + if (IsHTMLElement(nsGkAtoms::dialog) && HasAttr(nsGkAtoms::open)) { + aRv.ThrowInvalidStateError("Element is an open element"); + return false; + } + + if (State().HasState(ElementState::FULLSCREEN)) { + aRv.ThrowInvalidStateError("Element is fullscreen"); + return false; + } + + return true; +} + +PopoverAttributeState nsGenericHTMLElement::GetPopoverAttributeState() const { + return GetPopoverData() ? GetPopoverData()->GetPopoverAttributeState() + : PopoverAttributeState::None; +} + +void nsGenericHTMLElement::PopoverPseudoStateUpdate(bool aOpen, bool aNotify) { + ElementState newPopoverState; + if (aOpen) { + newPopoverState = ElementState::POPOVER_OPEN; + } + + ElementState oldPopoverState = State() & ElementState::POPOVER_OPEN; + ElementState changedState = newPopoverState ^ oldPopoverState; + ToggleStates(changedState, aNotify); +} + +bool nsGenericHTMLElement::FireToggleEvent(PopoverVisibilityState aOldState, + PopoverVisibilityState aNewState, + const nsAString& aType) { + auto stringForState = [](PopoverVisibilityState state) { + return state == PopoverVisibilityState::Hidden ? u"closed"_ns : u"open"_ns; + }; + + ToggleEventInit init; + init.mBubbles = false; + init.mOldState = stringForState(aOldState); + init.mNewState = stringForState(aNewState); + if (aType == u"beforetoggle"_ns && + aNewState == PopoverVisibilityState::Showing) { + init.mCancelable = true; + } else { + init.mCancelable = false; + } + RefPtr event = ToggleEvent::Constructor(this, aType, init); + event->SetTrusted(true); + event->SetTarget(this); + + EventDispatcher::DispatchDOMEvent(MOZ_KnownLive(ToSupports(this)), nullptr, + event, nullptr, nullptr); + return event->DefaultPrevented(); +} + +// https://html.spec.whatwg.org/#queue-a-popover-toggle-event-task +void nsGenericHTMLElement::QueuePopoverEventTask( + PopoverVisibilityState aOldState) { + auto* data = GetPopoverData(); + MOZ_ASSERT(data, "Should have popover data"); + + if (auto* queuedToggleEventTask = data->GetToggleEventTask()) { + aOldState = queuedToggleEventTask->GetOldState(); + } + + auto task = + MakeRefPtr(do_GetWeakReference(this), aOldState); + data->SetToggleEventTask(task); + + OwnerDoc()->Dispatch(TaskCategory::UI, task.forget()); +} + +void nsGenericHTMLElement::RunPopoverToggleEventTask( + PopoverToggleEventTask* aTask, PopoverVisibilityState aOldState) { + auto* data = GetPopoverData(); + if (!data) { + return; + } + + auto* popoverToggleEventTask = data->GetToggleEventTask(); + if (!popoverToggleEventTask || aTask != popoverToggleEventTask) { + return; + } + data->ClearToggleEventTask(); + // Intentionally ignore the return value here as only on open event the + // cancelable attribute is initialized to true for beforetoggle event. + FireToggleEvent(aOldState, data->GetPopoverVisibilityState(), u"toggle"_ns); +} + +// https://html.spec.whatwg.org/#dom-showpopover +void nsGenericHTMLElement::ShowPopover(ErrorResult& aRv) { + if (!CheckPopoverValidity(PopoverVisibilityState::Hidden, nullptr, aRv)) { + return; + } + RefPtr document = OwnerDoc(); + MOZ_ASSERT(!OwnerDoc()->TopLayerContains(*this)); + + // Fire beforetoggle event and re-check popover validity. + if (FireToggleEvent(PopoverVisibilityState::Hidden, + PopoverVisibilityState::Showing, u"beforetoggle"_ns)) { + return; + } + if (!CheckPopoverValidity(PopoverVisibilityState::Hidden, document, aRv)) { + return; + } + + bool shouldRestoreFocus = false; + nsWeakPtr originallyFocusedElement; + if (IsAutoPopover()) { + RefPtr ancestor = GetTopmostPopoverAncestor(); + if (!ancestor) { + ancestor = document; + } + document->HideAllPopoversUntil(*ancestor, false, true); + + // TODO: Handle if document changes, see + // https://github.com/whatwg/html/issues/9177 + if (!IsAutoPopover() || + !CheckPopoverValidity(PopoverVisibilityState::Hidden, document, aRv)) { + return; + } + + shouldRestoreFocus = !document->GetTopmostAutoPopover(); + // Let originallyFocusedElement be document's focused area of the document's + // DOM anchor. + if (nsIContent* unretargetedFocus = + document->GetUnretargetedFocusedContent()) { + originallyFocusedElement = + do_GetWeakReference(unretargetedFocus->AsElement()); + } + } + + document->AddPopoverToTopLayer(*this); + + PopoverPseudoStateUpdate(true, true); + GetPopoverData()->SetPopoverVisibilityState(PopoverVisibilityState::Showing); + + // Run the popover focusing steps given element. + FocusPopover(); + if (shouldRestoreFocus && + GetPopoverAttributeState() != PopoverAttributeState::None) { + GetPopoverData()->SetPreviouslyFocusedElement(originallyFocusedElement); + } + + // Queue popover toggle event task. + QueuePopoverEventTask(PopoverVisibilityState::Hidden); +} + +void nsGenericHTMLElement::HidePopoverWithoutRunningScript() { + HidePopoverInternal(/* aFocusPreviousElement = */ false, + /* aFireEvents = */ false, IgnoreErrors()); +} + +// https://html.spec.whatwg.org/#dom-hidepopover +void nsGenericHTMLElement::HidePopover(ErrorResult& aRv) { + HidePopoverInternal(/* aFocusPreviousElement = */ true, + /* aFireEvents = */ true, aRv); +} + +void nsGenericHTMLElement::HidePopoverInternal(bool aFocusPreviousElement, + bool aFireEvents, + ErrorResult& aRv) { + OwnerDoc()->HidePopover(*this, aFocusPreviousElement, aFireEvents, aRv); +} + +void nsGenericHTMLElement::ForgetPreviouslyFocusedElementAfterHidingPopover() { + auto* data = GetPopoverData(); + MOZ_ASSERT(data, "Should have popover data"); + data->SetPreviouslyFocusedElement(nullptr); +} + +void nsGenericHTMLElement::FocusPreviousElementAfterHidingPopover() { + auto* data = GetPopoverData(); + MOZ_ASSERT(data, "Should have popover data"); + + RefPtr control = + do_QueryReferent(data->GetPreviouslyFocusedElement().get()); + data->SetPreviouslyFocusedElement(nullptr); + + if (!control) { + return; + } + + // Run the focusing steps for previouslyFocusedElement + FocusOptions options; + options.mPreventScroll = true; + control->Focus(options, CallerType::NonSystem, IgnoreErrors()); +} + +// https://html.spec.whatwg.org/multipage/popover.html#dom-togglepopover +void nsGenericHTMLElement::TogglePopover(const Optional& aForce, + ErrorResult& aRv) { + if (PopoverOpen() && (!aForce.WasPassed() || !aForce.Value())) { + HidePopover(aRv); + } else if (!aForce.WasPassed() || aForce.Value()) { + ShowPopover(aRv); + } +} + +// https://html.spec.whatwg.org/multipage/popover.html#popover-focusing-steps +void nsGenericHTMLElement::FocusPopover() { + if (auto* dialog = HTMLDialogElement::FromNode(this)) { + return MOZ_KnownLive(dialog)->FocusDialog(); + } + + if (RefPtr doc = GetComposedDoc()) { + doc->FlushPendingNotifications(FlushType::Frames); + } + + // This diverges from the spec a bit, + // see https://github.com/whatwg/html/pull/8998 + RefPtr control = + GetBoolAttr(nsGkAtoms::autofocus) + ? this + : GetFocusDelegate(false /* aWithMouse */, true /* aAutofocusOnly */); + if (!control) { + return; + } + FocusCandidate(*control, false /* aClearUpFocus */); +} + +void nsGenericHTMLElement::FocusCandidate(Element& aControl, + bool aClearUpFocus) { + // 1) Run the focusing steps given control. + IgnoredErrorResult rv; + nsIFrame* frame = aControl.GetPrimaryFrame(); + if (frame && frame->IsFocusable()) { + aControl.Focus(FocusOptions(), CallerType::NonSystem, rv); + if (rv.Failed()) { + return; + } + } else if (aClearUpFocus) { + if (RefPtr fm = nsFocusManager::GetFocusManager()) { + // Clear the focus which ends up making the body gets focused + nsCOMPtr outerWindow = OwnerDoc()->GetWindow(); + fm->ClearFocus(outerWindow); + } + } + + // 2) Let topDocument be the active document of control's node document's + // browsing context's top-level browsing context. + // 3) If control's node document's origin is not the same as the origin of + // topDocument, then return. + BrowsingContext* bc = aControl.OwnerDoc()->GetBrowsingContext(); + if (bc && bc->IsInProcess() && bc->SameOriginWithTop()) { + if (nsCOMPtr docShell = bc->Top()->GetDocShell()) { + if (Document* topDocument = docShell->GetExtantDocument()) { + // 4) Empty topDocument's autofocus candidates. + // 5) Set topDocument's autofocus processed flag to true. + topDocument->SetAutoFocusFired(); + } + } + } +} + +already_AddRefed nsGenericHTMLElement::AttachInternals( + ErrorResult& aRv) { + // ElementInternals is only available on autonomous custom element, so throws + // an error by default. The spec steps are implemented in HTMLElement because + // ElementInternals needs to hold a pointer to HTMLElement in order to forward + // form operation to it. + aRv.ThrowNotSupportedError(nsPrintfCString( + "Cannot attach ElementInternals to a customized built-in or non-custom " + "element " + "'%s'", + NS_ConvertUTF16toUTF8(NodeInfo()->NameAtom()->GetUTF16String()).get())); + return nullptr; +} + +ElementInternals* nsGenericHTMLElement::GetInternals() const { + if (CustomElementData* data = GetCustomElementData()) { + return data->GetElementInternals(); + } + return nullptr; +} + +bool nsGenericHTMLElement::IsFormAssociatedCustomElements() const { + if (CustomElementData* data = GetCustomElementData()) { + return data->IsFormAssociated(); + } + return false; +} + +void nsGenericHTMLElement::GetAutocapitalize(nsAString& aValue) const { + GetEnumAttr(nsGkAtoms::autocapitalize, nullptr, kDefaultAutocapitalize->tag, + aValue); +} + +bool nsGenericHTMLElement::Translate() const { + if (const nsAttrValue* attr = mAttrs.GetAttr(nsGkAtoms::translate)) { + if (attr->IsEmptyString() || attr->Equals(nsGkAtoms::yes, eIgnoreCase)) { + return true; + } + if (attr->Equals(nsGkAtoms::no, eIgnoreCase)) { + return false; + } + } + return nsGenericHTMLElementBase::Translate(); +} + +void nsGenericHTMLElement::GetPopover(nsString& aPopover) const { + GetHTMLEnumAttr(nsGkAtoms::popover, aPopover); + if (aPopover.IsEmpty() && !DOMStringIsNull(aPopover)) { + aPopover.Assign(NS_ConvertUTF8toUTF16(kPopoverAttributeValueAuto)); + } +} diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h new file mode 100644 index 0000000000..4dae91a5ef --- /dev/null +++ b/dom/html/nsGenericHTMLElement.h @@ -0,0 +1,1469 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ +#ifndef nsGenericHTMLElement_h___ +#define nsGenericHTMLElement_h___ + +#include "mozilla/Attributes.h" +#include "mozilla/EventForwards.h" +#include "nsMappedAttributeElement.h" +#include "nsNameSpaceManager.h" // for kNameSpaceID_None +#include "nsIFormControl.h" +#include "nsGkAtoms.h" +#include "nsContentCreatorFunctions.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/DOMRect.h" +#include "mozilla/dom/ValidityState.h" +#include "mozilla/dom/PopoverData.h" +#include "mozilla/dom/ToggleEvent.h" + +class nsDOMTokenList; +class nsIFormControlFrame; +class nsIFrame; +class nsILayoutHistoryState; +class nsIURI; +struct nsSize; + +namespace mozilla { +class EditorBase; +class ErrorResult; +class EventChainPostVisitor; +class EventChainPreVisitor; +class EventChainVisitor; +class EventListenerManager; +class PresState; +namespace dom { +class ElementInternals; +class HTMLFormElement; +} // namespace dom +} // namespace mozilla + +using nsGenericHTMLElementBase = nsMappedAttributeElement; + +/** + * A common superclass for HTML elements + */ +class nsGenericHTMLElement : public nsGenericHTMLElementBase { + public: + using Element::Focus; + using Element::SetTabIndex; + explicit nsGenericHTMLElement( + already_AddRefed&& aNodeInfo) + : nsGenericHTMLElementBase(std::move(aNodeInfo)) { + NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML, + "Unexpected namespace"); + AddStatesSilently(mozilla::dom::ElementState::LTR); + SetFlags(NODE_HAS_DIRECTION_LTR); + } + + NS_INLINE_DECL_REFCOUNTING_INHERITED(nsGenericHTMLElement, + nsGenericHTMLElementBase) + + NS_IMPL_FROMNODE(nsGenericHTMLElement, kNameSpaceID_XHTML) + + // From Element + nsresult CopyInnerTo(mozilla::dom::Element* aDest); + + void GetTitle(mozilla::dom::DOMString& aTitle) { + GetHTMLAttr(nsGkAtoms::title, aTitle); + } + void SetTitle(const nsAString& aTitle) { + SetHTMLAttr(nsGkAtoms::title, aTitle); + } + void GetLang(mozilla::dom::DOMString& aLang) { + GetHTMLAttr(nsGkAtoms::lang, aLang); + } + void SetLang(const nsAString& aLang) { SetHTMLAttr(nsGkAtoms::lang, aLang); } + bool Translate() const override; + void SetTranslate(bool aTranslate, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::translate, aTranslate ? u"yes"_ns : u"no"_ns, + aError); + } + void GetDir(nsAString& aDir) { GetHTMLEnumAttr(nsGkAtoms::dir, aDir); } + void SetDir(const nsAString& aDir, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::dir, aDir, aError); + } + void GetPopover(nsString& aPopover) const; + void SetPopover(const nsAString& aPopover, mozilla::ErrorResult& aError) { + SetOrRemoveNullableStringAttr(nsGkAtoms::popover, aPopover, aError); + } + bool Hidden() const { return GetBoolAttr(nsGkAtoms::hidden); } + void SetHidden(bool aHidden, mozilla::ErrorResult& aError) { + SetHTMLBoolAttr(nsGkAtoms::hidden, aHidden, aError); + } + bool Inert() const { return GetBoolAttr(nsGkAtoms::inert); } + void SetInert(bool aInert, mozilla::ErrorResult& aError) { + SetHTMLBoolAttr(nsGkAtoms::inert, aInert, aError); + } + MOZ_CAN_RUN_SCRIPT void Click(mozilla::dom::CallerType aCallerType); + void GetAccessKey(nsString& aAccessKey) { + GetHTMLAttr(nsGkAtoms::accesskey, aAccessKey); + } + void SetAccessKey(const nsAString& aAccessKey, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::accesskey, aAccessKey, aError); + } + void GetAccessKeyLabel(nsString& aAccessKeyLabel); + virtual bool Draggable() const { + return AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable, + nsGkAtoms::_true, eIgnoreCase); + } + void SetDraggable(bool aDraggable, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::draggable, aDraggable ? u"true"_ns : u"false"_ns, + aError); + } + void GetContentEditable(nsString& aContentEditable) { + ContentEditableTristate value = GetContentEditableValue(); + if (value == eTrue) { + aContentEditable.AssignLiteral("true"); + } else if (value == eFalse) { + aContentEditable.AssignLiteral("false"); + } else { + aContentEditable.AssignLiteral("inherit"); + } + } + void SetContentEditable(const nsAString& aContentEditable, + mozilla::ErrorResult& aError) { + if (aContentEditable.LowerCaseEqualsLiteral("inherit")) { + UnsetHTMLAttr(nsGkAtoms::contenteditable, aError); + } else if (aContentEditable.LowerCaseEqualsLiteral("true")) { + SetHTMLAttr(nsGkAtoms::contenteditable, u"true"_ns, aError); + } else if (aContentEditable.LowerCaseEqualsLiteral("false")) { + SetHTMLAttr(nsGkAtoms::contenteditable, u"false"_ns, aError); + } else { + aError.Throw(NS_ERROR_DOM_SYNTAX_ERR); + } + } + bool IsContentEditable() { + for (nsIContent* node = this; node; node = node->GetParent()) { + nsGenericHTMLElement* element = FromNode(node); + if (element) { + ContentEditableTristate value = element->GetContentEditableValue(); + if (value != eInherit) { + return value == eTrue; + } + } + } + return false; + } + + mozilla::dom::PopoverAttributeState GetPopoverAttributeState() const; + void PopoverPseudoStateUpdate(bool aOpen, bool aNotify); + bool PopoverOpen() const; + bool CheckPopoverValidity(mozilla::dom::PopoverVisibilityState aExpectedState, + Document* aExpectedDocument, ErrorResult& aRv); + /** Returns true if the event has been cancelled. */ + MOZ_CAN_RUN_SCRIPT bool FireToggleEvent( + mozilla::dom::PopoverVisibilityState aOldState, + mozilla::dom::PopoverVisibilityState aNewState, const nsAString& aType); + MOZ_CAN_RUN_SCRIPT void QueuePopoverEventTask( + mozilla::dom::PopoverVisibilityState aOldState); + MOZ_CAN_RUN_SCRIPT void RunPopoverToggleEventTask( + mozilla::dom::PopoverToggleEventTask* aTask, + mozilla::dom::PopoverVisibilityState aOldState); + MOZ_CAN_RUN_SCRIPT void ShowPopover(ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT_BOUNDARY void HidePopoverWithoutRunningScript(); + MOZ_CAN_RUN_SCRIPT void HidePopoverInternal(bool aFocusPreviousElement, + bool aFireEvents, + ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT void HidePopover(ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT void TogglePopover( + const mozilla::dom::Optional& aForce, ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT void FocusPopover(); + void ForgetPreviouslyFocusedElementAfterHidingPopover(); + MOZ_CAN_RUN_SCRIPT void FocusPreviousElementAfterHidingPopover(); + + MOZ_CAN_RUN_SCRIPT void FocusCandidate(Element&, bool aClearUpFocus); + + void SetNonce(const nsAString& aNonce) { + SetProperty(nsGkAtoms::nonce, new nsString(aNonce), + nsINode::DeleteProperty, /* aTransfer = */ true); + } + void RemoveNonce() { RemoveProperty(nsGkAtoms::nonce); } + void GetNonce(nsAString& aNonce) const { + nsString* cspNonce = static_cast(GetProperty(nsGkAtoms::nonce)); + if (cspNonce) { + aNonce = *cspNonce; + } + } + + /** Returns whether a form control should be default-focusable. */ + bool IsFormControlDefaultFocusable(bool aWithMouse) const; + + /** + * Returns the count of descendants (inclusive of this node) in + * the uncomposed document that are explicitly set as editable. + */ + uint32_t EditableInclusiveDescendantCount(); + + bool Spellcheck(); + void SetSpellcheck(bool aSpellcheck, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::spellcheck, aSpellcheck ? u"true"_ns : u"false"_ns, + aError); + } + + MOZ_CAN_RUN_SCRIPT + void GetInnerText(mozilla::dom::DOMString& aValue, ErrorResult& aError); + MOZ_CAN_RUN_SCRIPT + void GetOuterText(mozilla::dom::DOMString& aValue, ErrorResult& aError) { + return GetInnerText(aValue, aError); + } + MOZ_CAN_RUN_SCRIPT void SetInnerText(const nsAString& aValue); + MOZ_CAN_RUN_SCRIPT void SetOuterText(const nsAString& aValue, + ErrorResult& aRv); + + void GetInputMode(nsAString& aValue) { + GetEnumAttr(nsGkAtoms::inputmode, nullptr, aValue); + } + void SetInputMode(const nsAString& aValue, ErrorResult& aRv) { + SetHTMLAttr(nsGkAtoms::inputmode, aValue, aRv); + } + virtual void GetAutocapitalize(nsAString& aValue) const; + void SetAutocapitalize(const nsAString& aValue, ErrorResult& aRv) { + SetHTMLAttr(nsGkAtoms::autocapitalize, aValue, aRv); + } + + void GetEnterKeyHint(nsAString& aValue) const { + GetEnumAttr(nsGkAtoms::enterkeyhint, nullptr, aValue); + } + void SetEnterKeyHint(const nsAString& aValue, ErrorResult& aRv) { + SetHTMLAttr(nsGkAtoms::enterkeyhint, aValue, aRv); + } + + /** + * Determine whether an attribute is an event (onclick, etc.) + * @param aName the attribute + * @return whether the name is an event handler name + */ + bool IsEventAttributeNameInternal(nsAtom* aName) override; + +#define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */ +// The using nsINode::Get/SetOn* are to avoid warnings about shadowing the XPCOM +// getter and setter on nsINode. +#define FORWARDED_EVENT(name_, id_, type_, struct_) \ + using nsINode::GetOn##name_; \ + using nsINode::SetOn##name_; \ + mozilla::dom::EventHandlerNonNull* GetOn##name_(); \ + void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler); +#define ERROR_EVENT(name_, id_, type_, struct_) \ + using nsINode::GetOn##name_; \ + using nsINode::SetOn##name_; \ + already_AddRefed GetOn##name_(); \ + void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler); +#include "mozilla/EventNameList.h" // IWYU pragma: keep +#undef ERROR_EVENT +#undef FORWARDED_EVENT +#undef EVENT + mozilla::dom::Element* GetOffsetParent() { + mozilla::CSSIntRect rcFrame; + return GetOffsetRect(rcFrame); + } + int32_t OffsetTop() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.y; + } + int32_t OffsetLeft() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.x; + } + int32_t OffsetWidth() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.Width(); + } + int32_t OffsetHeight() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.Height(); + } + + // These methods are already implemented in nsIContent but we want something + // faster for HTMLElements ignoring the namespace checking. + // This is safe because we already know that we are in the HTML namespace. + inline bool IsHTMLElement() const { return true; } + + inline bool IsHTMLElement(nsAtom* aTag) const { + return mNodeInfo->Equals(aTag); + } + + template + inline bool IsAnyOfHTMLElements(First aFirst, Args... aArgs) const { + return IsNodeInternal(aFirst, aArgs...); + } + + // https://html.spec.whatwg.org/multipage/custom-elements.html#dom-attachinternals + virtual already_AddRefed AttachInternals( + ErrorResult& aRv); + + mozilla::dom::ElementInternals* GetInternals() const; + + bool IsFormAssociatedCustomElements() const; + + // Returns true if the event should not be handled from GetEventTargetParent. + virtual bool IsDisabledForEvents(mozilla::WidgetEvent* aEvent) { + return false; + } + + bool Autofocus() const { return GetBoolAttr(nsGkAtoms::autofocus); } + void SetAutofocus(bool aVal, ErrorResult& aRv) { + SetHTMLBoolAttr(nsGkAtoms::autofocus, aVal, aRv); + } + + protected: + virtual ~nsGenericHTMLElement() = default; + + public: + // Implementation for nsIContent + nsresult BindToTree(BindContext&, nsINode& aParent) override; + void UnbindFromTree(bool aNullParent = true) override; + + bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override { + bool isFocusable = false; + IsHTMLFocusable(aWithMouse, &isFocusable, aTabIndex); + return isFocusable; + } + /** + * Returns true if a subclass is not allowed to override the value returned + * in aIsFocusable. + */ + virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex); + MOZ_CAN_RUN_SCRIPT + mozilla::Result PerformAccesskey( + bool aKeyCausesActivation, bool aIsTrustedEvent) override; + + /** + * Check if an event for an anchor can be handled + * @return true if the event can be handled, false otherwise + */ + bool CheckHandleEventForAnchorsPreconditions( + mozilla::EventChainVisitor& aVisitor); + void GetEventTargetParentForAnchors(mozilla::EventChainPreVisitor& aVisitor); + MOZ_CAN_RUN_SCRIPT + nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor); + bool IsHTMLLink(nsIURI** aURI) const; + + // HTML element methods + void Compact() { mAttrs.Compact(); } + + void UpdateEditableState(bool aNotify) override; + + mozilla::dom::ElementState IntrinsicState() const override; + + // Helper for setting our editable flag and notifying + void DoSetEditableFlag(bool aEditable, bool aNotify) { + SetEditableFlag(aEditable); + UpdateState(aNotify); + } + + bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) override; + + bool ParseBackgroundAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, nsAttrValue& aResult); + + NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override; + nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; + + /** + * Get the base target for any links within this piece + * of content. Generally, this is the document's base target, + * but certain content carries a local base for backward + * compatibility. + * + * @param aBaseTarget the base target [OUT] + */ + void GetBaseTarget(nsAString& aBaseTarget) const; + + /** + * Get the primary form control frame for this element. Same as + * GetPrimaryFrame(), except it QI's to nsIFormControlFrame. + * + * @param aFlush whether to flush out frames so that they're up to date. + * @return the primary frame as nsIFormControlFrame + */ + nsIFormControlFrame* GetFormControlFrame(bool aFlushFrames); + + //---------------------------------------- + + /** + * Parse an alignment attribute (top/middle/bottom/baseline) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseAlignValue(const nsAString& aString, nsAttrValue& aResult); + + /** + * Parse a div align string to value (left/right/center/middle/justify) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseDivAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a table halign string to value (left/right/center/char/justify) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseTableHAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a table cell halign string to value + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseTableCellHAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a table valign string to value (left/right/center/char/justify/ + * abscenter/absmiddle/middle) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseTableVAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert an image attribute to value (width, height, hspace, vspace, border) + * + * @param aAttribute the attribute to parse + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseImageAttribute(nsAtom* aAttribute, const nsAString& aString, + nsAttrValue& aResult); + + static bool ParseReferrerAttribute(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a frameborder string to value (yes/no/1/0) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseFrameborderValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a scrolling string to value (yes/no/on/off/scroll/noscroll/auto) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseScrollingValue(const nsAString& aString, + nsAttrValue& aResult); + + /* + * Attribute Mapping Helpers + */ + + /** + * A style attribute mapping function for the most common attributes, to be + * called by subclasses' attribute mapping functions. Currently handles + * dir, lang and hidden, could handle others. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapCommonAttributesInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + /** + * Same as MapCommonAttributesInto except that it does not handle hidden. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapCommonAttributesIntoExceptHidden( + const nsMappedAttributes* aAttributes, mozilla::MappedDeclarations&); + + static const MappedAttributeEntry sCommonAttributeMap[]; + static const MappedAttributeEntry sImageMarginSizeAttributeMap[]; + static const MappedAttributeEntry sImageBorderAttributeMap[]; + static const MappedAttributeEntry sImageAlignAttributeMap[]; + static const MappedAttributeEntry sDivAlignAttributeMap[]; + static const MappedAttributeEntry sBackgroundAttributeMap[]; + static const MappedAttributeEntry sBackgroundColorAttributeMap[]; + + /** + * Helper to map the align attribute into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + + /** + * Helper to map the align attribute into a style struct for things + * like
,

, etc. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + + /** + * Helper to map the valign attribute into a style struct for things + * like , ,
, etc. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapVAlignAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + + /** + * Helper to map the image border attribute into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + /** + * Helper to map the image margin attribute into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + + // Whether to map the width and height attributes to aspect-ratio. + enum class MapAspectRatio { No, Yes }; + + /** + * Helper to map the image position attribute into a style struct. + */ + static void MapImageSizeAttributesInto(const nsMappedAttributes*, + mozilla::MappedDeclarations&, + MapAspectRatio = MapAspectRatio::No); + /** + * Helper to map the iamge source attributes into a style stuct. + * Note: + * This will override the declaration created by the presentation attributes + * of HTMLImageElement (i.e. mapped by MapImageSizeAttributeInto). + * https://html.spec.whatwg.org/multipage/embedded-content.html#the-source-element + */ + static void MapPictureSourceSizeAttributesInto(const nsMappedAttributes*, + mozilla::MappedDeclarations&); + + /** + * Helper to map the width and height attributes into the aspect-ratio + * property. + * + * If you also map the width/height attributes to width/height (as you should + * for any HTML element that isn't ) then you should use + * MapImageSizeAttributesInto instead, passing MapAspectRatio::Yes instead, as + * that'd be faster. + */ + static void MapAspectRatioInto(const nsMappedAttributes*, + mozilla::MappedDeclarations&); + + /** + * Helper to map `width` attribute into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapWidthAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + /** + * Helper to map `height` attribute into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapHeightAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + /** + * Helper to map the background attribute + * into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapBackgroundInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + /** + * Helper to map the bgcolor attribute + * into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapBGColorInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + /** + * Helper to map the background attributes (currently background and bgcolor) + * into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + /** + * Helper to map the scrolling attribute on FRAME and IFRAME + * into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapScrollingAttributeInto(const nsMappedAttributes* aAttributes, + mozilla::MappedDeclarations&); + + // Form Helper Routines + /** + * Find an ancestor of this content node which is a form (could be null) + * @param aCurrentForm the current form for this node. If this is + * non-null, and no ancestor form is found, and the current form is in + * a connected subtree with the node, the current form will be + * returned. This is needed to handle cases when HTML elements have a + * current form that they're not descendants of. + * @note This method should not be called if the element has a form attribute. + */ + mozilla::dom::HTMLFormElement* FindAncestorForm( + mozilla::dom::HTMLFormElement* aCurrentForm = nullptr); + + /** + * See if the document being tested has nav-quirks mode enabled. + * @param doc the document + */ + static bool InNavQuirksMode(Document*); + + /** + * Gets the absolute URI value of an attribute, by resolving any relative + * URIs in the attribute against the baseuri of the element. If the attribute + * isn't a relative URI the value of the attribute is returned as is. Only + * works for attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aBaseAttr name of base attribute. + * @param aResult result value [out] + */ + void GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, nsAString& aResult) const; + + /** + * Gets the absolute URI values of an attribute, by resolving any relative + * URIs in the attribute against the baseuri of the element. If a substring + * isn't a relative URI, the substring is returned as is. Only works for + * attributes in null namespace. + */ + bool GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, nsIURI** aURI) const; + + bool IsHidden() const { + return HasAttr(kNameSpaceID_None, nsGkAtoms::hidden); + } + + bool IsLabelable() const override; + + static bool MatchLabelsElement(Element* aElement, int32_t aNamespaceID, + nsAtom* aAtom, void* aData); + + already_AddRefed Labels(); + + static bool LegacyTouchAPIEnabled(JSContext* aCx, JSObject* aObj); + + static inline bool CanHaveName(nsAtom* aTag) { + return aTag == nsGkAtoms::img || aTag == nsGkAtoms::form || + aTag == nsGkAtoms::embed || aTag == nsGkAtoms::object; + } + static inline bool ShouldExposeNameAsHTMLDocumentProperty(Element* aElement) { + return aElement->IsHTMLElement() && + CanHaveName(aElement->NodeInfo()->NameAtom()); + } + static inline bool ShouldExposeIdAsHTMLDocumentProperty(Element* aElement) { + if (aElement->IsHTMLElement(nsGkAtoms::object)) { + return true; + } + + // Per spec, is exposed by id only if it also has a nonempty + // name (which doesn't have to match the id or anything). + // HasName() is true precisely when name is nonempty. + return aElement->IsHTMLElement(nsGkAtoms::img) && aElement->HasName(); + } + + virtual inline void ResultForDialogSubmit(nsAString& aResult) { + GetAttr(kNameSpaceID_None, nsGkAtoms::value, aResult); + } + + protected: + /** + * Add/remove this element to the documents name cache + */ + void AddToNameTable(nsAtom* aName); + void RemoveFromNameTable(); + + /** + * Register or unregister an access key to this element based on the + * accesskey attribute. + */ + void RegUnRegAccessKey(bool aDoReg) override { + if (!HasFlag(NODE_HAS_ACCESSKEY)) { + return; + } + + nsStyledElement::RegUnRegAccessKey(aDoReg); + } + + protected: + void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, bool aNotify) override; + // TODO: Convert AfterSetAttr to MOZ_CAN_RUN_SCRIPT and get rid of + // kungFuDeathGrip in it. + MOZ_CAN_RUN_SCRIPT_BOUNDARY void AfterSetAttr( + int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, + const nsAttrValue* aOldValue, nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) override; + + MOZ_CAN_RUN_SCRIPT void AfterSetPopoverAttr(); + + mozilla::EventListenerManager* GetEventListenerManagerForAttr( + nsAtom* aAttrName, bool* aDefer) override; + + /** + * Handles dispatching a simulated click on `this` on space or enter. + * TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) + */ + MOZ_CAN_RUN_SCRIPT_BOUNDARY void HandleKeyboardActivation( + mozilla::EventChainPostVisitor&); + + /** Dispatch a simulated mouse click by keyboard to the given element. */ + MOZ_CAN_RUN_SCRIPT static nsresult DispatchSimulatedClick( + nsGenericHTMLElement* aElement, bool aIsTrusted, + nsPresContext* aPresContext); + + /** + * Create a URI for the given aURISpec string. + * Returns INVALID_STATE_ERR and nulls *aURI if aURISpec is empty + * and the document's URI matches the element's base URI. + */ + nsresult NewURIFromString(const nsAString& aURISpec, nsIURI** aURI); + + void GetHTMLAttr(nsAtom* aName, nsAString& aResult) const { + GetAttr(aName, aResult); + } + void GetHTMLAttr(nsAtom* aName, mozilla::dom::DOMString& aResult) const { + GetAttr(kNameSpaceID_None, aName, aResult); + } + void GetHTMLEnumAttr(nsAtom* aName, nsAString& aResult) const { + GetEnumAttr(aName, nullptr, aResult); + } + void GetHTMLURIAttr(nsAtom* aName, nsAString& aResult) const { + GetURIAttr(aName, nullptr, aResult); + } + + void SetHTMLAttr(nsAtom* aName, const nsAString& aValue) { + SetAttr(kNameSpaceID_None, aName, aValue, true); + } + void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, + mozilla::ErrorResult& aError) { + SetAttr(aName, aValue, aError); + } + void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, + nsIPrincipal* aTriggeringPrincipal, + mozilla::ErrorResult& aError) { + SetAttr(aName, aValue, aTriggeringPrincipal, aError); + } + void UnsetHTMLAttr(nsAtom* aName, mozilla::ErrorResult& aError) { + UnsetAttr(aName, aError); + } + void SetHTMLBoolAttr(nsAtom* aName, bool aValue, + mozilla::ErrorResult& aError) { + if (aValue) { + SetHTMLAttr(aName, u""_ns, aError); + } else { + UnsetHTMLAttr(aName, aError); + } + } + template + void SetHTMLIntAttr(nsAtom* aName, T aValue, mozilla::ErrorResult& aError) { + nsAutoString value; + value.AppendInt(aValue); + + SetHTMLAttr(aName, value, aError); + } + + /** + * Gets the integer-value of an attribute, returns specified default value + * if the attribute isn't set or isn't set to an integer. Only works for + * attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aDefault default-value to return if attribute isn't set. + */ + int32_t GetIntAttr(nsAtom* aAttr, int32_t aDefault) const; + + /** + * Sets value of attribute to specified integer. Only works for attributes + * in null namespace. + * + * @param aAttr name of attribute. + * @param aValue Integer value of attribute. + */ + nsresult SetIntAttr(nsAtom* aAttr, int32_t aValue); + + /** + * Gets the unsigned integer-value of an attribute, returns specified default + * value if the attribute isn't set or isn't set to an integer. Only works for + * attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aDefault default-value to return if attribute isn't set. + */ + uint32_t GetUnsignedIntAttr(nsAtom* aAttr, uint32_t aDefault) const; + + /** + * Sets value of attribute to specified unsigned integer. Only works for + * attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aValue Integer value of attribute. + * @param aDefault Default value (in case value is out of range). If the spec + * doesn't provide one, should be 1 if the value is limited to + * nonzero values, and 0 otherwise. + */ + void SetUnsignedIntAttr(nsAtom* aName, uint32_t aValue, uint32_t aDefault, + mozilla::ErrorResult& aError) { + nsAutoString value; + if (aValue > INT32_MAX) { + value.AppendInt(aDefault); + } else { + value.AppendInt(aValue); + } + + SetHTMLAttr(aName, value, aError); + } + + /** + * Gets the unsigned integer-value of an attribute that is stored as a + * dimension (i.e. could be an integer or a percentage), returns specified + * default value if the attribute isn't set or isn't set to a dimension. Only + * works for attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aDefault default-value to return if attribute isn't set. + */ + uint32_t GetDimensionAttrAsUnsignedInt(nsAtom* aAttr, + uint32_t aDefault) const; + + /** + * Sets value of attribute to specified double. Only works for attributes + * in null namespace. + * + * @param aAttr name of attribute. + * @param aValue Double value of attribute. + */ + void SetDoubleAttr(nsAtom* aAttr, double aValue, mozilla::ErrorResult& aRv) { + nsAutoString value; + value.AppendFloat(aValue); + + SetHTMLAttr(aAttr, value, aRv); + } + + /** + * Locates the EditorBase associated with this node. In general this is + * equivalent to GetEditorInternal(), but for designmode or contenteditable, + * this may need to get an editor that's not actually on this element's + * associated TextControlFrame. This is used by the spellchecking routines + * to get the editor affected by changing the spellcheck attribute on this + * node. + */ + virtual already_AddRefed GetAssociatedEditor(); + + /** + * Get the frame's offset information for offsetTop/Left/Width/Height. + * Returns the parent the offset is relative to. + * @note This method flushes pending notifications (FlushType::Layout). + * @param aRect the offset information [OUT] + */ + mozilla::dom::Element* GetOffsetRect(mozilla::CSSIntRect& aRect); + + /** + * Ensures all editors associated with a subtree are synced, for purposes of + * spellchecking. + */ + static void SyncEditorsOnSubtree(nsIContent* content); + + enum ContentEditableTristate { eInherit = -1, eFalse = 0, eTrue = 1 }; + + /** + * Returns eTrue if the element has a contentEditable attribute and its value + * is "true" or an empty string. Returns eFalse if the element has a + * contentEditable attribute and its value is "false". Otherwise returns + * eInherit. + */ + ContentEditableTristate GetContentEditableValue() const { + static const Element::AttrValuesArray values[] = { + nsGkAtoms::_false, nsGkAtoms::_true, nsGkAtoms::_empty, nullptr}; + + if (!MayHaveContentEditableAttr()) return eInherit; + + int32_t value = FindAttrValueIn( + kNameSpaceID_None, nsGkAtoms::contenteditable, values, eIgnoreCase); + + return value > 0 ? eTrue : (value == 0 ? eFalse : eInherit); + } + + // Used by A, AREA, LINK, and STYLE. + already_AddRefed GetHrefURIForAnchors() const; + + public: + /** + * Returns whether this element is an editable root. There are two types of + * editable roots: + * 1) the documentElement if the whole document is editable (for example for + * desginMode=on) + * 2) an element that is marked editable with contentEditable=true and that + * doesn't have a parent or whose parent is not editable. + * Note that this doesn't return input and textarea elements that haven't been + * made editable through contentEditable or designMode. + */ + bool IsEditableRoot() const; + + private: + void ChangeEditableState(int32_t aChange); +}; + +namespace mozilla::dom { +class HTMLFieldSetElement; +} // namespace mozilla::dom + +#define HTML_ELEMENT_FLAG_BIT(n_) \ + NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) + +// HTMLElement specific bits +enum { + // Used to handle keyboard activation. + HTML_ELEMENT_ACTIVE_FOR_KEYBOARD = HTML_ELEMENT_FLAG_BIT(0), + + // Remaining bits are type specific. + HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = + ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1, +}; + +ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET); + +#define FORM_ELEMENT_FLAG_BIT(n_) \ + NODE_FLAG_BIT(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) + +// Form element specific bits +enum { + // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement, + // that means that we have added ourselves to our mForm. It's possible to + // have a non-null mForm, but not have this flag set. That happens when the + // form is set via the content sink. + ADDED_TO_FORM = FORM_ELEMENT_FLAG_BIT(0), + + // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement, + // that means that its form is in the process of being unbound from the tree, + // and this form element hasn't re-found its form in + // nsGenericHTMLFormElement::UnbindFromTree yet. + MAYBE_ORPHAN_FORM_ELEMENT = FORM_ELEMENT_FLAG_BIT(1), + + // If this flag is set on an nsGenericHTMLElement or an HTMLImageElement, then + // the element might be in the past names map of its form. + MAY_BE_IN_PAST_NAMES_MAP = FORM_ELEMENT_FLAG_BIT(2) +}; + +// NOTE: I don't think it's possible to have both ADDED_TO_FORM and +// MAYBE_ORPHAN_FORM_ELEMENT set at the same time, so if it becomes an issue we +// can probably merge them into the same bit. --bz + +ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3); + +#undef FORM_ELEMENT_FLAG_BIT + +/** + * A helper class for form elements that can contain children + */ +class nsGenericHTMLFormElement : public nsGenericHTMLElement { + public: + nsGenericHTMLFormElement( + already_AddRefed&& aNodeInfo); + + // nsIContent + nsresult BindToTree(BindContext&, nsINode& aParent) override; + void UnbindFromTree(bool aNullParent = true) override; + + /** + * This callback is called by a fieldest on all its elements whenever its + * disabled attribute is changed so the element knows its disabled state + * might have changed. + * + * @note Classes redefining this method should not do any content + * state updates themselves but should just make sure to call into + * nsGenericHTMLFormElement::FieldSetDisabledChanged. + */ + virtual void FieldSetDisabledChanged(bool aNotify); + + void FieldSetFirstLegendChanged(bool aNotify) { UpdateFieldSet(aNotify); } + + /** + * This callback is called by a fieldset on all it's elements when it's being + * destroyed. When called, the elements should check that aFieldset is there + * first parent fieldset and null mFieldset in that case only. + * + * @param aFieldSet The fieldset being removed. + */ + void ForgetFieldSet(nsIContent* aFieldset); + + void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete); + + protected: + virtual ~nsGenericHTMLFormElement() = default; + + void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, bool aNotify) override; + + void AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, + const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) override; + + virtual void BeforeSetForm(mozilla::dom::HTMLFormElement* aForm, + bool aBindToTree) {} + + virtual void AfterClearForm(bool aUnbindOrDelete) {} + + /** + * Check our disabled content attribute and fieldset's (if it exists) disabled + * state to decide whether our disabled flag should be toggled. + */ + virtual void UpdateDisabledState(bool aNotify); + + virtual void SetFormInternal(mozilla::dom::HTMLFormElement* aForm, + bool aBindToTree) {} + + virtual mozilla::dom::HTMLFormElement* GetFormInternal() const { + return nullptr; + } + + virtual mozilla::dom::HTMLFieldSetElement* GetFieldSetInternal() const { + return nullptr; + } + + virtual void SetFieldSetInternal( + mozilla::dom::HTMLFieldSetElement* aFieldset) {} + + /** + * This method will update the form owner, using @form or looking to a parent. + * + * @param aBindToTree Whether the element is being attached to the tree. + * @param aFormIdElement The element associated with the id in @form. If + * aBindToTree is false, aFormIdElement *must* contain the element associated + * with the id in @form. Otherwise, it *must* be null. + * + * @note Callers of UpdateFormOwner have to be sure the element is in a + * document (GetUncomposedDoc() != nullptr). + */ + virtual void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement); + + /** + * This method will update mFieldset and set it to the first fieldset parent. + */ + void UpdateFieldSet(bool aNotify); + + /** + * Add a form id observer which will observe when the element with the id in + * @form will change. + * + * @return The element associated with the current id in @form (may be null). + */ + Element* AddFormIdObserver(); + + /** + * Remove the form id observer. + */ + void RemoveFormIdObserver(); + + /** + * This method is a a callback for IDTargetObserver (from Document). + * It will be called each time the element associated with the id in @form + * changes. + */ + static bool FormIdUpdated(Element* aOldElement, Element* aNewElement, + void* aData); + + // Returns true if the event should not be handled from GetEventTargetParent + bool IsElementDisabledForEvents(mozilla::WidgetEvent* aEvent, + nsIFrame* aFrame); + + /** + * Returns if the control can be disabled. + */ + virtual bool CanBeDisabled() const { return false; } + + /** + * Returns if the readonly attribute applies. + */ + virtual bool DoesReadOnlyApply() const { return false; } + + /** + * Returns true if the element is a form associated element. + * See https://html.spec.whatwg.org/#form-associated-element. + */ + virtual bool IsFormAssociatedElement() const { return false; } +}; + +class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement, + public nsIFormControl { + public: + nsGenericHTMLFormControlElement( + already_AddRefed&& aNodeInfo, FormControlType); + + NS_DECL_ISUPPORTS_INHERITED + + NS_IMPL_FROMNODE_HELPER(nsGenericHTMLFormControlElement, + IsHTMLFormControlElement()) + + // nsINode + nsINode* GetScopeChainParent() const override; + bool IsHTMLFormControlElement() const final { return true; } + + // nsIContent + void SaveSubtreeState() override; + IMEState GetDesiredIMEState() override; + void UnbindFromTree(bool aNullParent = true) override; + + // nsGenericHTMLElement + // autocapitalize attribute support + void GetAutocapitalize(nsAString& aValue) const override; + bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex) override; + + // EventTarget + void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override; + nsresult PreHandleEvent(mozilla::EventChainVisitor& aVisitor) override; + + // nsIFormControl + mozilla::dom::HTMLFieldSetElement* GetFieldSet() override; + mozilla::dom::HTMLFormElement* GetForm() const override { return mForm; } + void SetForm(mozilla::dom::HTMLFormElement* aForm) override; + void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override; + bool AllowDrop() override { return true; } + + protected: + virtual ~nsGenericHTMLFormControlElement(); + + // Element + mozilla::dom::ElementState IntrinsicState() const override; + bool IsLabelable() const override; + + // nsGenericHTMLFormElement + bool CanBeDisabled() const override; + bool DoesReadOnlyApply() const override; + void SetFormInternal(mozilla::dom::HTMLFormElement* aForm, + bool aBindToTree) override; + mozilla::dom::HTMLFormElement* GetFormInternal() const override; + mozilla::dom::HTMLFieldSetElement* GetFieldSetInternal() const override; + void SetFieldSetInternal( + mozilla::dom::HTMLFieldSetElement* aFieldset) override; + bool IsFormAssociatedElement() const override { return true; } + + /** + * Update our required/optional flags to match the given aIsRequired boolean. + */ + void UpdateRequiredState(bool aIsRequired, bool aNotify); + + bool IsAutocapitalizeInheriting() const; + + /** + * Save to presentation state. The form control will determine whether it + * has anything to save and if so, create an entry in the layout history for + * its pres context. + */ + virtual void SaveState() {} + + /** The form that contains this control */ + mozilla::dom::HTMLFormElement* mForm; + + /* This is a pointer to our closest fieldset parent if any */ + mozilla::dom::HTMLFieldSetElement* mFieldSet; +}; + +enum class PopoverTargetAction : uint8_t { + Toggle, + Show, + Hide, +}; + +class nsGenericHTMLFormControlElementWithState + : public nsGenericHTMLFormControlElement { + public: + nsGenericHTMLFormControlElementWithState( + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser, FormControlType); + + bool IsGenericHTMLFormControlElementWithState() const final { return true; } + NS_IMPL_FROMNODE_HELPER(nsGenericHTMLFormControlElementWithState, + IsGenericHTMLFormControlElementWithState()) + + // Element + bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) override; + + // PopoverInvokerElement + mozilla::dom::Element* GetPopoverTargetElement() const; + void SetPopoverTargetElement(mozilla::dom::Element*); + void GetPopoverTargetAction(nsAString& aValue) const { + GetHTMLEnumAttr(nsGkAtoms::popovertargetaction, aValue); + } + void SetPopoverTargetAction(const nsAString& aValue) { + SetHTMLAttr(nsGkAtoms::popovertargetaction, aValue); + } + + /** + * https://html.spec.whatwg.org/#popover-target-attribute-activation-behavior + */ + MOZ_CAN_RUN_SCRIPT void HandlePopoverTargetAction(); + + /** + * Get the presentation state for a piece of content, or create it if it does + * not exist. Generally used by SaveState(). + */ + mozilla::PresState* GetPrimaryPresState(); + + /** + * Get the layout history object for a particular piece of content. + * + * @param aRead if true, won't return a layout history state if the + * layout history state is empty. + * @return the history state object + */ + already_AddRefed GetLayoutHistory(bool aRead); + + /** + * Called when we have been cloned and adopted, and the information of the + * node has been changed. + */ + void NodeInfoChanged(Document* aOldDoc) override; + + void GetFormAction(nsString& aValue); + + protected: + /** + * Restore from presentation state. You pass in the presentation state for + * this form control (generated with GenerateStateKey() + "-C") and the form + * control will grab its state from there. + * + * @param aState the pres state to use to restore the control + * @return true if the form control was a checkbox and its + * checked state was restored, false otherwise. + */ + virtual bool RestoreState(mozilla::PresState* aState) { return false; } + + /** + * Restore the state for a form control in response to the element being + * inserted into the document by the parser. Ends up calling RestoreState(). + * + * GenerateStateKey() must already have been called. + * + * @return false if RestoreState() was not called, the return + * value of RestoreState() otherwise. + */ + bool RestoreFormControlState(); + + /* Generates the state key for saving the form state in the session if not + computed already. The result is stored in mStateKey. */ + void GenerateStateKey(); + + int32_t GetParserInsertedControlNumberForStateKey() const override { + return mControlNumber; + } + + /* Used to store the key to that element in the session. Is void until + GenerateStateKey has been used */ + nsCString mStateKey; + + // A number for this form control that is unique within its owner document. + // This is only set to a number for elements inserted into the document by + // the parser from the network. Otherwise, it is -1. + int32_t mControlNumber; +}; + +#define NS_INTERFACE_MAP_ENTRY_IF_TAG(_interface, _tag) \ + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, \ + mNodeInfo->Equals(nsGkAtoms::_tag)) + +namespace mozilla::dom { + +using HTMLContentCreatorFunction = + nsGenericHTMLElement* (*)(already_AddRefed&&, + mozilla::dom::FromParser); + +} // namespace mozilla::dom + +/** + * A macro to declare the NS_NewHTMLXXXElement() functions. + */ +#define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName) \ + namespace mozilla { \ + namespace dom { \ + class HTML##_elementName##Element; \ + } \ + } \ + nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + +#define NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(_elementName) \ + inline nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER) { \ + return NS_NewHTMLSharedElement(std::move(aNodeInfo), aFromParser); \ + } + +/** + * A macro to implement the NS_NewHTMLXXXElement() functions. + */ +#define NS_IMPL_NS_NEW_HTML_ELEMENT(_elementName) \ + nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser) { \ + RefPtr nodeInfo(aNodeInfo); \ + auto* nim = nodeInfo->NodeInfoManager(); \ + MOZ_ASSERT(nim); \ + return new (nim) \ + mozilla::dom::HTML##_elementName##Element(nodeInfo.forget()); \ + } + +#define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName) \ + nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser) { \ + RefPtr nodeInfo(aNodeInfo); \ + auto* nim = nodeInfo->NodeInfoManager(); \ + MOZ_ASSERT(nim); \ + return new (nim) mozilla::dom::HTML##_elementName##Element( \ + nodeInfo.forget(), aFromParser); \ + } + +// Here, we expand 'NS_DECLARE_NS_NEW_HTML_ELEMENT()' by hand. +// (Calling the macro directly (with no args) produces compiler warnings.) +nsGenericHTMLElement* NS_NewHTMLElement( + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + +// Distinct from the above in order to have function pointer that compared +// unequal to a function pointer to the above. +nsGenericHTMLElement* NS_NewCustomElement( + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + +NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared) +NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList) + +NS_DECLARE_NS_NEW_HTML_ELEMENT(Anchor) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Area) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Audio) +NS_DECLARE_NS_NEW_HTML_ELEMENT(BR) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Body) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Button) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Canvas) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Content) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Mod) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Data) +NS_DECLARE_NS_NEW_HTML_ELEMENT(DataList) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Details) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Dialog) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Div) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Embed) +NS_DECLARE_NS_NEW_HTML_ELEMENT(FieldSet) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Font) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Form) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Frame) +NS_DECLARE_NS_NEW_HTML_ELEMENT(FrameSet) +NS_DECLARE_NS_NEW_HTML_ELEMENT(HR) +NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Head) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Heading) +NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Html) +NS_DECLARE_NS_NEW_HTML_ELEMENT(IFrame) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Image) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Input) +NS_DECLARE_NS_NEW_HTML_ELEMENT(LI) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Label) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Legend) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Link) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Marquee) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Map) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Menu) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Meta) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Meter) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Object) +NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Option) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Output) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Paragraph) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Picture) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Script) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Select) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Slot) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Source) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Span) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Style) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Summary) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCaption) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCell) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCol) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Table) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableRow) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableSection) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Tbody) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Template) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TextArea) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Tfoot) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Thead) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Time) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Title) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Track) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Unknown) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Video) + +#endif /* nsGenericHTMLElement_h___ */ diff --git a/dom/html/nsGenericHTMLFrameElement.cpp b/dom/html/nsGenericHTMLFrameElement.cpp new file mode 100644 index 0000000000..2a015d2c6c --- /dev/null +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -0,0 +1,359 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "nsGenericHTMLFrameElement.h" + +#include "mozilla/dom/Document.h" +#include "mozilla/dom/HTMLIFrameElement.h" +#include "mozilla/dom/XULFrameElement.h" +#include "mozilla/dom/BrowserBridgeChild.h" +#include "mozilla/dom/WindowProxyHolder.h" +#include "mozilla/Preferences.h" +#include "mozilla/PresShell.h" +#include "mozilla/ProfilerLabels.h" +#include "mozilla/StaticPrefs_dom.h" +#include "mozilla/ErrorResult.h" +#include "nsAttrValueInlines.h" +#include "nsContentUtils.h" +#include "nsIDocShell.h" +#include "nsIFrame.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIPermissionManager.h" +#include "nsPresContext.h" +#include "nsServiceManagerUtils.h" +#include "nsSubDocumentFrame.h" +#include "nsAttrValueOrString.h" + +using namespace mozilla; +using namespace mozilla::dom; + +NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement, + nsGenericHTMLElement) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAPI) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGenericHTMLFrameElement, + nsGenericHTMLElement) + if (tmp->mFrameLoader) { + tmp->mFrameLoader->Destroy(); + } + + NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameLoader) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAPI) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED( + nsGenericHTMLFrameElement, nsGenericHTMLElement, nsFrameLoaderOwner, + nsIDOMMozBrowserFrame, nsIMozBrowserFrame, nsGenericHTMLFrameElement) + +NS_IMETHODIMP +nsGenericHTMLFrameElement::GetMozbrowser(bool* aValue) { + *aValue = GetBoolAttr(nsGkAtoms::mozbrowser); + return NS_OK; +} +NS_IMETHODIMP +nsGenericHTMLFrameElement::SetMozbrowser(bool aValue) { + return SetBoolAttr(nsGkAtoms::mozbrowser, aValue); +} + +int32_t nsGenericHTMLFrameElement::TabIndexDefault() { return 0; } + +nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement() { + if (mFrameLoader) { + mFrameLoader->Destroy(); + } +} + +Document* nsGenericHTMLFrameElement::GetContentDocument( + nsIPrincipal& aSubjectPrincipal) { + RefPtr bc = GetContentWindowInternal(); + if (!bc) { + return nullptr; + } + + nsPIDOMWindowOuter* window = bc->GetDOMWindow(); + if (!window) { + // Either our browsing context contents are out-of-process (in which case + // clearly this is a cross-origin call and we should return null), or our + // browsing context is torn-down enough to no longer have a window or a + // document, and we should still return null. + return nullptr; + } + Document* doc = window->GetDoc(); + if (!doc) { + return nullptr; + } + + // Return null for cross-origin contentDocument. + if (!aSubjectPrincipal.SubsumesConsideringDomain(doc->NodePrincipal())) { + return nullptr; + } + return doc; +} + +BrowsingContext* nsGenericHTMLFrameElement::GetContentWindowInternal() { + EnsureFrameLoader(); + + if (!mFrameLoader) { + return nullptr; + } + + if (mFrameLoader->DepthTooGreat()) { + // Claim to have no contentWindow + return nullptr; + } + + RefPtr bc = mFrameLoader->GetBrowsingContext(); + return bc; +} + +Nullable nsGenericHTMLFrameElement::GetContentWindow() { + RefPtr bc = GetContentWindowInternal(); + if (!bc) { + return nullptr; + } + return WindowProxyHolder(bc); +} + +void nsGenericHTMLFrameElement::EnsureFrameLoader() { + if (!IsInComposedDoc() || mFrameLoader || OwnerDoc()->IsStaticDocument()) { + // If frame loader is there, we just keep it around, cached + return; + } + + // Strangely enough, this method doesn't actually ensure that the + // frameloader exists. It's more of a best-effort kind of thing. + mFrameLoader = nsFrameLoader::Create(this, mNetworkCreated); +} + +void nsGenericHTMLFrameElement::SwapFrameLoaders( + HTMLIFrameElement& aOtherLoaderOwner, ErrorResult& rv) { + if (&aOtherLoaderOwner == this) { + // nothing to do + return; + } + + aOtherLoaderOwner.SwapFrameLoaders(this, rv); +} + +void nsGenericHTMLFrameElement::SwapFrameLoaders( + XULFrameElement& aOtherLoaderOwner, ErrorResult& rv) { + aOtherLoaderOwner.SwapFrameLoaders(this, rv); +} + +void nsGenericHTMLFrameElement::SwapFrameLoaders( + nsFrameLoaderOwner* aOtherLoaderOwner, mozilla::ErrorResult& rv) { + if (RefPtr doc = GetComposedDoc()) { + // SwapWithOtherLoader relies on frames being up-to-date. + doc->FlushPendingNotifications(FlushType::Frames); + } + + RefPtr loader = GetFrameLoader(); + RefPtr otherLoader = aOtherLoaderOwner->GetFrameLoader(); + if (!loader || !otherLoader) { + rv.Throw(NS_ERROR_NOT_IMPLEMENTED); + return; + } + + rv = loader->SwapWithOtherLoader(otherLoader, this, aOtherLoaderOwner); +} + +void nsGenericHTMLFrameElement::LoadSrc() { + EnsureFrameLoader(); + + if (!mFrameLoader) { + return; + } + + bool origSrc = !mSrcLoadHappened; + mSrcLoadHappened = true; + mFrameLoader->LoadFrame(origSrc); +} + +nsresult nsGenericHTMLFrameElement::BindToTree(BindContext& aContext, + nsINode& aParent) { + nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent); + NS_ENSURE_SUCCESS(rv, rv); + + if (IsInComposedDoc()) { + NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), + "Missing a script blocker!"); + + AUTO_PROFILER_LABEL("nsGenericHTMLFrameElement::BindToTree", OTHER); + + // We're in a document now. Kick off the frame load. + LoadSrc(); + } + + // We're now in document and scripts may move us, so clear + // the mNetworkCreated flag. + mNetworkCreated = false; + return rv; +} + +void nsGenericHTMLFrameElement::UnbindFromTree(bool aNullParent) { + if (mFrameLoader) { + // This iframe is being taken out of the document, destroy the + // iframe's frame loader (doing that will tear down the window in + // this iframe). + // XXXbz we really want to only partially destroy the frame + // loader... we don't want to tear down the docshell. Food for + // later bug. + mFrameLoader->Destroy(); + mFrameLoader = nullptr; + } + + nsGenericHTMLElement::UnbindFromTree(aNullParent); +} + +/* static */ +ScrollbarPreference nsGenericHTMLFrameElement::MapScrollingAttribute( + const nsAttrValue* aValue) { + if (aValue && aValue->Type() == nsAttrValue::eEnum) { + auto scrolling = static_cast(aValue->GetEnumValue()); + if (scrolling == ScrollingAttribute::Off || + scrolling == ScrollingAttribute::Noscroll || + scrolling == ScrollingAttribute::No) { + return ScrollbarPreference::Never; + } + } + return ScrollbarPreference::Auto; +} + +/* virtual */ +void nsGenericHTMLFrameElement::AfterSetAttr( + int32_t aNameSpaceID, nsAtom* aName, const nsAttrValue* aValue, + const nsAttrValue* aOldValue, nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) { + if (aValue) { + nsAttrValueOrString value(aValue); + AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aMaybeScriptedPrincipal, + aNotify); + } else { + AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aMaybeScriptedPrincipal, + aNotify); + } + + if (aNameSpaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::scrolling) { + if (mFrameLoader) { + ScrollbarPreference pref = MapScrollingAttribute(aValue); + if (nsDocShell* docshell = mFrameLoader->GetExistingDocShell()) { + docshell->SetScrollbarPreference(pref); + } else if (auto* child = mFrameLoader->GetBrowserBridgeChild()) { + // NOTE(emilio): We intentionally don't deal with the + // GetBrowserParent() case, and only deal with the fission iframe + // case. We could make it work, but it's a bit of boilerplate for + // something that we don't use, and we'd need to think how it + // interacts with the scrollbar window flags... + child->SendScrollbarPreferenceChanged(pref); + } + } + } else if (aName == nsGkAtoms::mozbrowser) { + mReallyIsBrowser = !!aValue && XRE_IsParentProcess() && + NodePrincipal()->IsSystemPrincipal(); + } + } + + return nsGenericHTMLElement::AfterSetAttr( + aNameSpaceID, aName, aValue, aOldValue, aMaybeScriptedPrincipal, aNotify); +} + +void nsGenericHTMLFrameElement::OnAttrSetButNotChanged( + int32_t aNamespaceID, nsAtom* aName, const nsAttrValueOrString& aValue, + bool aNotify) { + AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, nullptr, aNotify); + + return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); +} + +void nsGenericHTMLFrameElement::AfterMaybeChangeAttr( + int32_t aNamespaceID, nsAtom* aName, const nsAttrValueOrString* aValue, + nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify) { + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::src) { + mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal( + this, aValue ? aValue->String() : u""_ns, aMaybeScriptedPrincipal); + if (!IsHTMLElement(nsGkAtoms::iframe) || + !HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc)) { + // Don't propagate error here. The attribute was successfully + // set or removed; that's what we should reflect. + LoadSrc(); + } + } else if (aName == nsGkAtoms::name) { + // Propagate "name" to the browsing context per HTML5. + RefPtr bc = + mFrameLoader ? mFrameLoader->GetExtantBrowsingContext() : nullptr; + if (bc) { + MOZ_ALWAYS_SUCCEEDS(bc->SetName(aValue ? aValue->String() : u""_ns)); + } + } + } +} + +void nsGenericHTMLFrameElement::DestroyContent() { + if (mFrameLoader) { + mFrameLoader->Destroy(); + mFrameLoader = nullptr; + } + + nsGenericHTMLElement::DestroyContent(); +} + +nsresult nsGenericHTMLFrameElement::CopyInnerTo(Element* aDest) { + nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + + Document* doc = aDest->OwnerDoc(); + if (doc->IsStaticDocument() && mFrameLoader) { + nsGenericHTMLFrameElement* dest = + static_cast(aDest); + doc->AddPendingFrameStaticClone(dest, mFrameLoader); + } + + return rv; +} + +bool nsGenericHTMLFrameElement::IsHTMLFocusable(bool aWithMouse, + bool* aIsFocusable, + int32_t* aTabIndex) { + if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, + aTabIndex)) { + return true; + } + + *aIsFocusable = true; + return false; +} + +/** + * Return true if this frame element really is a mozbrowser. (It + * needs to have the right attributes, and its creator must have the right + * permissions.) + */ +/* [infallible] */ +nsresult nsGenericHTMLFrameElement::GetReallyIsBrowser(bool* aOut) { + *aOut = mReallyIsBrowser; + return NS_OK; +} + +NS_IMETHODIMP +nsGenericHTMLFrameElement::InitializeBrowserAPI() { + MOZ_ASSERT(mFrameLoader); + InitBrowserElementAPI(); + return NS_OK; +} + +NS_IMETHODIMP +nsGenericHTMLFrameElement::DestroyBrowserFrameScripts() { + MOZ_ASSERT(mFrameLoader); + DestroyBrowserElementFrameScripts(); + return NS_OK; +} diff --git a/dom/html/nsGenericHTMLFrameElement.h b/dom/html/nsGenericHTMLFrameElement.h new file mode 100644 index 0000000000..72d785be24 --- /dev/null +++ b/dom/html/nsGenericHTMLFrameElement.h @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef nsGenericHTMLFrameElement_h +#define nsGenericHTMLFrameElement_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/nsBrowserElement.h" + +#include "nsFrameLoader.h" +#include "nsFrameLoaderOwner.h" +#include "nsGenericHTMLElement.h" +#include "nsIMozBrowserFrame.h" + +namespace mozilla { +class ErrorResult; + +namespace dom { +class BrowserParent; +template +struct Nullable; +class WindowProxyHolder; +class XULFrameElement; +} // namespace dom +} // namespace mozilla + +#define NS_GENERICHTMLFRAMEELEMENT_IID \ + { \ + 0x8190db72, 0xdab0, 0x4d72, { \ + 0x94, 0x26, 0x87, 0x5f, 0x5a, 0x8a, 0x2a, 0xe5 \ + } \ + } + +/** + * A helper class for frame elements + */ +class nsGenericHTMLFrameElement : public nsGenericHTMLElement, + public nsFrameLoaderOwner, + public mozilla::nsBrowserElement, + public nsIMozBrowserFrame { + public: + nsGenericHTMLFrameElement( + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser) + : nsGenericHTMLElement(std::move(aNodeInfo)), + nsBrowserElement(), + mSrcLoadHappened(false), + mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK), + mBrowserFrameListenersRegistered(false), + mReallyIsBrowser(false) {} + + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_NSIDOMMOZBROWSERFRAME + NS_DECL_NSIMOZBROWSERFRAME + + NS_DECLARE_STATIC_IID_ACCESSOR(NS_GENERICHTMLFRAMEELEMENT_IID) + + // nsIContent + virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex) override; + virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; + virtual void UnbindFromTree(bool aNullParent = true) override; + virtual void DestroyContent() override; + + nsresult CopyInnerTo(mozilla::dom::Element* aDest); + + virtual int32_t TabIndexDefault() override; + + virtual nsIMozBrowserFrame* GetAsMozBrowserFrame() override { return this; } + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGenericHTMLFrameElement, + nsGenericHTMLElement) + + void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner, + mozilla::ErrorResult& aError); + + void SwapFrameLoaders(mozilla::dom::XULFrameElement& aOtherLoaderOwner, + mozilla::ErrorResult& aError); + + void SwapFrameLoaders(nsFrameLoaderOwner* aOtherLoaderOwner, + mozilla::ErrorResult& rv); + + /** + * Helper method to map a HTML 'scrolling' attribute value (which can be null) + * to a ScrollbarPreference value value. scrolling="no" (and its synonyms) + * map to Never, and anything else to Auto. + */ + static mozilla::ScrollbarPreference MapScrollingAttribute(const nsAttrValue*); + + nsIPrincipal* GetSrcTriggeringPrincipal() const { + return mSrcTriggeringPrincipal; + } + + // Needed for nsBrowserElement + already_AddRefed GetFrameLoader() override { + return nsFrameLoaderOwner::GetFrameLoader(); + } + + protected: + virtual ~nsGenericHTMLFrameElement(); + + // This doesn't really ensure a frame loader in all cases, only when + // it makes sense. + void EnsureFrameLoader(); + void LoadSrc(); + Document* GetContentDocument(nsIPrincipal& aSubjectPrincipal); + mozilla::dom::Nullable GetContentWindow(); + + virtual void AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + nsIPrincipal* aSubjectPrincipal, + bool aNotify) override; + virtual void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; + + nsCOMPtr mSrcTriggeringPrincipal; + + /** + * True if we have already loaded the frame's original src + */ + bool mSrcLoadHappened; + + /** + * True when the element is created by the parser using the + * NS_FROM_PARSER_NETWORK flag. + * If the element is modified, it may lose the flag. + */ + bool mNetworkCreated; + + bool mBrowserFrameListenersRegistered; + bool mReallyIsBrowser; + + // This flag is only used by + + + diff --git a/dom/html/reftests/autofocus/autofocus-leaves-iframe.html b/dom/html/reftests/autofocus/autofocus-leaves-iframe.html new file mode 100644 index 0000000000..9069156878 --- /dev/null +++ b/dom/html/reftests/autofocus/autofocus-leaves-iframe.html @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/dom/html/reftests/autofocus/button-create.html b/dom/html/reftests/autofocus/button-create.html new file mode 100644 index 0000000000..ae49d162ad --- /dev/null +++ b/dom/html/reftests/autofocus/button-create.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/dom/html/reftests/autofocus/button-load.html b/dom/html/reftests/autofocus/button-load.html new file mode 100644 index 0000000000..a9e28e2bb6 --- /dev/null +++ b/dom/html/reftests/autofocus/button-load.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/html/reftests/autofocus/button-ref.html b/dom/html/reftests/autofocus/button-ref.html new file mode 100644 index 0000000000..878c8e2681 --- /dev/null +++ b/dom/html/reftests/autofocus/button-ref.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/html/reftests/autofocus/input-create.html b/dom/html/reftests/autofocus/input-create.html new file mode 100644 index 0000000000..c6d0c28089 --- /dev/null +++ b/dom/html/reftests/autofocus/input-create.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/dom/html/reftests/autofocus/input-load.html b/dom/html/reftests/autofocus/input-load.html new file mode 100644 index 0000000000..d40b49177a --- /dev/null +++ b/dom/html/reftests/autofocus/input-load.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/html/reftests/autofocus/input-number-ref.html b/dom/html/reftests/autofocus/input-number-ref.html new file mode 100644 index 0000000000..384915edb8 --- /dev/null +++ b/dom/html/reftests/autofocus/input-number-ref.html @@ -0,0 +1,17 @@ + + + + + + + + + +
+ + + diff --git a/dom/html/reftests/autofocus/input-number.html b/dom/html/reftests/autofocus/input-number.html new file mode 100644 index 0000000000..7816ee9bd9 --- /dev/null +++ b/dom/html/reftests/autofocus/input-number.html @@ -0,0 +1,26 @@ + + + + + + + + + + +
+ + + diff --git a/dom/html/reftests/autofocus/input-ref.html b/dom/html/reftests/autofocus/input-ref.html new file mode 100644 index 0000000000..6e2e546d24 --- /dev/null +++ b/dom/html/reftests/autofocus/input-ref.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/html/reftests/autofocus/input-time-ref.html b/dom/html/reftests/autofocus/input-time-ref.html new file mode 100644 index 0000000000..abaa6feeac --- /dev/null +++ b/dom/html/reftests/autofocus/input-time-ref.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/dom/html/reftests/autofocus/input-time.html b/dom/html/reftests/autofocus/input-time.html new file mode 100644 index 0000000000..a86a91bbfc --- /dev/null +++ b/dom/html/reftests/autofocus/input-time.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/dom/html/reftests/autofocus/reftest.list b/dom/html/reftests/autofocus/reftest.list new file mode 100644 index 0000000000..03ddce4149 --- /dev/null +++ b/dom/html/reftests/autofocus/reftest.list @@ -0,0 +1,13 @@ +needs-focus == input-load.html input-ref.html +needs-focus == input-create.html input-ref.html +needs-focus == input-number.html input-number-ref.html +fuzzy(0-5,0-1) needs-focus == input-time.html input-time-ref.html # One anti-aliased outline corner. +needs-focus == button-load.html button-ref.html +needs-focus == button-create.html button-ref.html +fuzzy-if(gtkWidget,0-18,0-1) needs-focus == textarea-load.html textarea-ref.html # One anti-aliased corner. +needs-focus == textarea-create.html textarea-ref.html +fuzzy-if(Android,0-10,0-5) needs-focus == select-load.html select-ref.html +fuzzy(0-10,0-5) needs-focus == select-create.html select-ref.html +fuzzy(0-1,0-1) needs-focus == autofocus-after-load.html autofocus-after-load-ref.html +needs-focus == autofocus-leaves-iframe.html autofocus-leaves-iframe-ref.html +fuzzy(0-5,0-1) needs-focus == autofocus-after-body-focus.html autofocus-after-body-focus-ref.html diff --git a/dom/html/reftests/autofocus/select-create.html b/dom/html/reftests/autofocus/select-create.html new file mode 100644 index 0000000000..fd9c29c954 --- /dev/null +++ b/dom/html/reftests/autofocus/select-create.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/dom/html/reftests/autofocus/select-load.html b/dom/html/reftests/autofocus/select-load.html new file mode 100644 index 0000000000..976005bec2 --- /dev/null +++ b/dom/html/reftests/autofocus/select-load.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/html/reftests/autofocus/select-ref.html b/dom/html/reftests/autofocus/select-ref.html new file mode 100644 index 0000000000..7fa9cd6559 --- /dev/null +++ b/dom/html/reftests/autofocus/select-ref.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/html/reftests/autofocus/style.css b/dom/html/reftests/autofocus/style.css new file mode 100644 index 0000000000..f0dd5d1498 --- /dev/null +++ b/dom/html/reftests/autofocus/style.css @@ -0,0 +1,10 @@ +:focus { background-color: green; } + +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1645773 */ +textarea { -moz-appearance: none; } + +/** + * autofocus is considered like a keyboard focus and .focus() isn't. + * We might change that with bug 620056 but for these tests, we don't really care. + */ +::-moz-focus-inner { border: none; } diff --git a/dom/html/reftests/autofocus/textarea-create.html b/dom/html/reftests/autofocus/textarea-create.html new file mode 100644 index 0000000000..e506bb2b72 --- /dev/null +++ b/dom/html/reftests/autofocus/textarea-create.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/dom/html/reftests/autofocus/textarea-load.html b/dom/html/reftests/autofocus/textarea-load.html new file mode 100644 index 0000000000..13ab2cb2cc --- /dev/null +++ b/dom/html/reftests/autofocus/textarea-load.html @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/dom/html/reftests/autofocus/textarea-ref.html b/dom/html/reftests/autofocus/textarea-ref.html new file mode 100644 index 0000000000..b79bd7abe8 --- /dev/null +++ b/dom/html/reftests/autofocus/textarea-ref.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html b/dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html new file mode 100644 index 0000000000..1e651db66d --- /dev/null +++ b/dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/dom/html/reftests/body-frame-margin-remove-other-pres-hint.html b/dom/html/reftests/body-frame-margin-remove-other-pres-hint.html new file mode 100644 index 0000000000..16428813af --- /dev/null +++ b/dom/html/reftests/body-frame-margin-remove-other-pres-hint.html @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/dom/html/reftests/body-topmargin-dynamic.html b/dom/html/reftests/body-topmargin-dynamic.html new file mode 100644 index 0000000000..e6c8c505e7 --- /dev/null +++ b/dom/html/reftests/body-topmargin-dynamic.html @@ -0,0 +1,12 @@ + + + +this text should have a margin of 100px on the top and left +

this text should have a margin of 100px on the right

+ + + diff --git a/dom/html/reftests/body-topmargin-ref.html b/dom/html/reftests/body-topmargin-ref.html new file mode 100644 index 0000000000..6530a0ae4b --- /dev/null +++ b/dom/html/reftests/body-topmargin-ref.html @@ -0,0 +1,7 @@ + + + +this text should have a margin of 100px on the top and left +

this text should have a margin of 100px on the right

+ + diff --git a/dom/html/reftests/bug1106522-1.html b/dom/html/reftests/bug1106522-1.html new file mode 100644 index 0000000000..db07c1010e --- /dev/null +++ b/dom/html/reftests/bug1106522-1.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/dom/html/reftests/bug1106522-2.html b/dom/html/reftests/bug1106522-2.html new file mode 100644 index 0000000000..15520982fc --- /dev/null +++ b/dom/html/reftests/bug1106522-2.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/dom/html/reftests/bug1106522-ref.html b/dom/html/reftests/bug1106522-ref.html new file mode 100644 index 0000000000..476c47c12d --- /dev/null +++ b/dom/html/reftests/bug1106522-ref.html @@ -0,0 +1,8 @@ + + + + + + + diff --git a/dom/html/reftests/bug1196784-no-srcset.html b/dom/html/reftests/bug1196784-no-srcset.html new file mode 100644 index 0000000000..df55d48631 --- /dev/null +++ b/dom/html/reftests/bug1196784-no-srcset.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/dom/html/reftests/bug1196784-with-srcset.html b/dom/html/reftests/bug1196784-with-srcset.html new file mode 100644 index 0000000000..1cd77bad9b --- /dev/null +++ b/dom/html/reftests/bug1196784-with-srcset.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/dom/html/reftests/bug1196784.png b/dom/html/reftests/bug1196784.png new file mode 100644 index 0000000000..8d0ed56825 Binary files /dev/null and b/dom/html/reftests/bug1196784.png differ diff --git a/dom/html/reftests/bug1228601-video-rotated-ref.html b/dom/html/reftests/bug1228601-video-rotated-ref.html new file mode 100644 index 0000000000..e489c9a75b --- /dev/null +++ b/dom/html/reftests/bug1228601-video-rotated-ref.html @@ -0,0 +1,13 @@ + + + + + + +
+ + + diff --git a/dom/html/reftests/bug448564-1_well-formed.html b/dom/html/reftests/bug448564-1_well-formed.html new file mode 100644 index 0000000000..46dbb8bdd0 --- /dev/null +++ b/dom/html/reftests/bug448564-1_well-formed.html @@ -0,0 +1,11 @@ + + + + + + +
a
+
b
+ + diff --git a/dom/html/reftests/bug448564-4a.html b/dom/html/reftests/bug448564-4a.html new file mode 100644 index 0000000000..6fbaf85c2f --- /dev/null +++ b/dom/html/reftests/bug448564-4a.html @@ -0,0 +1,10 @@ + + + + +
form contents
+ bold text +
+ + diff --git a/dom/html/reftests/bug448564-4b.html b/dom/html/reftests/bug448564-4b.html new file mode 100644 index 0000000000..f04d5fe48f --- /dev/null +++ b/dom/html/reftests/bug448564-4b.html @@ -0,0 +1,6 @@ + + +
form contents
+ bold text + + diff --git a/dom/html/reftests/bug448564_forms.css b/dom/html/reftests/bug448564_forms.css new file mode 100644 index 0000000000..b98788862c --- /dev/null +++ b/dom/html/reftests/bug448564_forms.css @@ -0,0 +1,2 @@ +/* make nesting obvious */ +form { border: 1px solid black; } diff --git a/dom/html/reftests/bug502168-1_malformed.html b/dom/html/reftests/bug502168-1_malformed.html new file mode 100644 index 0000000000..efe23ac47f --- /dev/null +++ b/dom/html/reftests/bug502168-1_malformed.html @@ -0,0 +1,10 @@ + + Bug 502168 - Particular images are displayed multiple times in a formated way - only FF 3.5 + + + + +
You should see this text only once
+ + + diff --git a/dom/html/reftests/bug502168-1_well-formed.html b/dom/html/reftests/bug502168-1_well-formed.html new file mode 100644 index 0000000000..5eb25c6b35 --- /dev/null +++ b/dom/html/reftests/bug502168-1_well-formed.html @@ -0,0 +1,9 @@ + + Bug 502168 - Particular images are displayed multiple times in a formated way - only FF 3.5 + + + + +
You should see this text only once
+ + diff --git a/dom/html/reftests/bug917595-1-ref.html b/dom/html/reftests/bug917595-1-ref.html new file mode 100644 index 0000000000..b777751ff8 --- /dev/null +++ b/dom/html/reftests/bug917595-1-ref.html @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/dom/html/reftests/bug917595-exif-rotated.jpg b/dom/html/reftests/bug917595-exif-rotated.jpg new file mode 100644 index 0000000000..e7b0c22f35 Binary files /dev/null and b/dom/html/reftests/bug917595-exif-rotated.jpg differ diff --git a/dom/html/reftests/bug917595-iframe-1.html b/dom/html/reftests/bug917595-iframe-1.html new file mode 100644 index 0000000000..f7fca8232c --- /dev/null +++ b/dom/html/reftests/bug917595-iframe-1.html @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/dom/html/reftests/bug917595-pixel-rotated.jpg b/dom/html/reftests/bug917595-pixel-rotated.jpg new file mode 100644 index 0000000000..ac39faadad Binary files /dev/null and b/dom/html/reftests/bug917595-pixel-rotated.jpg differ diff --git a/dom/html/reftests/bug917595-unrotated.jpg b/dom/html/reftests/bug917595-unrotated.jpg new file mode 100644 index 0000000000..a787797c5e Binary files /dev/null and b/dom/html/reftests/bug917595-unrotated.jpg differ diff --git a/dom/html/reftests/figure-ref.html b/dom/html/reftests/figure-ref.html new file mode 100644 index 0000000000..23ca9f6037 --- /dev/null +++ b/dom/html/reftests/figure-ref.html @@ -0,0 +1,11 @@ + +The figure element + + + +
+
Caption
+Figure +
diff --git a/dom/html/reftests/figure.html b/dom/html/reftests/figure.html new file mode 100644 index 0000000000..ad83670b80 --- /dev/null +++ b/dom/html/reftests/figure.html @@ -0,0 +1,8 @@ + +The figure element + + +
+
Caption
+Figure +
diff --git a/dom/html/reftests/href-attr-change-restyles-ref.html b/dom/html/reftests/href-attr-change-restyles-ref.html new file mode 100644 index 0000000000..4ebaec9249 --- /dev/null +++ b/dom/html/reftests/href-attr-change-restyles-ref.html @@ -0,0 +1,33 @@ + + + + Test for bug 549797 - Removing href attribute doesn't remove link styling + + + +

+ Test anchor 1 + + Test anchor 2 + + Test anchor 3 + +

+ + diff --git a/dom/html/reftests/href-attr-change-restyles.html b/dom/html/reftests/href-attr-change-restyles.html new file mode 100644 index 0000000000..1fa54bfd6f --- /dev/null +++ b/dom/html/reftests/href-attr-change-restyles.html @@ -0,0 +1,48 @@ + + + + Test for bug 549797 - Removing href attribute doesn't remove link styling + + + + +

+ Test anchor 1 + + Test anchor 2 + + Test anchor 3 + +

+ + diff --git a/dom/html/reftests/image-load-shortcircuit-1.html b/dom/html/reftests/image-load-shortcircuit-1.html new file mode 100644 index 0000000000..28e16b7464 --- /dev/null +++ b/dom/html/reftests/image-load-shortcircuit-1.html @@ -0,0 +1,8 @@ + +
+ + diff --git a/dom/html/reftests/image-load-shortcircuit-2.html b/dom/html/reftests/image-load-shortcircuit-2.html new file mode 100644 index 0000000000..3c4baa43be --- /dev/null +++ b/dom/html/reftests/image-load-shortcircuit-2.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/dom/html/reftests/image-load-shortcircuit-ref.html b/dom/html/reftests/image-load-shortcircuit-ref.html new file mode 100644 index 0000000000..7dd28922d4 --- /dev/null +++ b/dom/html/reftests/image-load-shortcircuit-ref.html @@ -0,0 +1 @@ +
diff --git a/dom/html/reftests/lime100x100.svg b/dom/html/reftests/lime100x100.svg new file mode 100644 index 0000000000..8bdec62c1f --- /dev/null +++ b/dom/html/reftests/lime100x100.svg @@ -0,0 +1,4 @@ + + + diff --git a/dom/html/reftests/pass.png b/dom/html/reftests/pass.png new file mode 100644 index 0000000000..3b30b1de7c Binary files /dev/null and b/dom/html/reftests/pass.png differ diff --git a/dom/html/reftests/pre-1-ref.html b/dom/html/reftests/pre-1-ref.html new file mode 100644 index 0000000000..a79b4f46a4 --- /dev/null +++ b/dom/html/reftests/pre-1-ref.html @@ -0,0 +1,22 @@ + +
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+12 diff --git a/dom/html/reftests/pre-1.html b/dom/html/reftests/pre-1.html new file mode 100644 index 0000000000..1b21bcd746 --- /dev/null +++ b/dom/html/reftests/pre-1.html @@ -0,0 +1,22 @@ + +
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM MMMMM
+
+
+ diff --git a/dom/html/reftests/red.png b/dom/html/reftests/red.png new file mode 100644 index 0000000000..aa9ce25263 Binary files /dev/null and b/dom/html/reftests/red.png differ diff --git a/dom/html/reftests/reftest.list b/dom/html/reftests/reftest.list new file mode 100644 index 0000000000..4dc3df7a4a --- /dev/null +++ b/dom/html/reftests/reftest.list @@ -0,0 +1,75 @@ +# autofocus attribute (we can't test with mochitests) +include autofocus/reftest.list +include toblob-todataurl/reftest.list + +== 41464-1a.html 41464-1-ref.html +== 41464-1b.html 41464-1-ref.html +== 52019-1.html 52019-1-ref.html +== 82711-1.html 82711-1-ref.html +== 82711-2.html 82711-2-ref.html +!= 82711-1-ref.html 82711-2-ref.html +!= 468263-1a.html about:blank +!= 468263-1b.html about:blank +!= 468263-1c.html about:blank +!= 468263-1d.html about:blank +== 468263-2.html 468263-2-ref.html +== 468263-2.html 468263-2-alternate-ref.html +== 484200-1.html 484200-1-ref.html +== 485377.html 485377-ref.html +== 557840.html 557840-ref.html +== 560059-video-dimensions.html 560059-video-dimensions-ref.html +== 573322-quirks.html 573322-quirks-ref.html +== 573322-no-quirks.html 573322-no-quirks-ref.html +== 596455-1a.html 596455-ref-1.html +== 596455-1b.html 596455-ref-1.html +== 596455-2a.html 596455-ref-2.html +== 596455-2b.html 596455-ref-2.html +== 610935.html 610935-ref.html +== 649134-1.html 649134-ref.html +skip-if(Android) == 649134-2.html 649134-2-ref.html +== 741776-1.vtt 741776-1-ref.html + +== bug448564-1_malformed.html bug448564-1_well-formed.html +== bug448564-1_malformed.html bug448564-1_ideal.html + +== bug448564-4a.html bug448564-4b.html +== bug502168-1_malformed.html bug502168-1_well-formed.html + +== responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit-ref.html +== image-load-shortcircuit-1.html image-load-shortcircuit-ref.html +== image-load-shortcircuit-2.html image-load-shortcircuit-ref.html + +# Test that image documents taken into account CSS properties like +# image-orientation when determining the size of the image. +# (Fuzzy necessary due to pixel-wise comparison of different JPEGs. +# The vast majority of the fuzziness comes from Linux and WinXP.) +skip-if(isCoverageBuild) fuzzy(0-2,0-830) random-if(useDrawSnapshot) == bug917595-iframe-1.html bug917595-1-ref.html +fuzzy(0-3,0-7544) fuzzy-if(!geckoview,2-3,50-7544) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869 + +# Test support for SVG-as-image in elements. +== bug1106522-1.html bug1106522-ref.html +== bug1106522-2.html bug1106522-ref.html + +== href-attr-change-restyles.html href-attr-change-restyles-ref.html +== figure.html figure-ref.html +== pre-1.html pre-1-ref.html +== table-border-1.html table-border-1-ref.html +== table-border-2.html table-border-2-ref.html +!= table-border-2.html table-border-2-notref.html + +# Test imageset is using permissions.default.image +pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784-no-srcset.html +pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-no-srcset.html + +# Test video with rotation information can be rotated. +fails-if(geckoview&&!swgl) == bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html # bug 1558285 for geckoview +fuzzy(0-1,0-30) fails-if(geckoview&&!swgl) random-if(geckoview&&swgl) == bug1423850-canvas-video-rotation-90.html bug1423850-canvas-video-rotated-ref.html # bug 1558285 for geckoview + +== bug1512297.html bug1512297-ref.html + +# Test that dynamically setting body margin attributes updates style appropriately +== body-topmargin-dynamic.html body-topmargin-ref.html + +# Test that dynamically removing a nonmargin mapped attribute does not +# destroy margins inherited from the frame. +== body-frame-margin-remove-other-pres-hint.html body-frame-margin-remove-other-pres-hint-ref.html diff --git a/dom/html/reftests/responsive-image-load-shortcircuit-ref.html b/dom/html/reftests/responsive-image-load-shortcircuit-ref.html new file mode 100644 index 0000000000..59d8925ba5 --- /dev/null +++ b/dom/html/reftests/responsive-image-load-shortcircuit-ref.html @@ -0,0 +1 @@ + diff --git a/dom/html/reftests/responsive-image-load-shortcircuit.html b/dom/html/reftests/responsive-image-load-shortcircuit.html new file mode 100644 index 0000000000..1cfb92cb20 --- /dev/null +++ b/dom/html/reftests/responsive-image-load-shortcircuit.html @@ -0,0 +1,15 @@ + + + + diff --git a/dom/html/reftests/table-border-1-ref.html b/dom/html/reftests/table-border-1-ref.html new file mode 100644 index 0000000000..ceac88e9a3 --- /dev/null +++ b/dom/html/reftests/table-border-1-ref.html @@ -0,0 +1,46 @@ + + +Table borders + + +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
diff --git a/dom/html/reftests/table-border-1.html b/dom/html/reftests/table-border-1.html new file mode 100644 index 0000000000..12bfb2af46 --- /dev/null +++ b/dom/html/reftests/table-border-1.html @@ -0,0 +1,36 @@ + + +Table borders + +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
diff --git a/dom/html/reftests/table-border-2-notref.html b/dom/html/reftests/table-border-2-notref.html new file mode 100644 index 0000000000..7558e5271a --- /dev/null +++ b/dom/html/reftests/table-border-2-notref.html @@ -0,0 +1,40 @@ + + +Table borders + + +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
diff --git a/dom/html/reftests/table-border-2-ref.html b/dom/html/reftests/table-border-2-ref.html new file mode 100644 index 0000000000..36d1e45106 --- /dev/null +++ b/dom/html/reftests/table-border-2-ref.html @@ -0,0 +1,30 @@ + + +Table borders + +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
diff --git a/dom/html/reftests/table-border-2.html b/dom/html/reftests/table-border-2.html new file mode 100644 index 0000000000..4f209545c2 --- /dev/null +++ b/dom/html/reftests/table-border-2.html @@ -0,0 +1,30 @@ + + +Table borders + +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
+ +
Test +
diff --git a/dom/html/reftests/toblob-todataurl/blob.js b/dom/html/reftests/toblob-todataurl/blob.js new file mode 100644 index 0000000000..4ed9fdb372 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/blob.js @@ -0,0 +1,68 @@ +function init() { + function end() { + document.documentElement.className = ''; + } + + function next() { + compressAndDisplay(original, end); + } + + var original = getImageFromDataUrl(sample); + setImgLoadListener(original, next); +} + +function compressAndDisplay(image, next) { + var canvas = document.createElement('canvas'); + canvas.width = image.naturalWidth; + canvas.height = image.naturalHeight; + var ctx = canvas.getContext('2d'); + ctx.drawImage(image, 0, 0); + + function gotBlob(blob) { + var img = getImageFromBlob(blob); + setImgLoadListener(img, next); + document.body.appendChild(img); + } + + // I want to test passing 'undefined' as quality as well + if ('quality' in window) { + canvas.toBlob(gotBlob, 'image/jpeg', quality); + } else { + canvas.toBlob(gotBlob, 'image/jpeg'); + } +} + +function setImgLoadListener(img, func) { + if (img.complete) { + func.call(img, { target: img}); + } else { + img.addEventListener('load', func); + } +} + +function naturalDimensionsHandler(e) { + var img = e.target; + img.width = img.naturalWidth; + img.height = img.naturalHeight; +} + +function getImageFromBlob(blob) { + var img = document.createElement('img'); + img.src = window.URL.createObjectURL(blob); + setImgLoadListener(img, naturalDimensionsHandler); + setImgLoadListener(img, function(e) { + window.URL.revokeObjectURL(e.target.src); + }); + + return img; +} + +function getImageFromDataUrl(url) { + var img = document.createElement('img'); + img.src = url; + setImgLoadListener(img, naturalDimensionsHandler); + + return img; +} + +init(); diff --git a/dom/html/reftests/toblob-todataurl/dataurl.js b/dom/html/reftests/toblob-todataurl/dataurl.js new file mode 100644 index 0000000000..8ffba1fa8e --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/dataurl.js @@ -0,0 +1,56 @@ +function init() { + function end() { + document.documentElement.className = ''; + } + + function next() { + compressAndDisplay(original, end); + } + + var original = getImageFromDataUrl(sample); + setImgLoadListener(original, next); +} + +function compressAndDisplay(image, next) { + var canvas = document.createElement('canvas'); + canvas.width = image.naturalWidth; + canvas.height = image.naturalHeight; + var ctx = canvas.getContext('2d'); + ctx.drawImage(image, 0, 0); + + var dataUrl; + // I want to test passing undefined as well + if ('quality' in window) { + dataUrl = canvas.toDataURL('image/jpeg', quality); + } else { + dataUrl = canvas.toDataURL('image/jpeg'); + } + + var img = getImageFromDataUrl(dataUrl); + setImgLoadListener(img, next); + document.body.appendChild(img); +} + +function setImgLoadListener(img, func) { + if (img.complete) { + func.call(img, { target: img}); + } else { + img.addEventListener('load', func); + } +} + +function naturalDimensionsHandler(e) { + var img = e.target; + img.width = img.naturalWidth; + img.height = img.naturalHeight; +} + +function getImageFromDataUrl(url) { + var img = document.createElement('img'); + img.src = url; + setImgLoadListener(img, naturalDimensionsHandler); + + return img; +} + +init(); diff --git a/dom/html/reftests/toblob-todataurl/images/original.png b/dom/html/reftests/toblob-todataurl/images/original.png new file mode 100644 index 0000000000..c2da5b3597 Binary files /dev/null and b/dom/html/reftests/toblob-todataurl/images/original.png differ diff --git a/dom/html/reftests/toblob-todataurl/images/q0.jpg b/dom/html/reftests/toblob-todataurl/images/q0.jpg new file mode 100644 index 0000000000..eb41ad3e93 Binary files /dev/null and b/dom/html/reftests/toblob-todataurl/images/q0.jpg differ diff --git a/dom/html/reftests/toblob-todataurl/images/q100.jpg b/dom/html/reftests/toblob-todataurl/images/q100.jpg new file mode 100644 index 0000000000..aaa79f2d31 Binary files /dev/null and b/dom/html/reftests/toblob-todataurl/images/q100.jpg differ diff --git a/dom/html/reftests/toblob-todataurl/images/q25.jpg b/dom/html/reftests/toblob-todataurl/images/q25.jpg new file mode 100644 index 0000000000..d8b1c9bfb2 Binary files /dev/null and b/dom/html/reftests/toblob-todataurl/images/q25.jpg differ diff --git a/dom/html/reftests/toblob-todataurl/images/q50.jpg b/dom/html/reftests/toblob-todataurl/images/q50.jpg new file mode 100644 index 0000000000..f93356ef22 Binary files /dev/null and b/dom/html/reftests/toblob-todataurl/images/q50.jpg differ diff --git a/dom/html/reftests/toblob-todataurl/images/q75.jpg b/dom/html/reftests/toblob-todataurl/images/q75.jpg new file mode 100644 index 0000000000..6c25c55a1a Binary files /dev/null and b/dom/html/reftests/toblob-todataurl/images/q75.jpg differ diff --git a/dom/html/reftests/toblob-todataurl/images/q92.jpg b/dom/html/reftests/toblob-todataurl/images/q92.jpg new file mode 100644 index 0000000000..1de242a171 Binary files /dev/null and b/dom/html/reftests/toblob-todataurl/images/q92.jpg differ diff --git a/dom/html/reftests/toblob-todataurl/quality-0-ref.html b/dom/html/reftests/toblob-todataurl/quality-0-ref.html new file mode 100644 index 0000000000..3d6923fd39 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/quality-0-ref.html @@ -0,0 +1,2 @@ + + diff --git a/dom/html/reftests/toblob-todataurl/quality-100-ref.html b/dom/html/reftests/toblob-todataurl/quality-100-ref.html new file mode 100644 index 0000000000..8b157d0ab3 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/quality-100-ref.html @@ -0,0 +1,2 @@ + + diff --git a/dom/html/reftests/toblob-todataurl/quality-25-ref.html b/dom/html/reftests/toblob-todataurl/quality-25-ref.html new file mode 100644 index 0000000000..385f2ab356 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/quality-25-ref.html @@ -0,0 +1,2 @@ + + diff --git a/dom/html/reftests/toblob-todataurl/quality-50-ref.html b/dom/html/reftests/toblob-todataurl/quality-50-ref.html new file mode 100644 index 0000000000..68b91f43f6 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/quality-50-ref.html @@ -0,0 +1,2 @@ + + diff --git a/dom/html/reftests/toblob-todataurl/quality-75-ref.html b/dom/html/reftests/toblob-todataurl/quality-75-ref.html new file mode 100644 index 0000000000..7e610d231b --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/quality-75-ref.html @@ -0,0 +1,2 @@ + + diff --git a/dom/html/reftests/toblob-todataurl/quality-92-ref.html b/dom/html/reftests/toblob-todataurl/quality-92-ref.html new file mode 100644 index 0000000000..15a930c942 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/quality-92-ref.html @@ -0,0 +1,2 @@ + + diff --git a/dom/html/reftests/toblob-todataurl/reftest.list b/dom/html/reftests/toblob-todataurl/reftest.list new file mode 100644 index 0000000000..efe5a3e7f6 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/reftest.list @@ -0,0 +1,16 @@ +fuzzy-if(Android,0-105,0-482) == toblob-quality-0.html quality-0-ref.html +fuzzy-if(Android,0-38,0-2024) == toblob-quality-25.html quality-25-ref.html +fuzzy-if(Android,0-29,0-2336) == toblob-quality-50.html quality-50-ref.html +fuzzy-if(Android,0-23,0-3533) == toblob-quality-75.html quality-75-ref.html +fuzzy-if(Android,0-16,0-4199) == toblob-quality-92.html quality-92-ref.html +fuzzy-if(Android,0-8,0-2461) == toblob-quality-100.html quality-100-ref.html +fuzzy-if(Android,0-16,0-4199) == toblob-quality-undefined.html quality-92-ref.html +fuzzy-if(Android,0-16,0-4199) == toblob-quality-default.html quality-92-ref.html +fuzzy-if(Android,0-105,0-482) == todataurl-quality-0.html quality-0-ref.html +fuzzy-if(Android,0-38,0-2024) == todataurl-quality-25.html quality-25-ref.html +fuzzy-if(Android,0-29,0-2336) == todataurl-quality-50.html quality-50-ref.html +fuzzy-if(Android,0-23,0-3533) == todataurl-quality-75.html quality-75-ref.html +fuzzy-if(Android,0-16,0-4199) == todataurl-quality-92.html quality-92-ref.html +fuzzy-if(Android,0-8,0-2461) == todataurl-quality-100.html quality-100-ref.html +fuzzy-if(Android,0-16,0-4199) == todataurl-quality-undefined.html quality-92-ref.html +fuzzy-if(Android,0-16,0-4199) == todataurl-quality-default.html quality-92-ref.html \ No newline at end of file diff --git a/dom/html/reftests/toblob-todataurl/sample.js b/dom/html/reftests/toblob-todataurl/sample.js new file mode 100644 index 0000000000..8948312c93 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/sample.js @@ -0,0 +1,2 @@ +var sample = + 'data:image/png;base64,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'; diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-0.html b/dom/html/reftests/toblob-todataurl/toblob-quality-0.html new file mode 100644 index 0000000000..7e7298cb6b --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-0.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-100.html b/dom/html/reftests/toblob-todataurl/toblob-quality-100.html new file mode 100644 index 0000000000..34f318e11f --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-100.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-25.html b/dom/html/reftests/toblob-todataurl/toblob-quality-25.html new file mode 100644 index 0000000000..ed4350e6eb --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-25.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-50.html b/dom/html/reftests/toblob-todataurl/toblob-quality-50.html new file mode 100644 index 0000000000..47e3b684fa --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-50.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-75.html b/dom/html/reftests/toblob-todataurl/toblob-quality-75.html new file mode 100644 index 0000000000..45ccfe1fe0 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-75.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-92.html b/dom/html/reftests/toblob-todataurl/toblob-quality-92.html new file mode 100644 index 0000000000..6a7f8788fb --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-92.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-default.html b/dom/html/reftests/toblob-todataurl/toblob-quality-default.html new file mode 100644 index 0000000000..c5b404744c --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-default.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/toblob-quality-undefined.html b/dom/html/reftests/toblob-todataurl/toblob-quality-undefined.html new file mode 100644 index 0000000000..3252900200 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/toblob-quality-undefined.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-0.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-0.html new file mode 100644 index 0000000000..1d4eb9b7f1 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-0.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-100.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-100.html new file mode 100644 index 0000000000..66b627c13e --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-100.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-25.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-25.html new file mode 100644 index 0000000000..15237cea8b --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-25.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-50.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-50.html new file mode 100644 index 0000000000..93e820e68b --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-50.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-75.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-75.html new file mode 100644 index 0000000000..acdc7416f8 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-75.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-92.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-92.html new file mode 100644 index 0000000000..ca3de4ee0b --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-92.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-default.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-default.html new file mode 100644 index 0000000000..cc7771dbf0 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-default.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dom/html/reftests/toblob-todataurl/todataurl-quality-undefined.html b/dom/html/reftests/toblob-todataurl/todataurl-quality-undefined.html new file mode 100644 index 0000000000..16801e4829 --- /dev/null +++ b/dom/html/reftests/toblob-todataurl/todataurl-quality-undefined.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/dom/html/reftests/video_rotated.mp4 b/dom/html/reftests/video_rotated.mp4 new file mode 100644 index 0000000000..38a1b77f93 Binary files /dev/null and b/dom/html/reftests/video_rotated.mp4 differ diff --git a/dom/html/reftests/video_rotation_90.mp4 b/dom/html/reftests/video_rotation_90.mp4 new file mode 100644 index 0000000000..85aa055fb9 Binary files /dev/null and b/dom/html/reftests/video_rotation_90.mp4 differ diff --git a/dom/html/test/347174transform.xsl b/dom/html/test/347174transform.xsl new file mode 100644 index 0000000000..1b201de3f3 --- /dev/null +++ b/dom/html/test/347174transform.xsl @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dom/html/test/347174transformable.xml b/dom/html/test/347174transformable.xml new file mode 100644 index 0000000000..68f7bc6dca --- /dev/null +++ b/dom/html/test/347174transformable.xml @@ -0,0 +1,3 @@ + + +This is a sample document. diff --git a/dom/html/test/allowMedia.sjs b/dom/html/test/allowMedia.sjs new file mode 100644 index 0000000000..f29619cd89 --- /dev/null +++ b/dom/html/test/allowMedia.sjs @@ -0,0 +1,12 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(req, resp) { + resp.setHeader("Cache-Control", "no-cache", false); + resp.setHeader("Content-Type", "text/plain", false); + + let stateKey = "allowMediaState"; + let state = getState(stateKey); + setState(stateKey, req.queryString ? "FAIL" : ""); + resp.write(state || "PASS"); +} diff --git a/dom/html/test/browser.ini b/dom/html/test/browser.ini new file mode 100644 index 0000000000..cb02f7f551 --- /dev/null +++ b/dom/html/test/browser.ini @@ -0,0 +1,37 @@ +[DEFAULT] +support-files = + bug592641_img.jpg + dummy_page.html + image.png + submission_flush.html + post_action_page.html + form_data_file.bin + form_data_file.txt + form_submit_server.sjs + head.js + +[browser_bug592641.js] +[browser_bug1081537.js] +[browser_bug1108547.js] +support-files = + file_bug1108547-1.html + file_bug1108547-2.html + file_bug1108547-3.html +[browser_bug436200.js] +support-files = + bug436200.html +[browser_DOMDocElementInserted.js] +skip-if = bits == 64 && (os == "mac" || os == "linux") #Bug 1646862 +[browser_form_post_from_file_to_http.js] +[browser_containerLoadingContent.js] +skip-if = + os == "win" && os_version == "6.1" # Skip on Azure - frequent failure +[browser_ImageDocument_svg_zoom.js] +[browser_submission_flush.js] +[browser_refresh_after_document_write.js] +support-files = + file_refresh_after_document_write.html +[browser_targetBlankNoOpener.js] +support-files = + empty.html + image_yellow.png diff --git a/dom/html/test/browser_DOMDocElementInserted.js b/dom/html/test/browser_DOMDocElementInserted.js new file mode 100644 index 0000000000..fdd123f04c --- /dev/null +++ b/dom/html/test/browser_DOMDocElementInserted.js @@ -0,0 +1,23 @@ +// Tests that the DOMDocElementInserted event is visible on the frame +add_task(async function () { + let tab = BrowserTestUtils.addTab(gBrowser); + let uri = "data:text/html;charset=utf-8,"; + + let eventPromise = ContentTask.spawn(tab.linkedBrowser, null, function () { + return new Promise(resolve => { + addEventListener( + "DOMDocElementInserted", + event => resolve(event.target.documentURIObject.spec), + { + once: true, + } + ); + }); + }); + + BrowserTestUtils.loadURIString(tab.linkedBrowser, uri); + let loadedURI = await eventPromise; + is(loadedURI, uri, "Should have seen the event for the right URI"); + + gBrowser.removeTab(tab); +}); diff --git a/dom/html/test/browser_ImageDocument_svg_zoom.js b/dom/html/test/browser_ImageDocument_svg_zoom.js new file mode 100644 index 0000000000..49e0fe410c --- /dev/null +++ b/dom/html/test/browser_ImageDocument_svg_zoom.js @@ -0,0 +1,38 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const URL = `data:image/svg+xml,`; + +function test_once() { + return BrowserTestUtils.withNewTab(URL, async browser => { + return await SpecialPowers.spawn(browser, [], async function () { + const rect = content.document.documentElement.getBoundingClientRect(); + info( + `${rect.width}x${rect.height}, ${content.innerWidth}x${content.innerHeight}` + ); + is( + Math.round(rect.height), + content.innerHeight, + "Should fill the viewport and not overflow" + ); + }); + }); +} + +add_task(async function test_with_no_text_zoom() { + await test_once(); +}); + +add_task(async function test_with_text_zoom() { + let dpi = window.devicePixelRatio; + + await SpecialPowers.pushPrefEnv({ set: [["ui.textScaleFactor", 200]] }); + ok( + window.devicePixelRatio > dpi, + "DPI should change as a result of the pref flip" + ); + + return test_once(); +}); diff --git a/dom/html/test/browser_bug1081537.js b/dom/html/test/browser_bug1081537.js new file mode 100644 index 0000000000..2a079be2f7 --- /dev/null +++ b/dom/html/test/browser_bug1081537.js @@ -0,0 +1,11 @@ +// This test is useful because mochitest-browser runs as an addon, so we test +// addon-scope paths here. +var ifr; +function test() { + ifr = document.createXULElement("iframe"); + document.getElementById("main-window").appendChild(ifr); + is(ifr.contentDocument.nodePrincipal.origin, "[System Principal]"); + ifr.contentDocument.open(); + ok(true, "Didn't throw"); +} +registerCleanupFunction(() => ifr.remove()); diff --git a/dom/html/test/browser_bug1108547.js b/dom/html/test/browser_bug1108547.js new file mode 100644 index 0000000000..4949827086 --- /dev/null +++ b/dom/html/test/browser_bug1108547.js @@ -0,0 +1,149 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +requestLongerTimeout(2); + +function test() { + waitForExplicitFinish(); + + runPass("file_bug1108547-2.html", function () { + runPass("file_bug1108547-3.html", function () { + finish(); + }); + }); +} + +function runPass(getterFile, finishedCallback) { + var rootDir = "http://mochi.test:8888/browser/dom/html/test/"; + var testBrowser; + var privateWin; + + function whenDelayedStartupFinished(win, callback) { + let topic = "browser-delayed-startup-finished"; + Services.obs.addObserver(function onStartup(aSubject) { + if (win != aSubject) { + return; + } + + Services.obs.removeObserver(onStartup, topic); + executeSoon(callback); + }, topic); + } + + // First, set the cookie in a normal window. + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + rootDir + "file_bug1108547-1.html" + ); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then( + afterOpenCookieSetter + ); + + function afterOpenCookieSetter() { + gBrowser.removeCurrentTab(); + + // Now, open a private window. + privateWin = OpenBrowserWindow({ private: true }); + whenDelayedStartupFinished(privateWin, afterPrivateWindowOpened); + } + + function afterPrivateWindowOpened() { + // In the private window, open the getter file, and wait for a new tab to be opened. + privateWin.gBrowser.selectedTab = BrowserTestUtils.addTab( + privateWin.gBrowser, + rootDir + getterFile + ); + testBrowser = privateWin.gBrowser.selectedBrowser; + privateWin.gBrowser.tabContainer.addEventListener( + "TabOpen", + onNewTabOpened, + true + ); + } + + function fetchResult() { + return SpecialPowers.spawn(testBrowser, [], function () { + return content.document.getElementById("result").textContent; + }); + } + + function onNewTabOpened() { + // When the new tab is opened, wait for it to load. + privateWin.gBrowser.tabContainer.removeEventListener( + "TabOpen", + onNewTabOpened, + true + ); + BrowserTestUtils.browserLoaded( + privateWin.gBrowser.tabs[privateWin.gBrowser.tabs.length - 1] + .linkedBrowser + ) + .then(fetchResult) + .then(onNewTabLoaded); + } + + function onNewTabLoaded(result) { + // Now, ensure that the private tab doesn't have access to the cookie set in normal mode. + is(result, "", "Shouldn't have access to the cookies"); + + // We're done with the private window, close it. + privateWin.close(); + + // Clear all cookies. + Cc["@mozilla.org/cookiemanager;1"] + .getService(Ci.nsICookieManager) + .removeAll(); + + // Open a new private window, this time to set a cookie inside it. + privateWin = OpenBrowserWindow({ private: true }); + whenDelayedStartupFinished(privateWin, afterPrivateWindowOpened2); + } + + function afterPrivateWindowOpened2() { + // In the private window, open the setter file, and wait for it to load. + privateWin.gBrowser.selectedTab = BrowserTestUtils.addTab( + privateWin.gBrowser, + rootDir + "file_bug1108547-1.html" + ); + BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser).then( + afterOpenCookieSetter2 + ); + } + + function afterOpenCookieSetter2() { + // We're done with the private window now, close it. + privateWin.close(); + + // Now try to read the cookie in a normal window, and wait for a new tab to be opened. + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + rootDir + getterFile + ); + testBrowser = gBrowser.selectedBrowser; + gBrowser.tabContainer.addEventListener("TabOpen", onNewTabOpened2, true); + } + + function onNewTabOpened2() { + // When the new tab is opened, wait for it to load. + gBrowser.tabContainer.removeEventListener("TabOpen", onNewTabOpened2, true); + BrowserTestUtils.browserLoaded( + gBrowser.tabs[gBrowser.tabs.length - 1].linkedBrowser + ) + .then(fetchResult) + .then(onNewTabLoaded2); + } + + function onNewTabLoaded2(result) { + // Now, ensure that the normal tab doesn't have access to the cookie set in private mode. + is(result, "", "Shouldn't have access to the cookies"); + + // Remove both of the tabs opened here. + gBrowser.removeCurrentTab(); + gBrowser.removeCurrentTab(); + + privateWin = null; + testBrowser = null; + + finishedCallback(); + } +} diff --git a/dom/html/test/browser_bug436200.js b/dom/html/test/browser_bug436200.js new file mode 100644 index 0000000000..7e739c02ad --- /dev/null +++ b/dom/html/test/browser_bug436200.js @@ -0,0 +1,60 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const kTestPage = "https://example.org/browser/dom/html/test/bug436200.html"; + +async function run_test(shouldShowPrompt, msg) { + let promptShown = false; + + function tabModalObserver(subject) { + promptShown = true; + subject.querySelector(".tabmodalprompt-button0").click(); + } + Services.obs.addObserver(tabModalObserver, "tabmodal-dialog-loaded"); + + function commonDialogObserver(subject) { + let dialog = subject.Dialog; + promptShown = true; + dialog.ui.button0.click(); + } + Services.obs.addObserver(commonDialogObserver, "common-dialog-loaded"); + + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kTestPage); + + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () { + let form = content.document.getElementById("test_form"); + form.submit(); + }); + Services.obs.removeObserver(tabModalObserver, "tabmodal-dialog-loaded"); + Services.obs.removeObserver(commonDialogObserver, "common-dialog-loaded"); + + is(promptShown, shouldShowPrompt, msg); + BrowserTestUtils.removeTab(tab); +} + +add_task(async function test_prompt() { + await run_test(true, "Should show prompt"); +}); + +add_task(async function test_noprompt() { + await SpecialPowers.pushPrefEnv({ + set: [["security.warn_submit_secure_to_insecure", false]], + }); + await run_test(false, "Should not show prompt"); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function test_prompt_modal() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "prompts.modalType.insecureFormSubmit", + Services.prompt.MODAL_TYPE_WINDOW, + ], + ], + }); + await run_test(true, "Should show prompt"); + await SpecialPowers.popPrefEnv(); +}); diff --git a/dom/html/test/browser_bug592641.js b/dom/html/test/browser_bug592641.js new file mode 100644 index 0000000000..761af6a568 --- /dev/null +++ b/dom/html/test/browser_bug592641.js @@ -0,0 +1,61 @@ +// Test for bug 592641 - Image document doesn't show dimensions of cached images + +// Globals +var testPath = "http://mochi.test:8888/browser/dom/html/test/"; +var ctx = { loadsDone: 0 }; + +// Entry point from Mochikit +function test() { + waitForExplicitFinish(); + + ctx.tab1 = BrowserTestUtils.addTab(gBrowser, testPath + "bug592641_img.jpg"); + ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1); + BrowserTestUtils.browserLoaded(ctx.tab1Browser).then(load1Soon); +} + +function checkTitle(title) { + ctx.loadsDone++; + ok( + /^bug592641_img\.jpg \(JPEG Image, 1500\u00A0\u00D7\u00A01500 pixels\)/.test( + title + ), + "Title should be correct on load #" + ctx.loadsDone + ", was: " + title + ); +} + +function load1Soon() { + // onload is fired in OnStopDecode, so let's use executeSoon() to make sure + // that any other OnStopDecode event handlers get the chance to fire first. + executeSoon(load1Done); +} + +function load1Done() { + // Check the title + var title = ctx.tab1Browser.contentTitle; + checkTitle(title); + + // Try loading the same image in a new tab to make sure things work in + // the cached case. + ctx.tab2 = BrowserTestUtils.addTab(gBrowser, testPath + "bug592641_img.jpg"); + ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2); + BrowserTestUtils.browserLoaded(ctx.tab2Browser).then(load2Soon); +} + +function load2Soon() { + // onload is fired in OnStopDecode, so let's use executeSoon() to make sure + // that any other OnStopDecode event handlers get the chance to fire first. + executeSoon(load2Done); +} + +function load2Done() { + // Check the title + var title = ctx.tab2Browser.contentTitle; + checkTitle(title); + + // Clean up + gBrowser.removeTab(ctx.tab1); + gBrowser.removeTab(ctx.tab2); + + // Test done + finish(); +} diff --git a/dom/html/test/browser_containerLoadingContent.js b/dom/html/test/browser_containerLoadingContent.js new file mode 100644 index 0000000000..c0b52ffe8a --- /dev/null +++ b/dom/html/test/browser_containerLoadingContent.js @@ -0,0 +1,130 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const syntheticBrowsingContexts = SpecialPowers.getBoolPref( + "browser.opaqueResponseBlocking.syntheticBrowsingContext", + false +); + +const DIRPATH = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "" +); + +const ORIGIN = "https://example.com"; +const CROSSORIGIN = "https://example.org"; + +const TABURL = `${ORIGIN}/${DIRPATH}dummy_page.html`; + +const IMAGEURL = `${ORIGIN}/${DIRPATH}image.png`; +const CROSSIMAGEURL = `${CROSSORIGIN}/${DIRPATH}image.png`; + +const DOCUMENTURL = `${ORIGIN}/${DIRPATH}dummy_page.html`; +const CROSSDOCUMENTURL = `${CROSSORIGIN}/${DIRPATH}dummy_page.html`; + +async function createElements({ element, attribute }, url1, url2) { + for (let url of [url1, url2]) { + const object = content.document.createElement(element); + object[attribute] = url; + const onloadPromise = new Promise(res => { + object.onload = res; + }); + content.document.body.appendChild(object); + await onloadPromise; + return object; + } +} + +function getPids(browser) { + return browser.browsingContext.children.map( + child => child.currentWindowContext.osPid + ); +} + +async function runTest(spec, tabUrl, imageurl, crossimageurl, check) { + await BrowserTestUtils.withNewTab(tabUrl, async browser => { + await SpecialPowers.spawn( + browser, + [spec, imageurl, crossimageurl], + async ({ element, attribute }, url1, url2) => { + for (let url of [url1, url2]) { + const object = content.document.createElement(element); + object[attribute] = url; + const onloadPromise = new Promise(res => { + object.onload = res; + }); + content.document.body.appendChild(object); + await onloadPromise; + } + } + ); + + await check(browser); + }); +} + +let iframe = { element: "iframe", attribute: "src" }; +let embed = { element: "embed", attribute: "src" }; +let object = { element: "object", attribute: "data" }; + +async function checkImage(browser) { + let pids = getPids(browser); + is(pids.length, 2, "There should be two browsing contexts"); + ok(pids[0], "The first pid should have a sane value"); + ok(pids[1], "The second pid should have a sane value"); + isnot(pids[0], pids[1], "The two pids should be different"); + + let images = []; + for (let context of browser.browsingContext.children) { + images.push( + await SpecialPowers.spawn(context, [], async () => { + let img = new URL(content.document.querySelector("img").src); + is( + `${img.protocol}//${img.host}`, + `${content.location.protocol}//${content.location.host}`, + "Images should be loaded in the same domain as the document" + ); + return img.href; + }) + ); + } + isnot(images[0], images[1], "The images should have different sources"); +} + +function checkDocument(browser) { + let pids = getPids(browser); + is(pids.length, 2, "There should be two browsing contexts"); + ok(pids[0], "The first pid should have a sane value"); + ok(pids[1], "The second pid should have a sane value"); + isnot(pids[0], pids[1], "The two pids should be different"); +} + +add_task(async function test_iframeImageDocument() { + await runTest(iframe, TABURL, IMAGEURL, CROSSIMAGEURL, checkImage); +}); + +if (syntheticBrowsingContexts) { + add_task(async function test_embedImageDocument() { + await runTest(embed, TABURL, IMAGEURL, CROSSIMAGEURL, checkImage); + }); + + add_task(async function test_objectImageDocument() { + await runTest(object, TABURL, IMAGEURL, CROSSIMAGEURL, checkImage); + }); +} + +add_task(async function test_iframeDocument() { + await runTest(iframe, TABURL, DOCUMENTURL, CROSSDOCUMENTURL, checkDocument); +}); + +if (syntheticBrowsingContexts) { + add_task(async function test_embedDocument() { + await runTest(embed, TABURL, DOCUMENTURL, CROSSDOCUMENTURL, checkDocument); + }); + + add_task(async function test_objectDocument() { + await runTest(object, TABURL, DOCUMENTURL, CROSSDOCUMENTURL, checkDocument); + }); +} diff --git a/dom/html/test/browser_form_post_from_file_to_http.js b/dom/html/test/browser_form_post_from_file_to_http.js new file mode 100644 index 0000000000..2b69210cc2 --- /dev/null +++ b/dom/html/test/browser_form_post_from_file_to_http.js @@ -0,0 +1,180 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + +const TEST_HTTP_POST = + "http://example.org/browser/dom/html/test/form_submit_server.sjs"; + +// Test for bug 1351358. +async function runTest(doNewTab) { + // Create file URI and test data file paths. + let testFile = getChromeDir(getResolvedURI(gTestPath)); + testFile.append("dummy_page.html"); + const fileUriString = Services.io.newFileURI(testFile).spec; + let filePaths = []; + testFile.leafName = "form_data_file.txt"; + filePaths.push(testFile.path); + testFile.leafName = "form_data_file.bin"; + filePaths.push(testFile.path); + + // Open file:// page tab in which to run the test. + await BrowserTestUtils.withNewTab( + fileUriString, + async function (fileBrowser) { + // Create a form to post to server that writes posted data into body as JSON. + + var promiseLoad; + if (doNewTab) { + promiseLoad = BrowserTestUtils.waitForNewTab( + gBrowser, + TEST_HTTP_POST, + true, + false + ); + } else { + promiseLoad = BrowserTestUtils.browserLoaded( + fileBrowser, + false, + TEST_HTTP_POST + ); + } + + /* eslint-disable no-shadow */ + await SpecialPowers.spawn( + fileBrowser, + [TEST_HTTP_POST, filePaths, doNewTab], + (actionUri, filePaths, doNewTab) => { + Cu.importGlobalProperties(["File"]); + + let doc = content.document; + let form = doc.body.appendChild(doc.createElement("form")); + form.action = actionUri; + form.method = "POST"; + form.enctype = "multipart/form-data"; + if (doNewTab) { + form.target = "_blank"; + } + + let inputText = form.appendChild(doc.createElement("input")); + inputText.type = "text"; + inputText.name = "text"; + inputText.value = "posted"; + + let inputCheckboxOn = form.appendChild(doc.createElement("input")); + inputCheckboxOn.type = "checkbox"; + inputCheckboxOn.name = "checked"; + inputCheckboxOn.checked = true; + + let inputCheckboxOff = form.appendChild(doc.createElement("input")); + inputCheckboxOff.type = "checkbox"; + inputCheckboxOff.name = "unchecked"; + inputCheckboxOff.checked = false; + + let inputFile = form.appendChild(doc.createElement("input")); + inputFile.type = "file"; + inputFile.name = "file"; + let fileList = []; + let promises = []; + for (let path of filePaths) { + promises.push( + File.createFromFileName(path).then(file => { + fileList.push(file); + }) + ); + } + + Promise.all(promises).then(() => { + inputFile.mozSetFileArray(fileList); + form.submit(); + }); + } + ); + /* eslint-enable no-shadow */ + + var href; + var testBrowser; + var newTab; + if (doNewTab) { + newTab = await promiseLoad; + testBrowser = newTab.linkedBrowser; + href = testBrowser.currentURI.spec; + } else { + testBrowser = fileBrowser; + href = await promiseLoad; + } + is( + href, + TEST_HTTP_POST, + "Check that the loaded page is the one to which we posted." + ); + + let binContentType; + if (AppConstants.platform == "macosx") { + binContentType = "application/macbinary"; + } else { + binContentType = "application/octet-stream"; + } + + /* eslint-disable no-shadow */ + await SpecialPowers.spawn( + testBrowser, + [binContentType], + binContentType => { + let data = JSON.parse(content.document.body.textContent); + is( + data[0].headers["Content-Disposition"], + 'form-data; name="text"', + "Check text input Content-Disposition" + ); + is(data[0].body, "posted", "Check text input body"); + + is( + data[1].headers["Content-Disposition"], + 'form-data; name="checked"', + "Check checkbox input Content-Disposition" + ); + is(data[1].body, "on", "Check checkbox input body"); + + // Note that unchecked checkbox details are not sent. + + is( + data[2].headers["Content-Disposition"], + 'form-data; name="file"; filename="form_data_file.txt"', + "Check text file input Content-Disposition" + ); + is( + data[2].headers["Content-Type"], + "text/plain", + "Check text file input Content-Type" + ); + is(data[2].body, "1234\n", "Check text file input body"); + + is( + data[3].headers["Content-Disposition"], + 'form-data; name="file"; filename="form_data_file.bin"', + "Check binary file input Content-Disposition" + ); + is( + data[3].headers["Content-Type"], + binContentType, + "Check binary file input Content-Type" + ); + is( + data[3].body, + "\u0001\u0002\u0003\u0004\n", + "Check binary file input body" + ); + } + ); + /* eslint-enable no-shadow */ + + if (newTab) { + BrowserTestUtils.removeTab(newTab); + } + } + ); +} + +add_task(async function runWithDocumentChannel() { + await runTest(false); + await runTest(true); +}); diff --git a/dom/html/test/browser_refresh_after_document_write.js b/dom/html/test/browser_refresh_after_document_write.js new file mode 100644 index 0000000000..88e0dbe489 --- /dev/null +++ b/dom/html/test/browser_refresh_after_document_write.js @@ -0,0 +1,52 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* +Test that after using document.write(...), refreshing the document and calling write again, +resulting document.URL is identical to the original URL. + +This testcase is aimed at preventing bug 619092 +*/ +var testURL = + "http://mochi.test:8888/browser/dom/html/test/file_refresh_after_document_write.html"; +let aTab, aBrowser; + +function test() { + waitForExplicitFinish(); + + aTab = BrowserTestUtils.addTab(gBrowser, testURL); + aBrowser = gBrowser.getBrowserForTab(aTab); + BrowserTestUtils.browserLoaded(aBrowser) + .then(() => { + is( + aBrowser.currentURI.spec, + testURL, + "Make sure we start at the correct URL" + ); + + SpecialPowers.spawn(aBrowser, [], () => { + // test_btn calls document.write() then reloads the document + let test_btn = content.document.getElementById("test_btn"); + + docShell.chromeEventHandler.addEventListener( + "load", + () => { + test_btn.click(); + }, + { once: true, capture: true } + ); + + test_btn.click(); + }); + + return BrowserTestUtils.browserLoaded(aBrowser); + }) + .then(() => { + return SpecialPowers.spawn(aBrowser, [], () => content.document.URL); + }) + .then(url => { + is(url, testURL, "Document URL should be identical after reload"); + gBrowser.removeTab(aTab); + finish(); + }); +} diff --git a/dom/html/test/browser_submission_flush.js b/dom/html/test/browser_submission_flush.js new file mode 100644 index 0000000000..add886c6a3 --- /dev/null +++ b/dom/html/test/browser_submission_flush.js @@ -0,0 +1,97 @@ +"use strict"; +// Form submissions triggered by the Javascript 'submit' event listener are +// deferred until the event listener finishes. However, changes to specific +// attributes ("action" and "target" attributes) need to cause an immediate +// flush of any pending submission to prevent the form submission from using the +// wrong action or target. This test ensures that such flushes happen properly. + +const kTestPage = + "https://example.org/browser/dom/html/test/submission_flush.html"; +// This is the page pointed to by the form action in the test HTML page. +const kPostActionPage = + "https://example.org/browser/dom/html/test/post_action_page.html"; + +const kFormId = "test_form"; +const kFrameId = "test_frame"; +const kSubmitButtonId = "submit_button"; + +// Take in a variety of actions (in the form of setting and unsetting form +// attributes). Then submit the form in the submit event listener to cause a +// deferred form submission. Then perform the test actions and ensure that the +// form used the correct attribute values rather than the changed ones. +async function runTest(aTestActions) { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kTestPage); + registerCleanupFunction(() => BrowserTestUtils.removeTab(tab)); + + /* eslint-disable no-shadow */ + let frame_url = await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [{ kFormId, kFrameId, kSubmitButtonId, aTestActions }], + async function ({ kFormId, kFrameId, kSubmitButtonId, aTestActions }) { + let form = content.document.getElementById(kFormId); + + form.addEventListener( + "submit", + event => { + // Need to trigger the deferred submission by submitting in the submit + // event handler. To prevent the form from being submitted twice, the + //
tag contains the attribute |onsubmit="return false;"| to cancel + // the original submission. + form.submit(); + + if (aTestActions.setattr) { + for (let { attr, value } of aTestActions.setattr) { + form.setAttribute(attr, value); + } + } + if (aTestActions.unsetattr) { + for (let attr of aTestActions.unsetattr) { + form.removeAttribute(attr); + } + } + }, + { capture: true, once: true } + ); + + // Trigger the above event listener + content.document.getElementById(kSubmitButtonId).click(); + + // Test that the form was submitted to the correct target (the frame) with + // the correct action (kPostActionPage). + let frame = content.document.getElementById(kFrameId); + await new Promise(resolve => { + frame.addEventListener("load", resolve, { once: true }); + }); + return frame.contentWindow.location.href; + } + ); + /* eslint-enable no-shadow */ + is( + frame_url, + kPostActionPage, + "Form should have submitted with correct target and action" + ); +} + +add_task(async function () { + info("Changing action should flush pending submissions"); + await runTest({ setattr: [{ attr: "action", value: "about:blank" }] }); +}); + +add_task(async function () { + info("Changing target should flush pending submissions"); + await runTest({ setattr: [{ attr: "target", value: "_blank" }] }); +}); + +add_task(async function () { + info("Unsetting action should flush pending submissions"); + await runTest({ unsetattr: ["action"] }); +}); + +// On failure, this test will time out rather than failing an assert. When the +// target attribute is not set, the form will submit the active page, navigating +// it away and preventing the wait for iframe load from ever finishing. +add_task(async function () { + info("Unsetting target should flush pending submissions"); + await runTest({ unsetattr: ["target"] }); +}); diff --git a/dom/html/test/browser_targetBlankNoOpener.js b/dom/html/test/browser_targetBlankNoOpener.js new file mode 100644 index 0000000000..1647df0be2 --- /dev/null +++ b/dom/html/test/browser_targetBlankNoOpener.js @@ -0,0 +1,121 @@ +const TEST_URL = "http://mochi.test:8888/browser/dom/html/test/empty.html"; + +async function checkOpener(browser, elm, name, rel) { + let p = BrowserTestUtils.waitForNewTab(gBrowser, null, true, true); + + await SpecialPowers.spawn( + browser, + [{ url: TEST_URL, name, rel, elm }], + async obj => { + let element; + + if (obj.elm == "anchor") { + element = content.document.createElement("a"); + content.document.body.appendChild(element); + element.appendChild(content.document.createTextNode(obj.name)); + } else { + let img = content.document.createElement("img"); + img.src = "image_yellow.png"; + content.document.body.appendChild(img); + + element = content.document.createElement("area"); + img.appendChild(element); + + element.setAttribute("shape", "rect"); + element.setAttribute("coords", "0,0,100,100"); + } + + element.setAttribute("target", "_blank"); + element.setAttribute("href", obj.url); + + if (obj.rel) { + element.setAttribute("rel", obj.rel); + } + + element.click(); + } + ); + + let newTab = await p; + let newBrowser = gBrowser.getBrowserForTab(newTab); + + let hasOpener = await SpecialPowers.spawn( + newTab.linkedBrowser, + [], + _ => !!content.window.opener + ); + + BrowserTestUtils.removeTab(newTab); + return hasOpener; +} + +async function runTests(browser, elm) { + info("Creating an " + elm + " with target=_blank rel=opener"); + ok( + !!(await checkOpener(browser, elm, "rel=opener", "opener")), + "We want the opener with rel=opener" + ); + + info("Creating an " + elm + " with target=_blank rel=noopener"); + ok( + !(await checkOpener(browser, elm, "rel=noopener", "noopener")), + "We don't want the opener with rel=noopener" + ); + + info("Creating an " + elm + " with target=_blank"); + ok( + !(await checkOpener(browser, elm, "no rel", null)), + "We don't want the opener with no rel is passed" + ); + + info("Creating an " + elm + " with target=_blank rel='noopener opener'"); + ok( + !(await checkOpener( + browser, + elm, + "rel=noopener+opener", + "noopener opener" + )), + "noopener wins with rel=noopener+opener" + ); + + info("Creating an " + elm + " with target=_blank rel='noreferrer opener'"); + ok( + !(await checkOpener(browser, elm, "noreferrer wins", "noreferrer opener")), + "We don't want the opener with rel=noreferrer+opener" + ); + + info("Creating an " + elm + " with target=_blank rel='opener noreferrer'"); + ok( + !(await checkOpener( + browser, + elm, + "noreferrer wins again", + "noreferrer opener" + )), + "We don't want the opener with rel=opener+noreferrer" + ); +} + +add_task(async _ => { + await SpecialPowers.flushPrefEnv(); + await SpecialPowers.pushPrefEnv({ + set: [ + ["dom.block_multiple_popups", false], + ["dom.disable_open_during_load", true], + ["dom.targetBlankNoOpener.enabled", true], + ], + }); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + await runTests(browser, "anchor"); + await runTests(browser, "area"); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); +}); diff --git a/dom/html/test/bug100533_iframe.html b/dom/html/test/bug100533_iframe.html new file mode 100644 index 0000000000..ddf58a15c6 --- /dev/null +++ b/dom/html/test/bug100533_iframe.html @@ -0,0 +1,8 @@ + + + + + +
+ + diff --git a/dom/html/test/bug100533_load.html b/dom/html/test/bug100533_load.html new file mode 100644 index 0000000000..99cf26640c --- /dev/null +++ b/dom/html/test/bug100533_load.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/dom/html/test/bug1260704_iframe.html b/dom/html/test/bug1260704_iframe.html new file mode 100644 index 0000000000..695dc7c1ac --- /dev/null +++ b/dom/html/test/bug1260704_iframe.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + diff --git a/dom/html/test/bug1260704_iframe_empty.html b/dom/html/test/bug1260704_iframe_empty.html new file mode 100644 index 0000000000..e826b1e5e6 --- /dev/null +++ b/dom/html/test/bug1260704_iframe_empty.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/dom/html/test/bug1292522_iframe.html b/dom/html/test/bug1292522_iframe.html new file mode 100644 index 0000000000..99a3369d00 --- /dev/null +++ b/dom/html/test/bug1292522_iframe.html @@ -0,0 +1,10 @@ + +iframe + +

var testvar = "testiframe"

+ + + diff --git a/dom/html/test/bug1292522_page.html b/dom/html/test/bug1292522_page.html new file mode 100644 index 0000000000..9570f12d2d --- /dev/null +++ b/dom/html/test/bug1292522_page.html @@ -0,0 +1,14 @@ + + + + Test for Bug 1292522 + + + + + + diff --git a/dom/html/test/bug1315146-iframe.html b/dom/html/test/bug1315146-iframe.html new file mode 100644 index 0000000000..280db53052 --- /dev/null +++ b/dom/html/test/bug1315146-iframe.html @@ -0,0 +1,4 @@ + + diff --git a/dom/html/test/bug1315146-main.html b/dom/html/test/bug1315146-main.html new file mode 100644 index 0000000000..e9f356dda6 --- /dev/null +++ b/dom/html/test/bug1315146-main.html @@ -0,0 +1,15 @@ + + + + diff --git a/dom/html/test/bug196523-subframe.html b/dom/html/test/bug196523-subframe.html new file mode 100644 index 0000000000..ac53572a7a --- /dev/null +++ b/dom/html/test/bug196523-subframe.html @@ -0,0 +1,37 @@ + + diff --git a/dom/html/test/bug199692-nested-d2.html b/dom/html/test/bug199692-nested-d2.html new file mode 100644 index 0000000000..70064efe74 --- /dev/null +++ b/dom/html/test/bug199692-nested-d2.html @@ -0,0 +1,14 @@ + + + + + Nested, nested iframe for bug 199692 tests + + + +
nested, depth 2
+ + + diff --git a/dom/html/test/bug199692-nested.html b/dom/html/test/bug199692-nested.html new file mode 100644 index 0000000000..27201a953d --- /dev/null +++ b/dom/html/test/bug199692-nested.html @@ -0,0 +1,15 @@ + + + + + Nested iframe for bug 199692 tests + + + +
nested, depth 1
+ + + + diff --git a/dom/html/test/bug199692-popup.html b/dom/html/test/bug199692-popup.html new file mode 100644 index 0000000000..e138921386 --- /dev/null +++ b/dom/html/test/bug199692-popup.html @@ -0,0 +1,188 @@ + + + + + + Popup in test for Bug 199692 + + + + + +Mozilla Bug 199692 + +
+ + +
txt
+ + +
+ + +

+ + +static + + +
float
+ + +fixed + + +abs + + +
rel
+ + +
+ +
+ + + + + +
+ + + + + + + + diff --git a/dom/html/test/bug199692-scrolled.html b/dom/html/test/bug199692-scrolled.html new file mode 100644 index 0000000000..f13bf7ab12 --- /dev/null +++ b/dom/html/test/bug199692-scrolled.html @@ -0,0 +1,34 @@ + + + + + Scrolled page for bug 199692 tests + + + + + +
first
+
second
+ + + diff --git a/dom/html/test/bug242709_iframe.html b/dom/html/test/bug242709_iframe.html new file mode 100644 index 0000000000..1155299692 --- /dev/null +++ b/dom/html/test/bug242709_iframe.html @@ -0,0 +1,20 @@ + + + + + + + + + +
+ +
+ + + diff --git a/dom/html/test/bug242709_load.html b/dom/html/test/bug242709_load.html new file mode 100644 index 0000000000..c9be79b241 --- /dev/null +++ b/dom/html/test/bug242709_load.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/dom/html/test/bug277724_iframe1.html b/dom/html/test/bug277724_iframe1.html new file mode 100644 index 0000000000..d0d881b766 --- /dev/null +++ b/dom/html/test/bug277724_iframe1.html @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/html/test/bug277724_iframe2.xhtml b/dom/html/test/bug277724_iframe2.xhtml new file mode 100644 index 0000000000..14423aa06c --- /dev/null +++ b/dom/html/test/bug277724_iframe2.xhtml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/html/test/bug277890_iframe.html b/dom/html/test/bug277890_iframe.html new file mode 100644 index 0000000000..c1cb4ff2e1 --- /dev/null +++ b/dom/html/test/bug277890_iframe.html @@ -0,0 +1,20 @@ + + + + + + + + + +
+ +
+ + + diff --git a/dom/html/test/bug277890_load.html b/dom/html/test/bug277890_load.html new file mode 100644 index 0000000000..c9be79b241 --- /dev/null +++ b/dom/html/test/bug277890_load.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/dom/html/test/bug340800_iframe.txt b/dom/html/test/bug340800_iframe.txt new file mode 100644 index 0000000000..369dfe7441 --- /dev/null +++ b/dom/html/test/bug340800_iframe.txt @@ -0,0 +1,4 @@ +Line 1. +Line 2. +Line 3. +Line 4. diff --git a/dom/html/test/bug369370-popup.png b/dom/html/test/bug369370-popup.png new file mode 100644 index 0000000000..9063d12648 Binary files /dev/null and b/dom/html/test/bug369370-popup.png differ diff --git a/dom/html/test/bug372098-link-target.html b/dom/html/test/bug372098-link-target.html new file mode 100644 index 0000000000..b22b8e020e --- /dev/null +++ b/dom/html/test/bug372098-link-target.html @@ -0,0 +1,7 @@ + + + diff --git a/dom/html/test/bug436200.html b/dom/html/test/bug436200.html new file mode 100644 index 0000000000..1ef7e73b5e --- /dev/null +++ b/dom/html/test/bug436200.html @@ -0,0 +1,12 @@ + + + + + Secure to Insecure Test + + +
+ +
+ + diff --git a/dom/html/test/bug441930_iframe.html b/dom/html/test/bug441930_iframe.html new file mode 100644 index 0000000000..532cd5c36a --- /dev/null +++ b/dom/html/test/bug441930_iframe.html @@ -0,0 +1,27 @@ + + + The content of this textarea should not disappear on page reload:
+ + + + diff --git a/dom/html/test/bug445004-inner.html b/dom/html/test/bug445004-inner.html new file mode 100644 index 0000000000..b946520ea6 --- /dev/null +++ b/dom/html/test/bug445004-inner.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/dom/html/test/bug445004-inner.js b/dom/html/test/bug445004-inner.js new file mode 100644 index 0000000000..2d751da454 --- /dev/null +++ b/dom/html/test/bug445004-inner.js @@ -0,0 +1,27 @@ +document.domain = "example.org"; +function $(str) { + return document.getElementById(str); +} +function hookLoad(str) { + $(str).onload = function () { + window.parent.parent.postMessage("end", "*"); + }; + window.parent.parent.postMessage("start", "*"); +} +window.onload = function () { + hookLoad("w"); + $("w").contentWindow.location.href = "test1.example.org.png"; + hookLoad("x"); + var doc = $("x").contentDocument; + doc.write(''); + doc.close(); +}; +function doIt() { + hookLoad("y"); + $("y").contentWindow.location.href = "example.org.png"; + hookLoad("z"); + var doc = $("z").contentDocument; + doc.write(''); + doc.close(); +} +window.addEventListener("message", doIt); diff --git a/dom/html/test/bug445004-outer-abs.html b/dom/html/test/bug445004-outer-abs.html new file mode 100644 index 0000000000..8a93ef2b73 --- /dev/null +++ b/dom/html/test/bug445004-outer-abs.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/dom/html/test/bug445004-outer-rel.html b/dom/html/test/bug445004-outer-rel.html new file mode 100644 index 0000000000..0967338899 --- /dev/null +++ b/dom/html/test/bug445004-outer-rel.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/dom/html/test/bug445004-outer-write.html b/dom/html/test/bug445004-outer-write.html new file mode 100644 index 0000000000..be6e37b6d7 --- /dev/null +++ b/dom/html/test/bug445004-outer-write.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/dom/html/test/bug446483-iframe.html b/dom/html/test/bug446483-iframe.html new file mode 100644 index 0000000000..fe5a6cf9f7 --- /dev/null +++ b/dom/html/test/bug446483-iframe.html @@ -0,0 +1,10 @@ + + diff --git a/dom/html/test/bug448564-echo.sjs b/dom/html/test/bug448564-echo.sjs new file mode 100644 index 0000000000..1eee116fd7 --- /dev/null +++ b/dom/html/test/bug448564-echo.sjs @@ -0,0 +1,6 @@ +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + response.setStatusLine(request.httpVersion, 200, "OK"); + + response.write(request.queryString); +} diff --git a/dom/html/test/bug448564-iframe-1.html b/dom/html/test/bug448564-iframe-1.html new file mode 100644 index 0000000000..4f3e79e5d2 --- /dev/null +++ b/dom/html/test/bug448564-iframe-1.html @@ -0,0 +1,16 @@ + + + + + + + + + + +
+ + + + + diff --git a/dom/html/test/bug448564-iframe-2.html b/dom/html/test/bug448564-iframe-2.html new file mode 100644 index 0000000000..dba19b37e2 --- /dev/null +++ b/dom/html/test/bug448564-iframe-2.html @@ -0,0 +1,16 @@ + + + +
+ + + + + +
+
+ + + + + diff --git a/dom/html/test/bug448564-iframe-3.html b/dom/html/test/bug448564-iframe-3.html new file mode 100644 index 0000000000..64288ebb15 --- /dev/null +++ b/dom/html/test/bug448564-iframe-3.html @@ -0,0 +1,16 @@ + + + + +
+
+ + + + +
+ + + + + diff --git a/dom/html/test/bug448564-submit.js b/dom/html/test/bug448564-submit.js new file mode 100644 index 0000000000..a650487d65 --- /dev/null +++ b/dom/html/test/bug448564-submit.js @@ -0,0 +1,6 @@ +var inputs = document.getElementsByTagName("input"); +for (var input, i = 0; (input = inputs[i]); ++i) { + if ("submit" == input.type) { + input.click(); + } +} diff --git a/dom/html/test/bug499092.html b/dom/html/test/bug499092.html new file mode 100644 index 0000000000..0476fa4e76 --- /dev/null +++ b/dom/html/test/bug499092.html @@ -0,0 +1,6 @@ + + diff --git a/dom/html/test/bug499092.xml b/dom/html/test/bug499092.xml new file mode 100644 index 0000000000..eedd2c77b3 --- /dev/null +++ b/dom/html/test/bug499092.xml @@ -0,0 +1,4 @@ + + +XML OK + diff --git a/dom/html/test/bug514856_iframe.html b/dom/html/test/bug514856_iframe.html new file mode 100644 index 0000000000..2abf9e91e2 --- /dev/null +++ b/dom/html/test/bug514856_iframe.html @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/dom/html/test/bug592641_img.jpg b/dom/html/test/bug592641_img.jpg new file mode 100644 index 0000000000..c9103b8b0e Binary files /dev/null and b/dom/html/test/bug592641_img.jpg differ diff --git a/dom/html/test/bug649134/file_bug649134-1.sjs b/dom/html/test/bug649134/file_bug649134-1.sjs new file mode 100644 index 0000000000..fed0a9d693 --- /dev/null +++ b/dom/html/test/bug649134/file_bug649134-1.sjs @@ -0,0 +1,12 @@ +function handleRequest(request, response) { + response.seizePower(); + var r = + "HTTP/1.1 200 OK\r\n" + + "Content-Type: text/html\r\n" + + 'Link: < \014>; rel="stylesheet"\r\n' + + "\r\n" + + "PASS\r\n"; + response.bodyOutputStream.write(r, r.length); + response.bodyOutputStream.flush(); + response.finish(); +} diff --git a/dom/html/test/bug649134/file_bug649134-2.sjs b/dom/html/test/bug649134/file_bug649134-2.sjs new file mode 100644 index 0000000000..3cbacf7184 --- /dev/null +++ b/dom/html/test/bug649134/file_bug649134-2.sjs @@ -0,0 +1,12 @@ +function handleRequest(request, response) { + response.seizePower(); + var r = + "HTTP/1.1 200 OK\r\n" + + "Content-Type: text/html\r\n" + + 'Link: < \014>; rel="stylesheet",\r\n' + + "\r\n" + + "PASS\r\n"; + response.bodyOutputStream.write(r, r.length); + response.bodyOutputStream.flush(); + response.finish(); +} diff --git a/dom/html/test/bug649134/index.html b/dom/html/test/bug649134/index.html new file mode 100644 index 0000000000..2f3973704e --- /dev/null +++ b/dom/html/test/bug649134/index.html @@ -0,0 +1,3 @@ +body { + display:none; +} diff --git a/dom/html/test/chrome.ini b/dom/html/test/chrome.ini new file mode 100644 index 0000000000..ec7f9d1fb5 --- /dev/null +++ b/dom/html/test/chrome.ini @@ -0,0 +1,9 @@ +[DEFAULT] +support-files = + file_anchor_ping.html + image.png + +[test_anchor_ping.html] +skip-if = os == 'android' +[test_bug1414077.html] +[test_external_protocol_iframe.html] diff --git a/dom/html/test/dialog/mochitest.ini b/dom/html/test/dialog/mochitest.ini new file mode 100644 index 0000000000..cff71ae303 --- /dev/null +++ b/dom/html/test/dialog/mochitest.ini @@ -0,0 +1,4 @@ +[DEFAULT] +prefs = + dom.dialog_element.enabled=true +[test_bug1648877_dialog_fullscreen_denied.html] diff --git a/dom/html/test/dialog/test_bug1648877_dialog_fullscreen_denied.html b/dom/html/test/dialog/test_bug1648877_dialog_fullscreen_denied.html new file mode 100644 index 0000000000..906c7dd53e --- /dev/null +++ b/dom/html/test/dialog/test_bug1648877_dialog_fullscreen_denied.html @@ -0,0 +1,52 @@ + + + + + Test for Bug 1648877 + + + + + + Requesting + fullscreen a dialog element should be denied +

+ + +
+ +
+
+
+ + diff --git a/dom/html/test/dummy_page.html b/dom/html/test/dummy_page.html new file mode 100644 index 0000000000..fd238954c6 --- /dev/null +++ b/dom/html/test/dummy_page.html @@ -0,0 +1,10 @@ + + + +Dummy test page + + + +

Dummy test page

+ + diff --git a/dom/html/test/empty.html b/dom/html/test/empty.html new file mode 100644 index 0000000000..0dc101b533 --- /dev/null +++ b/dom/html/test/empty.html @@ -0,0 +1 @@ + diff --git a/dom/html/test/file.webm b/dom/html/test/file.webm new file mode 100644 index 0000000000..7bc738b8b4 Binary files /dev/null and b/dom/html/test/file.webm differ diff --git a/dom/html/test/file_anchor_ping.html b/dom/html/test/file_anchor_ping.html new file mode 100644 index 0000000000..3b9717263f --- /dev/null +++ b/dom/html/test/file_anchor_ping.html @@ -0,0 +1,13 @@ + + + + + file_anchor_ping.html + + + click me + + + diff --git a/dom/html/test/file_broadcast_load.html b/dom/html/test/file_broadcast_load.html new file mode 100644 index 0000000000..ffae9c6536 --- /dev/null +++ b/dom/html/test/file_broadcast_load.html @@ -0,0 +1,16 @@ + +

file_broadcast_load.html

+ diff --git a/dom/html/test/file_bug1108547-1.html b/dom/html/test/file_bug1108547-1.html new file mode 100644 index 0000000000..efc0eae494 --- /dev/null +++ b/dom/html/test/file_bug1108547-1.html @@ -0,0 +1,4 @@ + + diff --git a/dom/html/test/file_bug1108547-2.html b/dom/html/test/file_bug1108547-2.html new file mode 100644 index 0000000000..f5d8c5f964 --- /dev/null +++ b/dom/html/test/file_bug1108547-2.html @@ -0,0 +1,6 @@ + + +
+
+
not tested yet
+ diff --git a/dom/html/test/file_bug1108547-3.html b/dom/html/test/file_bug1108547-3.html new file mode 100644 index 0000000000..e6a8ba3fa2 --- /dev/null +++ b/dom/html/test/file_bug1108547-3.html @@ -0,0 +1,5 @@ + + +test +
not tested yet
+ diff --git a/dom/html/test/file_bug1166138_1x.png b/dom/html/test/file_bug1166138_1x.png new file mode 100644 index 0000000000..df421453c2 Binary files /dev/null and b/dom/html/test/file_bug1166138_1x.png differ diff --git a/dom/html/test/file_bug1166138_2x.png b/dom/html/test/file_bug1166138_2x.png new file mode 100644 index 0000000000..6f76d44387 Binary files /dev/null and b/dom/html/test/file_bug1166138_2x.png differ diff --git a/dom/html/test/file_bug1166138_def.png b/dom/html/test/file_bug1166138_def.png new file mode 100644 index 0000000000..144a2f0b93 Binary files /dev/null and b/dom/html/test/file_bug1166138_def.png differ diff --git a/dom/html/test/file_bug1260704.png b/dom/html/test/file_bug1260704.png new file mode 100644 index 0000000000..df421453c2 Binary files /dev/null and b/dom/html/test/file_bug1260704.png differ diff --git a/dom/html/test/file_bug209275_1.html b/dom/html/test/file_bug209275_1.html new file mode 100644 index 0000000000..3f7233876b --- /dev/null +++ b/dom/html/test/file_bug209275_1.html @@ -0,0 +1,28 @@ + + + + + + +Initial state + + + + + diff --git a/dom/html/test/file_bug209275_2.html b/dom/html/test/file_bug209275_2.html new file mode 100644 index 0000000000..36e9ff4672 --- /dev/null +++ b/dom/html/test/file_bug209275_2.html @@ -0,0 +1,23 @@ + + + + + + +Page 2 initial state + + + + + diff --git a/dom/html/test/file_bug209275_3.html b/dom/html/test/file_bug209275_3.html new file mode 100644 index 0000000000..2544115901 --- /dev/null +++ b/dom/html/test/file_bug209275_3.html @@ -0,0 +1,23 @@ + + + + + + +Initial state + + + + + diff --git a/dom/html/test/file_bug297761.html b/dom/html/test/file_bug297761.html new file mode 100644 index 0000000000..5e861a00fd --- /dev/null +++ b/dom/html/test/file_bug297761.html @@ -0,0 +1,13 @@ + + + + + + +
+ + + +
+ + diff --git a/dom/html/test/file_bug417760.png b/dom/html/test/file_bug417760.png new file mode 100644 index 0000000000..743292dc6f Binary files /dev/null and b/dom/html/test/file_bug417760.png differ diff --git a/dom/html/test/file_bug871161-1.html b/dom/html/test/file_bug871161-1.html new file mode 100644 index 0000000000..16015f0c4e --- /dev/null +++ b/dom/html/test/file_bug871161-1.html @@ -0,0 +1,16 @@ + + + + +Page with non-default charset + + + +
+ + + diff --git a/dom/html/test/file_bug871161-2.html b/dom/html/test/file_bug871161-2.html new file mode 100644 index 0000000000..18cf825b2d --- /dev/null +++ b/dom/html/test/file_bug871161-2.html @@ -0,0 +1,14 @@ + + + +Page without declared charset + + + + + + diff --git a/dom/html/test/file_bug893537.html b/dom/html/test/file_bug893537.html new file mode 100644 index 0000000000..1dcb454ff1 --- /dev/null +++ b/dom/html/test/file_bug893537.html @@ -0,0 +1,9 @@ + + + + + + + diff --git a/dom/html/test/file_cookiemanager.js b/dom/html/test/file_cookiemanager.js new file mode 100644 index 0000000000..08c9d72898 --- /dev/null +++ b/dom/html/test/file_cookiemanager.js @@ -0,0 +1,20 @@ +/* eslint-env mozilla/chrome-script */ + +addMessageListener("getCookieFromManager", ({ host, path }) => { + let cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager); + let values = []; + path = path.substring(0, path.lastIndexOf("/")); + for (let cookie of cm.cookies) { + if (!cookie) { + break; + } + if (host != cookie.host || path != cookie.path) { + continue; + } + values.push(cookie.name + "=" + cookie.value); + } + + sendAsyncMessage("getCookieFromManager:return", { + cookie: values.join("; "), + }); +}); diff --git a/dom/html/test/file_formSubmission_img.jpg b/dom/html/test/file_formSubmission_img.jpg new file mode 100644 index 0000000000..dcd99b9670 Binary files /dev/null and b/dom/html/test/file_formSubmission_img.jpg differ diff --git a/dom/html/test/file_formSubmission_text.txt b/dom/html/test/file_formSubmission_text.txt new file mode 100644 index 0000000000..a496efee84 --- /dev/null +++ b/dom/html/test/file_formSubmission_text.txt @@ -0,0 +1 @@ +This is a text file diff --git a/dom/html/test/file_iframe_sandbox_a_if1.html b/dom/html/test/file_iframe_sandbox_a_if1.html new file mode 100644 index 0000000000..b60d52ca00 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if1.html @@ -0,0 +1,13 @@ + + + + + Test for Bug 341604 + + + + I am sandboxed without any permissions + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if10.html b/dom/html/test/file_iframe_sandbox_a_if10.html new file mode 100644 index 0000000000..14306eb613 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if10.html @@ -0,0 +1,12 @@ + + + + + Test for Bug 341604 + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if11.html b/dom/html/test/file_iframe_sandbox_a_if11.html new file mode 100644 index 0000000000..8eee71df1d --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if11.html @@ -0,0 +1,23 @@ + + + + + Test for Bug 341604 + + + + + + +I'm a <frame> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + + diff --git a/dom/html/test/file_iframe_sandbox_a_if12.html b/dom/html/test/file_iframe_sandbox_a_if12.html new file mode 100644 index 0000000000..d49d4e5625 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if12.html @@ -0,0 +1,23 @@ + + + + + Test for Bug 341604 + + + + + I'm a <frame> inside a <frame> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if13.html b/dom/html/test/file_iframe_sandbox_a_if13.html new file mode 100644 index 0000000000..8737a7682e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if13.html @@ -0,0 +1,13 @@ + + + + + Test for Bug 886262 + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if14.html b/dom/html/test/file_iframe_sandbox_a_if14.html new file mode 100644 index 0000000000..b588f7ec50 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if14.html @@ -0,0 +1,34 @@ + + + + + Test for Bug 886262 + + + + + + +I'm a <object> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if15.html b/dom/html/test/file_iframe_sandbox_a_if15.html new file mode 100644 index 0000000000..9c5a003d7c --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if15.html @@ -0,0 +1,33 @@ + + + + + Test for Bug 886262 + + + + + + + I'm a <object> inside a <frame> or <object> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + +
+ First name: + Last name: + +
+ + + diff --git a/dom/html/test/file_iframe_sandbox_a_if16.html b/dom/html/test/file_iframe_sandbox_a_if16.html new file mode 100644 index 0000000000..141d3c2b06 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if16.html @@ -0,0 +1,25 @@ + + + + + Test for Bug 886262 + + + + + + +I'm a <frame> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if17.html b/dom/html/test/file_iframe_sandbox_a_if17.html new file mode 100644 index 0000000000..a736924bf5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if17.html @@ -0,0 +1,27 @@ + + + + + Test for Bug 886262 + + + + + + + I am sandboxed but with "allow-scripts". I change the sandbox flags on if_18_19 to + "allow-scripts allow-same-origin" then get it to re-navigate itself to + file_iframe_sandbox_a_if18.html, which attemps to call a function in my parent. + This should fail since my sandbox flags should be copied to it when the sandbox + flags are changed. + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if18.html b/dom/html/test/file_iframe_sandbox_a_if18.html new file mode 100644 index 0000000000..bbe90970d4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if18.html @@ -0,0 +1,26 @@ + + + + + Test for Bug 886262 + + + + + + + I'm an iframe whose sandbox flags have been changed to include allow-same-origin. + I should not be able to call a function in my parent's parent because my parent's + iframe does not have allow-same-origin set. + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if19.html b/dom/html/test/file_iframe_sandbox_a_if19.html new file mode 100644 index 0000000000..e4d3d68887 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if19.html @@ -0,0 +1,21 @@ + + + + + Test for Bug 886262 + + + + + + + + I'm just here to navigate to file_iframe_sandbox_a_if18.html after my owning + iframe has had allow-same-origin added. + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if2.html b/dom/html/test/file_iframe_sandbox_a_if2.html new file mode 100644 index 0000000000..72bde69e41 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if2.html @@ -0,0 +1,21 @@ + + + + + Test for Bug 341604 + + + + + + + I am NOT sandboxed or am sandboxed with "allow-scripts" but am contained within an iframe sandboxed with sandbox = "" + or am sandboxed with sandbox='' inside an iframe sandboxed with "allow-scripts" + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if3.html b/dom/html/test/file_iframe_sandbox_a_if3.html new file mode 100644 index 0000000000..899c2f1093 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if3.html @@ -0,0 +1,24 @@ + + + + + Test for Bug 341604 + + + + + + + + I am sandboxed but with "allow-scripts" + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if4.html b/dom/html/test/file_iframe_sandbox_a_if4.html new file mode 100644 index 0000000000..a216fb572a --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if4.html @@ -0,0 +1,30 @@ + + + + + Test for Bug 341604 + + + + + + + + I am not sandboxed but contained within a sandboxed document with 'allow-scripts' + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if5.html b/dom/html/test/file_iframe_sandbox_a_if5.html new file mode 100644 index 0000000000..c1081c5039 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if5.html @@ -0,0 +1,22 @@ + + + + + Test for Bug 341604 + + + + + + + + I am sandboxed but with "allow-scripts allow-same-origin" + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if6.html b/dom/html/test/file_iframe_sandbox_a_if6.html new file mode 100644 index 0000000000..62a7114316 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if6.html @@ -0,0 +1,21 @@ + + + + + Test for Bug 341604 + + + + + + + + I am sandboxed with 'allow-scripts allow-same-origin' and contained within a sandboxed document with 'allow-scripts allow-same-origin' + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if7.html b/dom/html/test/file_iframe_sandbox_a_if7.html new file mode 100644 index 0000000000..6480eebdba --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if7.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + + + + I am NOT sandboxed but am contained within an iframe contained within an iframe sandboxed with sandbox = "allow-scripts" + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if8.html b/dom/html/test/file_iframe_sandbox_a_if8.html new file mode 100644 index 0000000000..87748f542a --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if8.html @@ -0,0 +1,26 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed but with "allow-scripts allow-same-origin". After my initial load, "allow-same-origin" is removed + and then I load file_iframe_sandbox_a_if9.html, which attemps to call a function in window.top. This should + succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded. + + + + + diff --git a/dom/html/test/file_iframe_sandbox_a_if9.html b/dom/html/test/file_iframe_sandbox_a_if9.html new file mode 100644 index 0000000000..da2bcf1fa3 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if9.html @@ -0,0 +1,18 @@ + + + + + Test for Bug 341604 + + + + + I'm a subloaded document of file_iframe_sandbox_a_if8.html. I should be able to call a function in window.top + because I should be same-origin with it. + + + diff --git a/dom/html/test/file_iframe_sandbox_b_if1.html b/dom/html/test/file_iframe_sandbox_b_if1.html new file mode 100644 index 0000000000..a65cbec6b9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_b_if1.html @@ -0,0 +1,11 @@ + + + + + Test for Bug 341604 + + + + I am sandboxed without any permissions + + diff --git a/dom/html/test/file_iframe_sandbox_b_if2.html b/dom/html/test/file_iframe_sandbox_b_if2.html new file mode 100644 index 0000000000..08e7453574 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_b_if2.html @@ -0,0 +1,49 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed but with "allow-same-origin" and "allow-scripts" + + diff --git a/dom/html/test/file_iframe_sandbox_b_if3.html b/dom/html/test/file_iframe_sandbox_b_if3.html new file mode 100644 index 0000000000..350e2ac472 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_b_if3.html @@ -0,0 +1,92 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed but with "allow-scripts" + + diff --git a/dom/html/test/file_iframe_sandbox_c_if1.html b/dom/html/test/file_iframe_sandbox_c_if1.html new file mode 100644 index 0000000000..c2fbf136ae --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if1.html @@ -0,0 +1,35 @@ + + + + + Test for Bug 341604 + + + + + + + I am sandboxed but with "allow-scripts" + +
+ First name: + Last name: + +
+ + click me + + diff --git a/dom/html/test/file_iframe_sandbox_c_if2.html b/dom/html/test/file_iframe_sandbox_c_if2.html new file mode 100644 index 0000000000..1ea8a90ca3 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if2.html @@ -0,0 +1,23 @@ + + + + + Test for Bug 341604 + + + + + + + I am sandboxed with no permissions + + + diff --git a/dom/html/test/file_iframe_sandbox_c_if3.html b/dom/html/test/file_iframe_sandbox_c_if3.html new file mode 100644 index 0000000000..fdf98d93d4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if3.html @@ -0,0 +1,26 @@ + + + + + Test for Bug 341604 + + + + + + + I am sandboxed but with "allow-scripts allow-forms" + +
+ First name: + Last name: + +
+ + diff --git a/dom/html/test/file_iframe_sandbox_c_if4.html b/dom/html/test/file_iframe_sandbox_c_if4.html new file mode 100644 index 0000000000..ee2438f28a --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if4.html @@ -0,0 +1,36 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed but with "allow-scripts allow-same-origin" + + open window + open window + + diff --git a/dom/html/test/file_iframe_sandbox_c_if5.html b/dom/html/test/file_iframe_sandbox_c_if5.html new file mode 100644 index 0000000000..bd368de425 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if5.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + + + + I am sandboxed but with "allow-same-origin" + + click me + + diff --git a/dom/html/test/file_iframe_sandbox_c_if6.html b/dom/html/test/file_iframe_sandbox_c_if6.html new file mode 100644 index 0000000000..e5ecf3051e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if6.html @@ -0,0 +1,24 @@ + + + + + Test for Bug 341604 + + + + + + + I am sandboxed but with "allow-same-origin" and "allow-scripts" + + diff --git a/dom/html/test/file_iframe_sandbox_c_if7.html b/dom/html/test/file_iframe_sandbox_c_if7.html new file mode 100644 index 0000000000..b9a55def6f --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if7.html @@ -0,0 +1,27 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed but with "allow-scripts" + + diff --git a/dom/html/test/file_iframe_sandbox_c_if8.html b/dom/html/test/file_iframe_sandbox_c_if8.html new file mode 100644 index 0000000000..d8b8948466 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if8.html @@ -0,0 +1,27 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed but with "allow-scripts allow-same-origin" + + diff --git a/dom/html/test/file_iframe_sandbox_c_if9.html b/dom/html/test/file_iframe_sandbox_c_if9.html new file mode 100644 index 0000000000..0c88a677cb --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if9.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 671389 + + + + I am +
    +
  • sandboxed but with "allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", and "allow-top-navigation",
  • +
  • sandboxed but with "allow-same-origin", "allow-scripts",
  • +
  • sandboxed, or
  • +
  • not sandboxed.
  • +
+ + diff --git a/dom/html/test/file_iframe_sandbox_close.html b/dom/html/test/file_iframe_sandbox_close.html new file mode 100644 index 0000000000..3b87534978 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_close.html @@ -0,0 +1,3 @@ + diff --git a/dom/html/test/file_iframe_sandbox_d_if1.html b/dom/html/test/file_iframe_sandbox_d_if1.html new file mode 100644 index 0000000000..744594e813 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if1.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if10.html b/dom/html/test/file_iframe_sandbox_d_if10.html new file mode 100644 index 0000000000..41fb46b586 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if10.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts' + + diff --git a/dom/html/test/file_iframe_sandbox_d_if11.html b/dom/html/test/file_iframe_sandbox_d_if11.html new file mode 100644 index 0000000000..63880587f5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if11.html @@ -0,0 +1,30 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts' + CLICK ME + + diff --git a/dom/html/test/file_iframe_sandbox_d_if12.html b/dom/html/test/file_iframe_sandbox_d_if12.html new file mode 100644 index 0000000000..0d7936512e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if12.html @@ -0,0 +1,16 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed with 'allow-scripts' + + diff --git a/dom/html/test/file_iframe_sandbox_d_if13.html b/dom/html/test/file_iframe_sandbox_d_if13.html new file mode 100644 index 0000000000..361c1e0e95 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if13.html @@ -0,0 +1,35 @@ + + + + + Test for Bug 341604 + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if14.html b/dom/html/test/file_iframe_sandbox_d_if14.html new file mode 100644 index 0000000000..237a9d704f --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if14.html @@ -0,0 +1,35 @@ + + + + + Tests for Bug 838692 + + + + + + + + I am sandboxed but with "allow-scripts allow-same-origin allow-top-navigation". + + navigate window + + diff --git a/dom/html/test/file_iframe_sandbox_d_if15.html b/dom/html/test/file_iframe_sandbox_d_if15.html new file mode 100644 index 0000000000..6c969c8fe1 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if15.html @@ -0,0 +1,14 @@ + + + + + Test for Bug 838692 + + + + + I am an unsandboxed iframe. + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if16.html b/dom/html/test/file_iframe_sandbox_d_if16.html new file mode 100644 index 0000000000..e50dd97ea0 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if16.html @@ -0,0 +1,22 @@ + + + + + Test for Bug 838692 + + + + + + + + I am sandboxed with 'allow-same-origin allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if17.html b/dom/html/test/file_iframe_sandbox_d_if17.html new file mode 100644 index 0000000000..047a08137d --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if17.html @@ -0,0 +1,24 @@ + + + + + Test for Bug 838692 + + + + + + + I am sandboxed with 'allow-scripts' + + diff --git a/dom/html/test/file_iframe_sandbox_d_if18.html b/dom/html/test/file_iframe_sandbox_d_if18.html new file mode 100644 index 0000000000..fdcb4198f4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if18.html @@ -0,0 +1,33 @@ + + + + + Test for Bug 838692 + + + + + + + + I am sandboxed with 'allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if19.html b/dom/html/test/file_iframe_sandbox_d_if19.html new file mode 100644 index 0000000000..d766d26492 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if19.html @@ -0,0 +1,13 @@ + + + + + Test for Bug 838692 + + + + I am sandboxed with 'allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if2.html b/dom/html/test/file_iframe_sandbox_d_if2.html new file mode 100644 index 0000000000..b45cb975ca --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if2.html @@ -0,0 +1,28 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts' + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if20.html b/dom/html/test/file_iframe_sandbox_d_if20.html new file mode 100644 index 0000000000..005c4bc823 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if20.html @@ -0,0 +1,25 @@ + + + + + Test for Bug 838692 + + + + + + + I am sandboxed with 'allow-scripts' + + diff --git a/dom/html/test/file_iframe_sandbox_d_if21.html b/dom/html/test/file_iframe_sandbox_d_if21.html new file mode 100644 index 0000000000..6d0ab232e0 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if21.html @@ -0,0 +1,14 @@ + + + + + Test for Bug 838692 + + + + + I am an unsandboxed iframe. + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if22.html b/dom/html/test/file_iframe_sandbox_d_if22.html new file mode 100644 index 0000000000..bd27157926 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if22.html @@ -0,0 +1,25 @@ + + + + + Test for Bug 838692 + + + + + + + I am sandboxed with 'allow-same-origin allow-scripts' + + diff --git a/dom/html/test/file_iframe_sandbox_d_if23.html b/dom/html/test/file_iframe_sandbox_d_if23.html new file mode 100644 index 0000000000..e755511e37 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if23.html @@ -0,0 +1,61 @@ + + + + + Test for Bug 838692 + + + + + + + + I am sandboxed with 'allow-scripts allow-popups' + + Test 27 anchor + + diff --git a/dom/html/test/file_iframe_sandbox_d_if3.html b/dom/html/test/file_iframe_sandbox_d_if3.html new file mode 100644 index 0000000000..cd2d53bce9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if3.html @@ -0,0 +1,13 @@ + + + + + Test for Bug 341604 + + + + I am sandboxed with 'allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if4.html b/dom/html/test/file_iframe_sandbox_d_if4.html new file mode 100644 index 0000000000..c11a414551 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if4.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if5.html b/dom/html/test/file_iframe_sandbox_d_if5.html new file mode 100644 index 0000000000..d8fe4289af --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if5.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts allow-same-origin' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if6.html b/dom/html/test/file_iframe_sandbox_d_if6.html new file mode 100644 index 0000000000..9bb48cbb20 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if6.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_d_if7.html b/dom/html/test/file_iframe_sandbox_d_if7.html new file mode 100644 index 0000000000..5023ee0294 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if7.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed with 'allow-scripts' + + diff --git a/dom/html/test/file_iframe_sandbox_d_if8.html b/dom/html/test/file_iframe_sandbox_d_if8.html new file mode 100644 index 0000000000..2b4398ef00 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if8.html @@ -0,0 +1,18 @@ + + + + + Test for Bug 341604 + + + + + + + I am sandboxed with 'allow-scripts' and 'allow-same-origin' the first time I am loaded, and with 'allow-scripts' the second time + + diff --git a/dom/html/test/file_iframe_sandbox_d_if9.html b/dom/html/test/file_iframe_sandbox_d_if9.html new file mode 100644 index 0000000000..ee641904fc --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if9.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed with 'allow-scripts' and 'allow-same-origin' the first time I am loaded, and with 'allow-same-origin' the second time + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if1.html b/dom/html/test/file_iframe_sandbox_e_if1.html new file mode 100644 index 0000000000..e3882dfb28 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if1.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if10.html b/dom/html/test/file_iframe_sandbox_e_if10.html new file mode 100644 index 0000000000..2484b8f342 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if10.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 838692 + + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if11.html b/dom/html/test/file_iframe_sandbox_e_if11.html new file mode 100644 index 0000000000..106c4c629b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if11.html @@ -0,0 +1,22 @@ + + + + + Test for Bug 838692 + + + + + I am sandboxed with 'allow-scripts and allow-top-navigation' + + diff --git a/dom/html/test/file_iframe_sandbox_e_if12.html b/dom/html/test/file_iframe_sandbox_e_if12.html new file mode 100644 index 0000000000..0b1b87e09b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if12.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 838692 + + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if13.html b/dom/html/test/file_iframe_sandbox_e_if13.html new file mode 100644 index 0000000000..f5cf912f67 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if13.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 838692 + + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if14.html b/dom/html/test/file_iframe_sandbox_e_if14.html new file mode 100644 index 0000000000..76d9787020 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if14.html @@ -0,0 +1,24 @@ + + + + + Test for Bug 838692 + + + + + I am sandboxed with 'allow-scripts' + + diff --git a/dom/html/test/file_iframe_sandbox_e_if15.html b/dom/html/test/file_iframe_sandbox_e_if15.html new file mode 100644 index 0000000000..bf4138e1d6 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if15.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 838692 + + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if16.html b/dom/html/test/file_iframe_sandbox_e_if16.html new file mode 100644 index 0000000000..06c8bf8714 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if16.html @@ -0,0 +1,27 @@ + + + + + Tests for Bug 838692 + + + + + + + I am sandboxed but with "allow-scripts" + + diff --git a/dom/html/test/file_iframe_sandbox_e_if2.html b/dom/html/test/file_iframe_sandbox_e_if2.html new file mode 100644 index 0000000000..739dbacbd5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if2.html @@ -0,0 +1,12 @@ + + + + + Test for Bug 341604 + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if3.html b/dom/html/test/file_iframe_sandbox_e_if3.html new file mode 100644 index 0000000000..ce010e6893 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if3.html @@ -0,0 +1,11 @@ + + + + + Test for Bug 341604 + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if4.html b/dom/html/test/file_iframe_sandbox_e_if4.html new file mode 100644 index 0000000000..740a33a94d --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if4.html @@ -0,0 +1,11 @@ + + + + + Test for Bug 341604 + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if5.html b/dom/html/test/file_iframe_sandbox_e_if5.html new file mode 100644 index 0000000000..e550df45e5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if5.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed with 'allow-scripts and allow-top-navigation' + + Click me + + diff --git a/dom/html/test/file_iframe_sandbox_e_if6.html b/dom/html/test/file_iframe_sandbox_e_if6.html new file mode 100644 index 0000000000..399c3c202b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if6.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + + I am sandboxed with 'allow-scripts' + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if7.html b/dom/html/test/file_iframe_sandbox_e_if7.html new file mode 100644 index 0000000000..9d60ed2dbc --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if7.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 838692 + + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_e_if8.html b/dom/html/test/file_iframe_sandbox_e_if8.html new file mode 100644 index 0000000000..97699abba9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if8.html @@ -0,0 +1,23 @@ + + + + + Tests for Bug 838692 + + + + + + + + I am sandboxed but with "allow-scripts" + + navigate top + + diff --git a/dom/html/test/file_iframe_sandbox_e_if9.html b/dom/html/test/file_iframe_sandbox_e_if9.html new file mode 100644 index 0000000000..f18a16dba6 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if9.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 838692 + + + + + + + + + diff --git a/dom/html/test/file_iframe_sandbox_fail.js b/dom/html/test/file_iframe_sandbox_fail.js new file mode 100644 index 0000000000..1f1290d046 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_fail.js @@ -0,0 +1,4 @@ +ok( + false, + "documents sandboxed with allow-scripts should NOT be able to run + + + + + I should NOT be loaded by a form submit from a sandbox without 'allow-forms' + + + + \ No newline at end of file diff --git a/dom/html/test/file_iframe_sandbox_form_pass.html b/dom/html/test/file_iframe_sandbox_form_pass.html new file mode 100644 index 0000000000..1ba8853fa5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_form_pass.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 341604 + + + + I should be loaded by a form submit from a sandbox with 'allow-forms' + + + + \ No newline at end of file diff --git a/dom/html/test/file_iframe_sandbox_g_if1.html b/dom/html/test/file_iframe_sandbox_g_if1.html new file mode 100644 index 0000000000..67604f1f64 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_g_if1.html @@ -0,0 +1,60 @@ + + + + + Test for Bug 341604 + + + + + + I am sandboxed but with "allow-scripts" + + diff --git a/dom/html/test/file_iframe_sandbox_h_if1.html b/dom/html/test/file_iframe_sandbox_h_if1.html new file mode 100644 index 0000000000..7c5cada2dc --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_h_if1.html @@ -0,0 +1,34 @@ + + + + + Tests for Bug 766282 + + + + + + + I am sandboxed but with "allow-popups allow-scripts allow-same-origin" + + open window + open window + + diff --git a/dom/html/test/file_iframe_sandbox_k_if1.html b/dom/html/test/file_iframe_sandbox_k_if1.html new file mode 100644 index 0000000000..f6f1238085 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if1.html @@ -0,0 +1,47 @@ + + + + + Test for Bug 766282 + + + + + + I am navigated to from file_iframe_sandbox_k_if8.html. + This was opened in an iframe with "allow-scripts allow-popups allow-same-origin". + However allow-same-origin was removed from the iframe before navigating to me, + so I should only have "allow-scripts allow-popups" in force. + open window + open window + + diff --git a/dom/html/test/file_iframe_sandbox_k_if2.html b/dom/html/test/file_iframe_sandbox_k_if2.html new file mode 100644 index 0000000000..dce42aef54 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if2.html @@ -0,0 +1,50 @@ + + + + + Test for Bug 766282 + + + + + + + I am not sandboxed directly, but opened from a sandboxed document with 'allow-scripts allow-popups' + +
+ First name: + Last name: + +
+ + + + + diff --git a/dom/html/test/file_iframe_sandbox_k_if3.html b/dom/html/test/file_iframe_sandbox_k_if3.html new file mode 100644 index 0000000000..a2619dd006 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if3.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 766282 + + + + + + I am sandboxed with 'allow-scripts allow-popups' + + + + diff --git a/dom/html/test/file_iframe_sandbox_k_if4.html b/dom/html/test/file_iframe_sandbox_k_if4.html new file mode 100644 index 0000000000..3d030158dc --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if4.html @@ -0,0 +1,34 @@ + + + + + Test for Bug 766282 + + + + + + + + I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation". + open window + open window + + open window + open window + + diff --git a/dom/html/test/file_iframe_sandbox_k_if5.html b/dom/html/test/file_iframe_sandbox_k_if5.html new file mode 100644 index 0000000000..8deb65852f --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if5.html @@ -0,0 +1,33 @@ + + + + + Test for Bug 766282 + + + + + + + I am not sandboxed directly, but opened from a sandboxed document with at least + 'allow-scripts allow-popups allow-same-origin allow-top-navigation' + + + + + diff --git a/dom/html/test/file_iframe_sandbox_k_if6.html b/dom/html/test/file_iframe_sandbox_k_if6.html new file mode 100644 index 0000000000..53ed080e3e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if6.html @@ -0,0 +1,21 @@ + + + + + Test for Bug 766282 + + + + + + + + I am sandboxed with at least 'allow-scripts allow-popups allow-top-navigation' + + + + diff --git a/dom/html/test/file_iframe_sandbox_k_if7.html b/dom/html/test/file_iframe_sandbox_k_if7.html new file mode 100644 index 0000000000..269e31eb5b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if7.html @@ -0,0 +1,26 @@ + + + + + Test for Bug 766282 + + + + + + + I am not sandboxed directly, but opened from a sandboxed document with at least + 'allow-scripts allow-popups allow-forms allow-same-origin' + +
+ First name: + Last name: + +
+ + diff --git a/dom/html/test/file_iframe_sandbox_k_if8.html b/dom/html/test/file_iframe_sandbox_k_if8.html new file mode 100644 index 0000000000..e4aad97f3b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if8.html @@ -0,0 +1,36 @@ + + + + + Test for Bug 766282 + + + + + + + + I am sandboxed but with "allow-scripts allow-popups allow-same-origin". + After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html + in 3 different ways, which attemps to call a function in my parent. + This should succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded. +
open window + open window + + Now navigate to file_iframe_sandbox_k_if1.html to do tests for a sandbox opening a window + when only "allow-scripts allow-popups" are specified. + navigate to if1 + + diff --git a/dom/html/test/file_iframe_sandbox_k_if9.html b/dom/html/test/file_iframe_sandbox_k_if9.html new file mode 100644 index 0000000000..56e8db3f9a --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if9.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 766282 + + + + + + + I'm a window opened from the sandboxed document of file_iframe_sandbox_k_if8.html. + I should be able to call ok_wrapper in main test page directly because I should be same-origin with it. + + diff --git a/dom/html/test/file_iframe_sandbox_navigation_fail.html b/dom/html/test/file_iframe_sandbox_navigation_fail.html new file mode 100644 index 0000000000..bae5276bd1 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_navigation_fail.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 341604 + + + +FAIL + + + diff --git a/dom/html/test/file_iframe_sandbox_navigation_pass.html b/dom/html/test/file_iframe_sandbox_navigation_pass.html new file mode 100644 index 0000000000..e07248247b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_navigation_pass.html @@ -0,0 +1,17 @@ + + + + + Test for Bug 341604 + + + + +PASS + + diff --git a/dom/html/test/file_iframe_sandbox_navigation_start.html b/dom/html/test/file_iframe_sandbox_navigation_start.html new file mode 100644 index 0000000000..fa56425177 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_navigation_start.html @@ -0,0 +1,11 @@ + + + + + Test for Bug 341604 + + + +I am just a normal HTML document, probably contained in a sandboxed iframe + + diff --git a/dom/html/test/file_iframe_sandbox_open_window_fail.html b/dom/html/test/file_iframe_sandbox_open_window_fail.html new file mode 100644 index 0000000000..64e0d36180 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_open_window_fail.html @@ -0,0 +1,19 @@ + + + + + Test for Bug 341604 + + + + + I should NOT be opened by a sandboxed iframe via any method + + + + diff --git a/dom/html/test/file_iframe_sandbox_open_window_pass.html b/dom/html/test/file_iframe_sandbox_open_window_pass.html new file mode 100644 index 0000000000..ac45c7fd32 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_open_window_pass.html @@ -0,0 +1,25 @@ + + + + + Test for Bug 766282 + + + + + I should be opened by a sandboxed iframe via any method when "allow-popups" is specified. + + + + diff --git a/dom/html/test/file_iframe_sandbox_pass.js b/dom/html/test/file_iframe_sandbox_pass.js new file mode 100644 index 0000000000..15b3e7d3ff --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_pass.js @@ -0,0 +1,4 @@ +ok( + true, + "documents sandboxed with allow-scripts should be able to run + +I have been redirected diff --git a/dom/html/test/file_iframe_sandbox_refresh.html b/dom/html/test/file_iframe_sandbox_refresh.html new file mode 100644 index 0000000000..1fad80c428 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_refresh.html @@ -0,0 +1,2 @@ + +refresh diff --git a/dom/html/test/file_iframe_sandbox_refresh.html^headers^ b/dom/html/test/file_iframe_sandbox_refresh.html^headers^ new file mode 100644 index 0000000000..a7cc383b4f --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_refresh.html^headers^ @@ -0,0 +1 @@ +Refresh: 0 url=data:text/html,Refreshed diff --git a/dom/html/test/file_iframe_sandbox_srcdoc_allow_scripts.html b/dom/html/test/file_iframe_sandbox_srcdoc_allow_scripts.html new file mode 100644 index 0000000000..7d585be04f --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_srcdoc_allow_scripts.html @@ -0,0 +1 @@ + diff --git a/dom/html/test/file_iframe_sandbox_srcdoc_no_allow_scripts.html b/dom/html/test/file_iframe_sandbox_srcdoc_no_allow_scripts.html new file mode 100644 index 0000000000..b6faf83cc9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_srcdoc_no_allow_scripts.html @@ -0,0 +1 @@ + diff --git a/dom/html/test/file_iframe_sandbox_top_navigation_fail.html b/dom/html/test/file_iframe_sandbox_top_navigation_fail.html new file mode 100644 index 0000000000..dad6b2c006 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_top_navigation_fail.html @@ -0,0 +1,18 @@ + + + + + Test for Bug 341604 + + + + +FAIL\ + + diff --git a/dom/html/test/file_iframe_sandbox_top_navigation_pass.html b/dom/html/test/file_iframe_sandbox_top_navigation_pass.html new file mode 100644 index 0000000000..712240ecb2 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_top_navigation_pass.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 341604 + + + + +PASS + + diff --git a/dom/html/test/file_iframe_sandbox_window_form_fail.html b/dom/html/test/file_iframe_sandbox_window_form_fail.html new file mode 100644 index 0000000000..2d678b3ac9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_form_fail.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 766282 + + + + + I should NOT be loaded by a form submit from a window opened from a sandbox without 'allow-forms'. + + + + diff --git a/dom/html/test/file_iframe_sandbox_window_form_pass.html b/dom/html/test/file_iframe_sandbox_window_form_pass.html new file mode 100644 index 0000000000..dd2656c1ec --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_form_pass.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 766282 + + + + + + + I should be loaded by a form submit from a window opened from a sandbox with 'allow-forms allow-same-origin'. + + diff --git a/dom/html/test/file_iframe_sandbox_window_navigation_fail.html b/dom/html/test/file_iframe_sandbox_window_navigation_fail.html new file mode 100644 index 0000000000..f8e3c83ce8 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_navigation_fail.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 838692 + + + + + + +FAIL + + diff --git a/dom/html/test/file_iframe_sandbox_window_navigation_pass.html b/dom/html/test/file_iframe_sandbox_window_navigation_pass.html new file mode 100644 index 0000000000..a1bff9eb83 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_navigation_pass.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 766282 + + + + + + +PASS + + diff --git a/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html b/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html new file mode 100644 index 0000000000..af50476045 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html @@ -0,0 +1,24 @@ + + + + + Test for Bug 766282 + + + + +FAIL + + diff --git a/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html b/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html new file mode 100644 index 0000000000..d3637fb04e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 766282 + + + + + + + I am navigated to from a window opened from a sandbox with allow-top-navigation. + + diff --git a/dom/html/test/file_iframe_sandbox_worker.js b/dom/html/test/file_iframe_sandbox_worker.js new file mode 100644 index 0000000000..3cb9f650dc --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_worker.js @@ -0,0 +1,3 @@ +self.onmessage = function (event) { + self.postMessage("make it so"); +}; diff --git a/dom/html/test/file_refresh_after_document_write.html b/dom/html/test/file_refresh_after_document_write.html new file mode 100644 index 0000000000..ebf3272e08 --- /dev/null +++ b/dom/html/test/file_refresh_after_document_write.html @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/dom/html/test/forms/file_login_fields.html b/dom/html/test/forms/file_login_fields.html new file mode 100644 index 0000000000..f23ee0ad6a --- /dev/null +++ b/dom/html/test/forms/file_login_fields.html @@ -0,0 +1,16 @@ + + + + + + + + + + Navigate + Back + + diff --git a/dom/html/test/forms/mochitest.ini b/dom/html/test/forms/mochitest.ini new file mode 100644 index 0000000000..ab67dc6091 --- /dev/null +++ b/dom/html/test/forms/mochitest.ini @@ -0,0 +1,121 @@ +[DEFAULT] +support-files = + save_restore_radio_groups.sjs + test_input_number_data.js + !/dom/html/test/reflect.js + FAIL.html + PASS.html +prefs = + formhelper.autozoom.force-disable.test-only=true + +[test_autocomplete.html] +[test_bug1039548.html] +[test_bug1283915.html] +[test_bug1286509.html] +[test_button_attributes_reflection.html] +[test_input_radio_indeterminate.html] +[test_input_radio_radiogroup.html] +[test_input_radio_required.html] +[test_change_event.html] +[test_datalist_element.html] +[test_double_submit.html] +support-files = file_double_submit.html +[test_form_attribute-1.html] +[test_form_attribute-2.html] +[test_form_attribute-3.html] +[test_form_attribute-4.html] +[test_form_attributes_reflection.html] +[test_form_named_getter_dynamic.html] +[test_formaction_attribute.html] +[test_formnovalidate_attribute.html] +[test_input_attributes_reflection.html] +[test_input_color_input_change_events.html] +[test_input_color_picker_datalist.html] +[test_input_color_picker_initial.html] +[test_input_color_picker_popup.html] +[test_input_color_picker_update.html] +[test_input_date_bad_input.html] +[test_input_date_key_events.html] +[test_input_datetime_input_change_events.html] +[test_input_datetime_disabled_focus.html] +[test_input_datetime_focus_blur.html] +[test_input_datetime_focus_blur_events.html] +[test_input_datetime_focus_state.html] +[test_input_datetime_hidden.html] +[test_input_datetime_readonly.html] +[test_input_datetime_calendar_button.html] +[test_input_datetime_reset_default_value_input_change_event.html] +[test_input_datetime_tabindex.html] +[test_input_defaultValue.html] +[test_input_email.html] +[test_input_event.html] +[test_input_file_picker.html] +[test_input_hasBeenTypePassword.html] +[test_input_hasBeenTypePassword_navigation.html] +support-files = file_login_fields.html +[test_input_list_attribute.html] +[test_input_number_l10n.html] +[test_input_number_key_events.html] +[test_input_number_mouse_events.html] +# Not run on Firefox for Android where the spin buttons are hidden: +skip-if = os == "android" + (os == "mac" && debug) # Bug 1484442 +[test_input_number_rounding.html] +[test_input_number_validation.html] +[test_input_number_focus.html] +[test_input_number_placeholder_shown.html] +[test_input_range_attr_order.html] +[test_input_range_key_events.html] +[test_input_range_mouse_and_touch_events.html] +[test_input_range_rounding.html] +[test_input_sanitization.html] +[test_input_setting_value.html] +[test_input_textarea_set_value_no_scroll.html] +[test_input_time_key_events.html] +[test_input_time_sec_millisec_field.html] +[test_input_types_pref.html] +[test_input_typing_sanitization.html] +[test_input_untrusted_key_events.html] +[test_input_url.html] +[test_interactive_content_in_label.html] +[test_interactive_content_in_summary.html] +[test_label_control_attribute.html] +[test_label_input_controls.html] +[test_max_attribute.html] +[test_maxlength_attribute.html] +[test_minlength_attribute.html] +[test_meter_element.html] +[test_meter_pseudo-classes.html] +[test_min_attribute.html] +[test_MozEditableElement_setUserInput.html] +[test_mozistextfield.html] +[test_novalidate_attribute.html] +[test_option_disabled.html] +[test_option_index_attribute.html] +[test_option_text.html] +[test_output_element.html] +[test_pattern_attribute.html] +[test_preserving_metadata_between_reloads.html] +[test_progress_element.html] +[test_radio_in_label.html] +[test_radio_radionodelist.html] +[test_required_attribute.html] +[test_restore_form_elements.html] +[test_save_restore_radio_groups.html] +[test_select_change_event.html] +skip-if = os == 'mac' +[test_select_input_change_event.html] +skip-if = os == 'mac' +[test_select_selectedOptions.html] +[test_select_validation.html] +[test_set_range_text.html] +[test_step_attribute.html] +[test_stepup_stepdown.html] +[test_textarea_attributes_reflection.html] +[test_validation.html] +[test_valueasdate_attribute.html] +[test_valueasnumber_attribute.html] +[test_validation_not_in_doc.html] +[test_reportValidation_preventDefault.html] +[test_input_password_show_password_button.html] +[test_input_password_click_show_password_button.html] diff --git a/dom/html/test/forms/save_restore_radio_groups.sjs b/dom/html/test/forms/save_restore_radio_groups.sjs new file mode 100644 index 0000000000..b4c9c4401a --- /dev/null +++ b/dom/html/test/forms/save_restore_radio_groups.sjs @@ -0,0 +1,48 @@ +var pages = [ + "" + + "" + + "
" + + "" + + "
" + + "", + "" + + "" + + "
" + + "" + + "
" + + "", +]; + +/** + * This SJS is going to send the same page the two first times it will be called + * and another page the two following times. After that, the response will have + * no content. + * The use case is to have two iframes using this SJS and both being reloaded + * once. + */ + +function handleRequest(request, response) { + var counter = +getState("counter"); // convert to number; +"" === 0 + + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/html"); + response.setHeader("Cache-Control", "no-cache"); + + switch (counter) { + case 0: + case 1: + response.write(pages[0]); + break; + case 2: + case 3: + response.write(pages[1]); + break; + } + + // When we finish the test case we need to reset the counter + if (counter == 3) { + setState("counter", "0"); + } else { + setState("counter", "" + ++counter); + } +} diff --git a/dom/html/test/forms/submit_invalid_file.sjs b/dom/html/test/forms/submit_invalid_file.sjs new file mode 100644 index 0000000000..3b4b576ec6 --- /dev/null +++ b/dom/html/test/forms/submit_invalid_file.sjs @@ -0,0 +1,13 @@ +function handleRequest(request, response) { + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/html"); + response.setHeader("Cache-Control", "no-cache"); + + var result = {}; + request.bodyInputStream.search("testfile", true, result, {}); + if (result.value) { + response.write("SUCCESS"); + } else { + response.write("FAIL"); + } +} diff --git a/dom/html/test/forms/test_MozEditableElement_setUserInput.html b/dom/html/test/forms/test_MozEditableElement_setUserInput.html new file mode 100644 index 0000000000..06380776f6 --- /dev/null +++ b/dom/html/test/forms/test_MozEditableElement_setUserInput.html @@ -0,0 +1,581 @@ + + + + Test for MozEditableElement.setUserInput() + + + + + +
+
+
+
+
+ + + + diff --git a/dom/html/test/forms/test_autocomplete.html b/dom/html/test/forms/test_autocomplete.html new file mode 100644 index 0000000000..de92254386 --- /dev/null +++ b/dom/html/test/forms/test_autocomplete.html @@ -0,0 +1,137 @@ + + + + + Test for @autocomplete + + + + + + +

+ +
+
+ + diff --git a/dom/html/test/forms/test_autocompleteinfo.html b/dom/html/test/forms/test_autocompleteinfo.html new file mode 100644 index 0000000000..5f8673d9ba --- /dev/null +++ b/dom/html/test/forms/test_autocompleteinfo.html @@ -0,0 +1,177 @@ + + + + + Test for getAutocompleteInfo() + + + + + +

+ +
+
+ + diff --git a/dom/html/test/forms/test_bug1283915.html b/dom/html/test/forms/test_bug1283915.html new file mode 100644 index 0000000000..90bffd4b20 --- /dev/null +++ b/dom/html/test/forms/test_bug1283915.html @@ -0,0 +1,67 @@ + + + + + + Test for Bug 1283915 + + + + + + +Mozilla Bug 1283915 +

+ + +
+
+ + diff --git a/dom/html/test/forms/test_bug1286509.html b/dom/html/test/forms/test_bug1286509.html new file mode 100644 index 0000000000..638e7fe85c --- /dev/null +++ b/dom/html/test/forms/test_bug1286509.html @@ -0,0 +1,49 @@ + + + + + + Test for Bug 1286509 + + + + + +Mozilla Bug 1286509 +

+
+ +
+
+  
+
+ + diff --git a/dom/html/test/forms/test_button_attributes_reflection.html b/dom/html/test/forms/test_button_attributes_reflection.html new file mode 100644 index 0000000000..9bc72ada72 --- /dev/null +++ b/dom/html/test/forms/test_button_attributes_reflection.html @@ -0,0 +1,161 @@ + + + + Test for HTMLButtonElement attributes reflection + + + + + +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_change_event.html b/dom/html/test/forms/test_change_event.html new file mode 100644 index 0000000000..8be4554c58 --- /dev/null +++ b/dom/html/test/forms/test_change_event.html @@ -0,0 +1,286 @@ + + + + +Test for Bug 722599 + + + + + +Mozilla Bug 722599 +

+
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_datalist_element.html b/dom/html/test/forms/test_datalist_element.html new file mode 100644 index 0000000000..5f05634018 --- /dev/null +++ b/dom/html/test/forms/test_datalist_element.html @@ -0,0 +1,118 @@ + + + + Test for the datalist element + + + + +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_double_submit.html b/dom/html/test/forms/test_double_submit.html new file mode 100644 index 0000000000..d27fb290a4 --- /dev/null +++ b/dom/html/test/forms/test_double_submit.html @@ -0,0 +1,33 @@ + + + + Test for multiple submissions in straightline code + + + + + + + diff --git a/dom/html/test/forms/test_form_attribute-1.html b/dom/html/test/forms/test_form_attribute-1.html new file mode 100644 index 0000000000..6735f514ae --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-1.html @@ -0,0 +1,473 @@ + + + + + Test for form attributes 1 + + + + +Mozilla Bug 588683 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_form_attribute-2.html b/dom/html/test/forms/test_form_attribute-2.html new file mode 100644 index 0000000000..b7fe5daa87 --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-2.html @@ -0,0 +1,53 @@ + + + + + Test for form attributes 2 + + + + +Mozilla Bug 588683 +

+ + + diff --git a/dom/html/test/forms/test_form_attribute-3.html b/dom/html/test/forms/test_form_attribute-3.html new file mode 100644 index 0000000000..9ceed86716 --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-3.html @@ -0,0 +1,68 @@ + + + + + Test for form attributes 3 + + + + +Mozilla Bug 588683 +

+
+
+ +
+
+ + + + +
+ + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_form_attribute-4.html b/dom/html/test/forms/test_form_attribute-4.html new file mode 100644 index 0000000000..f2228cec45 --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-4.html @@ -0,0 +1,48 @@ + + + + + Test for form attributes 4 + + + + +Mozilla Bug 588683 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_form_attributes_reflection.html b/dom/html/test/forms/test_form_attributes_reflection.html new file mode 100644 index 0000000000..0d0ef6b870 --- /dev/null +++ b/dom/html/test/forms/test_form_attributes_reflection.html @@ -0,0 +1,90 @@ + + + + Test for HTMLFormElement attributes reflection + + + + + +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_form_named_getter_dynamic.html b/dom/html/test/forms/test_form_named_getter_dynamic.html new file mode 100644 index 0000000000..4a19768453 --- /dev/null +++ b/dom/html/test/forms/test_form_named_getter_dynamic.html @@ -0,0 +1,54 @@ + + + + + Test for Bug 377413 + + + + + +Mozilla Bug 377413 +

+
+
+ + + +
+
+
+ + + + diff --git a/dom/html/test/forms/test_formaction_attribute.html b/dom/html/test/forms/test_formaction_attribute.html new file mode 100644 index 0000000000..0dee2f172d --- /dev/null +++ b/dom/html/test/forms/test_formaction_attribute.html @@ -0,0 +1,169 @@ + + + + + Test for Bug 566160 + + + + + +Mozilla Bug 566160 +

+ + + + + + + + + +
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+ + +
+ +
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_formnovalidate_attribute.html b/dom/html/test/forms/test_formnovalidate_attribute.html new file mode 100644 index 0000000000..2e3714d2fe --- /dev/null +++ b/dom/html/test/forms/test_formnovalidate_attribute.html @@ -0,0 +1,125 @@ + + + + + Test for Bug 589696 + + + + + +Mozilla Bug 589696 +

+ +
+ +
+ + + +
+
+ + + +
+ +
+ +
+ +
+ + +
+
+ + +
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_attributes_reflection.html b/dom/html/test/forms/test_input_attributes_reflection.html new file mode 100644 index 0000000000..88aeb7f16f --- /dev/null +++ b/dom/html/test/forms/test_input_attributes_reflection.html @@ -0,0 +1,269 @@ + + + + Test for HTMLInputElement attributes reflection + + + + + +

+
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_color_input_change_events.html b/dom/html/test/forms/test_input_color_input_change_events.html new file mode 100644 index 0000000000..f97d54f66e --- /dev/null +++ b/dom/html/test/forms/test_input_color_input_change_events.html @@ -0,0 +1,119 @@ + + + + + + Test for Bug 1234567 + + + + + + +Mozilla Bug 885996 +

+
+ + + + +
+
+
+ + diff --git a/dom/html/test/forms/test_input_color_picker_datalist.html b/dom/html/test/forms/test_input_color_picker_datalist.html new file mode 100644 index 0000000000..1a268c0701 --- /dev/null +++ b/dom/html/test/forms/test_input_color_picker_datalist.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dom/html/test/forms/test_input_color_picker_initial.html b/dom/html/test/forms/test_input_color_picker_initial.html new file mode 100644 index 0000000000..c7467c7520 --- /dev/null +++ b/dom/html/test/forms/test_input_color_picker_initial.html @@ -0,0 +1,78 @@ + + + + + + Test for Bug 1234567 + + + + + + +Mozilla Bug 885996 +

+
+
+ + + + +
+
+ + + +
+
+ + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_color_picker_popup.html b/dom/html/test/forms/test_input_color_picker_popup.html new file mode 100644 index 0000000000..9fbebf15bc --- /dev/null +++ b/dom/html/test/forms/test_input_color_picker_popup.html @@ -0,0 +1,144 @@ + + + + + + Test for Bug 1234567 + + + + + + + +Mozilla Bug 885996 +

+
+ + + + + + + + + + +
click
+
click
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_color_picker_update.html b/dom/html/test/forms/test_input_color_picker_update.html new file mode 100644 index 0000000000..5c22b667e1 --- /dev/null +++ b/dom/html/test/forms/test_input_color_picker_update.html @@ -0,0 +1,86 @@ + + + + + + Test for Bug 1234567 + + + + + + + +Mozilla Bug 885996 +

+
+ + + +
+
+
+ + diff --git a/dom/html/test/forms/test_input_date_bad_input.html b/dom/html/test/forms/test_input_date_bad_input.html new file mode 100644 index 0000000000..516d48263f --- /dev/null +++ b/dom/html/test/forms/test_input_date_bad_input.html @@ -0,0 +1,113 @@ + + + + + Test for <input type='date'> bad input validity state + + + + + + +Mozilla Bug 1372369 +

+
+
+ + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_date_key_events.html b/dom/html/test/forms/test_input_date_key_events.html new file mode 100644 index 0000000000..28004d3ce3 --- /dev/null +++ b/dom/html/test/forms/test_input_date_key_events.html @@ -0,0 +1,270 @@ + + + + + Test key events for date control + + + + + + +Mozilla Bug 1286182 +Mozilla Bug 1804669 +

+
+ +
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_calendar_button.html b/dom/html/test/forms/test_input_datetime_calendar_button.html new file mode 100644 index 0000000000..d7bbe28dd8 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_calendar_button.html @@ -0,0 +1,177 @@ + + + + +Test required date/datetime-local input's Calendar button + + + + + +Created for Mozilla Bug 1479708 and updated by Mozilla Bug 1676068 +

+
+ + + + + + + + + + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_disabled_focus.html b/dom/html/test/forms/test_input_datetime_disabled_focus.html new file mode 100644 index 0000000000..b4b7ce2c0b --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_disabled_focus.html @@ -0,0 +1,42 @@ + +Test for bug 1772841 + + + +Mozilla Bug 1772841 +
+ + + + + + + +
+ diff --git a/dom/html/test/forms/test_input_datetime_focus_blur.html b/dom/html/test/forms/test_input_datetime_focus_blur.html new file mode 100644 index 0000000000..bff7b2ceb8 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_focus_blur.html @@ -0,0 +1,64 @@ + + + + + Test focus/blur behaviour for date/time input types + + + + +Mozilla Bug 1288591 +

+
+ + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_focus_blur_events.html b/dom/html/test/forms/test_input_datetime_focus_blur_events.html new file mode 100644 index 0000000000..2e4e918119 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_focus_blur_events.html @@ -0,0 +1,93 @@ + + + + +Test for Bug 1301306 + + + + + +Mozilla Bug 722599 +

+
+ + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_focus_state.html b/dom/html/test/forms/test_input_datetime_focus_state.html new file mode 100644 index 0000000000..3b771f2394 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_focus_state.html @@ -0,0 +1,79 @@ + + + + + Test moving focus in onfocus/onblur handler + + + + +Mozilla Bug 1346085 +

+
+ + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_hidden.html b/dom/html/test/forms/test_input_datetime_hidden.html new file mode 100644 index 0000000000..7d8a6766a9 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_hidden.html @@ -0,0 +1,32 @@ + + + + + Test construction of hidden date input type + + + + + +Mozilla Bug 1514040 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_input_change_events.html b/dom/html/test/forms/test_input_datetime_input_change_events.html new file mode 100644 index 0000000000..63c8012252 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_input_change_events.html @@ -0,0 +1,143 @@ + + + + +Test for Bugs 1370858 and 1804881 + + + + + +Mozilla Bug 1370858 +Mozilla Bug 1804881 +

+
+ + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_readonly.html b/dom/html/test/forms/test_input_datetime_readonly.html new file mode 100644 index 0000000000..aa7b40753b --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_readonly.html @@ -0,0 +1,20 @@ + +Test for bug 1461509 + + + + + diff --git a/dom/html/test/forms/test_input_datetime_reset_default_value_input_change_event.html b/dom/html/test/forms/test_input_datetime_reset_default_value_input_change_event.html new file mode 100644 index 0000000000..393de9fdee --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_reset_default_value_input_change_event.html @@ -0,0 +1,122 @@ + + + + +Test for bug 1446722 + + + + + + +Mozilla bug 1446722 +

+
+ + + + + + + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_tabindex.html b/dom/html/test/forms/test_input_datetime_tabindex.html new file mode 100644 index 0000000000..207a7a8a8e --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_tabindex.html @@ -0,0 +1,113 @@ + + + + + Test tabindex attribute for date/time input types + + + + + +Mozilla Bug 1288591 +

+
+ + + + + + + + + + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_defaultValue.html b/dom/html/test/forms/test_input_defaultValue.html new file mode 100644 index 0000000000..03849d7f54 --- /dev/null +++ b/dom/html/test/forms/test_input_defaultValue.html @@ -0,0 +1,81 @@ + + + + + Test for Bug 977029 + + + +
+ Bug 977029 +

+ Goal of this test is to check that modifying defaultValue and value attribute + of input types is working as expected. +

+
+ + + + + + + + + + +
+
+ + + + diff --git a/dom/html/test/forms/test_input_email.html b/dom/html/test/forms/test_input_email.html new file mode 100644 index 0000000000..96ff939215 --- /dev/null +++ b/dom/html/test/forms/test_input_email.html @@ -0,0 +1,237 @@ + + + + + Test for <input type='email'> validity + + + + +Mozilla Bug 555559 +Mozilla Bug 668817 +Mozilla Bug 854812 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_input_event.html b/dom/html/test/forms/test_input_event.html new file mode 100644 index 0000000000..72863ca335 --- /dev/null +++ b/dom/html/test/forms/test_input_event.html @@ -0,0 +1,409 @@ + + + + +Test for input event + + + + + +Mozilla Bug 851780 +

+
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_file_picker.html b/dom/html/test/forms/test_input_file_picker.html new file mode 100644 index 0000000000..f59c9e759c --- /dev/null +++ b/dom/html/test/forms/test_input_file_picker.html @@ -0,0 +1,280 @@ + + + + Test for <input type='file'> file picker + + + + + +Mozilla Bug 36619 +Mozilla Bug 377624 +Mozilla Bug 565274 +Mozilla Bug 701353 +Mozilla Bug 826176 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foo
+
foo
+
foo
+ foo + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_hasBeenTypePassword.html b/dom/html/test/forms/test_input_hasBeenTypePassword.html new file mode 100644 index 0000000000..ac577ae3a9 --- /dev/null +++ b/dom/html/test/forms/test_input_hasBeenTypePassword.html @@ -0,0 +1,67 @@ + + + + + Test input.hasBeenTypePassword + + + + +Mozilla Bug 1330228 + + + diff --git a/dom/html/test/forms/test_input_hasBeenTypePassword_navigation.html b/dom/html/test/forms/test_input_hasBeenTypePassword_navigation.html new file mode 100644 index 0000000000..70a0f8427e --- /dev/null +++ b/dom/html/test/forms/test_input_hasBeenTypePassword_navigation.html @@ -0,0 +1,68 @@ + + + + + Test hasBeenTypePassword is used with bfcache + + + + +Mozilla Bug 1330228 +

+ +

+
+
+
+ + diff --git a/dom/html/test/forms/test_input_list_attribute.html b/dom/html/test/forms/test_input_list_attribute.html new file mode 100644 index 0000000000..62a07dd91a --- /dev/null +++ b/dom/html/test/forms/test_input_list_attribute.html @@ -0,0 +1,253 @@ + + + + + Test for Bug 556007 + + + + +Mozilla Bug 556007 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_input_number_data.js b/dom/html/test/forms/test_input_number_data.js new file mode 100644 index 0000000000..9ec53f136f --- /dev/null +++ b/dom/html/test/forms/test_input_number_data.js @@ -0,0 +1,54 @@ +var tests = [ + { + desc: "British English", + langTag: "en-GB", + inputWithGrouping: "123,456.78", + inputWithoutGrouping: "123456.78", + value: 123456.78, + }, + { + desc: "Farsi", + langTag: "fa", + inputWithGrouping: "۱۲۳٬۴۵۶٫۷۸", + inputWithoutGrouping: "۱۲۳۴۵۶٫۷۸", + value: 123456.78, + }, + { + desc: "French", + langTag: "fr-FR", + inputWithGrouping: "123 456,78", + inputWithoutGrouping: "123456,78", + value: 123456.78, + }, + { + desc: "German", + langTag: "de", + inputWithGrouping: "123.456,78", + inputWithoutGrouping: "123456,78", + value: 123456.78, + }, + // Bug 1509057 disables grouping separators for now, so this test isn't + // currently relevant. + // Extra german test to check that a locale that uses '.' as its grouping + // separator doesn't result in it being invalid (due to step mismatch) due + // to the de-localization code mishandling numbers that look like other + // numbers formatted for English speakers (i.e. treating this as 123.456 + // instead of 123456): + //{ desc: "German (test 2)", + // langTag: "de", inputWithGrouping: "123.456", + // inputWithoutGrouping: "123456", value: 123456 + //}, + { + desc: "Hebrew", + langTag: "he", + inputWithGrouping: "123,456.78", + inputWithoutGrouping: "123456.78", + value: 123456.78, + }, +]; + +var invalidTests = [ + // Right now this will pass in a 'de' build, but not in the 'en' build that + // are used for testing. See bug 1216831. + // { desc: "Invalid German", langTag: "de", input: "12.34" } +]; diff --git a/dom/html/test/forms/test_input_number_focus.html b/dom/html/test/forms/test_input_number_focus.html new file mode 100644 index 0000000000..4126ecc496 --- /dev/null +++ b/dom/html/test/forms/test_input_number_focus.html @@ -0,0 +1,109 @@ + + + + + Test focus behaviour for <input type='number'> + + + + + +Mozilla Bug 1268556 +Mozilla Bug 1057858 +

+
+ + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_number_key_events.html b/dom/html/test/forms/test_input_number_key_events.html new file mode 100644 index 0000000000..eb537f5617 --- /dev/null +++ b/dom/html/test/forms/test_input_number_key_events.html @@ -0,0 +1,238 @@ + + + + + Test key events for number control + + + + + + +Mozilla Bug 935506 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_number_l10n.html b/dom/html/test/forms/test_input_number_l10n.html new file mode 100644 index 0000000000..c8202028ed --- /dev/null +++ b/dom/html/test/forms/test_input_number_l10n.html @@ -0,0 +1,77 @@ + + + + + Test localization of number control input + + + + + + + +Mozilla Bug 844744 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_number_mouse_events.html b/dom/html/test/forms/test_input_number_mouse_events.html new file mode 100644 index 0000000000..6d14eb2263 --- /dev/null +++ b/dom/html/test/forms/test_input_number_mouse_events.html @@ -0,0 +1,259 @@ + + + + + Test mouse events for number + + + + + + + + +Mozilla Bug 935501 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_number_placeholder_shown.html b/dom/html/test/forms/test_input_number_placeholder_shown.html new file mode 100644 index 0000000000..c9c2a7f515 --- /dev/null +++ b/dom/html/test/forms/test_input_number_placeholder_shown.html @@ -0,0 +1,30 @@ + +Test for :placeholder-shown on input elements and invalid values. + + + + + diff --git a/dom/html/test/forms/test_input_number_rounding.html b/dom/html/test/forms/test_input_number_rounding.html new file mode 100644 index 0000000000..d162727557 --- /dev/null +++ b/dom/html/test/forms/test_input_number_rounding.html @@ -0,0 +1,120 @@ + + + + + Test rounding behaviour for <input type='number'> + + + + + + +Mozilla Bug 783607 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_number_validation.html b/dom/html/test/forms/test_input_number_validation.html new file mode 100644 index 0000000000..c19c1fde1c --- /dev/null +++ b/dom/html/test/forms/test_input_number_validation.html @@ -0,0 +1,139 @@ + + + + + Test validation of number control input + + + + + + + +Mozilla Bug 827161 +

+
+ + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_password_click_show_password_button.html b/dom/html/test/forms/test_input_password_click_show_password_button.html new file mode 100644 index 0000000000..fd5cfe6935 --- /dev/null +++ b/dom/html/test/forms/test_input_password_click_show_password_button.html @@ -0,0 +1,95 @@ + + + + + + Test for Bug 502258 + + + + + + + +Mozilla Bug 502258 +

+ + +
+
+ + diff --git a/dom/html/test/forms/test_input_password_show_password_button.html b/dom/html/test/forms/test_input_password_show_password_button.html new file mode 100644 index 0000000000..0bb5fdbee6 --- /dev/null +++ b/dom/html/test/forms/test_input_password_show_password_button.html @@ -0,0 +1,80 @@ + + + + + + Test for Bug 502258 + + + + + + + +Mozilla Bug 502258 +

+ + +
+
+ + diff --git a/dom/html/test/forms/test_input_radio_indeterminate.html b/dom/html/test/forms/test_input_radio_indeterminate.html new file mode 100644 index 0000000000..0fe7028b1e --- /dev/null +++ b/dom/html/test/forms/test_input_radio_indeterminate.html @@ -0,0 +1,109 @@ + + + + + Test for Bug 885359 + + + + +Mozilla Bug 343444 +

+ +
+ + +
+
+ + +
+ + + + + + diff --git a/dom/html/test/forms/test_input_radio_radiogroup.html b/dom/html/test/forms/test_input_radio_radiogroup.html new file mode 100644 index 0000000000..62767def72 --- /dev/null +++ b/dom/html/test/forms/test_input_radio_radiogroup.html @@ -0,0 +1,75 @@ + + + + + Test for Bug 343444 + + + + + + +Mozilla Bug 343444 +

+
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + diff --git a/dom/html/test/forms/test_input_radio_required.html b/dom/html/test/forms/test_input_radio_required.html new file mode 100644 index 0000000000..ae02aab2ff --- /dev/null +++ b/dom/html/test/forms/test_input_radio_required.html @@ -0,0 +1,31 @@ + + + + + Test for Bug 1100535 + + + + + +Mozilla Bug 1100535 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_input_range_attr_order.html b/dom/html/test/forms/test_input_range_attr_order.html new file mode 100644 index 0000000000..dc3f1ac95c --- /dev/null +++ b/dom/html/test/forms/test_input_range_attr_order.html @@ -0,0 +1,48 @@ + + + + + Test @min/@max/@step order for range + + + + + + +Mozilla Bug 841941 +

+
+ + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_range_key_events.html b/dom/html/test/forms/test_input_range_key_events.html new file mode 100644 index 0000000000..6daf572916 --- /dev/null +++ b/dom/html/test/forms/test_input_range_key_events.html @@ -0,0 +1,207 @@ + + + + + Test key events for range + + + + + + +Mozilla Bug 843725 +

+
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_range_mouse_and_touch_events.html b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html new file mode 100644 index 0000000000..92cd1b3095 --- /dev/null +++ b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html @@ -0,0 +1,227 @@ + + + + + Test mouse and touch events for range + + + + + + + + +Mozilla Bug 846380 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_range_rounding.html b/dom/html/test/forms/test_input_range_rounding.html new file mode 100644 index 0000000000..9c3c21ce6e --- /dev/null +++ b/dom/html/test/forms/test_input_range_rounding.html @@ -0,0 +1,103 @@ + + + + + Test key events for range + + + + + + +Mozilla Bug 853525 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_sanitization.html b/dom/html/test/forms/test_input_sanitization.html new file mode 100644 index 0000000000..474ddd621d --- /dev/null +++ b/dom/html/test/forms/test_input_sanitization.html @@ -0,0 +1,585 @@ + + + + + Test for Bug 549475 + + + + +Mozilla Bug 549475 +

+
+
+
+
+
+ +
+ + diff --git a/dom/html/test/forms/test_input_setting_value.html b/dom/html/test/forms/test_input_setting_value.html new file mode 100644 index 0000000000..b6ddd66d24 --- /dev/null +++ b/dom/html/test/forms/test_input_setting_value.html @@ -0,0 +1,619 @@ + + + + Test for setting input value + + + + + +
+
+
+
+
+ + + + diff --git a/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html b/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html new file mode 100644 index 0000000000..8c3855960b --- /dev/null +++ b/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html @@ -0,0 +1,123 @@ + + + + + + Test for Bug 829606 + + + + + + + +Mozilla Bug 829606 +

+
+ + +
+
+
+ + diff --git a/dom/html/test/forms/test_input_time_key_events.html b/dom/html/test/forms/test_input_time_key_events.html new file mode 100644 index 0000000000..c738816653 --- /dev/null +++ b/dom/html/test/forms/test_input_time_key_events.html @@ -0,0 +1,221 @@ + + + + + Test key events for time control + + + + + + +Mozilla Bug 1288591 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_time_sec_millisec_field.html b/dom/html/test/forms/test_input_time_sec_millisec_field.html new file mode 100644 index 0000000000..71db4942a9 --- /dev/null +++ b/dom/html/test/forms/test_input_time_sec_millisec_field.html @@ -0,0 +1,134 @@ + + + + + Test second and millisecond fields in input type=time + + + + + + +Mozilla Bug 1374967 +

+
+ + + + + + + + + + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_types_pref.html b/dom/html/test/forms/test_input_types_pref.html new file mode 100644 index 0000000000..1222e88a86 --- /dev/null +++ b/dom/html/test/forms/test_input_types_pref.html @@ -0,0 +1,77 @@ + + + + + Test for Bug 764481 + + + + +Mozilla Bug 764481 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_input_typing_sanitization.html b/dom/html/test/forms/test_input_typing_sanitization.html new file mode 100644 index 0000000000..fef0ebed06 --- /dev/null +++ b/dom/html/test/forms/test_input_typing_sanitization.html @@ -0,0 +1,217 @@ + + + + + Test for Bug 765772 + + + + + +Mozilla Bug 765772 +

+ +
+
+ +
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_untrusted_key_events.html b/dom/html/test/forms/test_input_untrusted_key_events.html new file mode 100644 index 0000000000..78e35f525f --- /dev/null +++ b/dom/html/test/forms/test_input_untrusted_key_events.html @@ -0,0 +1,90 @@ + + + + Test for untrusted DOM KeyboardEvent on input element + + + + + +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_url.html b/dom/html/test/forms/test_input_url.html new file mode 100644 index 0000000000..3cdf1070bb --- /dev/null +++ b/dom/html/test/forms/test_input_url.html @@ -0,0 +1,91 @@ + + + + Tests for <input type='url'> validity + + + + +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_interactive_content_in_label.html b/dom/html/test/forms/test_interactive_content_in_label.html new file mode 100644 index 0000000000..b8d9c81d51 --- /dev/null +++ b/dom/html/test/forms/test_interactive_content_in_label.html @@ -0,0 +1,101 @@ + + + + + Test for Bug 229925 + + + + + + +Mozilla Bug 229925 +

+
+ +
+ + + + + diff --git a/dom/html/test/forms/test_interactive_content_in_summary.html b/dom/html/test/forms/test_interactive_content_in_summary.html new file mode 100644 index 0000000000..f8bac77d89 --- /dev/null +++ b/dom/html/test/forms/test_interactive_content_in_summary.html @@ -0,0 +1,97 @@ + + + + + Test for Bug 1524893 + + + + + + +Mozilla Bug 1524893 + +
+ + a + + +
details
+ embed + + + + + + object + + + + + +
+ + + a + + + + object + + + tabindex + + + + object + +
+
This is details
+
+ + + + + diff --git a/dom/html/test/forms/test_label_control_attribute.html b/dom/html/test/forms/test_label_control_attribute.html new file mode 100644 index 0000000000..efc04cd787 --- /dev/null +++ b/dom/html/test/forms/test_label_control_attribute.html @@ -0,0 +1,100 @@ + + + + + Test for Bug 562932 + + + + +Mozilla Bug 562932 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_label_input_controls.html b/dom/html/test/forms/test_label_input_controls.html new file mode 100644 index 0000000000..fe9410b608 --- /dev/null +++ b/dom/html/test/forms/test_label_input_controls.html @@ -0,0 +1,84 @@ + + + + + Test for Bug 597650 + + + + + + Mozilla Bug 597650 +

+
+ + +
+
+    
+  
+ + + diff --git a/dom/html/test/forms/test_max_attribute.html b/dom/html/test/forms/test_max_attribute.html new file mode 100644 index 0000000000..f6e9c9bd8e --- /dev/null +++ b/dom/html/test/forms/test_max_attribute.html @@ -0,0 +1,473 @@ + + + + + Test for Bug 635499 + + + + +Mozilla Bug 635499 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_maxlength_attribute.html b/dom/html/test/forms/test_maxlength_attribute.html new file mode 100644 index 0000000000..bd76e277e5 --- /dev/null +++ b/dom/html/test/forms/test_maxlength_attribute.html @@ -0,0 +1,129 @@ + + + + + Test for Bug 345624 + + + + + + +Mozilla Bug 345624 +

+
+ + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_meter_element.html b/dom/html/test/forms/test_meter_element.html new file mode 100644 index 0000000000..5e1073d53d --- /dev/null +++ b/dom/html/test/forms/test_meter_element.html @@ -0,0 +1,376 @@ + + + + + Test for <meter> + + + + +Mozilla Bug 657938 +

+ + +
+
+
+ + diff --git a/dom/html/test/forms/test_meter_pseudo-classes.html b/dom/html/test/forms/test_meter_pseudo-classes.html new file mode 100644 index 0000000000..e317a58405 --- /dev/null +++ b/dom/html/test/forms/test_meter_pseudo-classes.html @@ -0,0 +1,169 @@ + + + + + Test for Bug 660238 + + + + +Mozilla Bug 660238 +

+
+
+
+ + diff --git a/dom/html/test/forms/test_min_attribute.html b/dom/html/test/forms/test_min_attribute.html new file mode 100644 index 0000000000..a603a37d29 --- /dev/null +++ b/dom/html/test/forms/test_min_attribute.html @@ -0,0 +1,473 @@ + + + + + Test for Bug 635553 + + + + +Mozilla Bug 635499 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_minlength_attribute.html b/dom/html/test/forms/test_minlength_attribute.html new file mode 100644 index 0000000000..154343a512 --- /dev/null +++ b/dom/html/test/forms/test_minlength_attribute.html @@ -0,0 +1,130 @@ + + + + + Test for Bug 345624 + + + + + + +Mozilla Bug 345624 +

+
+ + +
+
+
+
+ + + diff --git a/dom/html/test/forms/test_mozistextfield.html b/dom/html/test/forms/test_mozistextfield.html new file mode 100644 index 0000000000..3f92a3d05d --- /dev/null +++ b/dom/html/test/forms/test_mozistextfield.html @@ -0,0 +1,111 @@ + + + + + Test for Bug 565538 + + + + +Mozilla Bug 565538 +

+
+
+
+ + diff --git a/dom/html/test/forms/test_novalidate_attribute.html b/dom/html/test/forms/test_novalidate_attribute.html new file mode 100644 index 0000000000..dcea207838 --- /dev/null +++ b/dom/html/test/forms/test_novalidate_attribute.html @@ -0,0 +1,85 @@ + + + + + Test for Bug 556013 + + + + + +Mozilla Bug 556013 +

+ +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_option_disabled.html b/dom/html/test/forms/test_option_disabled.html new file mode 100644 index 0000000000..421e4546be --- /dev/null +++ b/dom/html/test/forms/test_option_disabled.html @@ -0,0 +1,123 @@ + + + + + + Test for HTMLOptionElement disabled attribute and pseudo-class + + + + +Mozilla Bug 759666 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_option_index_attribute.html b/dom/html/test/forms/test_option_index_attribute.html new file mode 100644 index 0000000000..f15520e5e6 --- /dev/null +++ b/dom/html/test/forms/test_option_index_attribute.html @@ -0,0 +1,76 @@ + + + + + + Test for option.index + + + + +Mozilla Bug 720385 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_option_text.html b/dom/html/test/forms/test_option_text.html new file mode 100644 index 0000000000..3afe3e786a --- /dev/null +++ b/dom/html/test/forms/test_option_text.html @@ -0,0 +1,57 @@ + + +HTMLOptionElement.text + + + + +
+ diff --git a/dom/html/test/forms/test_output_element.html b/dom/html/test/forms/test_output_element.html new file mode 100644 index 0000000000..ab11443d83 --- /dev/null +++ b/dom/html/test/forms/test_output_element.html @@ -0,0 +1,182 @@ + + + + + Test for Bug 346485 + + + + + + +Mozilla Bug 346485 +

+ + +
+
+
+ + diff --git a/dom/html/test/forms/test_pattern_attribute.html b/dom/html/test/forms/test_pattern_attribute.html new file mode 100644 index 0000000000..74b0517c51 --- /dev/null +++ b/dom/html/test/forms/test_pattern_attribute.html @@ -0,0 +1,324 @@ + + + + + Test for Bug 345512 + + + + + +Mozilla Bug 345512 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_preserving_metadata_between_reloads.html b/dom/html/test/forms/test_preserving_metadata_between_reloads.html new file mode 100644 index 0000000000..07ca05f7ce --- /dev/null +++ b/dom/html/test/forms/test_preserving_metadata_between_reloads.html @@ -0,0 +1,84 @@ + + + + + Test preserving metadata between page reloads + + + + + +

+
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/dom/html/test/forms/test_progress_element.html b/dom/html/test/forms/test_progress_element.html new file mode 100644 index 0000000000..065adf94ea --- /dev/null +++ b/dom/html/test/forms/test_progress_element.html @@ -0,0 +1,307 @@ + + + + + Test for progress element content and layout + + + + +Mozilla Bug 514437 +and +Mozilla Bug 633913 +

+ + +
+
+
+ + diff --git a/dom/html/test/forms/test_radio_in_label.html b/dom/html/test/forms/test_radio_in_label.html new file mode 100644 index 0000000000..7e8a232cc3 --- /dev/null +++ b/dom/html/test/forms/test_radio_in_label.html @@ -0,0 +1,54 @@ + + + + + Test for Bug 229925 + + + + + + +Mozilla Bug 229925 +

+
+ +
+ + + + diff --git a/dom/html/test/forms/test_radio_radionodelist.html b/dom/html/test/forms/test_radio_radionodelist.html new file mode 100644 index 0000000000..8761c22b58 --- /dev/null +++ b/dom/html/test/forms/test_radio_radionodelist.html @@ -0,0 +1,57 @@ + + + + + Test for Bug 779723 + + + + + + +Mozilla Bug 779723 +

+
+ + + +
+ + + + + diff --git a/dom/html/test/forms/test_reportValidation_preventDefault.html b/dom/html/test/forms/test_reportValidation_preventDefault.html new file mode 100644 index 0000000000..3f3b99d140 --- /dev/null +++ b/dom/html/test/forms/test_reportValidation_preventDefault.html @@ -0,0 +1,89 @@ + + + + + Test for Bug 1088761 + + + + + +Mozilla Bug 1088761 +

+ + +
+
+
+ + diff --git a/dom/html/test/forms/test_required_attribute.html b/dom/html/test/forms/test_required_attribute.html new file mode 100644 index 0000000000..4fca31f9af --- /dev/null +++ b/dom/html/test/forms/test_required_attribute.html @@ -0,0 +1,420 @@ + + + + + Test for Bug 345822 + + + + +Mozilla Bug 345822 +

+
+
+
+
+
+
+
+ + diff --git a/dom/html/test/forms/test_restore_form_elements.html b/dom/html/test/forms/test_restore_form_elements.html new file mode 100644 index 0000000000..be22a29b7b --- /dev/null +++ b/dom/html/test/forms/test_restore_form_elements.html @@ -0,0 +1,174 @@ + + + + + + + Test for Bug 737851 + + + + + + + +Mozilla Bug 737851 + +

+ + +
+ + + +
+ + +
+
+
+ + diff --git a/dom/html/test/forms/test_save_restore_radio_groups.html b/dom/html/test/forms/test_save_restore_radio_groups.html new file mode 100644 index 0000000000..c5ef924a0e --- /dev/null +++ b/dom/html/test/forms/test_save_restore_radio_groups.html @@ -0,0 +1,70 @@ + + + + + Test for Bug 350022 + + + + +Mozilla Bug 350022 +

+
+ + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_select_change_event.html b/dom/html/test/forms/test_select_change_event.html new file mode 100644 index 0000000000..ec3ed58c5e --- /dev/null +++ b/dom/html/test/forms/test_select_change_event.html @@ -0,0 +1,54 @@ + + + + + Test for Bug 1265968 + + + + + +Mozilla Bug 1265968 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_select_input_change_event.html b/dom/html/test/forms/test_select_input_change_event.html new file mode 100644 index 0000000000..fcf384e423 --- /dev/null +++ b/dom/html/test/forms/test_select_input_change_event.html @@ -0,0 +1,122 @@ + + + + + Test for Bug 1024350 + + + + + +Mozilla Bug 1024350 +

+
+ + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_select_selectedOptions.html b/dom/html/test/forms/test_select_selectedOptions.html new file mode 100644 index 0000000000..745e0ba4f3 --- /dev/null +++ b/dom/html/test/forms/test_select_selectedOptions.html @@ -0,0 +1,119 @@ + + + + + Test for HTMLSelectElement.selectedOptions + + + + +Mozilla Bug 596681 +

+
+
+
+ + diff --git a/dom/html/test/forms/test_select_validation.html b/dom/html/test/forms/test_select_validation.html new file mode 100644 index 0000000000..6d02aa0746 --- /dev/null +++ b/dom/html/test/forms/test_select_validation.html @@ -0,0 +1,39 @@ + + + + + Test for Bug 942321 + + + + + + +Mozilla Bug 942321 +

+
+ + +
+ + + + + diff --git a/dom/html/test/forms/test_set_range_text.html b/dom/html/test/forms/test_set_range_text.html new file mode 100644 index 0000000000..f85014ae77 --- /dev/null +++ b/dom/html/test/forms/test_set_range_text.html @@ -0,0 +1,242 @@ + + + + +Tests for Bug 850364 && Bug 918940 + + + + + +Mozilla Bug 850364 +

+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_step_attribute.html b/dom/html/test/forms/test_step_attribute.html new file mode 100644 index 0000000000..f0af250c06 --- /dev/null +++ b/dom/html/test/forms/test_step_attribute.html @@ -0,0 +1,1060 @@ + + + + + Test for Bug 635553 + + + + +Mozilla Bug 635499 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_stepup_stepdown.html b/dom/html/test/forms/test_stepup_stepdown.html new file mode 100644 index 0000000000..8ad7fbfeee --- /dev/null +++ b/dom/html/test/forms/test_stepup_stepdown.html @@ -0,0 +1,1137 @@ + + + + + Test for Bug 636627 + + + + +Mozilla Bug 636627 +

+
+
+
+ + diff --git a/dom/html/test/forms/test_submit_invalid_file.html b/dom/html/test/forms/test_submit_invalid_file.html new file mode 100644 index 0000000000..4fcadc37ce --- /dev/null +++ b/dom/html/test/forms/test_submit_invalid_file.html @@ -0,0 +1,55 @@ + + + + + + Test invalid file submission + + + + +Mozilla Bug 702949 +

+ +
+
+ + + diff --git a/dom/html/test/forms/test_textarea_attributes_reflection.html b/dom/html/test/forms/test_textarea_attributes_reflection.html new file mode 100644 index 0000000000..8f8e810b0e --- /dev/null +++ b/dom/html/test/forms/test_textarea_attributes_reflection.html @@ -0,0 +1,104 @@ + + + + Test for HTMLTextAreaElement attributes reflection + + + + + +

+
+
+
+ + diff --git a/dom/html/test/forms/test_validation.html b/dom/html/test/forms/test_validation.html new file mode 100644 index 0000000000..666d4a45c0 --- /dev/null +++ b/dom/html/test/forms/test_validation.html @@ -0,0 +1,343 @@ + + + + + Test for Bug 345624 + + + + + +Mozilla Bug 345624 +

+ +
+
+
+ + diff --git a/dom/html/test/forms/test_validation_not_in_doc.html b/dom/html/test/forms/test_validation_not_in_doc.html new file mode 100644 index 0000000000..1500c60869 --- /dev/null +++ b/dom/html/test/forms/test_validation_not_in_doc.html @@ -0,0 +1,19 @@ + + +Test for constraint validation of form controls not in documents + + +
+ diff --git a/dom/html/test/forms/test_valueasdate_attribute.html b/dom/html/test/forms/test_valueasdate_attribute.html new file mode 100644 index 0000000000..9055879a85 --- /dev/null +++ b/dom/html/test/forms/test_valueasdate_attribute.html @@ -0,0 +1,751 @@ + + + + + Test for input.valueAsDate + + + + +Mozilla Bug 769370 + +

+
+
+
+ + diff --git a/dom/html/test/forms/test_valueasnumber_attribute.html b/dom/html/test/forms/test_valueasnumber_attribute.html new file mode 100644 index 0000000000..5f7537f7a8 --- /dev/null +++ b/dom/html/test/forms/test_valueasnumber_attribute.html @@ -0,0 +1,858 @@ + + + + + Test for Bug input.valueAsNumber + + + + +Mozilla Bug 636737 +

+
+
+
+ + diff --git a/dom/html/test/forms/without_selectionchange/mochitest.ini b/dom/html/test/forms/without_selectionchange/mochitest.ini new file mode 100644 index 0000000000..8224e29b34 --- /dev/null +++ b/dom/html/test/forms/without_selectionchange/mochitest.ini @@ -0,0 +1,5 @@ +[DEFAULT] +prefs = + dom.select_events.textcontrols.enabled=false + +[test_select.html] diff --git a/dom/html/test/forms/without_selectionchange/test_select.html b/dom/html/test/forms/without_selectionchange/test_select.html new file mode 100644 index 0000000000..3d11611b1b --- /dev/null +++ b/dom/html/test/forms/without_selectionchange/test_select.html @@ -0,0 +1,21 @@ + + +Test for Bug 1717435 + + + + + + diff --git a/dom/html/test/head.js b/dom/html/test/head.js new file mode 100644 index 0000000000..1e3b435d0c --- /dev/null +++ b/dom/html/test/head.js @@ -0,0 +1,65 @@ +function pushPrefs(...aPrefs) { + return SpecialPowers.pushPrefEnv({ set: aPrefs }); +} + +function promiseWaitForEvent( + object, + eventName, + capturing = false, + chrome = false +) { + return new Promise(resolve => { + function listener(event) { + info("Saw " + eventName); + object.removeEventListener(eventName, listener, capturing, chrome); + resolve(event); + } + + info("Waiting for " + eventName); + object.addEventListener(eventName, listener, capturing, chrome); + }); +} + +/** + * Waits for the next load to complete in any browser or the given browser. + * If a is given it waits for a load in any of its browsers. + * + * @return promise + */ +function waitForDocLoadComplete(aBrowser = gBrowser) { + return new Promise(resolve => { + let listener = { + onStateChange(webProgress, req, flags, status) { + let docStop = + Ci.nsIWebProgressListener.STATE_IS_NETWORK | + Ci.nsIWebProgressListener.STATE_STOP; + info( + "Saw state " + + flags.toString(16) + + " and status " + + status.toString(16) + ); + // When a load needs to be retargetted to a new process it is cancelled + // with NS_BINDING_ABORTED so ignore that case + if ((flags & docStop) == docStop && status != Cr.NS_BINDING_ABORTED) { + aBrowser.removeProgressListener(this); + waitForDocLoadComplete.listeners.delete(this); + let chan = req.QueryInterface(Ci.nsIChannel); + info("Browser loaded " + chan.originalURI.spec); + resolve(); + } + }, + QueryInterface: ChromeUtils.generateQI([ + "nsIWebProgressListener", + "nsISupportsWeakReference", + ]), + }; + aBrowser.addProgressListener(listener); + waitForDocLoadComplete.listeners.add(listener); + info("Waiting for browser load"); + }); +} +// Keep a set of progress listeners for waitForDocLoadComplete() to make sure +// they're not GC'ed before we saw the page load. +waitForDocLoadComplete.listeners = new Set(); +registerCleanupFunction(() => waitForDocLoadComplete.listeners.clear()); diff --git a/dom/html/test/image-allow-credentials.png b/dom/html/test/image-allow-credentials.png new file mode 100644 index 0000000000..df24ac6d34 Binary files /dev/null and b/dom/html/test/image-allow-credentials.png differ diff --git a/dom/html/test/image-allow-credentials.png^headers^ b/dom/html/test/image-allow-credentials.png^headers^ new file mode 100644 index 0000000000..a03f99a9c0 --- /dev/null +++ b/dom/html/test/image-allow-credentials.png^headers^ @@ -0,0 +1,2 @@ +Access-Control-Allow-Origin: http://mochi.test:8888 +Access-Control-Allow-Credentials: true diff --git a/dom/html/test/image.png b/dom/html/test/image.png new file mode 100644 index 0000000000..d26878c9f2 Binary files /dev/null and b/dom/html/test/image.png differ diff --git a/dom/html/test/image_yellow.png b/dom/html/test/image_yellow.png new file mode 100644 index 0000000000..51e8aaf38c Binary files /dev/null and b/dom/html/test/image_yellow.png differ diff --git a/dom/html/test/mochitest.ini b/dom/html/test/mochitest.ini new file mode 100644 index 0000000000..bd1dfc146f --- /dev/null +++ b/dom/html/test/mochitest.ini @@ -0,0 +1,604 @@ +[DEFAULT] +prefs = + dom.forms.inputmode=true # only for test_inputmode.html + gfx.font_loader.delay=0 +support-files = + 347174transform.xsl + 347174transformable.xml + allowMedia.sjs + bug100533_iframe.html + bug100533_load.html + bug196523-subframe.html + bug199692-nested-d2.html + bug199692-nested.html + bug199692-popup.html + bug199692-scrolled.html + bug242709_iframe.html + bug242709_load.html + bug277724_iframe1.html + bug277724_iframe2.xhtml + bug277890_iframe.html + bug277890_load.html + bug340800_iframe.txt + bug369370-popup.png + bug372098-link-target.html + bug441930_iframe.html + bug445004-inner.html + bug445004-inner.js + bug445004-outer-abs.html + bug445004-outer-rel.html + bug445004-outer-write.html + bug446483-iframe.html + bug448564-echo.sjs + bug448564-iframe-1.html + bug448564-iframe-2.html + bug448564-iframe-3.html + bug448564-submit.js + bug499092.html + bug499092.xml + bug514856_iframe.html + bug1260704_iframe.html + bug1260704_iframe_empty.html + bug1292522_iframe.html + bug1292522_page.html + bug1315146-iframe.html + bug1315146-main.html + dummy_page.html + test_non-ascii-cookie.html^headers^ + file_bug209275_1.html + file_bug209275_2.html + file_bug209275_3.html + file_bug297761.html + file_bug417760.png + file_bug893537.html + file_bug1260704.png + file_formSubmission_img.jpg + file_formSubmission_text.txt + file_iframe_sandbox_a_if1.html + file_iframe_sandbox_a_if10.html + file_iframe_sandbox_a_if11.html + file_iframe_sandbox_a_if12.html + file_iframe_sandbox_a_if13.html + file_iframe_sandbox_a_if14.html + file_iframe_sandbox_a_if15.html + file_iframe_sandbox_a_if16.html + file_iframe_sandbox_a_if17.html + file_iframe_sandbox_a_if18.html + file_iframe_sandbox_a_if19.html + file_iframe_sandbox_a_if2.html + file_iframe_sandbox_a_if3.html + file_iframe_sandbox_a_if4.html + file_iframe_sandbox_a_if5.html + file_iframe_sandbox_a_if6.html + file_iframe_sandbox_a_if7.html + file_iframe_sandbox_a_if8.html + file_iframe_sandbox_a_if9.html + file_iframe_sandbox_b_if1.html + file_iframe_sandbox_b_if2.html + file_iframe_sandbox_b_if3.html + file_iframe_sandbox_c_if1.html + file_iframe_sandbox_c_if2.html + file_iframe_sandbox_c_if3.html + file_iframe_sandbox_c_if4.html + file_iframe_sandbox_c_if5.html + file_iframe_sandbox_c_if6.html + file_iframe_sandbox_c_if7.html + file_iframe_sandbox_c_if8.html + file_iframe_sandbox_c_if9.html + file_iframe_sandbox_close.html + file_iframe_sandbox_d_if1.html + file_iframe_sandbox_d_if10.html + file_iframe_sandbox_d_if11.html + file_iframe_sandbox_d_if12.html + file_iframe_sandbox_d_if13.html + file_iframe_sandbox_d_if14.html + file_iframe_sandbox_d_if15.html + file_iframe_sandbox_d_if16.html + file_iframe_sandbox_d_if17.html + file_iframe_sandbox_d_if18.html + file_iframe_sandbox_d_if19.html + file_iframe_sandbox_d_if2.html + file_iframe_sandbox_d_if20.html + file_iframe_sandbox_d_if21.html + file_iframe_sandbox_d_if22.html + file_iframe_sandbox_d_if23.html + file_iframe_sandbox_d_if3.html + file_iframe_sandbox_d_if4.html + file_iframe_sandbox_d_if5.html + file_iframe_sandbox_d_if6.html + file_iframe_sandbox_d_if7.html + file_iframe_sandbox_d_if8.html + file_iframe_sandbox_d_if9.html + file_iframe_sandbox_e_if1.html + file_iframe_sandbox_e_if10.html + file_iframe_sandbox_e_if11.html + file_iframe_sandbox_e_if12.html + file_iframe_sandbox_e_if13.html + file_iframe_sandbox_e_if14.html + file_iframe_sandbox_e_if15.html + file_iframe_sandbox_e_if16.html + file_iframe_sandbox_e_if2.html + file_iframe_sandbox_e_if3.html + file_iframe_sandbox_e_if4.html + file_iframe_sandbox_e_if5.html + file_iframe_sandbox_e_if6.html + file_iframe_sandbox_e_if7.html + file_iframe_sandbox_e_if8.html + file_iframe_sandbox_e_if9.html + file_iframe_sandbox_fail.js + file_iframe_sandbox_form_fail.html + file_iframe_sandbox_form_pass.html + file_iframe_sandbox_g_if1.html + file_iframe_sandbox_h_if1.html + file_iframe_sandbox_k_if1.html + file_iframe_sandbox_k_if2.html + file_iframe_sandbox_k_if3.html + file_iframe_sandbox_k_if4.html + file_iframe_sandbox_k_if5.html + file_iframe_sandbox_k_if6.html + file_iframe_sandbox_k_if7.html + file_iframe_sandbox_k_if8.html + file_iframe_sandbox_k_if9.html + file_iframe_sandbox_navigation_fail.html + file_iframe_sandbox_navigation_pass.html + file_iframe_sandbox_navigation_start.html + file_iframe_sandbox_open_window_fail.html + file_iframe_sandbox_open_window_pass.html + file_iframe_sandbox_pass.js + file_iframe_sandbox_redirect.html + file_iframe_sandbox_redirect.html^headers^ + file_iframe_sandbox_redirect_target.html + file_iframe_sandbox_refresh.html + file_iframe_sandbox_refresh.html^headers^ + file_iframe_sandbox_srcdoc_allow_scripts.html + file_iframe_sandbox_srcdoc_no_allow_scripts.html + file_iframe_sandbox_top_navigation_fail.html + file_iframe_sandbox_top_navigation_pass.html + file_iframe_sandbox_window_form_fail.html + file_iframe_sandbox_window_form_pass.html + file_iframe_sandbox_window_navigation_fail.html + file_iframe_sandbox_window_navigation_pass.html + file_iframe_sandbox_window_top_navigation_pass.html + file_iframe_sandbox_window_top_navigation_fail.html + file_iframe_sandbox_worker.js + file_srcdoc-2.html + file_srcdoc.html + file_srcdoc_iframe3.html + file_window_open_close_outer.html + file_window_open_close_inner.html + formSubmission_chrome.js + form_submit_server.sjs + formData_worker.js + formData_test.js + image.png + image-allow-credentials.png + image-allow-credentials.png^headers^ + nnc_lockup.gif + reflect.js + simpleFileOpener.js + file_bug1166138_1x.png + file_bug1166138_2x.png + file_bug1166138_def.png + script_fakepath.js + sw_formSubmission.js + object_bug287465_o1.html + object_bug287465_o2.html + object_bug556645.html + file.webm + !/gfx/layers/apz/test/mochitest/apz_test_utils.js + +[test_a_text.html] +[test_anchor_href_cache_invalidation.html] +[test_base_attributes_reflection.html] +[test_bug100533.html] +[test_bug109445.html] +[test_bug109445.xhtml] +[test_bug1297.html] +[test_bug1366.html] +[test_bug1400.html] +[test_bug143220.html] +[test_bug182279.html] +[test_bug2082.html] +[test_bug209275.xhtml] +skip-if = toolkit == 'android' #TIMED_OUT +[test_bug237071.html] +[test_bug242709.html] +[test_bug24958.html] +[test_bug274626.html] +[test_bug277724.html] +[test_bug277890.html] +[test_bug287465.html] +[test_bug295561.html] +[test_bug297761.html] +[test_bug300691-1.html] +[test_bug300691-2.html] +[test_bug300691-3.xhtml] +[test_bug330705-1.html] +[test_bug332246.html] +[test_bug332893-1.html] +[test_bug332893-2.html] +[test_bug332893-3.html] +[test_bug332893-4.html] +[test_bug332893-5.html] +[test_bug332893-6.html] +[test_bug332893-7.html] +[test_bug3348.html] +[test_bug340800.html] +[test_bug347174.html] +[test_bug347174_write.html] +[test_bug347174_xsl.html] +[test_bug347174_xslp.html] +[test_bug353415-1.html] +[test_bug353415-2.html] +[test_bug371375.html] +[test_bug372098.html] +[test_bug373589.html] +[test_bug375003-1.html] +[test_bug375003-2.html] +[test_bug377624.html] +[test_bug383383.html] +[test_bug383383_2.xhtml] +[test_bug384419.html] +[test_bug386496.html] +[test_bug386728.html] +[test_bug386996.html] +[test_bug388558.html] +[test_bug388746.html] +[test_bug388794.html] +[test_bug389797.html] +[test_bug390975.html] +[test_bug391994.html] +[test_bug394700.html] +[test_bug395107.html] +[test_bug401160.xhtml] +[test_bug405242.html] +[test_bug406596.html] +[test_bug417760.html] +[test_bug421640.html] +[test_bug424698.html] +[test_bug428135.xhtml] +[test_bug430351.html] +skip-if = toolkit == 'android' # Bug 1525959 +[test_bug441930.html] +[test_bug442801.html] +[test_bug448166.html] +[test_bug456229.html] +[test_bug458037.xhtml] +allow_xul_xbl = true +skip-if = + http3 +[test_bug460568.html] +[test_bug481335.xhtml] +skip-if = toolkit == 'android' #TIMED_OUT +[test_bug500885.html] +[test_bug514856.html] +[test_bug518122.html] +[test_bug519987.html] +[test_bug523771.html] +[test_bug529819.html] +[test_bug529859.html] +[test_bug535043.html] +[test_bug536891.html] +[test_bug536895.html] +[test_bug546995.html] +[test_bug547850.html] +[test_bug551846.html] +[test_bug555567.html] +[test_bug556645.html] +[test_bug557087-1.html] +[test_bug557087-2.html] +[test_bug557087-3.html] +[test_bug557087-4.html] +[test_bug557087-5.html] +[test_bug557087-6.html] +[test_bug557620.html] +[test_bug558788-1.html] +[test_bug558788-2.html] +[test_bug560112.html] +[test_bug561634.html] +[test_bug561636.html] +[test_bug561640.html] +[test_bug564001.html] +[test_bug566046.html] +[test_bug567938-1.html] +[test_bug567938-2.html] +[test_bug567938-3.html] +[test_bug567938-4.html] +[test_bug569955.html] +[test_bug573969.html] +[test_bug579079.html] +[test_bug582412-1.html] +[test_bug582412-2.html] +[test_bug583514.html] +[test_bug583533.html] +[test_bug586763.html] +[test_bug586786.html] +[test_bug587469.html] +[test_bug589.html] +[test_bug590353-1.html] +[test_bug590353-2.html] +[test_bug590363.html] +[test_bug592802.html] +[test_bug593689.html] +[test_bug595429.html] +[test_bug595447.html] +[test_bug595449.html] +[test_bug596350.html] +[test_bug596511.html] +[test_bug598643.html] +[test_bug598833-1.html] +[test_bug600155.html] +[test_bug601030.html] +[test_bug605124-1.html] +[test_bug605124-2.html] +[test_bug605125-1.html] +[test_bug605125-2.html] +[test_bug606817.html] +[test_bug607145.html] +skip-if = + http3 +[test_bug610212.html] +[test_bug610687.html] +[test_bug611189.html] +[test_bug612730.html] +skip-if = toolkit == 'android' # form control not selected/checked with synthesizeMouse +[test_bug613113.html] +[test_bug613019.html] +[test_bug613722.html] +[test_bug613979.html] +[test_bug615595.html] +fail-if = xorigin +[test_bug615833.html] +skip-if = toolkit == 'android' + os == 'mac' #TIMED_OUT # form control not selected/checked with synthesizeMouse, osx(bug 1275664) +[test_bug618948.html] +[test_bug619278.html] +[test_bug622558.html] +[test_bug622597.html] +[test_bug623291.html] +[test_bug6296.html] +[test_bug629801.html] +[test_bug633058.html] +[test_bug636336.html] +[test_bug641219.html] +[test_bug643051.html] +[test_bug646157.html] +[test_bug649134.html] +# This extra subdirectory is needed due to the nature of this test. +# With the bug, the test loads the base URL of the bug649134/file_*.sjs +# files, and the mochitest server responds with the contents of index.html if +# it exists in that case, which we use to detect failure. +# We cannot have index.html in this directory because it would prevent +# running the tests here. +support-files = + bug649134/file_bug649134-1.sjs + bug649134/file_bug649134-2.sjs + bug649134/index.html +skip-if = + http3 +[test_bug651956.html] +[test_bug658746.html] +[test_bug659596.html] +[test_bug659743.xml] +[test_bug660663.html] +[test_bug660959-1.html] +[test_bug660959-2.html] +[test_bug660959-3.html] +[test_bug666200.html] +[test_bug666666.html] +[test_bug669012.html] +[test_bug674558.html] +[test_bug674927.html] +[test_bug677658.html] +[test_bug682886.html] +[test_bug691.html] +[test_bug694.html] +[test_bug694503.html] +skip-if = toolkit == 'android' # Bug 1525959 +[test_bug696.html] +[test_bug717819.html] +[test_bug742030.html] +[test_bug742549.html] +[test_bug745685.html] +[test_bug763626.html] +[test_bug780993.html] +[test_bug787134.html] +[test_bug797113.html] +[test_bug803677.html] +[test_bug821307.html] +[test_bug827126.html] +[test_bug838582.html] +[test_bug839371.html] +[test_bug839913.html] +[test_bug841466.html] +[test_bug845057.html] +[test_bug869040.html] +[test_bug870787.html] +[test_bug874758.html] +[test_bug879319.html] +[test_bug885024.html] +[test_bug893537.html] +[test_bug95530.html] +[test_bug969346.html] +[test_bug982039.html] +[test_bug1003539.html] +[test_bug1045270.html] +[test_bug1089326.html] +[test_bug1146116.html] +[test_bug1264157.html] +[test_bug1287321.html] +[test_bug1323815.html] +[test_change_crossorigin.html] +skip-if = + http3 +[test_checked.html] +[test_dir_attributes_reflection.html] +[test_dl_attributes_reflection.html] +[test_element_prototype.html] +[test_embed_attributes_reflection.html] +[test_focusshift_button.html] +[test_formData.html] +[test_formSubmission.html] +skip-if = toolkit == 'android' #TIMED_OUT +[test_formSubmission2.html] +skip-if = toolkit == 'android' +[test_formelements.html] +[test_hidden.html] +[test_html_attributes_reflection.html] +[test_htmlcollection.html] +[test_iframe_sandbox_general.html] +tags = openwindow +skip-if = + http3 +[test_iframe_sandbox_inheritance.html] +tags = openwindow +[test_iframe_sandbox_navigation.html] +tags = openwindow +[test_iframe_sandbox_navigation2.html] +tags = openwindow +[test_iframe_sandbox_popups.html] +tags = openwindow +[test_iframe_sandbox_popups_inheritance.html] +tags = openwindow +[test_iframe_sandbox_redirect.html] +[test_iframe_sandbox_refresh.html] +[test_iframe_sandbox_same_origin.html] +[test_iframe_sandbox_workers.html] +[test_img_attributes_reflection.html] +[test_imageSrcSet.html] +[test_inputmode.html] +[test_li_attributes_reflection.html] +[test_link_attributes_reflection.html] +[test_link_sizes.html] +[test_map_attributes_reflection.html] +[test_meta_attributes_reflection.html] +[test_mod_attributes_reflection.html] +[test_named_options.html] +[test_nested_invalid_fieldsets.html] +[test_object_attributes_reflection.html] +[test_ol_attributes_reflection.html] +[test_option_defaultSelected.html] +[test_option_selected_state.html] +[test_param_attributes_reflection.html] +[test_q_attributes_reflection.html] +[test_restore_from_parser_fragment.html] +[test_rowscollection.html] +[test_srcdoc-2.html] +[test_srcdoc.html] +[test_style_attributes_reflection.html] +[test_track.html] +[test_ul_attributes_reflection.html] +[test_input_file_cancel_event.html] +[test_input_files_not_nsIFile.html] +[test_input_lastInteractiveValue.html] +[test_fragment_form_pointer.html] +[test_bug1682.html] +[test_bug1823.html] +[test_bug57600.html] +[test_bug196523.html] +skip-if = + http3 +[test_bug199692.html] +[test_bug255820.html] +[test_bug259332.html] +[test_bug311681.html] +[test_bug311681.xhtml] +[test_bug324378.html] +[test_bug332848.xhtml] +[test_bug340017.xhtml] +[test_bug359657.html] +[test_bug369370.html] +skip-if = toolkit == "android" + os == 'linux' # disabled on linux bug 1258103 +[test_bug380383.html] +[test_bug402680.html] +[test_bug403868.html] +[test_bug403868.xhtml] +[test_bug435128.html] +skip-if = true # Disabled for timeouts. +[test_bug463104.html] +[test_form-parsing.html] +[test_documentAll.html] +[test_document-element-inserted.html] +[test_bug445004.html] +skip-if = true # Disabled permanently (bug 559932). +[test_bug446483.html] +[test_bug448564.html] +[test_bug478251.html] +[test_bug481440.html] +[test_bug481647.html] +[test_bug482659.html] +[test_bug486741.html] +[test_bug489532.html] +[test_bug497242.xhtml] +[test_bug499092.html] +[test_bug512367.html] +[test_bug677495.html] +[test_bug677495-1.html] +[test_bug741266.html] +skip-if = toolkit == "android" # Android: needs control of popup window size +[test_non-ascii-cookie.html] +support-files = file_cookiemanager.js +skip-if = + xorigin + http3 +[test_bug765780.html] +[test_bug871161.html] +support-files = file_bug871161-1.html file_bug871161-2.html +skip-if = + http3 +[test_bug1013316.html] +[test_window_open_close.html] +tags = openwindow +skip-if = (toolkit == "android" && debug) || (os == "linux") || (os == "win" && debug && bits == 64) # Bug 1533759 +[test_viewport_resize.html] +[test_image_clone_load.html] +skip-if = + http3 +[test_bug1203668.html] +[test_bug1166138.html] +[test_bug1230665.html] +[test_filepicker_default_directory.html] +[test_bug1250401.html] +[test_bug1260664.html] +[test_bug1261673.html] +skip-if = (os == 'android' || os == 'mac') +[test_bug1261674-1.html] +skip-if = (os == 'android' || os == 'mac') +[test_bug1261674-2.html] +skip-if = (os == 'mac') +[test_bug1260704.html] +skip-if = + http3 +[test_allowMedia.html] +skip-if = (verify && (os == 'linux' || os == 'win')) || ((!debug && os == "mac" && bits == 64) || (debug && os == "win") || (debug && os == "linux" && os_version == '18.04')) #Bug 1434744 +[test_bug1292522_same_domain_with_different_port_number.html] +skip-if = + http3 +[test_bug1295719_event_sequence_for_arrow_keys.html] +skip-if = os == "android" # up/down arrow keys not supported on android +[test_bug1295719_event_sequence_for_number_keys.html] +[test_bug1310865.html] +[test_bug1315146.html] +skip-if = + http3 +[test_bug1322678.html] +skip-if = toolkit == "android" +[test_bug1472426.html] +[test_bug1785739.html] +[test_fakepath.html] +[test_script_module.html] +support-files = + file_script_module.html + file_script_nomodule.html +[test_getElementsByName_after_mutation.html] +[test_bug1279218.html] +[test_set_input_files.html] +[test_nestediframe.html] +[test_multipleFilePicker.html] +[test_window_open_from_closing.html] +skip-if = toolkit == "android" # test does not function on android due to aggressive background tab freezing +support-files = + file_window_close_and_open.html + file_broadcast_load.html +[test_frame_count_with_synthetic_doc.html] diff --git a/dom/html/test/nnc_lockup.gif b/dom/html/test/nnc_lockup.gif new file mode 100644 index 0000000000..f746bb71d9 Binary files /dev/null and b/dom/html/test/nnc_lockup.gif differ diff --git a/dom/html/test/object_bug287465_o1.html b/dom/html/test/object_bug287465_o1.html new file mode 100644 index 0000000000..0a65a7f9e1 --- /dev/null +++ b/dom/html/test/object_bug287465_o1.html @@ -0,0 +1 @@ + diff --git a/dom/html/test/object_bug287465_o2.html b/dom/html/test/object_bug287465_o2.html new file mode 100644 index 0000000000..18ecdcb795 --- /dev/null +++ b/dom/html/test/object_bug287465_o2.html @@ -0,0 +1 @@ + diff --git a/dom/html/test/object_bug556645.html b/dom/html/test/object_bug556645.html new file mode 100644 index 0000000000..773837502a --- /dev/null +++ b/dom/html/test/object_bug556645.html @@ -0,0 +1 @@ + diff --git a/dom/html/test/post_action_page.html b/dom/html/test/post_action_page.html new file mode 100644 index 0000000000..ba6ae514f2 --- /dev/null +++ b/dom/html/test/post_action_page.html @@ -0,0 +1,10 @@ + + + + + Submission Flush Test Post Action Page + + +

Post Action Page

+ + diff --git a/dom/html/test/reflect.js b/dom/html/test/reflect.js new file mode 100644 index 0000000000..44f73ae4a2 --- /dev/null +++ b/dom/html/test/reflect.js @@ -0,0 +1,1078 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * reflect.js is a collection of methods to test HTML attribute reflection. + * Each of attribute is reflected differently, depending on various parameters, + * see: + * http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes + * + * Do not forget to add these line at the beginning of each new reflect* method: + * ok(attr in element, attr + " should be an IDL attribute of this element"); + * is(typeof element[attr], , attr + " IDL attribute should be a "); + */ + +/** + * Checks that a given attribute is correctly reflected as a string. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + * - otherValues Array [optional] other values to test in addition of the default ones + * - extendedAttributes Object object which can have 'TreatNullAs': "EmptyString" + */ +function reflectString(aParameters) { + var element = aParameters.element; + var contentAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.content; + var idlAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.idl; + var otherValues = + aParameters.otherValues !== undefined ? aParameters.otherValues : []; + var treatNullAs = aParameters.extendedAttributes + ? aParameters.extendedAttributes.TreatNullAs + : null; + + ok( + idlAttr in element, + idlAttr + " should be an IDL attribute of this element" + ); + is( + typeof element[idlAttr], + "string", + "'" + idlAttr + "' IDL attribute should be a string" + ); + + // Tests when the attribute isn't set. + is( + element.getAttribute(contentAttr), + null, + "When not set, the content attribute should be null." + ); + is( + element[idlAttr], + "", + "When not set, the IDL attribute should return the empty string" + ); + + /** + * TODO: as long as null stringification doesn't follow the WebIDL + * specifications, don't add it to the loop below and keep it here. + */ + element.setAttribute(contentAttr, null); + is( + element.getAttribute(contentAttr), + "null", + "null should have been stringified to 'null' for '" + contentAttr + "'" + ); + is( + element[idlAttr], + "null", + "null should have been stringified to 'null' for '" + idlAttr + "'" + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = null; + if (treatNullAs == "EmptyString") { + is( + element.getAttribute(contentAttr), + "", + "null should have been stringified to '' for '" + contentAttr + "'" + ); + is( + element[idlAttr], + "", + "null should have been stringified to '' for '" + idlAttr + "'" + ); + } else { + is( + element.getAttribute(contentAttr), + "null", + "null should have been stringified to 'null' for '" + contentAttr + "'" + ); + is( + element[idlAttr], + "null", + "null should have been stringified to 'null' for '" + contentAttr + "'" + ); + } + element.removeAttribute(contentAttr); + + // Tests various strings. + var stringsToTest = [ + // [ test value, expected result ] + ["", ""], + ["null", "null"], + ["undefined", "undefined"], + ["foo", "foo"], + [contentAttr, contentAttr], + [idlAttr, idlAttr], + // TODO: uncomment this when null stringification will follow the specs. + // [ null, "null" ], + [undefined, "undefined"], + [true, "true"], + [false, "false"], + [42, "42"], + // ES5, verse 8.12.8. + [ + { + toString() { + return "foo"; + }, + }, + "foo", + ], + [ + { + valueOf() { + return "foo"; + }, + }, + "[object Object]", + ], + [ + { + valueOf() { + return "quux"; + }, + toString: undefined, + }, + "quux", + ], + [ + { + valueOf() { + return "foo"; + }, + toString() { + return "bar"; + }, + }, + "bar", + ], + ]; + + otherValues.forEach(function (v) { + stringsToTest.push([v, v]); + }); + + stringsToTest.forEach(function ([v, r]) { + element.setAttribute(contentAttr, v); + is( + element[idlAttr], + r, + "IDL attribute '" + + idlAttr + + "' should return the value it has been set to." + ); + is( + element.getAttribute(contentAttr), + r, + "Content attribute '" + + contentAttr + + "'should return the value it has been set to." + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + is( + element[idlAttr], + r, + "IDL attribute '" + + idlAttr + + "' should return the value it has been set to." + ); + is( + element.getAttribute(contentAttr), + r, + "Content attribute '" + + contentAttr + + "' should return the value it has been set to." + ); + element.removeAttribute(contentAttr); + }); + + // Tests after removeAttribute() is called. Should be equivalent with not set. + is( + element.getAttribute(contentAttr), + null, + "When not set, the content attribute should be null." + ); + is( + element[idlAttr], + "", + "When not set, the IDL attribute should return the empty string" + ); +} + +/** + * Checks that a given attribute name for a given element is correctly reflected + * as an unsigned int. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * - nonZero Boolean whether the attribute should be non-null + * - defaultValue Integer [optional] default value, if different from the default one + */ +function reflectUnsignedInt(aParameters) { + var element = aParameters.element; + var attr = aParameters.attribute; + var nonZero = aParameters.nonZero; + var defaultValue = aParameters.defaultValue; + var fallback = aParameters.fallback; + + if (defaultValue === undefined) { + if (nonZero) { + defaultValue = 1; + } else { + defaultValue = 0; + } + } + + if (fallback === undefined) { + fallback = false; + } + + ok(attr in element, attr + " should be an IDL attribute of this element"); + is( + typeof element[attr], + "number", + attr + " IDL attribute should be a number" + ); + + // Check default value. + is(element[attr], defaultValue, "default value should be " + defaultValue); + ok(!element.hasAttribute(attr), attr + " shouldn't be present"); + + var values = [1, 3, 42, 2147483647]; + + for (var value of values) { + element[attr] = value; + is(element[attr], value, "." + attr + " should be equals " + value); + is( + element.getAttribute(attr), + String(value), + "@" + attr + " should be equals " + value + ); + + element.setAttribute(attr, value); + is(element[attr], value, "." + attr + " should be equals " + value); + is( + element.getAttribute(attr), + String(value), + "@" + attr + " should be equals " + value + ); + } + + // -3000000000 is equivalent to 1294967296 when using the IDL attribute. + element[attr] = -3000000000; + is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296"); + is( + element.getAttribute(attr), + "1294967296", + "@" + attr + " should be equals to 1294967296" + ); + + // When setting the content attribute, it's a string so it will be invalid. + element.setAttribute(attr, -3000000000); + is( + element.getAttribute(attr), + "-3000000000", + "@" + attr + " should be equals to " + -3000000000 + ); + is( + element[attr], + defaultValue, + "." + attr + " should be equals to " + defaultValue + ); + + // When interpreted as unsigned 32-bit integers, all of these fall between + // 2^31 and 2^32 - 1, so per spec they return the default value. + var nonValidValues = [-2147483648, -1, 3147483647]; + + for (var value of nonValidValues) { + element[attr] = value; + is( + element.getAttribute(attr), + String(defaultValue), + "@" + attr + " should be equals to " + defaultValue + ); + is( + element[attr], + defaultValue, + "." + attr + " should be equals to " + defaultValue + ); + } + + for (var values of nonValidValues) { + element.setAttribute(attr, values[0]); + is( + element.getAttribute(attr), + String(values[0]), + "@" + attr + " should be equals to " + values[0] + ); + is( + element[attr], + defaultValue, + "." + attr + " should be equals to " + defaultValue + ); + } + + // Setting to 0 should throw an error if nonZero is true. + var caught = false; + try { + element[attr] = 0; + } catch (e) { + caught = true; + is(e.name, "IndexSizeError", "exception should be IndexSizeError"); + is( + e.code, + DOMException.INDEX_SIZE_ERR, + "exception code should be INDEX_SIZE_ERR" + ); + } + + if (nonZero && !fallback) { + ok(caught, "an exception should have been caught"); + } else { + ok(!caught, "no exception should have been caught"); + } + + // If 0 is set in @attr, it will be ignored when calling .attr. + element.setAttribute(attr, "0"); + is(element.getAttribute(attr), "0", "@" + attr + " should be equals to 0"); + if (nonZero) { + is( + element[attr], + defaultValue, + "." + attr + " should be equals to " + defaultValue + ); + } else { + is(element[attr], 0, "." + attr + " should be equals to 0"); + } +} + +/** + * Checks that a given attribute is correctly reflected as limited to known + * values enumerated attribute. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + * - validValues Array valid values we support + * - invalidValues Array invalid values + * - defaultValue String [optional] default value when no valid value is set + * OR + * defaultValue Object [optional] object containing two attributes, 'invalid' and 'missing' + * - unsupportedValues Array [optional] valid values we do not support + * - nullable boolean [optional] whether the attribute is nullable + */ +function reflectLimitedEnumerated(aParameters) { + var element = aParameters.element; + var contentAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.content; + var idlAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.idl; + var validValues = aParameters.validValues; + var invalidValues = aParameters.invalidValues; + var defaultValueInvalid = + aParameters.defaultValue === undefined + ? "" + : typeof aParameters.defaultValue === "string" + ? aParameters.defaultValue + : aParameters.defaultValue.invalid; + var defaultValueMissing = + aParameters.defaultValue === undefined + ? "" + : typeof aParameters.defaultValue === "string" + ? aParameters.defaultValue + : aParameters.defaultValue.missing; + var unsupportedValues = + aParameters.unsupportedValues !== undefined + ? aParameters.unsupportedValues + : []; + var nullable = aParameters.nullable; + + ok( + idlAttr in element, + idlAttr + " should be an IDL attribute of this element" + ); + if (nullable) { + // The missing value default is null, which is typeof == "object" + is( + typeof element[idlAttr], + "object", + "'" + + idlAttr + + "' IDL attribute should be null, which has typeof == object" + ); + is( + element[idlAttr], + null, + "'" + idlAttr + "' IDL attribute should be null" + ); + } else { + is( + typeof element[idlAttr], + "string", + "'" + idlAttr + "' IDL attribute should be a string" + ); + } + + if (nullable) { + element.setAttribute(contentAttr, "something"); + // Now it will be a string + is( + typeof element[idlAttr], + "string", + "'" + idlAttr + "' IDL attribute should be a string" + ); + } + + // Explicitly check the default value. + element.removeAttribute(contentAttr); + is( + element[idlAttr], + defaultValueMissing, + "When no attribute is set, the value should be the default value." + ); + + // Check valid values. + validValues.forEach(function (v) { + element.setAttribute(contentAttr, v); + is( + element[idlAttr], + v, + "'" + v + "' should be accepted as a valid value for " + idlAttr + ); + is( + element.getAttribute(contentAttr), + v, + "Content attribute should return the value it has been set to." + ); + element.removeAttribute(contentAttr); + + element.setAttribute(contentAttr, v.toUpperCase()); + is( + element[idlAttr], + v, + "Enumerated attributes should be case-insensitive." + ); + is( + element.getAttribute(contentAttr), + v.toUpperCase(), + "Content attribute should not be lower-cased." + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + is( + element[idlAttr], + v, + "'" + v + "' should be accepted as a valid value for " + idlAttr + ); + is( + element.getAttribute(contentAttr), + v, + "Content attribute should return the value it has been set to." + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = v.toUpperCase(); + is( + element[idlAttr], + v, + "Enumerated attributes should be case-insensitive." + ); + is( + element.getAttribute(contentAttr), + v.toUpperCase(), + "Content attribute should not be lower-cased." + ); + element.removeAttribute(contentAttr); + }); + + // Check invalid values. + invalidValues.forEach(function (v) { + element.setAttribute(contentAttr, v); + is( + element[idlAttr], + defaultValueInvalid, + "When the content attribute is set to an invalid value, the default value should be returned." + ); + is( + element.getAttribute(contentAttr), + v, + "Content attribute should not have been changed." + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + is( + element[idlAttr], + defaultValueInvalid, + "When the value is set to an invalid value, the default value should be returned." + ); + is( + element.getAttribute(contentAttr), + v, + "Content attribute should not have been changed." + ); + element.removeAttribute(contentAttr); + }); + + // Check valid values we currently do not support. + // Basically, it's like the checks for the valid values but with some todo's. + unsupportedValues.forEach(function (v) { + element.setAttribute(contentAttr, v); + todo_is( + element[idlAttr], + v, + "'" + v + "' should be accepted as a valid value for " + idlAttr + ); + is( + element.getAttribute(contentAttr), + v, + "Content attribute should return the value it has been set to." + ); + element.removeAttribute(contentAttr); + + element.setAttribute(contentAttr, v.toUpperCase()); + todo_is( + element[idlAttr], + v, + "Enumerated attributes should be case-insensitive." + ); + is( + element.getAttribute(contentAttr), + v.toUpperCase(), + "Content attribute should not be lower-cased." + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + todo_is( + element[idlAttr], + v, + "'" + v + "' should be accepted as a valid value for " + idlAttr + ); + is( + element.getAttribute(contentAttr), + v, + "Content attribute should return the value it has been set to." + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = v.toUpperCase(); + todo_is( + element[idlAttr], + v, + "Enumerated attributes should be case-insensitive." + ); + is( + element.getAttribute(contentAttr), + v.toUpperCase(), + "Content attribute should not be lower-cased." + ); + element.removeAttribute(contentAttr); + }); + + if (nullable) { + is( + defaultValueMissing, + null, + "Missing default value should be null for nullable attributes" + ); + ok(validValues.length, "We better have at least one valid value"); + element.setAttribute(contentAttr, validValues[0]); + ok( + element.hasAttribute(contentAttr), + "Should have content attribute: we just set it" + ); + element[idlAttr] = null; + ok( + !element.hasAttribute(contentAttr), + "Should have removed content attribute" + ); + } +} + +/** + * Checks that a given attribute is correctly reflected as a boolean. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + */ +function reflectBoolean(aParameters) { + var element = aParameters.element; + var contentAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.content; + var idlAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.idl; + + ok( + idlAttr in element, + idlAttr + " should be an IDL attribute of this element" + ); + is( + typeof element[idlAttr], + "boolean", + idlAttr + " IDL attribute should be a boolean" + ); + + // Tests when the attribute isn't set. + is( + element.getAttribute(contentAttr), + null, + "When not set, the content attribute should be null." + ); + is( + element[idlAttr], + false, + "When not set, the IDL attribute should return false" + ); + + /** + * Test various values. + * Each value to test is actually an object containing a 'value' property + * containing the value to actually test, a 'stringified' property containing + * the stringified value and a 'result' property containing the expected + * result when the value is set to the IDL attribute. + */ + var valuesToTest = [ + { value: true, stringified: "true", result: true }, + { value: false, stringified: "false", result: false }, + { value: "true", stringified: "true", result: true }, + { value: "false", stringified: "false", result: true }, + { value: "foo", stringified: "foo", result: true }, + { value: idlAttr, stringified: idlAttr, result: true }, + { value: contentAttr, stringified: contentAttr, result: true }, + { value: "null", stringified: "null", result: true }, + { value: "undefined", stringified: "undefined", result: true }, + { value: "", stringified: "", result: false }, + { value: undefined, stringified: "undefined", result: false }, + { value: null, stringified: "null", result: false }, + { value: +0, stringified: "0", result: false }, + { value: -0, stringified: "0", result: false }, + { value: NaN, stringified: "NaN", result: false }, + { value: 42, stringified: "42", result: true }, + { value: Infinity, stringified: "Infinity", result: true }, + { value: -Infinity, stringified: "-Infinity", result: true }, + // ES5, verse 9.2. + { + value: { + toString() { + return "foo"; + }, + }, + stringified: "foo", + result: true, + }, + { + value: { + valueOf() { + return "foo"; + }, + }, + stringified: "[object Object]", + result: true, + }, + { + value: { + valueOf() { + return "quux"; + }, + toString: undefined, + }, + stringified: "quux", + result: true, + }, + { + value: { + valueOf() { + return "foo"; + }, + toString() { + return "bar"; + }, + }, + stringified: "bar", + result: true, + }, + { + value: { + valueOf() { + return false; + }, + }, + stringified: "[object Object]", + result: true, + }, + { + value: { foo: false, bar: false }, + stringified: "[object Object]", + result: true, + }, + { value: {}, stringified: "[object Object]", result: true }, + ]; + + valuesToTest.forEach(function (v) { + element.setAttribute(contentAttr, v.value); + is( + element[idlAttr], + true, + "IDL attribute should return always return 'true' if the content attribute has been set" + ); + is( + element.getAttribute(contentAttr), + v.stringified, + "Content attribute should return the stringified value it has been set to." + ); + element.removeAttribute(contentAttr); + + element[idlAttr] = v.value; + is(element[idlAttr], v.result, "IDL attribute should return " + v.result); + is( + element.getAttribute(contentAttr), + v.result ? "" : null, + v.result + ? "Content attribute should return the empty string." + : "Content attribute should return null." + ); + is( + element.hasAttribute(contentAttr), + v.result, + v.result + ? contentAttr + " should not be present" + : contentAttr + " should be present" + ); + element.removeAttribute(contentAttr); + }); + + // Tests after removeAttribute() is called. Should be equivalent with not set. + is( + element.getAttribute(contentAttr), + null, + "When not set, the content attribute should be null." + ); + is( + element[contentAttr], + false, + "When not set, the IDL attribute should return false" + ); +} + +/** + * Checks that a given attribute name for a given element is correctly reflected + * as an signed integer. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * - nonNegative Boolean true if the attribute is limited to 'non-negative numbers', false otherwise + * - defaultValue Integer [optional] default value, if one exists + */ +function reflectInt(aParameters) { + // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute(). + function expectedGetAttributeResult(value) { + return String(value); + } + + function stringToInteger(value, nonNegative, defaultValue) { + // Parse: Ignore leading whitespace, find [+/-][numbers] + var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value); + if (result) { + var resultInt = parseInt(result[1], 10); + if ( + (nonNegative ? 0 : -0x80000000) <= resultInt && + resultInt <= 0x7fffffff + ) { + // If the value is within allowed value range for signed/unsigned + // integer, return it -- but add 0 to it to convert a possible -0 into + // +0, the only zero present in the signed integer range. + return resultInt + 0; + } + } + return defaultValue; + } + + // Expected value returned by .getAttribute(attr) or .attr if |value| has been set via the IDL attribute. + function expectedIdlAttributeResult(value) { + // This returns the result of calling the ES ToInt32 algorithm on value. + return value << 0; + } + + var element = aParameters.element; + var attr = aParameters.attribute; + var nonNegative = aParameters.nonNegative; + + var defaultValue = + aParameters.defaultValue !== undefined + ? aParameters.defaultValue + : nonNegative + ? -1 + : 0; + + ok(attr in element, attr + " should be an IDL attribute of this element"); + is( + typeof element[attr], + "number", + attr + " IDL attribute should be a number" + ); + + // Check default value. + is(element[attr], defaultValue, "default value should be " + defaultValue); + ok(!element.hasAttribute(attr), attr + " shouldn't be present"); + + /** + * Test various values. + * value: The test value that will be set using both setAttribute(value) and + * element[attr] = value + */ + var valuesToTest = [ + // Test numeric inputs up to max signed integer + 0, + 1, + 55555, + 2147483647, + +42, + // Test string inputs up to max signed integer + "0", + "1", + "777777", + "2147483647", + "+42", + // Test negative numeric inputs up to min signed integer + -0, + -1, + -3333, + -2147483648, + // Test negative string inputs up to min signed integer + "-0", + "-1", + "-222", + "-2147483647", + "-2147483648", + // Test numeric inputs that are outside legal 32 bit signed values + -2147483649, + -3000000000, + -4294967296, + 2147483649, + 4000000000, + -4294967297, + // Test string inputs with extra padding + " 1111111", + " 23456 ", + // Test non-numeric string inputs + "", + " ", + "+", + "-", + "foo", + "+foo", + "-foo", + "+ foo", + "- foo", + "+-2", + "-+2", + "++2", + "--2", + "hello1234", + "1234hello", + "444 world 555", + "why 567 what", + "-3 nots", + "2e5", + "300e2", + "42+-$", + "+42foo", + "-514not", + "\vblah", + "0x10FFFF", + "-0xABCDEF", + // Test decimal numbers + 1.2345, + 42.0, + 3456789.1, + -2.3456, + -6789.12345, + -2147483649.1234, + // Test decimal strings + "1.2345", + "42.0", + "3456789.1", + "-2.3456", + "-6789.12345", + "-2147483649.1234", + // Test special values + undefined, + null, + NaN, + Infinity, + -Infinity, + ]; + + valuesToTest.forEach(function (v) { + var intValue = stringToInteger(v, nonNegative, defaultValue); + + element.setAttribute(attr, v); + + is( + element.getAttribute(attr), + expectedGetAttributeResult(v), + element.localName + + ".setAttribute(" + + attr + + ", " + + v + + "), " + + element.localName + + ".getAttribute(" + + attr + + ") " + ); + + is( + element[attr], + intValue, + element.localName + + ".setAttribute(" + + attr + + ", " + + v + + "), " + + element.localName + + "[" + + attr + + "] " + ); + element.removeAttribute(attr); + + if (nonNegative && expectedIdlAttributeResult(v) < 0) { + try { + element[attr] = v; + ok( + false, + element.localName + + "[" + + attr + + "] = " + + v + + " should throw IndexSizeError" + ); + } catch (e) { + is( + e.name, + "IndexSizeError", + element.localName + + "[" + + attr + + "] = " + + v + + " should throw IndexSizeError" + ); + is( + e.code, + DOMException.INDEX_SIZE_ERR, + element.localName + + "[" + + attr + + "] = " + + v + + " should throw INDEX_SIZE_ERR" + ); + } + } else { + element[attr] = v; + is( + element[attr], + expectedIdlAttributeResult(v), + element.localName + + "[" + + attr + + "] = " + + v + + ", " + + element.localName + + "[" + + attr + + "] " + ); + is( + element.getAttribute(attr), + String(expectedIdlAttributeResult(v)), + element.localName + + "[" + + attr + + "] = " + + v + + ", " + + element.localName + + ".getAttribute(" + + attr + + ") " + ); + } + element.removeAttribute(attr); + }); + + // Tests after removeAttribute() is called. Should be equivalent with not set. + is( + element.getAttribute(attr), + null, + "When not set, the content attribute should be null." + ); + is( + element[attr], + defaultValue, + "When not set, the IDL attribute should return default value." + ); +} + +/** + * Checks that a given attribute is correctly reflected as a url. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + */ +function reflectURL(aParameters) { + var element = aParameters.element; + var contentAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.content; + var idlAttr = + typeof aParameters.attribute === "string" + ? aParameters.attribute + : aParameters.attribute.idl; + + element[idlAttr] = ""; + is( + element[idlAttr], + document.URL, + "Empty string should resolve to document URL" + ); +} diff --git a/dom/html/test/script_fakepath.js b/dom/html/test/script_fakepath.js new file mode 100644 index 0000000000..ac24dc90a2 --- /dev/null +++ b/dom/html/test/script_fakepath.js @@ -0,0 +1,15 @@ +/* eslint-env mozilla/chrome-script */ + +Cu.importGlobalProperties(["File"]); + +addMessageListener("file.open", function (e) { + var tmpFile = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIDirectoryService) + .QueryInterface(Ci.nsIProperties) + .get("ProfD", Ci.nsIFile); + tmpFile.append("prefs.js"); + + File.createFromNsIFile(tmpFile).then(file => { + sendAsyncMessage("file.opened", { data: [file] }); + }); +}); diff --git a/dom/html/test/simpleFileOpener.js b/dom/html/test/simpleFileOpener.js new file mode 100644 index 0000000000..9cec9cbf18 --- /dev/null +++ b/dom/html/test/simpleFileOpener.js @@ -0,0 +1,37 @@ +/* eslint-env mozilla/chrome-script */ + +Cu.importGlobalProperties(["File"]); + +var file; + +addMessageListener("file.open", function (stem) { + try { + if (!file) { + file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties) + .get("TmpD", Ci.nsIFile); + file.append(stem); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + } + + File.createFromNsIFile(file).then(function (domFile) { + sendAsyncMessage("file.opened", { + fullPath: file.path, + leafName: file.leafName, + domFile, + }); + }); + } catch (e) { + sendAsyncMessage("fail", e.toString()); + } +}); + +addMessageListener("file.remove", function () { + try { + file.remove(/* recursive: */ false); + file = undefined; + sendAsyncMessage("file.removed", null); + } catch (e) { + sendAsyncMessage("fail", e.toString()); + } +}); diff --git a/dom/html/test/submission_flush.html b/dom/html/test/submission_flush.html new file mode 100644 index 0000000000..f70884c66a --- /dev/null +++ b/dom/html/test/submission_flush.html @@ -0,0 +1,13 @@ + + + + + Submission Flush Test + + +
+ +
+ + + diff --git a/dom/html/test/sw_formSubmission.js b/dom/html/test/sw_formSubmission.js new file mode 100644 index 0000000000..e7b4a7872c --- /dev/null +++ b/dom/html/test/sw_formSubmission.js @@ -0,0 +1,36 @@ +/** + * We are used by test_formSubmission.html to immediately activate and start + * controlling its page. We operate in 3 modes, conveyed via ?MODE appended to + * our URL. + * + * - "no-fetch": Don't register a fetch listener so that the optimized fetch + * event bypass happens. + * - "reset-fetch": Do register a fetch listener, reset every interception. + * - "proxy-fetch": Do register a fetch listener, resolve every interception + * with fetch(event.request). + */ + +const mode = location.search.slice(1); + +// Fetch handling. +if (mode !== "no-fetch") { + addEventListener("fetch", function (event) { + if (mode === "reset-fetch") { + // Don't invoke respondWith, resetting the interception. + return; + } else if (mode === "proxy-fetch") { + // Per the spec, there's an automatic waitUntil() on this too. + event.respondWith(fetch(event.request)); + return; + } + }); +} + +// Go straight to activation, bypassing waiting. +addEventListener("install", function (event) { + event.waitUntil(skipWaiting()); +}); +// Control the test document ASAP. +addEventListener("activate", function (event) { + event.waitUntil(clients.claim()); +}); diff --git a/dom/html/test/test_a_text.html b/dom/html/test/test_a_text.html new file mode 100644 index 0000000000..5ffc1995f8 --- /dev/null +++ b/dom/html/test/test_a_text.html @@ -0,0 +1,44 @@ + + + + Test for a.text + + + + + + +
+
+
+ + diff --git a/dom/html/test/test_allowMedia.html b/dom/html/test/test_allowMedia.html new file mode 100644 index 0000000000..46a692283a --- /dev/null +++ b/dom/html/test/test_allowMedia.html @@ -0,0 +1,97 @@ + + + + + + Test for Bug 759964 + + + + + +Mozilla Bug 759964 +

+

+ + diff --git a/dom/html/test/test_anchor_href_cache_invalidation.html b/dom/html/test/test_anchor_href_cache_invalidation.html new file mode 100644 index 0000000000..c1a8327e62 --- /dev/null +++ b/dom/html/test/test_anchor_href_cache_invalidation.html @@ -0,0 +1,30 @@ + + + + Test for anchor cache invalidation + + + + +

+ +
+
+
+ + diff --git a/dom/html/test/test_anchor_ping.html b/dom/html/test/test_anchor_ping.html new file mode 100644 index 0000000000..309542b80e --- /dev/null +++ b/dom/html/test/test_anchor_ping.html @@ -0,0 +1,300 @@ + + + + + + Test for Bug 786347 + + + + + +Mozilla Bug 786347 +

+ + +
+
+
+
+ + + diff --git a/dom/html/test/test_bug1013316.html b/dom/html/test/test_bug1013316.html new file mode 100644 index 0000000000..fdb9e5363d --- /dev/null +++ b/dom/html/test/test_bug1013316.html @@ -0,0 +1,46 @@ + + + + + + Test for Bug 1013316 + + + + + +Mozilla Bug 1013316 +

+