summaryrefslogtreecommitdiffstats
path: root/layout/base/tests
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /layout/base/tests
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'layout/base/tests')
-rw-r--r--layout/base/tests/Ahem.ttfbin0 -> 12480 bytes
-rw-r--r--layout/base/tests/border_radius_hit_testing_iframe.html27
-rw-r--r--layout/base/tests/browser.ini6
-rw-r--r--layout/base/tests/browser_bug617076.js46
-rw-r--r--layout/base/tests/browser_disableDialogs_onbeforeunload.js56
-rw-r--r--layout/base/tests/browser_onbeforeunload_only_after_interaction.js53
-rw-r--r--layout/base/tests/browser_onbeforeunload_only_after_interaction_in_frame.js59
-rw-r--r--layout/base/tests/bug1007065-1-ref.html15
-rw-r--r--layout/base/tests/bug1007065-1.html15
-rw-r--r--layout/base/tests/bug1007067-1-ref.html20
-rw-r--r--layout/base/tests/bug1007067-1.html20
-rw-r--r--layout/base/tests/bug1061468-ref.html13
-rw-r--r--layout/base/tests/bug1061468.html40
-rw-r--r--layout/base/tests/bug106855-1-ref.html27
-rw-r--r--layout/base/tests/bug106855-1.html25
-rw-r--r--layout/base/tests/bug106855-2.html26
-rw-r--r--layout/base/tests/bug1078327_inner.html107
-rw-r--r--layout/base/tests/bug1080360_inner.html83
-rw-r--r--layout/base/tests/bug1080361_inner.html113
-rw-r--r--layout/base/tests/bug1082486-1-ref.html18
-rw-r--r--layout/base/tests/bug1082486-1.html27
-rw-r--r--layout/base/tests/bug1082486-2-ref.html12
-rw-r--r--layout/base/tests/bug1082486-2.html12
-rw-r--r--layout/base/tests/bug1093686_inner.html84
-rw-r--r--layout/base/tests/bug1097242-1-ref.html14
-rw-r--r--layout/base/tests/bug1097242-1.html18
-rw-r--r--layout/base/tests/bug1109968-1-ref.html17
-rw-r--r--layout/base/tests/bug1109968-1.html23
-rw-r--r--layout/base/tests/bug1109968-2-ref.html17
-rw-r--r--layout/base/tests/bug1109968-2.html23
-rw-r--r--layout/base/tests/bug1123067-1.html38
-rw-r--r--layout/base/tests/bug1123067-2.html34
-rw-r--r--layout/base/tests/bug1123067-3.html35
-rw-r--r--layout/base/tests/bug1123067-ref.html33
-rw-r--r--layout/base/tests/bug1132768-1-ref.html12
-rw-r--r--layout/base/tests/bug1132768-1.html17
-rw-r--r--layout/base/tests/bug1153130_inner.html72
-rw-r--r--layout/base/tests/bug1162990_inner_1.html145
-rw-r--r--layout/base/tests/bug1162990_inner_2.html146
-rw-r--r--layout/base/tests/bug1226904.html35
-rw-r--r--layout/base/tests/bug1237236-1-ref.html30
-rw-r--r--layout/base/tests/bug1237236-1.html31
-rw-r--r--layout/base/tests/bug1237236-2-ref.html32
-rw-r--r--layout/base/tests/bug1237236-2.html30
-rw-r--r--layout/base/tests/bug1258308-1-ref.html32
-rw-r--r--layout/base/tests/bug1258308-1.html40
-rw-r--r--layout/base/tests/bug1258308-2-ref.html37
-rw-r--r--layout/base/tests/bug1258308-2.html31
-rw-r--r--layout/base/tests/bug1259949-1-ref.html30
-rw-r--r--layout/base/tests/bug1259949-1.html34
-rw-r--r--layout/base/tests/bug1259949-2-ref.html36
-rw-r--r--layout/base/tests/bug1259949-2.html30
-rw-r--r--layout/base/tests/bug1263288-ref.html28
-rw-r--r--layout/base/tests/bug1263288.html30
-rw-r--r--layout/base/tests/bug1263357-1-ref.html28
-rw-r--r--layout/base/tests/bug1263357-1.html34
-rw-r--r--layout/base/tests/bug1263357-2-ref.html28
-rw-r--r--layout/base/tests/bug1263357-2.html34
-rw-r--r--layout/base/tests/bug1263357-3-ref.html27
-rw-r--r--layout/base/tests/bug1263357-3.html28
-rw-r--r--layout/base/tests/bug1263357-4-ref.html27
-rw-r--r--layout/base/tests/bug1263357-4.html28
-rw-r--r--layout/base/tests/bug1263357-5-ref.html27
-rw-r--r--layout/base/tests/bug1263357-5.html28
-rw-r--r--layout/base/tests/bug240933-1-ref.html12
-rw-r--r--layout/base/tests/bug240933-1.html13
-rw-r--r--layout/base/tests/bug240933-2.html15
-rw-r--r--layout/base/tests/bug369950-subframe.xml11
-rw-r--r--layout/base/tests/bug389321-1-ref.html17
-rw-r--r--layout/base/tests/bug389321-1.html19
-rw-r--r--layout/base/tests/bug389321-2-ref.html9
-rw-r--r--layout/base/tests/bug389321-2.html9
-rw-r--r--layout/base/tests/bug389321-3-ref.html9
-rw-r--r--layout/base/tests/bug389321-3.html9
-rw-r--r--layout/base/tests/bug450930.xhtml181
-rw-r--r--layout/base/tests/bug482484-ref.html18
-rw-r--r--layout/base/tests/bug482484.html22
-rw-r--r--layout/base/tests/bug503399-ref.html44
-rw-r--r--layout/base/tests/bug503399.html43
-rw-r--r--layout/base/tests/bug512295-1-ref.html28
-rw-r--r--layout/base/tests/bug512295-1.html34
-rw-r--r--layout/base/tests/bug512295-2-ref.html28
-rw-r--r--layout/base/tests/bug512295-2.html34
-rw-r--r--layout/base/tests/bug558663.html101
-rw-r--r--layout/base/tests/bug583889_inner1.html67
-rw-r--r--layout/base/tests/bug583889_inner2.html5
-rw-r--r--layout/base/tests/bug585922-ref.html21
-rw-r--r--layout/base/tests/bug585922.html35
-rw-r--r--layout/base/tests/bug597519-1-ref.html12
-rw-r--r--layout/base/tests/bug597519-1.html16
-rw-r--r--layout/base/tests/bug602141-1-ref.html18
-rw-r--r--layout/base/tests/bug602141-1.html21
-rw-r--r--layout/base/tests/bug602141-2-ref.html18
-rw-r--r--layout/base/tests/bug602141-2.html23
-rw-r--r--layout/base/tests/bug602141-3-ref.html18
-rw-r--r--layout/base/tests/bug602141-3.html21
-rw-r--r--layout/base/tests/bug602141-4-ref.html18
-rw-r--r--layout/base/tests/bug602141-4.html21
-rw-r--r--layout/base/tests/bug612271-1.html15
-rw-r--r--layout/base/tests/bug612271-2.html15
-rw-r--r--layout/base/tests/bug612271-3.html15
-rw-r--r--layout/base/tests/bug612271-ref.html17
-rw-r--r--layout/base/tests/bug613433-1.html24
-rw-r--r--layout/base/tests/bug613433-2.html24
-rw-r--r--layout/base/tests/bug613433-3.html24
-rw-r--r--layout/base/tests/bug613433-ref.html21
-rw-r--r--layout/base/tests/bug613807-1-ref.html6
-rw-r--r--layout/base/tests/bug613807-1.html90
-rw-r--r--layout/base/tests/bug632215-1.html29
-rw-r--r--layout/base/tests/bug632215-2.html28
-rw-r--r--layout/base/tests/bug632215-ref.html17
-rw-r--r--layout/base/tests/bug633044-1-ref.html16
-rw-r--r--layout/base/tests/bug633044-1.html24
-rw-r--r--layout/base/tests/bug634406-1-ref.html10
-rw-r--r--layout/base/tests/bug634406-1.html16
-rw-r--r--layout/base/tests/bug644428-1-ref.html17
-rw-r--r--layout/base/tests/bug644428-1.html19
-rw-r--r--layout/base/tests/bug646382-1-ref.html17
-rw-r--r--layout/base/tests/bug646382-1.html22
-rw-r--r--layout/base/tests/bug646382-2-ref.html14
-rw-r--r--layout/base/tests/bug646382-2.html21
-rw-r--r--layout/base/tests/bug664087-1-ref.html21
-rw-r--r--layout/base/tests/bug664087-1.html25
-rw-r--r--layout/base/tests/bug664087-2-ref.html21
-rw-r--r--layout/base/tests/bug664087-2.html25
-rw-r--r--layout/base/tests/bug682712-1-ref.html24
-rw-r--r--layout/base/tests/bug682712-1.html32
-rw-r--r--layout/base/tests/bug687297_a.html17
-rw-r--r--layout/base/tests/bug687297_b.html17
-rw-r--r--layout/base/tests/bug687297_c.html17
-rw-r--r--layout/base/tests/bug746993-1-ref.html20
-rw-r--r--layout/base/tests/bug746993-1.html22
-rw-r--r--layout/base/tests/bug851445_helper.html11
-rw-r--r--layout/base/tests/bug921928_event_target_iframe_apps_oop.html8
-rw-r--r--layout/base/tests/bug923376-ref.html11
-rw-r--r--layout/base/tests/bug923376.html15
-rw-r--r--layout/base/tests/bug956530-1-ref.html27
-rw-r--r--layout/base/tests/bug956530-1.html35
-rw-r--r--layout/base/tests/bug966992-1-ref.html40
-rw-r--r--layout/base/tests/bug966992-1.html36
-rw-r--r--layout/base/tests/bug966992-2-ref.html42
-rw-r--r--layout/base/tests/bug966992-2.html38
-rw-r--r--layout/base/tests/bug966992-3-ref.html28
-rw-r--r--layout/base/tests/bug966992-3.html26
-rw-r--r--layout/base/tests/bug968148_inner.html295
-rw-r--r--layout/base/tests/bug970964_inner.html342
-rw-r--r--layout/base/tests/bug976963_inner.html241
-rw-r--r--layout/base/tests/bug977003_inner_1.html100
-rw-r--r--layout/base/tests/bug977003_inner_2.html75
-rw-r--r--layout/base/tests/bug977003_inner_3.html95
-rw-r--r--layout/base/tests/bug977003_inner_4.html100
-rw-r--r--layout/base/tests/bug977003_inner_5.html115
-rw-r--r--layout/base/tests/bug977003_inner_6.html101
-rw-r--r--layout/base/tests/bug989012-1-ref.html21
-rw-r--r--layout/base/tests/bug989012-1.html24
-rw-r--r--layout/base/tests/bug989012-2-ref.html26
-rw-r--r--layout/base/tests/bug989012-2.html29
-rw-r--r--layout/base/tests/bug989012-3-ref.html28
-rw-r--r--layout/base/tests/bug989012-3.html31
-rw-r--r--layout/base/tests/chrome/animated.gifbin0 -> 527 bytes
-rw-r--r--layout/base/tests/chrome/blue-32x32.pngbin0 -> 110 bytes
-rw-r--r--layout/base/tests/chrome/bug1041200_window.html45
-rw-r--r--layout/base/tests/chrome/bug495648.rdf214
-rw-r--r--layout/base/tests/chrome/bug551434_childframe.html4
-rw-r--r--layout/base/tests/chrome/chrome.ini49
-rw-r--r--layout/base/tests/chrome/chrome_content_integration_window.xul45
-rw-r--r--layout/base/tests/chrome/chrome_over_plugin_window.xul62
-rw-r--r--layout/base/tests/chrome/default_background_window.xul60
-rw-r--r--layout/base/tests/chrome/dialog_with_positioning_window.xul30
-rw-r--r--layout/base/tests/chrome/file_bug1018265.xul51
-rw-r--r--layout/base/tests/chrome/no_clip_iframe_subdoc.html7
-rw-r--r--layout/base/tests/chrome/no_clip_iframe_window.xul96
-rw-r--r--layout/base/tests/chrome/printpreview_bug396024_helper.xul123
-rw-r--r--layout/base/tests/chrome/printpreview_bug482976_helper.xul82
-rw-r--r--layout/base/tests/chrome/printpreview_helper.xul274
-rw-r--r--layout/base/tests/chrome/test_bug1018265.xul38
-rw-r--r--layout/base/tests/chrome/test_bug1041200.xul23
-rw-r--r--layout/base/tests/chrome/test_bug396367-1.html49
-rw-r--r--layout/base/tests/chrome/test_bug396367-2.html56
-rw-r--r--layout/base/tests/chrome/test_bug420499.xul129
-rw-r--r--layout/base/tests/chrome/test_bug458898.html39
-rw-r--r--layout/base/tests/chrome/test_bug495648.xul46
-rw-r--r--layout/base/tests/chrome/test_bug504311.xul35
-rw-r--r--layout/base/tests/chrome/test_bug514660.xul40
-rw-r--r--layout/base/tests/chrome/test_bug533845.xul44
-rw-r--r--layout/base/tests/chrome/test_bug551434.html97
-rw-r--r--layout/base/tests/chrome/test_bug708062.html47
-rw-r--r--layout/base/tests/chrome/test_bug812817.xul38
-rw-r--r--layout/base/tests/chrome/test_bug847890_paintFlashing.html31
-rw-r--r--layout/base/tests/chrome/test_chrome_content_integration.xul26
-rw-r--r--layout/base/tests/chrome/test_chrome_over_plugin.xul24
-rw-r--r--layout/base/tests/chrome/test_default_background.xul23
-rw-r--r--layout/base/tests/chrome/test_dialog_with_positioning.html20
-rw-r--r--layout/base/tests/chrome/test_fixed_bg_scrolling_repaints.html41
-rw-r--r--layout/base/tests/chrome/test_leaf_layers_partition_browser_window.xul114
-rw-r--r--layout/base/tests/chrome/test_no_clip_iframe.xul23
-rw-r--r--layout/base/tests/chrome/test_prerendered_transforms.html47
-rw-r--r--layout/base/tests/chrome/test_printpreview.xul16
-rw-r--r--layout/base/tests/chrome/test_printpreview_bug396024.xul22
-rw-r--r--layout/base/tests/chrome/test_printpreview_bug482976.xul22
-rw-r--r--layout/base/tests/chrome/test_scrolling_repaints.html49
-rw-r--r--layout/base/tests/chrome/test_will_change.html99
-rw-r--r--layout/base/tests/file_bug607529.html40
-rw-r--r--layout/base/tests/file_bug842853.html13
-rw-r--r--layout/base/tests/file_bug842853.sjs14
-rw-r--r--layout/base/tests/image_rgrg-256x256.pngbin0 -> 131 bytes
-rw-r--r--layout/base/tests/image_rrgg-256x256.pngbin0 -> 120 bytes
-rw-r--r--layout/base/tests/input-invalid-ref.html7
-rw-r--r--layout/base/tests/input-maxlength-invalid-change.html25
-rw-r--r--layout/base/tests/input-maxlength-ui-invalid-change.html25
-rw-r--r--layout/base/tests/input-maxlength-ui-valid-change.html28
-rw-r--r--layout/base/tests/input-maxlength-valid-before-change.html15
-rw-r--r--layout/base/tests/input-maxlength-valid-change.html28
-rw-r--r--layout/base/tests/input-minlength-invalid-change.html25
-rw-r--r--layout/base/tests/input-minlength-ui-invalid-change.html25
-rw-r--r--layout/base/tests/input-minlength-ui-valid-change.html28
-rw-r--r--layout/base/tests/input-minlength-valid-before-change.html15
-rw-r--r--layout/base/tests/input-minlength-valid-change.html28
-rw-r--r--layout/base/tests/input-ui-valid-ref.html6
-rw-r--r--layout/base/tests/input-valid-ref.html7
-rw-r--r--layout/base/tests/marionette/manifest.ini5
-rw-r--r--layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py298
-rw-r--r--layout/base/tests/marionette/test_accessiblecaret_selection_mode.py632
-rw-r--r--layout/base/tests/mochitest.ini316
-rw-r--r--layout/base/tests/multi-range-script-select-ref.html173
-rw-r--r--layout/base/tests/multi-range-script-select.html185
-rw-r--r--layout/base/tests/multi-range-user-select-ref.html166
-rw-r--r--layout/base/tests/multi-range-user-select.html223
-rw-r--r--layout/base/tests/preserve3d_sorting_hit_testing2_iframe.html97
-rw-r--r--layout/base/tests/preserve3d_sorting_hit_testing_iframe.html32
-rw-r--r--layout/base/tests/resize_flush_iframe.html17
-rw-r--r--layout/base/tests/scroll_selection_into_view_window.html66
-rw-r--r--layout/base/tests/selection-utils.js154
-rw-r--r--layout/base/tests/test_after_paint_pref.html111
-rw-r--r--layout/base/tests/test_border_radius_hit_testing.html106
-rw-r--r--layout/base/tests/test_bug1078327.html37
-rw-r--r--layout/base/tests/test_bug1080360.html37
-rw-r--r--layout/base/tests/test_bug1080361.html38
-rw-r--r--layout/base/tests/test_bug1093686.html41
-rw-r--r--layout/base/tests/test_bug1120705.html85
-rw-r--r--layout/base/tests/test_bug114649.html67
-rw-r--r--layout/base/tests/test_bug1153130.html37
-rw-r--r--layout/base/tests/test_bug1162990.html39
-rw-r--r--layout/base/tests/test_bug1226904.html44
-rw-r--r--layout/base/tests/test_bug1246622.html45
-rw-r--r--layout/base/tests/test_bug1278021.html45
-rw-r--r--layout/base/tests/test_bug332655-1.html60
-rw-r--r--layout/base/tests/test_bug332655-2.html79
-rw-r--r--layout/base/tests/test_bug369950.html91
-rw-r--r--layout/base/tests/test_bug370436.html93
-rw-r--r--layout/base/tests/test_bug386575.xhtml46
-rw-r--r--layout/base/tests/test_bug388019.html44
-rw-r--r--layout/base/tests/test_bug394057.html88
-rw-r--r--layout/base/tests/test_bug399284.html116
-rw-r--r--layout/base/tests/test_bug399951.html34
-rw-r--r--layout/base/tests/test_bug404209.xhtml47
-rw-r--r--layout/base/tests/test_bug416896.html65
-rw-r--r--layout/base/tests/test_bug423523.html104
-rw-r--r--layout/base/tests/test_bug435293-interaction.html49
-rw-r--r--layout/base/tests/test_bug435293-scale.html103
-rw-r--r--layout/base/tests/test_bug435293-skew.html173
-rw-r--r--layout/base/tests/test_bug449781.html68
-rw-r--r--layout/base/tests/test_bug450930.xhtml28
-rw-r--r--layout/base/tests/test_bug465448.xul45
-rw-r--r--layout/base/tests/test_bug469170.html49
-rw-r--r--layout/base/tests/test_bug471126.html34
-rw-r--r--layout/base/tests/test_bug499538-1.html60
-rw-r--r--layout/base/tests/test_bug514127.html55
-rw-r--r--layout/base/tests/test_bug518777.html48
-rw-r--r--layout/base/tests/test_bug548545.xhtml47
-rw-r--r--layout/base/tests/test_bug558663.html37
-rw-r--r--layout/base/tests/test_bug559499.html26
-rw-r--r--layout/base/tests/test_bug569520.html67
-rw-r--r--layout/base/tests/test_bug582181-1.html60
-rw-r--r--layout/base/tests/test_bug582181-2.html63
-rw-r--r--layout/base/tests/test_bug582771.html128
-rw-r--r--layout/base/tests/test_bug583889.html55
-rw-r--r--layout/base/tests/test_bug588174.html67
-rw-r--r--layout/base/tests/test_bug603550.html113
-rw-r--r--layout/base/tests/test_bug607529.html64
-rw-r--r--layout/base/tests/test_bug629838.html97
-rw-r--r--layout/base/tests/test_bug644768.html62
-rw-r--r--layout/base/tests/test_bug646757.html43
-rw-r--r--layout/base/tests/test_bug66619.html62
-rw-r--r--layout/base/tests/test_bug667512.html41
-rw-r--r--layout/base/tests/test_bug677878.html54
-rw-r--r--layout/base/tests/test_bug687297.html54
-rw-r--r--layout/base/tests/test_bug696020.html47
-rw-r--r--layout/base/tests/test_bug718809.html28
-rw-r--r--layout/base/tests/test_bug725426.html23
-rw-r--r--layout/base/tests/test_bug731777.html49
-rw-r--r--layout/base/tests/test_bug749186.html41
-rw-r--r--layout/base/tests/test_bug761572.html40
-rw-r--r--layout/base/tests/test_bug770106.html24
-rw-r--r--layout/base/tests/test_bug842853-2.html54
-rw-r--r--layout/base/tests/test_bug842853.html50
-rw-r--r--layout/base/tests/test_bug849219.html50
-rw-r--r--layout/base/tests/test_bug851445.html34
-rw-r--r--layout/base/tests/test_bug851485.html76
-rw-r--r--layout/base/tests/test_bug858459.html59
-rw-r--r--layout/base/tests/test_bug93077-1.html32
-rw-r--r--layout/base/tests/test_bug93077-2.html32
-rw-r--r--layout/base/tests/test_bug93077-3.html35
-rw-r--r--layout/base/tests/test_bug93077-4.html35
-rw-r--r--layout/base/tests/test_bug93077-5.html35
-rw-r--r--layout/base/tests/test_bug93077-6.html35
-rw-r--r--layout/base/tests/test_bug968148.html36
-rw-r--r--layout/base/tests/test_bug970964.html36
-rw-r--r--layout/base/tests/test_bug976963.html35
-rw-r--r--layout/base/tests/test_bug977003.html39
-rw-r--r--layout/base/tests/test_bug990340.html60
-rw-r--r--layout/base/tests/test_bug993936.html161
-rw-r--r--layout/base/tests/test_emulateMedium.html141
-rw-r--r--layout/base/tests/test_event_target_iframe_oop.html178
-rw-r--r--layout/base/tests/test_event_target_radius.html293
-rw-r--r--layout/base/tests/test_flush_on_paint.html64
-rw-r--r--layout/base/tests/test_frame_reconstruction_for_pseudo_elements.html74
-rw-r--r--layout/base/tests/test_frame_reconstruction_scroll_restore.html68
-rw-r--r--layout/base/tests/test_getBoxQuads_convertPointRectQuad.html713
-rw-r--r--layout/base/tests/test_getClientRects_emptytext.html26
-rw-r--r--layout/base/tests/test_mozPaintCount.html72
-rw-r--r--layout/base/tests/test_preserve3d_sorting_hit_testing.html48
-rw-r--r--layout/base/tests/test_preserve3d_sorting_hit_testing2.html40
-rw-r--r--layout/base/tests/test_reftests_with_caret.html341
-rw-r--r--layout/base/tests/test_remote_frame.html66
-rw-r--r--layout/base/tests/test_resize_flush.html51
-rw-r--r--layout/base/tests/test_scroll_event_ordering.html63
-rw-r--r--layout/base/tests/test_scroll_selection_into_view.html99
-rw-r--r--layout/base/tests/test_scroll_snapping.html806
-rw-r--r--layout/base/tests/test_scroll_snapping_scrollbars.html349
-rw-r--r--layout/base/tests/test_transformed_scrolling_repaints.html54
-rw-r--r--layout/base/tests/test_transformed_scrolling_repaints_2.html54
-rw-r--r--layout/base/tests/test_transformed_scrolling_repaints_3.html24
-rw-r--r--layout/base/tests/textarea-invalid-ref.html7
-rw-r--r--layout/base/tests/textarea-maxlength-invalid-change.html25
-rw-r--r--layout/base/tests/textarea-maxlength-ui-invalid-change.html25
-rw-r--r--layout/base/tests/textarea-maxlength-ui-valid-change.html28
-rw-r--r--layout/base/tests/textarea-maxlength-valid-before-change.html15
-rw-r--r--layout/base/tests/textarea-maxlength-valid-change.html28
-rw-r--r--layout/base/tests/textarea-minlength-invalid-change.html25
-rw-r--r--layout/base/tests/textarea-minlength-ui-invalid-change.html25
-rw-r--r--layout/base/tests/textarea-minlength-ui-valid-change.html28
-rw-r--r--layout/base/tests/textarea-minlength-valid-before-change.html15
-rw-r--r--layout/base/tests/textarea-minlength-valid-change.html28
-rw-r--r--layout/base/tests/textarea-valid-ref.html7
-rw-r--r--layout/base/tests/transformed_scrolling_repaints_3_window.html115
346 files changed, 19640 insertions, 0 deletions
diff --git a/layout/base/tests/Ahem.ttf b/layout/base/tests/Ahem.ttf
new file mode 100644
index 000000000..ac81cb031
--- /dev/null
+++ b/layout/base/tests/Ahem.ttf
Binary files differ
diff --git a/layout/base/tests/border_radius_hit_testing_iframe.html b/layout/base/tests/border_radius_hit_testing_iframe.html
new file mode 100644
index 000000000..a0f7ba1b9
--- /dev/null
+++ b/layout/base/tests/border_radius_hit_testing_iframe.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<title>border-radius hit testing</title>
+<style>
+
+ body { margin: 0; }
+
+ #one, #two {
+ border-radius: 100px 60px 40px 120px / 40px 60px 60px 80px;
+ margin-bottom: 100px;
+ }
+
+ #two { overflow: hidden }
+
+ #one, #two > div {
+ height: 200px;
+ background: blue;
+ cursor: progress;
+ }
+
+ #one:hover, #two > div:hover {
+ background: fuchsia;
+ }
+
+</style>
+<body>
+<div id="one"></div>
+<div id="two"><div></div></div>
diff --git a/layout/base/tests/browser.ini b/layout/base/tests/browser.ini
new file mode 100644
index 000000000..54b78b92f
--- /dev/null
+++ b/layout/base/tests/browser.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+
+[browser_bug617076.js]
+[browser_disableDialogs_onbeforeunload.js]
+[browser_onbeforeunload_only_after_interaction.js]
+[browser_onbeforeunload_only_after_interaction_in_frame.js]
diff --git a/layout/base/tests/browser_bug617076.js b/layout/base/tests/browser_bug617076.js
new file mode 100644
index 000000000..d4e55f9b8
--- /dev/null
+++ b/layout/base/tests/browser_bug617076.js
@@ -0,0 +1,46 @@
+/**
+ * 1. load about:addons in a new tab and select that tab
+ * 2. insert a button with tooltiptext
+ * 3. create a new blank tab and select that tab
+ * 4. select the about:addons tab and hover the inserted button
+ * 5. remove the about:addons tab
+ * 6. remove the blank tab
+ *
+ * the test succeeds if it doesn't trigger any assertions
+ */
+
+add_task(function* test() {
+ // Open the test tab
+ let testTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:addons");
+
+ // insert button into test page content
+ yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
+ let doc = content.document;
+ let e = doc.createElement("button");
+ e.setAttribute("label", "hello");
+ e.setAttribute("tooltiptext", "world");
+ e.setAttribute("id", "test-button");
+ doc.documentElement.insertBefore(e, doc.documentElement.firstChild);
+ });
+
+ // open a second tab and select it
+ let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", true);
+ gBrowser.selectedTab = tab2;
+
+ // Select the testTab then perform mouse events on inserted button
+ gBrowser.selectedTab = testTab;
+ let browser = gBrowser.selectedBrowser;
+ EventUtils.disableNonTestMouseEvents(true);
+ try {
+ yield BrowserTestUtils.synthesizeMouse("#test-button", 1, 1, { type: "mouseover" }, browser);
+ yield BrowserTestUtils.synthesizeMouse("#test-button", 2, 6, { type: "mousemove" }, browser);
+ yield BrowserTestUtils.synthesizeMouse("#test-button", 2, 4, { type: "mousemove" }, browser);
+ } finally {
+ EventUtils.disableNonTestMouseEvents(false);
+ }
+
+ // cleanup
+ yield BrowserTestUtils.removeTab(testTab);
+ yield BrowserTestUtils.removeTab(tab2);
+ ok(true, "pass if no assertions");
+});
diff --git a/layout/base/tests/browser_disableDialogs_onbeforeunload.js b/layout/base/tests/browser_disableDialogs_onbeforeunload.js
new file mode 100644
index 000000000..c9385f670
--- /dev/null
+++ b/layout/base/tests/browser_disableDialogs_onbeforeunload.js
@@ -0,0 +1,56 @@
+function pageScript() {
+ window.addEventListener("beforeunload", function (event) {
+ var str = "Some text that causes the beforeunload dialog to be shown";
+ event.returnValue = str;
+ return str;
+ }, true);
+}
+
+SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
+
+const PAGE_URL =
+ "data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
+
+add_task(function* enableDialogs() {
+ // The onbeforeunload dialog should appear.
+ let dialogShown = false;
+ function onDialogShown(node) {
+ dialogShown = true;
+ let dismissButton = node.ui.button0;
+ dismissButton.click();
+ }
+ let obsName = "tabmodal-dialog-loaded";
+ Services.obs.addObserver(onDialogShown, obsName, false);
+ yield openPage(true);
+ Services.obs.removeObserver(onDialogShown, obsName);
+ Assert.ok(dialogShown);
+});
+
+add_task(function* disableDialogs() {
+ // The onbeforeunload dialog should NOT appear.
+ yield openPage(false);
+ info("If we time out here, then the dialog was shown...");
+});
+
+function* openPage(enableDialogs) {
+ // Open about:blank in a new tab.
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) {
+ // Load the content script in the frame.
+ let methodName = enableDialogs ? "enableDialogs" : "disableDialogs";
+ yield ContentTask.spawn(browser, methodName, function* (name) {
+ Components.utils.import("resource://gre/modules/Services.jsm");
+ Services.obs.addObserver(doc => {
+ if (content && doc == content.document) {
+ content.QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIDOMWindowUtils)[name]();
+ }
+ }, "document-element-inserted", false);
+ });
+ // Load the page.
+ yield BrowserTestUtils.loadURI(browser, PAGE_URL);
+ yield BrowserTestUtils.browserLoaded(browser);
+ // And then navigate away.
+ yield BrowserTestUtils.loadURI(browser, "http://example.com/");
+ yield BrowserTestUtils.browserLoaded(browser);
+ });
+}
diff --git a/layout/base/tests/browser_onbeforeunload_only_after_interaction.js b/layout/base/tests/browser_onbeforeunload_only_after_interaction.js
new file mode 100644
index 000000000..d079bcb38
--- /dev/null
+++ b/layout/base/tests/browser_onbeforeunload_only_after_interaction.js
@@ -0,0 +1,53 @@
+function pageScript() {
+ window.addEventListener("beforeunload", function (event) {
+ var str = "Some text that causes the beforeunload dialog to be shown";
+ event.returnValue = str;
+ return str;
+ }, true);
+}
+
+SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", true]]});
+
+const PAGE_URL =
+ "data:text/html," + encodeURIComponent("<script>(" + pageScript.toSource() + ")();</script>");
+
+add_task(function* doClick() {
+ // The onbeforeunload dialog should appear.
+ let dialogShown = false;
+ function onDialogShown(node) {
+ dialogShown = true;
+ let dismissButton = node.ui.button0;
+ dismissButton.click();
+ }
+ let obsName = "tabmodal-dialog-loaded";
+ Services.obs.addObserver(onDialogShown, obsName, false);
+ yield* openPage(true);
+ Services.obs.removeObserver(onDialogShown, obsName);
+ Assert.ok(dialogShown, "Should have shown dialog.");
+});
+
+add_task(function* noClick() {
+ // The onbeforeunload dialog should NOT appear.
+ yield openPage(false);
+ info("If we time out here, then the dialog was shown...");
+});
+
+function* openPage(shouldClick) {
+ // Open about:blank in a new tab.
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) {
+ // Load the page.
+ yield BrowserTestUtils.loadURI(browser, PAGE_URL);
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ if (shouldClick) {
+ yield BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);
+ }
+ let hasInteractedWith = yield ContentTask.spawn(browser, "", function() {
+ return content.document.userHasInteracted;
+ });
+ is(shouldClick, hasInteractedWith, "Click should update document interactivity state");
+ // And then navigate away.
+ yield BrowserTestUtils.loadURI(browser, "http://example.com/");
+ yield BrowserTestUtils.browserLoaded(browser);
+ });
+}
diff --git a/layout/base/tests/browser_onbeforeunload_only_after_interaction_in_frame.js b/layout/base/tests/browser_onbeforeunload_only_after_interaction_in_frame.js
new file mode 100644
index 000000000..34dbf2308
--- /dev/null
+++ b/layout/base/tests/browser_onbeforeunload_only_after_interaction_in_frame.js
@@ -0,0 +1,59 @@
+function pageScript() {
+ window.addEventListener("beforeunload", function (event) {
+ var str = "Some text that causes the beforeunload dialog to be shown";
+ event.returnValue = str;
+ return str;
+ }, true);
+}
+
+SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", true]]});
+
+const FRAME_URL =
+ "data:text/html," + encodeURIComponent("<body>Just a frame</body>");
+
+const PAGE_URL =
+ "data:text/html," + encodeURIComponent("<iframe src='" + FRAME_URL + "'></iframe><script>(" + pageScript.toSource() + ")();</script>");
+
+add_task(function* doClick() {
+ // The onbeforeunload dialog should appear.
+ let dialogShown = false;
+ function onDialogShown(node) {
+ dialogShown = true;
+ let dismissButton = node.ui.button0;
+ dismissButton.click();
+ }
+ let obsName = "tabmodal-dialog-loaded";
+ Services.obs.addObserver(onDialogShown, obsName, false);
+ yield* openPage(true);
+ Services.obs.removeObserver(onDialogShown, obsName);
+ Assert.ok(dialogShown, "Should have shown dialog.");
+});
+
+add_task(function* noClick() {
+ // The onbeforeunload dialog should NOT appear.
+ yield openPage(false);
+ info("If we time out here, then the dialog was shown...");
+});
+
+function* openPage(shouldClick) {
+ // Open about:blank in a new tab.
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) {
+ // Load the page.
+ yield BrowserTestUtils.loadURI(browser, PAGE_URL);
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ if (shouldClick) {
+ yield BrowserTestUtils.synthesizeMouse(function() {
+ return content.frames[0].document.body;
+ }, 2, 2, {}, browser);
+ }
+ let hasInteractedWith = yield ContentTask.spawn(browser, "", function() {
+ return [content.document.userHasInteracted, content.frames[0].document.userHasInteracted];
+ });
+ is(shouldClick, hasInteractedWith[0], "Click should update parent interactivity state");
+ is(shouldClick, hasInteractedWith[1], "Click should update frame interactivity state");
+ // And then navigate away.
+ yield BrowserTestUtils.loadURI(browser, "http://example.com/");
+ yield BrowserTestUtils.browserLoaded(browser);
+ });
+}
diff --git a/layout/base/tests/bug1007065-1-ref.html b/layout/base/tests/bug1007065-1-ref.html
new file mode 100644
index 000000000..fe867dfa0
--- /dev/null
+++ b/layout/base/tests/bug1007065-1-ref.html
@@ -0,0 +1,15 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body onload="start()">
+ <input type="text" style="text-align:right; border-width:0;">
+ <script>
+ function start() {
+ var input = document.querySelector("input");
+ input.focus();
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1007065-1.html b/layout/base/tests/bug1007065-1.html
new file mode 100644
index 000000000..174ffb888
--- /dev/null
+++ b/layout/base/tests/bug1007065-1.html
@@ -0,0 +1,15 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body onload="start()">
+ <input type="text" style="text-align:right; overflow:hidden; border-width:0;">
+ <script>
+ function start() {
+ var input = document.querySelector("input");
+ input.focus();
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1007067-1-ref.html b/layout/base/tests/bug1007067-1-ref.html
new file mode 100644
index 000000000..b303167dd
--- /dev/null
+++ b/layout/base/tests/bug1007067-1-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<meta charset="utf-8">
+</head>
+<body onload="start()">
+<textarea style="width:500px; height: 200px; border-width:0">-----------------------------------------
+{insert newline before opening bracket}-----------------------------------b</textarea>
+<select><option value="AED">AED - United Arab Emirates Dirham - د.إ</option></select>
+ <script>
+ function start() {
+ var input = document.querySelector("textarea");
+ input.selectionStart = 42
+ input.selectionEnd = 42
+ input.focus();
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1007067-1.html b/layout/base/tests/bug1007067-1.html
new file mode 100644
index 000000000..6284d13ef
--- /dev/null
+++ b/layout/base/tests/bug1007067-1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<meta charset="utf-8">
+</head>
+<body onload="start()">
+<textarea style="width:500px; height: 200px; border-width:0">-----------------------------------------{insert newline before opening bracket}-----------------------------------b</textarea>
+<select><option value="AED">AED - United Arab Emirates Dirham - د.إ</option></select>
+ <script>
+ function start() {
+ var input = document.querySelector("textarea");
+ input.selectionStart = 41
+ input.selectionEnd = 41
+ input.focus();
+ window.parent.synthesizeKey("VK_RETURN", { }, window)
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1061468-ref.html b/layout/base/tests/bug1061468-ref.html
new file mode 100644
index 000000000..9a3330c9f
--- /dev/null
+++ b/layout/base/tests/bug1061468-ref.html
@@ -0,0 +1,13 @@
+<html>
+<head></head>
+<body>
+
+<div id="firstDiv">
+Parent1
+</div>
+
+<div id="secondDiv">
+Parent2<div contenteditable id="editable">Testing 1</div></div>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug1061468.html b/layout/base/tests/bug1061468.html
new file mode 100644
index 000000000..720c0e610
--- /dev/null
+++ b/layout/base/tests/bug1061468.html
@@ -0,0 +1,40 @@
+<html>
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+function runTest() {
+ var sel = window.getSelection();
+ var r = new Range()
+ r.setStart(document.querySelector("#firstDiv"),0);
+ r.setEnd(document.querySelector("#firstDiv"),1);
+ sel.addRange(r)
+
+ document.querySelector("#editable").focus();
+ document.querySelector("#secondDiv").appendChild(document.querySelector("#editable"));
+
+ is(sel.rangeCount, 1, "still have a range in Selection")
+ var s=""
+ try {
+ var r2 = sel.getRangeAt(0)
+ s+=r2.startContainer.tagName
+ s+=r2.startOffset
+ s+=r2.endContainer.tagName
+ s+=r2.endOffset
+ } catch(e) {}
+
+ is(s, "DIV1DIV1", "the range gravitated correctly")
+}
+</script>
+</head>
+<body onload="runTest()">
+
+<div id="firstDiv">
+Parent1
+<div contenteditable id="editable">Testing 1</div>
+</div>
+
+<div id="secondDiv">
+Parent2</div>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug106855-1-ref.html b/layout/base/tests/bug106855-1-ref.html
new file mode 100644
index 000000000..2d3ceea40
--- /dev/null
+++ b/layout/base/tests/bug106855-1-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+x<br>
+<textarea id="t" rows="4" spellcheck="false" style="-moz-appearance: none">
+A
+
+
+</textarea><br>
+y
+<script>
+ // Position the caret at the last line
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+
+ var area = document.getElementById('t');
+ area.focus();
+
+ sendKey('RIGHT'); // now after "A"
+ sendKey('RIGHT'); //
+ sendKey('RIGHT'); //
+ sendKey('RIGHT'); // now at the last line
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug106855-1.html b/layout/base/tests/bug106855-1.html
new file mode 100644
index 000000000..6c0934211
--- /dev/null
+++ b/layout/base/tests/bug106855-1.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+x<br>
+<textarea id="t" rows="4" spellcheck="false" style="-moz-appearance: none">
+A
+
+
+</textarea><br>
+y
+<script>
+ // Position the caret at the last line
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+
+ var area = document.getElementById('t');
+ area.focus();
+
+ sendKey('DOWN'); // now after "A"
+ sendKey('DOWN'); //
+ sendKey('DOWN'); // now at the last line
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug106855-2.html b/layout/base/tests/bug106855-2.html
new file mode 100644
index 000000000..34c50fafd
--- /dev/null
+++ b/layout/base/tests/bug106855-2.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+x<br>
+<textarea id="t" rows="4" spellcheck="false" style="-moz-appearance: none">
+A
+
+
+</textarea><br>
+y
+<script>
+ // Position the caret at the last line
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+
+ var area = document.getElementById('t');
+ area.focus();
+
+ sendKey('DOWN'); // now after "A"
+ sendKey('DOWN'); //
+ sendKey('DOWN'); //
+ sendKey('DOWN'); // now at the last line
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1078327_inner.html b/layout/base/tests/bug1078327_inner.html
new file mode 100644
index 000000000..9e32fc996
--- /dev/null
+++ b/layout/base/tests/bug1078327_inner.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1078327
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1078327</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #listener { background: yellow; padding: 10px; }
+ #mediator { background: red; padding: 20px; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var mediator = undefined;
+ var listener = undefined;
+ var test_target = false;
+ var test_capture = false;
+ var test_mediator_over = false;
+ var test_mediator_move = false;
+ var test_mediator_out = false;
+ var test_listener = false;
+
+ function TargetHandler(event) {
+ logger("Target receive event: " + event.type + ". Mediator.setPointerCapture()");
+ mediator.setPointerCapture(event.pointerId);
+ test_target = true;
+ }
+ function MediatorHandler(event) {
+ logger("Mediator receive event: " + event.type);
+ if(event.type == "gotpointercapture")
+ test_capture = true;
+ if(!test_capture)
+ return;
+ if(event.type == "pointermove")
+ test_mediator_move++;
+ if(event.type == "pointerover")
+ test_mediator_over++;
+ if(event.type == "pointerout")
+ test_mediator_out++;
+ if(event.type == "lostpointercapture")
+ test_capture = false;
+ }
+ function ListenerHandler(event) {
+ logger("Listener receive event: " + event.type);
+ test_listener = true;
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ mediator = document.getElementById("mediator");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetHandler, false);
+ mediator.addEventListener("gotpointercapture", MediatorHandler, false);
+ mediator.addEventListener("pointerover", MediatorHandler, false);
+ mediator.addEventListener("pointermove", MediatorHandler, false);
+ mediator.addEventListener("pointerout", MediatorHandler, false);
+ mediator.addEventListener("lostpointercapture", MediatorHandler, false);
+ listener.addEventListener("pointermove", ListenerHandler, false);
+ var rect_t = target.getBoundingClientRect();
+ var rect_m = mediator.getBoundingClientRect();
+ var rect_l = listener.getBoundingClientRect();
+ synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointerdown"});
+ synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointermove"});
+ synthesizePointer(mediator, rect_m.width/2, rect_m.height/20, {type: "pointermove"});
+ synthesizePointer(listener, rect_l.width/2, rect_l.height/20, {type: "pointermove"});
+ synthesizePointer(mediator, rect_m.width/2, rect_m.height/20, {type: "pointermove"});
+ synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointermove"});
+ synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointerup"});
+ synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointermove"});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_target, true, "pointerdown event should be received by target");
+ parent.is(test_capture, false, "test_capture should be false at the end of the test");
+ parent.is(test_mediator_over, 1, "mediator should receive pointerover event only once");
+ parent.is(test_mediator_move, 5, "mediator should receive pointermove event five times");
+ parent.is(test_mediator_out, 1, "mediator should receive pointerout event only once");
+ parent.is(test_listener, false, "listener should not receive any events");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1078327">Mozilla Bug 1078327</a>
+ <div id="mediator">
+ <div id="listener">div id=listener</div>
+ </div>
+ <div id="target">div id=target</div>
+ <pre id="log"></pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug1080360_inner.html b/layout/base/tests/bug1080360_inner.html
new file mode 100644
index 000000000..95862f9c6
--- /dev/null
+++ b/layout/base/tests/bug1080360_inner.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1080360
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1080360</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #listener { background: yellow; padding: 10px; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var listener = undefined;
+ var test_target = false;
+ var test_listener_got = false;
+ var test_listener_lost = false;
+ var test_document = false;
+
+ function TargetHandler(event) {
+ logger("Target receive event: " + event.type);
+ listener.setPointerCapture(event.pointerId);
+ test_target = true;
+ }
+ function ListenerHandler(event) {
+ logger("Listener receive event: " + event.type);
+ if(event.type == "gotpointercapture") {
+ test_listener_got = true;
+ listener.parentNode.removeChild(listener);
+ }
+ if(event.type == "lostpointercapture")
+ test_listener_lost = true;
+ }
+ function DocumentHandler(event) {
+ logger("Document receive event: " + event.type);
+ if(event.type == "lostpointercapture")
+ test_document = true;
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetHandler, false);
+ listener.addEventListener("gotpointercapture", ListenerHandler, false);
+ listener.addEventListener("lostpointercapture", ListenerHandler, false);
+ document.addEventListener("lostpointercapture", DocumentHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_target, true, "pointerdown event should be received by target");
+ parent.is(test_listener_got, true, "gotpointercapture event should be received by listener");
+ parent.is(test_listener_lost, false, "listener should not receive lostpointercapture event");
+ parent.is(test_document, true, "document should receive lostpointercapture event");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1080360">Mozilla Bug 1080360</a>
+ <div id="target">div id=target</div>
+ <div id="listener">div id=listener</div>
+ <pre id="log"></pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug1080361_inner.html b/layout/base/tests/bug1080361_inner.html
new file mode 100644
index 000000000..be2d8766f
--- /dev/null
+++ b/layout/base/tests/bug1080361_inner.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1080361
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1080361</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #mediator, #listener { background: yellow; margin: 10px; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var mediator = undefined;
+ var listener = undefined;
+ var test_target_down = false;
+ var test_target_up = false;
+ var test_first_exc = false;
+ var test_second_exc = false;
+ var test_third_exc = false;
+ var test_fourth_exc = false;
+ var test_listener = false;
+
+ function TargetDownHandler(event) {
+ logger("Target receive event: " + event.type);
+ test_target_down = true;
+ try {
+ logger("target.setPointerCapture()");
+ target.setPointerCapture(31415);
+ } catch(exc) {
+ test_first_exc = true;
+ parent.is(exc.name, "InvalidPointerId", "Exception InvalidPointerId should be fired");
+ }
+ try {
+ logger("mediator.setPointerCapture()");
+ mediator.parentNode.removeChild(mediator);
+ mediator.setPointerCapture(event.pointerId);
+ } catch(exc) {
+ test_second_exc = true;
+ parent.is(exc.name, "InvalidStateError", "Exception InvalidStateError should be fired");
+ }
+ try {
+ logger("listener.setPointerCapture()");
+ listener.setPointerCapture(event.pointerId);
+ } catch(exc) {
+ test_third_exc = true;
+ }
+ }
+ function TargetUpHandler(event) {
+ logger("Target receive event: " + event.type);
+ test_target_up = true;
+ try {
+ logger("target.setPointerCapture()");
+ target.setPointerCapture(event.pointerId);
+ } catch(exc) {
+ test_fourth_exc = true;
+ }
+ }
+ function ListenerHandler(event) {
+ logger("Listener receive event: " + event.type);
+ test_listener = true;
+ listener.releasePointerCapture(event.pointerId);
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ mediator = document.getElementById("mediator");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetDownHandler, false);
+ target.addEventListener("pointerup", TargetUpHandler, false);
+ listener.addEventListener("gotpointercapture", ListenerHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
+ finishTest();
+ }
+ function finishTest() {
+ setTimeout(function() {
+ parent.is(test_target_down, true, "pointerdown event should be received by target");
+ parent.is(test_target_up, true, "pointerup event should be received by target");
+ parent.is(test_first_exc, true, "first exception should be thrown");
+ parent.is(test_second_exc, true, "second exception should be thrown");
+ parent.is(test_third_exc, false, "third exception should not be thrown");
+ parent.is(test_fourth_exc, false, "fourth exception should not be thrown");
+ parent.is(test_listener, true, "listener should receive gotpointercapture event");
+ logger("finishTest");
+ parent.finishTest();
+ }, 1000);
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1080361">Mozilla Bug 1080361</a>
+ <div id="target">div id=target</div>
+ <div id="mediator">div id=mediator</div>
+ <div id="listener">div id=listener</div>
+ <pre id="log"></pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug1082486-1-ref.html b/layout/base/tests/bug1082486-1-ref.html
new file mode 100644
index 000000000..043779cb9
--- /dev/null
+++ b/layout/base/tests/bug1082486-1-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <style>
+ /* Eliminate the blue glow when focusing the element. */
+ input {
+ background: none;
+ border: none;
+ outline: none;
+ }
+ </style>
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzil.la/1082486">Mozilla Bug 1082486</a>
+ <input id='i' value="abcdefghd" style="text-indent: -10px">
+ </body>
+</html>
diff --git a/layout/base/tests/bug1082486-1.html b/layout/base/tests/bug1082486-1.html
new file mode 100644
index 000000000..de6801f39
--- /dev/null
+++ b/layout/base/tests/bug1082486-1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <style>
+ /* Eliminate the blue glow when focusing the element. */
+ input {
+ background: none;
+ border: none;
+ outline: none;
+ }
+ </style>
+ </head>
+ <body onload="focusInput();">
+ <script>
+ function focusInput() {
+ var inp = document.getElementById('i');
+ inp.focus();
+ }
+ </script>
+
+ <a target="_blank" href="https://bugzil.la/1082486">Mozilla Bug 1082486</a>
+
+ <!-- The caret will not be seen when the input is focused. -->
+ <input id='i' value="abcdefghd" style="text-indent: -10px">
+ </body>
+</html>
diff --git a/layout/base/tests/bug1082486-2-ref.html b/layout/base/tests/bug1082486-2-ref.html
new file mode 100644
index 000000000..5b61a54b6
--- /dev/null
+++ b/layout/base/tests/bug1082486-2-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzil.la/1082486">Mozilla Bug 1082486</a>
+
+ <!-- The whole input will not be seen. -->
+ <input id='i' value="abcdefghd" style="position: absolute; top: -100px; left: 0px;">
+ </body>
+</html>
diff --git a/layout/base/tests/bug1082486-2.html b/layout/base/tests/bug1082486-2.html
new file mode 100644
index 000000000..d367883eb
--- /dev/null
+++ b/layout/base/tests/bug1082486-2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body onload="document.getElementById('i').focus();">
+ <a target="_blank" href="https://bugzil.la/1082486">Mozilla Bug 1082486</a>
+
+ <!-- The whole input will not be seen. -->
+ <input id='i' value="abcdefghd" style="position: absolute; top: -100px; left: 0px;">
+ </body>
+</html>
diff --git a/layout/base/tests/bug1093686_inner.html b/layout/base/tests/bug1093686_inner.html
new file mode 100644
index 000000000..527673108
--- /dev/null
+++ b/layout/base/tests/bug1093686_inner.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html id="html" style="height:100%">
+<head>
+ <title>Testing effect of listener on body</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .target { position:absolute; left:200px; top:200px; width:200px; height:200px; background:blue; }
+ </style>
+</head>
+<body id="body" onload="setTimeout(runTest, 0)" style="margin:0; width:100%; height:100%; overflow:hidden">
+<div id="content">
+ <div id="ruler" style="position:absolute; left:0; top:0; width:1mozmm; height:0;"></div>
+ <div class="target" id="t"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+var eventTarget;
+window.onmousedown = function(event) { eventTarget = event.target; };
+
+// Make sure the target div is "clickable" by adding a click listener on it.
+document.getElementById('t').addEventListener('click', function(e) {
+ parent.ok(true, "target was clicked on");
+}, false);
+
+// Helper functions
+
+function testMouseClick(aX, aY, aExpectedId, aMsg) {
+ eventTarget = null;
+ synthesizeMouseAtPoint(aX, aY, {});
+ try {
+ parent.is(eventTarget.id, aExpectedId,
+ "checking offset " + aX + "," + aY + " hit " + aExpectedId + " [" + aMsg + "]");
+ } catch (ex) {
+ parent.ok(false, "checking offset " + aX + "," + aY + " hit " + aExpectedId + " [" + aMsg + "]; got " + eventTarget);
+ }
+}
+
+function testWithAndWithoutBodyListener(aX, aY, aExpectedId, aMsg) {
+ var func = function(e) {
+ // no-op function
+ parent.ok(true, "body was clicked on");
+ };
+ testMouseClick(aX, aY, aExpectedId, aMsg + " without listener on body");
+ document.body.addEventListener("click", func, false);
+ testMouseClick(aX, aY, aExpectedId, aMsg + " with listener on body");
+ document.body.removeEventListener("click", func, false);
+}
+
+// Main tests
+
+var mm;
+function runTest() {
+ mm = document.getElementById("ruler").getBoundingClientRect().width;
+ parent.ok(4*mm >= 10, "WARNING: mm " + mm + " too small in this configuration. Test results will be bogus");
+
+ // Test near the target, check it hits the target
+ testWithAndWithoutBodyListener(200 - 2*mm, 200 - 2*mm, "t", "basic click retargeting");
+ // Test on the target, check it hits the target
+ testWithAndWithoutBodyListener(200 + 2*mm, 200 + 2*mm, "t", "direct click");
+ // Test outside the target, check it hits the root
+ testWithAndWithoutBodyListener(40, 40, "body", "click way outside target");
+
+ SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.enabled", false]]}, runTest2);
+}
+
+function runTest2() {
+ // In this test, mouse event retargeting is disabled.
+
+ // Test near the target, check it hits the body
+ testWithAndWithoutBodyListener(200 - 2*mm, 200 - 2*mm, "body", "basic click retargeting");
+ // Test on the target, check it hits the target
+ testWithAndWithoutBodyListener(200 + 2*mm, 200 + 2*mm, "t", "direct click");
+ // Test outside the target, check it hits the root
+ testWithAndWithoutBodyListener(40, 40, "body", "click way outside target");
+
+ parent.finishTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug1097242-1-ref.html b/layout/base/tests/bug1097242-1-ref.html
new file mode 100644
index 000000000..dd62f18ee
--- /dev/null
+++ b/layout/base/tests/bug1097242-1-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <script>
+ function test() {
+ focus();
+ var div = document.querySelector("div");
+ div.focus();
+ getSelection().collapse(div.firstChild, 0);
+ }
+ </script>
+ <body onload="test()">
+ <div contenteditable spellcheck="false" style="outline: none">foo<span>bar</span>baz</div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1097242-1.html b/layout/base/tests/bug1097242-1.html
new file mode 100644
index 000000000..dc5d55eb1
--- /dev/null
+++ b/layout/base/tests/bug1097242-1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function test() {
+ focus();
+ synthesizeMouseAtCenter(document.querySelector("span"), {});
+ }
+ function focused() {
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ <body onload="setTimeout(test, 0)">
+ <div contenteditable spellcheck="false" onfocus="focused()"
+ style="outline: none">foo<span contenteditable=false
+ style="-moz-user-select: none">bar</span>baz</div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1109968-1-ref.html b/layout/base/tests/bug1109968-1-ref.html
new file mode 100644
index 000000000..28bcf608a
--- /dev/null
+++ b/layout/base/tests/bug1109968-1-ref.html
@@ -0,0 +1,17 @@
+<html class="reftest-wait">
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<div contenteditable="false"><a href="#">bar</a></div>baz</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ // Set the caret right before "baz"
+ sel.collapse(div.lastChild, 0);
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1109968-1.html b/layout/base/tests/bug1109968-1.html
new file mode 100644
index 000000000..a8d0d216f
--- /dev/null
+++ b/layout/base/tests/bug1109968-1.html
@@ -0,0 +1,23 @@
+<html class="reftest-wait">
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<div contenteditable="false"><a href="#">bar</a></div>baz</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ sel.collapse(div, 0);
+ // Press Right four times to set the caret right before "baz"
+ for (var i = 0; i < 5; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1109968-2-ref.html b/layout/base/tests/bug1109968-2-ref.html
new file mode 100644
index 000000000..9638c35b3
--- /dev/null
+++ b/layout/base/tests/bug1109968-2-ref.html
@@ -0,0 +1,17 @@
+<html class="reftest-wait">
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<div contenteditable="false"><img src="image_rgrg-256x256.png" width="10" height="10"></div>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ // Set the caret right before "bar"
+ sel.collapse(div.lastChild, 0);
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1109968-2.html b/layout/base/tests/bug1109968-2.html
new file mode 100644
index 000000000..159311ad3
--- /dev/null
+++ b/layout/base/tests/bug1109968-2.html
@@ -0,0 +1,23 @@
+<html class="reftest-wait">
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<div contenteditable="false"><img src="image_rgrg-256x256.png" width="10" height="10"></div>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ sel.collapse(div, 0);
+ // Press Right four times to set the caret right before "bar"
+ for (var i = 0; i < 6; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1123067-1.html b/layout/base/tests/bug1123067-1.html
new file mode 100644
index 000000000..86c8357ff
--- /dev/null
+++ b/layout/base/tests/bug1123067-1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase for bug 1123067</title>
+ <script>
+ function click(id) {
+ var e = document.querySelector(id);
+ synthesizeMouse(e, 1, 1, {type: "mousedown"}, window);
+ synthesizeMouse(e, 1, 1, {type: "mouseup"}, window);
+ }
+ function test() {
+ for (var i = 0; i < 5; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ synthesizeKey("VK_LEFT", {});
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ click('#test1')
+ }
+ </script>
+ <style>
+ div { -moz-user-select:none; }
+ div:focus { outline:1px solid black; }
+ </style>
+</head>
+<body>
+
+<div id="test1" contenteditable="true" spellcheck="false" onfocus="test()">This text is NOT selectable.</div>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1123067-2.html b/layout/base/tests/bug1123067-2.html
new file mode 100644
index 000000000..0139e7ac7
--- /dev/null
+++ b/layout/base/tests/bug1123067-2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1123067</title>
+ <script>
+ function test() {
+ for (var i = 0; i < 5; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ synthesizeKey("VK_LEFT", {});
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ var e = document.querySelector('#test1');
+ e.focus();
+ }
+ </script>
+ <style>
+ div { -moz-user-select:none; }
+ div:focus { outline:1px solid black; }
+ </style>
+</head>
+<body>
+
+<div id="test1" contenteditable="true" spellcheck="false" onfocus="setTimeout(test,0)">This text is NOT selectable.</div>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1123067-3.html b/layout/base/tests/bug1123067-3.html
new file mode 100644
index 000000000..71c6bf1a3
--- /dev/null
+++ b/layout/base/tests/bug1123067-3.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait" style="-moz-user-select:none" spellcheck="false">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1123067</title>
+ <script>
+ function test() {
+ for (var i = 0; i < 5; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ synthesizeKey("VK_LEFT", {});
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ document.designMode='on';
+ document.querySelector('div').focus();
+ document.body.offsetHeight;
+ setTimeout(test,0)
+ }
+ </script>
+ <style>
+ div { outline:1px solid black; }
+ </style>
+</head>
+<body>
+
+<div>This text is NOT selectable.</div>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1123067-ref.html b/layout/base/tests/bug1123067-ref.html
new file mode 100644
index 000000000..5fe2a5981
--- /dev/null
+++ b/layout/base/tests/bug1123067-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase for bug 1123067</title>
+ <script>
+ function test() {
+ for (var i = 0; i < 5; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ synthesizeKey("VK_LEFT", {});
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ var e = document.querySelector('#test1');
+ e.focus();
+ }
+ </script>
+ <style>
+ div:focus { outline:1px solid black; }
+ </style>
+</head>
+<body>
+
+<div id="test1" contenteditable="true" spellcheck="false" onfocus="test()">This text is NOT selectable.</div>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1132768-1-ref.html b/layout/base/tests/bug1132768-1-ref.html
new file mode 100644
index 000000000..0fea14cf0
--- /dev/null
+++ b/layout/base/tests/bug1132768-1-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <script>
+ function test() {
+ focus();
+ getSelection().selectAllChildren(document.querySelector("span"));
+ }
+ </script>
+ <body onload="test()">
+ <div>foo<span>bar</span>baz</div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1132768-1.html b/layout/base/tests/bug1132768-1.html
new file mode 100644
index 000000000..dafa3aa3e
--- /dev/null
+++ b/layout/base/tests/bug1132768-1.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function test() {
+ focus();
+ synthesizeMouseAtCenter(document.querySelector("span"), {});
+ }
+ function focused() {
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ <body onload="setTimeout(test, 0)">
+ <div contenteditable spellcheck="false" onfocus="focused()"
+ style="outline: none">foo<span contenteditable=false>bar</span>baz</div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug1153130_inner.html b/layout/base/tests/bug1153130_inner.html
new file mode 100644
index 000000000..0bb8c0cd7
--- /dev/null
+++ b/layout/base/tests/bug1153130_inner.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1153130
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1153130</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target { background: yellow; padding: 10px; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var test_down = false;
+ var test_capture = false;
+ var test_move = false;
+ var test_success = false;
+
+ function TargetHandler(event) {
+ logger("Target receive event: " + event.type);
+ if(event.type == "pointerdown") {
+ test_down = true;
+ target.setPointerCapture(event.pointerId);
+ } else if(event.type == "gotpointercapture") {
+ test_capture = true;
+ } else if(event.type == "pointermove" && test_capture) {
+ test_move = true;
+ }
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('target');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest() {
+ logger("executeTest");
+ target = document.getElementById("target");
+ target.addEventListener("pointerdown", TargetHandler, false);
+ target.addEventListener("gotpointercapture", TargetHandler, false);
+ target.addEventListener("pointermove", TargetHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/5, rect.height/5, {type: "pointermove"});
+ synthesizePointer(target, rect.width/5, rect.height/5, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointermove"});
+ synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
+ synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointerup"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
+ test_success = true;
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_down, true, "pointerdown event should be received by target");
+ parent.is(test_capture, true, "gotpointercapture event should be received by target");
+ parent.is(test_move, true, "pointermove event should be received by target while pointer capture is active");
+ parent.is(test_success, true, "Firefox should be live!");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1153130">Mozilla Bug 1153130</a>
+ <div id="target">div id=target</div>
+</body>
+</html>
diff --git a/layout/base/tests/bug1162990_inner_1.html b/layout/base/tests/bug1162990_inner_1.html
new file mode 100644
index 000000000..4ea5edb5c
--- /dev/null
+++ b/layout/base/tests/bug1162990_inner_1.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1162990
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1162990</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ div#basket {
+ background: red;
+ padding: 10px;
+ margin: 10px;
+ }
+ div#target {
+ background: lightgreen;
+ padding: 10px;
+ margin: 10px;
+ }
+ div#child {
+ background: lightblue;
+ padding: 10px;
+ margin: 10px;
+ }
+ div#listener {
+ background: yellow;
+ padding: 10px;
+ margin: 10px;
+ }
+ </style>
+ <script type="application/javascript">
+ var basket;
+ var target;
+ var child;
+ var listener;
+
+ var test_basketLeave = 0;
+ var test_targetGotCapture = 0;
+ var test_targetLostCapture = 0;
+ var test_targetLeave = 0;
+ var test_childLeave = 0;
+ var test_listenerDown = 0;
+ var test_listenerLeave = 0;
+
+ function basketLeaveHandler(event) {
+ logger("basket: " + event.type);
+ test_basketLeave++;
+ }
+ function targetGotHandler(event) {
+ logger("target: " + event.type);
+ test_targetGotCapture++;
+ }
+ function targetLostHandler(event) {
+ logger("target: " + event.type);
+ test_targetLostCapture++;
+ }
+ function targetLeaveHandler(event) {
+ logger("target: " + event.type);
+ test_targetLeave++;
+ }
+ function childLeaveHandler(event) {
+ logger("child: " + event.type);
+ test_childLeave++;
+ }
+ function listenerDownHandler(event) {
+ logger("listener: " + event.type);
+ target.setPointerCapture(event.pointerId);
+ test_listenerDown++;
+ }
+ function listenerLeaveHandler(event) {
+ logger("listener: " + event.type);
+ test_listenerLeave++;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+
+ function setEventHandlers() {
+ basket = document.getElementById("basket");
+ target = document.getElementById("target");
+ child = document.getElementById("child");
+ listener = document.getElementById("listener");
+
+ basket.addEventListener("pointerleave", basketLeaveHandler, false);
+ target.addEventListener("gotpointercapture", targetGotHandler, false);
+ target.addEventListener("lostpointercapture", targetLostHandler, false);
+ target.addEventListener("pointerleave", targetLeaveHandler, false);
+ child.addEventListener("pointerleave", childLeaveHandler, false);
+ listener.addEventListener("pointerdown", listenerDownHandler, false);
+ listener.addEventListener("pointerleave", listenerLeaveHandler, false);
+ }
+
+ function executeTest()
+ {
+ logger("executeTest");
+ setEventHandlers();
+ var rectCd = child.getBoundingClientRect();
+ var rectLr = listener.getBoundingClientRect();
+ synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointerdown"});
+ synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
+ synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointermove"});
+ synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
+ synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointermove"});
+ synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointerup"});
+ synthesizePointer(listener, rectLr.width/3, rectLr.height/3, {type: "pointermove"});
+ finishTest();
+ }
+
+ function finishTest() {
+ parent.is(test_basketLeave, 0, "Part1: basket should not receive pointerleave event after pointer capturing");
+ parent.is(test_targetGotCapture, 1, "Part1: target should receive gotpointercapture event");
+ parent.is(test_targetLostCapture, 1, "Part1: target should receive lostpointercapture event");
+ parent.is(test_targetLeave, 2, "Part1: target should receive pointerleave event two times");
+ parent.is(test_childLeave, 0, "Part1: child should not receive pointerleave event after pointer capturing");
+ parent.is(test_listenerDown, 1, "Part1: listener should receive pointerdown event");
+ parent.is(test_listenerLeave, 1, "Part1: listener should receive pointerleave event only one time");
+ logger("finishTest");
+ parent.finishTest();
+ }
+
+ function logger(message) {
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162990">Mozilla Bug 1162990 Test 1</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="basket">div id=basket
+ <div id="target">div id=target
+ <div id="child">div id=child</div>
+ </div>
+ </div>
+ <div id="listener">div id=listener</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug1162990_inner_2.html b/layout/base/tests/bug1162990_inner_2.html
new file mode 100644
index 000000000..54aa74ca3
--- /dev/null
+++ b/layout/base/tests/bug1162990_inner_2.html
@@ -0,0 +1,146 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1162990
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1162990</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ div#basket {
+ background: red;
+ padding: 10px;
+ margin: 10px;
+ }
+ div#target {
+ background: lightgreen;
+ padding: 10px;
+ margin: 10px;
+ }
+ div#child {
+ background: lightblue;
+ padding: 10px;
+ margin: 10px;
+ }
+ div#listener {
+ background: yellow;
+ padding: 10px;
+ margin: 10px;
+ }
+ </style>
+ <script type="application/javascript">
+ var basket;
+ var target;
+ var child;
+ var listener;
+
+ var test_basketLeave = 0;
+ var test_targetDown = 0;
+ var test_targetGotCapture = 0;
+ var test_targetLostCapture = 0;
+ var test_targetLeave = 0;
+ var test_childLeave = 0;
+ var test_listenerLeave = 0;
+
+ function basketLeaveHandler(event) {
+ logger("basket: " + event.type);
+ test_basketLeave++;
+ }
+ function targetDownHandler(event) {
+ logger("target: " + event.type);
+ target.setPointerCapture(event.pointerId);
+ test_targetDown++;
+ }
+ function targetGotHandler(event) {
+ logger("target: " + event.type);
+ test_targetGotCapture++;
+ }
+ function targetLostHandler(event) {
+ logger("target: " + event.type);
+ test_targetLostCapture++;
+ }
+ function targetLeaveHandler(event) {
+ logger("target: " + event.type);
+ test_targetLeave++;
+ }
+ function childLeaveHandler(event) {
+ logger("child: " + event.type);
+ test_childLeave++;
+ }
+ function listenerLeaveHandler(event) {
+ logger("listener: " + event.type);
+ test_listenerLeave++;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+
+ function setEventHandlers() {
+ basket = document.getElementById("basket");
+ target = document.getElementById("target");
+ child = document.getElementById("child");
+ listener = document.getElementById("listener");
+
+ basket.addEventListener("pointerleave", basketLeaveHandler, false);
+ target.addEventListener("pointerdown", targetDownHandler, false);
+ target.addEventListener("gotpointercapture", targetGotHandler, false);
+ target.addEventListener("lostpointercapture", targetLostHandler, false);
+ target.addEventListener("pointerleave", targetLeaveHandler, false);
+ child.addEventListener("pointerleave", childLeaveHandler, false);
+ listener.addEventListener("pointerleave", listenerLeaveHandler, false);
+ }
+
+ function executeTest()
+ {
+ logger("executeTest");
+ setEventHandlers();
+ var rectTg = target.getBoundingClientRect();
+ var rectCd = child.getBoundingClientRect();
+ var rectLr = listener.getBoundingClientRect();
+ synthesizePointer(target, rectTg.width/3, rectTg.height/7, {type: "pointerdown"});
+ synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
+ synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointermove"});
+ synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
+ synthesizePointer(target, rectTg.width/3, rectTg.height/7, {type: "pointermove"});
+ synthesizePointer(target, rectTg.width/3, rectTg.height/7, {type: "pointerup"});
+ synthesizePointer(target, rectTg.width/3, rectTg.height/9, {type: "pointermove"});
+ finishTest();
+ }
+
+ function finishTest() {
+ parent.is(test_basketLeave, 0, "Part2: basket should not receive pointerleave event after pointer capturing");
+ parent.is(test_targetDown, 1, "Part2: target should receive pointerdown event");
+ parent.is(test_targetGotCapture, 1, "Part2: target should receive gotpointercapture event");
+ parent.is(test_targetLostCapture, 1, "Part2: target should receive lostpointercapture event");
+ parent.is(test_targetLeave, 1, "Part2: target should receive pointerleave event");
+ parent.is(test_childLeave, 0, "Part2: child should not receive pointerleave event after pointer capturing");
+ parent.is(test_listenerLeave, 0, "Part2: listener should not receive pointerleave event after pointer capturing");
+ logger("finishTest");
+ parent.finishTest();
+ }
+
+ function logger(message) {
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162990">Mozilla Bug 1162990 Test 2</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="basket">div id=basket
+ <div id="target">div id=target
+ <div id="child">div id=child</div>
+ </div>
+ </div>
+ <div id="listener">div id=listener</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug1226904.html b/layout/base/tests/bug1226904.html
new file mode 100644
index 000000000..646608b1c
--- /dev/null
+++ b/layout/base/tests/bug1226904.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=684759
+-->
+<head>
+ <title>Test for Bug 684759</title>
+</head>
+<style>
+ #container {
+ transform-style: preserve-3d;
+ transform: translate3d(400px, 0px, 10px);
+ background-color: black;
+ }
+ #separator {
+ width: 400px;
+ height: 400px;
+ background-color: green;
+ }
+ #transformed {
+ width: 400px;
+ height: 400px;
+ background-color: blue;
+ transform: translate3d(-400px, 0px, 10px);
+ }
+</style>
+<body onload="run()">
+<div>
+ <div id="container">
+ <div id="separator"></div>
+ <div id="transformed"></div>
+ </div>
+</div>
+</body>
+</html>
diff --git a/layout/base/tests/bug1237236-1-ref.html b/layout/base/tests/bug1237236-1-ref.html
new file mode 100644
index 000000000..d8bca78b7
--- /dev/null
+++ b/layout/base/tests/bug1237236-1-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1237236</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_DOWN", { }); // move caret to the second line
+ // caret should now be at the start of the second line
+ document.body.offsetHeight;
+ setTimeout(function(){ document.documentElement.removeAttribute("class"); },0);
+ }
+ function runTests() {
+ document.querySelector('textarea').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<textarea onfocus="test1()" spellcheck="false" style="-moz-appearance:none">abc
+def</textarea>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1237236-1.html b/layout/base/tests/bug1237236-1.html
new file mode 100644
index 000000000..6ed32fea3
--- /dev/null
+++ b/layout/base/tests/bug1237236-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1237236</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_DOWN", { shiftKey: true }); // select first line including the newline
+ synthesizeKey("VK_RIGHT", { }); // collapse to the end of the selection
+ // caret should now be at the start of the second line
+ document.body.offsetHeight;
+ setTimeout(function(){ document.documentElement.removeAttribute("class"); },0);
+ }
+ function runTests() {
+ document.querySelector('textarea').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<textarea onfocus="test1()" spellcheck="false" style="-moz-appearance:none">abc
+def</textarea>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1237236-2-ref.html b/layout/base/tests/bug1237236-2-ref.html
new file mode 100644
index 000000000..141b33f6e
--- /dev/null
+++ b/layout/base/tests/bug1237236-2-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1237236</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ document.body.offsetHeight;
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ document.querySelector('pre').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<pre contenteditable tabindex=1 onfocus="test1()" spellcheck="false">abc
+def</pre>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1237236-2.html b/layout/base/tests/bug1237236-2.html
new file mode 100644
index 000000000..8b7707fa1
--- /dev/null
+++ b/layout/base/tests/bug1237236-2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1237236</title>
+ <script>
+ function test1() {
+ document.body.offsetHeight;
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ var pre = document.querySelector('pre');
+ window.getSelection().collapse(pre.firstChild, 4/*after the newline*/)
+ pre.focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<pre contenteditable tabindex=1 onfocus="test1()" spellcheck="false">abc
+def</pre>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1258308-1-ref.html b/layout/base/tests/bug1258308-1-ref.html
new file mode 100644
index 000000000..3c975569c
--- /dev/null
+++ b/layout/base/tests/bug1258308-1-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1258308</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_DOWN", { });
+ synthesizeKey("VK_DOWN", { });
+ // caret should now be at the start of the third line
+ document.body.offsetHeight;
+ setTimeout(function(){ document.documentElement.removeAttribute("class"); },0);
+ }
+ function runTests() {
+ document.querySelector('textarea').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<textarea onfocus="test1()" spellcheck="false" style="-moz-appearance:none">abc
+def
+ghi</textarea>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1258308-1.html b/layout/base/tests/bug1258308-1.html
new file mode 100644
index 000000000..3f6c25540
--- /dev/null
+++ b/layout/base/tests/bug1258308-1.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1258308</title>
+ <script>
+ function test1() {
+ const kIsMac = navigator.platform.indexOf("Mac") == 0;
+ synthesizeKey("VK_DOWN", {}); // go to the second line
+ // go to the end of the second line
+ if (kIsMac) {
+ synthesizeKey("VK_RIGHT", {accelKey: true});
+ } else {
+ synthesizeKey("VK_END", {});
+ }
+ synthesizeKey("VK_RIGHT", { shiftKey: true }); // select the newline
+ synthesizeKey("VK_RIGHT", {}); // collapse to the end of the selection
+ // caret should now be at the start of the third line
+ document.body.offsetHeight;
+ setTimeout(function(){ document.documentElement.removeAttribute("class"); },0);
+ }
+ function runTests() {
+ document.querySelector('textarea').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<textarea onfocus="test1()" spellcheck="false" style="-moz-appearance:none">abc
+def
+ghi</textarea>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1258308-2-ref.html b/layout/base/tests/bug1258308-2-ref.html
new file mode 100644
index 000000000..88659d3f4
--- /dev/null
+++ b/layout/base/tests/bug1258308-2-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1258308</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ document.body.offsetHeight;
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ document.querySelector('pre').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<pre contenteditable tabindex=1 onfocus="test1()" spellcheck="false">abc
+def
+ghi</pre>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1258308-2.html b/layout/base/tests/bug1258308-2.html
new file mode 100644
index 000000000..f1472dc66
--- /dev/null
+++ b/layout/base/tests/bug1258308-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1258308</title>
+ <script>
+ function test1() {
+ document.body.offsetHeight;
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ var pre = document.querySelector('pre');
+ window.getSelection().collapse(pre.firstChild, 8/*after the 2nd line newline*/)
+ pre.focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<pre contenteditable tabindex=1 onfocus="test1()" spellcheck="false">abc
+def
+ghi</pre>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1259949-1-ref.html b/layout/base/tests/bug1259949-1-ref.html
new file mode 100644
index 000000000..26b58f604
--- /dev/null
+++ b/layout/base/tests/bug1259949-1-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1259949</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_DOWN", {});
+ // caret should now be at the start of the second line
+ document.body.offsetHeight;
+ setTimeout(function(){ document.documentElement.removeAttribute("class"); },0);
+ }
+ function runTests() {
+ document.querySelector('textarea').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<textarea onfocus="test1()" spellcheck="false" style="-moz-appearance:none">abcdef
+</textarea>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1259949-1.html b/layout/base/tests/bug1259949-1.html
new file mode 100644
index 000000000..52304b427
--- /dev/null
+++ b/layout/base/tests/bug1259949-1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1259949</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_RIGHT", {});
+ synthesizeKey("VK_RIGHT", {});
+ synthesizeKey("VK_RIGHT", {}); // caret is now between "c" and "d"
+ synthesizeKey("VK_DOWN", {shiftKey: true}); // select "def\n"
+ synthesizeKey("VK_RIGHT", {}); // collapse to the end of the selection
+ // caret should now be at the start of the second line
+ document.body.offsetHeight;
+ setTimeout(function(){ document.documentElement.removeAttribute("class"); },0);
+ }
+ function runTests() {
+ document.querySelector('textarea').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<textarea onfocus="test1()" spellcheck="false" style="-moz-appearance:none">abcdef
+</textarea>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1259949-2-ref.html b/layout/base/tests/bug1259949-2-ref.html
new file mode 100644
index 000000000..8ca51a286
--- /dev/null
+++ b/layout/base/tests/bug1259949-2-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1259949</title>
+ <script>
+ function test1() {
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ synthesizeKey("VK_RIGHT", { });
+ document.body.offsetHeight;
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ document.querySelector('pre').focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body>
+
+<pre contenteditable tabindex=1 onfocus="test1()" spellcheck="false">abcdef
+
+</pre>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1259949-2.html b/layout/base/tests/bug1259949-2.html
new file mode 100644
index 000000000..999cadda3
--- /dev/null
+++ b/layout/base/tests/bug1259949-2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1259949</title>
+ <script>
+ function test1() {
+ document.body.offsetHeight;
+ document.documentElement.removeAttribute("class");
+ }
+ function runTests() {
+ var pre = document.querySelector('pre');
+ window.getSelection().collapse(pre, 1/*after the text*/)
+ pre.focus();
+ document.body.offsetHeight;
+ }
+ </script>
+</head>
+<body onload="runTests()">
+
+<pre contenteditable tabindex=1 onfocus="test1()" spellcheck="false">abcdef
+<br></pre>
+
+<script>
+SimpleTest.waitForFocus(runTests);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263288-ref.html b/layout/base/tests/bug1263288-ref.html
new file mode 100644
index 000000000..3213a2624
--- /dev/null
+++ b/layout/base/tests/bug1263288-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1263288
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1263288</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="readonly">xyz</div>
+<div id="editable" spellcheck=false contenteditable='true' style="outline: 1px solid;"><span>xyz</span><br></br></div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theDiv.focus();
+ sel.collapse(theDiv, 1);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263288.html b/layout/base/tests/bug1263288.html
new file mode 100644
index 000000000..121fe21e8
--- /dev/null
+++ b/layout/base/tests/bug1263288.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1263288
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1263288</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="readonly">xyz</div>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span contentEditable='false'>xyz<!-- comment --></span><br></br></div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theDiv.focus();
+ sel.collapse(theDiv, 0);
+ synthesizeMouse(theDiv, 100, 2, {});
+ synthesizeKey("VK_END", {});
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-1-ref.html b/layout/base/tests/bug1263357-1-ref.html
new file mode 100644
index 000000000..6b4e888cf
--- /dev/null
+++ b/layout/base/tests/bug1263357-1-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p id="theP"><tt>xyz<br></tt><br></p></div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theP = document.getElementById("theP");
+ theDiv.focus();
+ sel.collapse(theP, 1);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-1.html b/layout/base/tests/bug1263357-1.html
new file mode 100644
index 000000000..4369d05cb
--- /dev/null
+++ b/layout/base/tests/bug1263357-1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p><tt>xyz</tt><br></p></div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theDiv.focus();
+ sel.collapse(theDiv, 0);
+ if (navigator.platform.indexOf("Win") == 0) {
+ synthesizeKey("VK_END", {});
+ } else {
+ // End key doesn't work as expected on Mac and Linux.
+ sel.modify("move", "right", "lineboundary");
+ }
+ synthesizeKey("VK_RETURN", {shiftKey: true});
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-2-ref.html b/layout/base/tests/bug1263357-2-ref.html
new file mode 100644
index 000000000..3625510e6
--- /dev/null
+++ b/layout/base/tests/bug1263357-2-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p id="theP"><font color=red><span>xyz<br></span></font><br></p></div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theP = document.getElementById("theP");
+ theDiv.focus();
+ sel.collapse(theP, 1);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-2.html b/layout/base/tests/bug1263357-2.html
new file mode 100644
index 000000000..b92a5e42e
--- /dev/null
+++ b/layout/base/tests/bug1263357-2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p><font color=red><span>xyz</span></font><br></p></div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theDiv.focus();
+ sel.collapse(theDiv, 0);
+ if (navigator.platform.indexOf("Win") == 0) {
+ synthesizeKey("VK_END", {});
+ } else {
+ // End key doesn't work as expected on Mac and Linux.
+ sel.modify("move", "right", "lineboundary");
+ }
+ synthesizeKey("VK_RETURN", {shiftKey: true});
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-3-ref.html b/layout/base/tests/bug1263357-3-ref.html
new file mode 100644
index 000000000..fad9d5851
--- /dev/null
+++ b/layout/base/tests/bug1263357-3-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #3 for bug 1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span><br>more</div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theDiv.focus();
+ sel.collapse(theDiv, 1);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-3.html b/layout/base/tests/bug1263357-3.html
new file mode 100644
index 000000000..5311068b0
--- /dev/null
+++ b/layout/base/tests/bug1263357-3.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #3 for bug1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span><br>more</div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theSpan = document.getElementById("theSpan");
+ theDiv.focus();
+ sel.collapse(theSpan, 2);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-4-ref.html b/layout/base/tests/bug1263357-4-ref.html
new file mode 100644
index 000000000..5b568d17d
--- /dev/null
+++ b/layout/base/tests/bug1263357-4-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #4 for bug 1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span>more</div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theDiv.focus();
+ sel.collapse(theDiv, 1);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-4.html b/layout/base/tests/bug1263357-4.html
new file mode 100644
index 000000000..dfd4618b6
--- /dev/null
+++ b/layout/base/tests/bug1263357-4.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #4 for bug1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span>more</div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theSpan = document.getElementById("theSpan");
+ theDiv.focus();
+ sel.collapse(theSpan, 2);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-5-ref.html b/layout/base/tests/bug1263357-5-ref.html
new file mode 100644
index 000000000..02290aa77
--- /dev/null
+++ b/layout/base/tests/bug1263357-5-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #5 for bug 1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span> more</div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theDiv.focus();
+ sel.collapse(theDiv, 1);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug1263357-5.html b/layout/base/tests/bug1263357-5.html
new file mode 100644
index 000000000..bab3cc65b
--- /dev/null
+++ b/layout/base/tests/bug1263357-5.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Testcase #5 for bug1263357</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span> more</div>
+<script>
+
+function start() {
+ var sel = window.getSelection();
+ // Focus on editable block.
+ theDiv = document.getElementById("editable");
+ theSpan = document.getElementById("theSpan");
+ theDiv.focus();
+ sel.collapse(theSpan, 2);
+}
+
+SimpleTest.waitForFocus(start);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug240933-1-ref.html b/layout/base/tests/bug240933-1-ref.html
new file mode 100644
index 000000000..778a0647b
--- /dev/null
+++ b/layout/base/tests/bug240933-1-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML><html>
+<body>
+<textarea id="t" rows="4" style="-moz-appearance: none">
+
+</textarea>
+<script>
+ var t = document.getElementById("t");
+ t.selectionStart = t.selectionEnd = t.value.length;
+ t.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug240933-1.html b/layout/base/tests/bug240933-1.html
new file mode 100644
index 000000000..ce96d4d09
--- /dev/null
+++ b/layout/base/tests/bug240933-1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<textarea id="t" rows="4" style="-moz-appearance: none"></textarea>
+<script>
+ var area = document.getElementById('t');
+ area.focus();
+
+ sendKey('RETURN'); // press Enter once
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug240933-2.html b/layout/base/tests/bug240933-2.html
new file mode 100644
index 000000000..6b95cf1a9
--- /dev/null
+++ b/layout/base/tests/bug240933-2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<textarea id="t" rows="4" style="-moz-appearance: none"></textarea>
+<script>
+ var area = document.getElementById('t');
+ area.focus();
+
+ sendKey('RETURN'); // press Enter twice
+ sendKey('RETURN');
+ sendKey('BACK_SPACE'); // press Backspace once
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug369950-subframe.xml b/layout/base/tests/bug369950-subframe.xml
new file mode 100644
index 000000000..8aed64cd4
--- /dev/null
+++ b/layout/base/tests/bug369950-subframe.xml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+</head>
+
+<body>
+
+<p>foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo <x></y></p>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug389321-1-ref.html b/layout/base/tests/bug389321-1-ref.html
new file mode 100644
index 000000000..4fb2021da
--- /dev/null
+++ b/layout/base/tests/bug389321-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<span contenteditable id="t" style="border: 1px dashed green; min-height: 2px; padding-right: 20px;"> </span></body>
+<script>
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+
+ // Focus the span to put the caret at its beginning.
+ var area = document.getElementById('t');
+ area.focus();
+
+ // Do nothing else.
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug389321-1.html b/layout/base/tests/bug389321-1.html
new file mode 100644
index 000000000..9915d9929
--- /dev/null
+++ b/layout/base/tests/bug389321-1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<span contenteditable id="t" style="border: 1px dashed green; min-height: 2px; padding-right: 20px;"> </span></body>
+<script>
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+
+ // Focus the span to put the caret at its beginning.
+ var area = document.getElementById('t');
+ area.focus();
+
+ // Enter a character in the span then delete it.
+ sendChar("W");
+ sendKey("BACK_SPACE");
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug389321-2-ref.html b/layout/base/tests/bug389321-2-ref.html
new file mode 100644
index 000000000..09adebf7e
--- /dev/null
+++ b/layout/base/tests/bug389321-2-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML><html>
+<body>
+ <div contenteditable id="x" style="height: 30px; outline: none;"></div>
+<script>
+ var div = document.getElementById('x');
+ div.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug389321-2.html b/layout/base/tests/bug389321-2.html
new file mode 100644
index 000000000..d878635a1
--- /dev/null
+++ b/layout/base/tests/bug389321-2.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML><html>
+<body>
+ <div contenteditable id="x" style="height: 50px; outline: none;"></div>
+<script>
+ var div = document.getElementById('x');
+ div.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug389321-3-ref.html b/layout/base/tests/bug389321-3-ref.html
new file mode 100644
index 000000000..387cbf25d
--- /dev/null
+++ b/layout/base/tests/bug389321-3-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML><html>
+<body>
+ <div contenteditable id="x" style="height: 30px; outline: none;">&nbsp;</div>
+<script>
+ var div = document.getElementById('x');
+ div.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug389321-3.html b/layout/base/tests/bug389321-3.html
new file mode 100644
index 000000000..09adebf7e
--- /dev/null
+++ b/layout/base/tests/bug389321-3.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML><html>
+<body>
+ <div contenteditable id="x" style="height: 30px; outline: none;"></div>
+<script>
+ var div = document.getElementById('x');
+ div.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug450930.xhtml b/layout/base/tests/bug450930.xhtml
new file mode 100644
index 000000000..36c284e49
--- /dev/null
+++ b/layout/base/tests/bug450930.xhtml
@@ -0,0 +1,181 @@
+<?xml version="1.0"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=450930
+-->
+<head>
+ <title>Test for Bug 450930 (MozAfterPaint)</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="runNext()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450930">Mozilla Bug 450930</a>
+<div id="display">
+ <div id="d" style="width:400px; height:200px;"></div>
+ <iframe id="iframe" style="width:400px; height:200px;"
+ src="data:text/html,&lt;div id='d'&gt;&lt;span style='margin-left:3px;'&gt;Hello&lt;/span&gt;
+ &lt;/div&gt;&lt;div style='margin-top:500px' id='d2'&gt;
+ &lt;span style='margin-left:3px;'&gt;Goodbye&lt;/span&gt;&lt;/div>"></iframe>
+ <svg:svg style="width:410px; height:210px;" id="svg">
+ <svg:foreignObject width="100%" height="100%">
+ <iframe id="iframe2" style="width:400px; height:200px;"
+ src="data:text/html,&lt;div id='d'&gt;&lt;span style='margin-left:3px;'&gt;Hello&lt;/span&gt;
+ &lt;/div&gt;&lt;div style='margin-top:500px' id='d2'&gt;
+ &lt;span style='margin-left:3px;'&gt;Goodbye&lt;/span&gt;&lt;/div>"></iframe>
+ </svg:foreignObject>
+ </svg:svg>
+</div>
+<div id="content" style="display: none">
+</div>
+
+
+<pre id="test">
+<script class="testbody" type="text/javascript"><![CDATA[
+
+function flash(doc, name) {
+ var d = doc.getElementById(name);
+ d.style.backgroundColor = d.style.backgroundColor == "blue" ? "yellow" : "blue";
+ // Now flush out style changes in that document, since our event listeners
+ // seem to assume that things will work that way.
+ d.getBoundingClientRect();
+}
+
+function le(v1, v2, s) {
+ window.opener.ok(v1 <= v2, s + " (" + v1 + "," + v2 + ")");
+}
+
+function checkContains(r1, r2, s) {
+ le(Math.round(r1.left), Math.round(r2.left), "Left edges out" + s);
+ le(Math.round(r2.right), Math.round(r1.right), "Right edges out" + s);
+ le(Math.round(r1.top), Math.round(r2.top), "Top edges out" + s);
+ le(Math.round(r2.bottom), Math.round(r1.bottom), "Bottom edges out" + s);
+}
+
+function isRect(r1, r2) {
+ return (Math.abs(r1.left - r2.left) <= 1 ||
+ Math.abs(r1.right - r2.right) <= 1 ||
+ Math.abs(r1.top - r2.top) <= 1 ||
+ Math.abs(r1.bottom - r2.bottom) <= 1);
+}
+
+function isRectInList(r, list) {
+ for (var i = 0; i < list.length; ++i) {
+ if (isRect(r, list[i]))
+ return true;
+ }
+ return false;
+}
+
+function doesRectContain(r1, r2) {
+ return Math.floor(r1.left) <= r2.left && r2.right <= Math.ceil(r1.right) &&
+ Math.floor(r1.top) <= r2.top && r2.bottom <= Math.ceil(r1.bottom);
+}
+
+function rectToString(r) {
+ return "(" + r.left + "," + r.top + "," + r.right + "," + r.bottom + ")";
+}
+
+function doesRectContainListElement(r, list) {
+ dump("Incoming rect: " + rectToString(r) + "\n");
+ for (var i = 0; i < list.length; ++i) {
+ dump("List rect " + i + ": " + rectToString(list[i]));
+ if (doesRectContain(r, list[i])) {
+ dump(" FOUND\n");
+ return true;
+ }
+ dump("\n");
+ }
+ dump("NOT FOUND\n");
+ return false;
+}
+
+function checkGotSubdoc(list, container) {
+ var r = container.getBoundingClientRect();
+ return doesRectContainListElement(r, list);
+}
+
+function runTest1() {
+ // test basic functionality
+ var iterations = 0;
+ var foundExactRect = false;
+
+ function listener(event) {
+ var r = SpecialPowers.wrap(event).boundingClientRect;
+ var bounds = document.getElementById('d').getBoundingClientRect();
+ checkContains(r, bounds, "");
+ if (isRectInList(bounds, SpecialPowers.wrap(event).clientRects)) {
+ foundExactRect = true;
+ }
+ window.removeEventListener("MozAfterPaint", listener, false);
+ ++iterations;
+ if (iterations < 4) {
+ setTimeout(triggerPaint, 100);
+ } else {
+ window.opener.ok(foundExactRect, "Found exact rect");
+ runNext();
+ }
+ }
+
+ function triggerPaint() {
+ window.addEventListener("MozAfterPaint", listener, false);
+ flash(document, 'd');
+ window.opener.ok(true, "trigger test1 paint");
+ }
+ triggerPaint();
+}
+
+function runTest2(frameID, containerID) {
+ // test reporting of painting in subdocuments
+ var fired = 0;
+ var gotSubdocPrivileged = false;
+ var iframe = document.getElementById(frameID);
+ var container = document.getElementById(containerID);
+
+ function listener(event) {
+ if (checkGotSubdoc(SpecialPowers.wrap(event).clientRects, container))
+ gotSubdocPrivileged = true;
+ if (SpecialPowers.wrap(event).clientRects.length > 0) {
+ if (++fired == 1)
+ setTimeout(check, 100);
+ }
+ }
+
+ function check() {
+ window.opener.is(fired, 1, "Wrong event count (" + frameID + ")");
+ window.opener.ok(gotSubdocPrivileged, "Didn't get subdoc invalidation while we were privileged (" + frameID + ")");
+ window.removeEventListener("MozAfterPaint", listener, false);
+ runNext();
+ }
+
+ function triggerPaint() {
+ window.addEventListener("MozAfterPaint", listener, false);
+ document.body.offsetTop;
+ flash(iframe.contentDocument, 'd');
+ }
+ triggerPaint();
+}
+
+var test = 0;
+var tests = [runTest1,
+ function() { runTest2("iframe", "iframe") },
+ function() { runTest2("iframe2", "svg") }];
+function runNext() {
+ if (SpecialPowers.DOMWindowUtils.isMozAfterPaintPending) {
+ // Wait until there are no pending paints before trying to run tests
+ setTimeout(runNext, 100);
+ return;
+ }
+ if (test < tests.length) {
+ ++test;
+ tests[test - 1]();
+ } else {
+ window.opener.finishTests();
+ }
+}
+
+
+]]></script>
+</pre>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug482484-ref.html b/layout/base/tests/bug482484-ref.html
new file mode 100644
index 000000000..c8b8c2bab
--- /dev/null
+++ b/layout/base/tests/bug482484-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML><html><head></head>
+<body>
+<div contentEditable="true" id="div" spellcheck="false"><p id="p">ABC</p></div>
+<script>
+ // Position the caret after the "A"
+ var div = document.getElementById('div');
+ var p = document.getElementById('p');
+ div.focus();
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ range.setStart(p.firstChild, 1)
+ range.setEnd(p.firstChild, 1);
+ sel.addRange(range);
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug482484.html b/layout/base/tests/bug482484.html
new file mode 100644
index 000000000..f1de00799
--- /dev/null
+++ b/layout/base/tests/bug482484.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div contentEditable="true" id="div" spellcheck="false"><p id="p">BC</p></div>
+<script>
+ // Position the caret before the "B"
+ var div = document.getElementById('div');
+ div.focus();
+ var p = document.getElementById('p');
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ range.setStart(p.firstChild, 0)
+ range.setEnd(p.firstChild, 0);
+ sel.addRange(range);
+
+ sendKey('UP'); // move UP
+ sendChar('A'); // insert "A"
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug503399-ref.html b/layout/base/tests/bug503399-ref.html
new file mode 100644
index 000000000..f165b1559
--- /dev/null
+++ b/layout/base/tests/bug503399-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Testcase for bug 503399</title>
+ <style type="text/css">
+ html, body {
+ color: black;
+ background-color: white;
+ font: 16px monospace;
+ }
+ p {
+ text-align: justify;
+ max-width: 180px;
+ height: 1em;
+ overflow: hidden;
+ position: relative;
+ }
+ span {
+ display: inline-block;
+ border-left: 1px solid black;
+ position: absolute;
+ height: 100%;
+ }
+ </style>
+ <script>
+ var done = false;
+ function runTest(p) {
+ if (done)
+ return;
+ try {
+ var r = window.getSelection().getRangeAt(0);
+ r.setStart(p.childNodes[0],14);
+ r.setEnd(p.childNodes[0],14);
+ } catch (e) {}
+ document.documentElement.removeAttribute('class');
+ done = true;
+ }
+ </script>
+</head>
+<body onload="var p = document.getElementsByTagName('p')[0]; p.focus(); setTimeout(function(){runTest(p)},1000)">
+ <p onfocus="runTest(this)" contentEditable="true">&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;<span></span> &nbsp;&nbsp; &nbsp;&nbsp;</p>
+</body>
+</html>
diff --git a/layout/base/tests/bug503399.html b/layout/base/tests/bug503399.html
new file mode 100644
index 000000000..5857cf27d
--- /dev/null
+++ b/layout/base/tests/bug503399.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Testcase for bug 503399</title>
+ <style type="text/css">
+ html, body {
+ color: black;
+ background-color: white;
+ font: 16px monospace;
+ }
+ p {
+ text-align: justify;
+ max-width: 180px;
+ height: 1em;
+ overflow: hidden;
+ position: relative;
+ }
+ span {
+ display: inline-block;
+ position: absolute;
+ height: 100%;
+ }
+ </style>
+ <script>
+ var done = false;
+ function runTest(p) {
+ if (done)
+ return;
+ try {
+ var r = window.getSelection().getRangeAt(0);
+ r.setStart(p.childNodes[0],14);
+ r.setEnd(p.childNodes[0],14);
+ } catch (e) {}
+ document.documentElement.removeAttribute('class');
+ done = true;
+ }
+ </script>
+</head>
+<body onload="var p = document.getElementsByTagName('p')[0]; p.focus(); setTimeout(function(){runTest(p)},1000)">
+ <p onfocus="runTest(this)" contentEditable="true">&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;<span></span> &nbsp;&nbsp; &nbsp;&nbsp;</p>
+</body>
+</html>
diff --git a/layout/base/tests/bug512295-1-ref.html b/layout/base/tests/bug512295-1-ref.html
new file mode 100644
index 000000000..b2f8201c7
--- /dev/null
+++ b/layout/base/tests/bug512295-1-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html class="reftest-wait"><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div contenteditable="true">
+<p id="p">A B CD EFG<br>
+ 1234567890</p>
+</div>
+x
+<script>
+ // Position the caret at the end of the P element
+ var p = document.getElementById('p');
+ var div = p.parentNode;
+ div.focus();
+ SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", window);
+ onSpellCheck(div, function () {
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ range.setStart(p, p.childNodes.length);
+ range.setEnd(p, p.childNodes.length);
+ sel.addRange(range);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug512295-1.html b/layout/base/tests/bug512295-1.html
new file mode 100644
index 000000000..b69974d6c
--- /dev/null
+++ b/layout/base/tests/bug512295-1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML><html class="reftest-wait"><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div contenteditable="true">
+<p id="p">A B CD EFG<br>
+ 1234567890</p>
+</div>
+x
+<script>
+ // Position the caret after "A"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var p = document.getElementById('p');
+ var t = p.firstChild;
+ range.setStart(t, 1);
+ range.setEnd(t, 1);
+ sel.addRange(range);
+ p.parentNode.focus();
+
+ SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", window);
+ onSpellCheck(p.parentNode, function () {
+ sendKey('DOWN'); // now after "1"
+ sendKey('DOWN'); // now make sure we get to the end
+ sendKey('DOWN'); // now make sure we get to the end
+ sendKey('DOWN'); // now make sure we get to the end
+ sendKey('DOWN'); // now make sure we get to the end
+ sendKey('DOWN'); // now make sure we get to the end
+ document.documentElement.classList.remove("reftest-wait");
+ });
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug512295-2-ref.html b/layout/base/tests/bug512295-2-ref.html
new file mode 100644
index 000000000..dddf935e4
--- /dev/null
+++ b/layout/base/tests/bug512295-2-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML><html class="reftest-wait"><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+x
+<div contenteditable="true">
+<p id="p">A B CD EFG<br>
+ 1234567890</p>
+</div>
+<script>
+ // Position the caret before the "A"
+ var p = document.getElementById('p');
+ var div = p.parentNode;
+ div.focus();
+ SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", window);
+ onSpellCheck(div, function () {
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ range.setStart(p.firstChild, 0);
+ range.setEnd(p.firstChild, 0);
+ sel.addRange(range);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug512295-2.html b/layout/base/tests/bug512295-2.html
new file mode 100644
index 000000000..3d64c44a6
--- /dev/null
+++ b/layout/base/tests/bug512295-2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML><html class="reftest-wait"><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+x
+<div contenteditable="true">
+<p id="p">A B CD EFG<br>
+ 1234567890</p>
+</div>
+<script>
+ // Position the caret after "A"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var p = document.getElementById('p');
+ var t = p.firstChild;
+ range.setStart(t, 1);
+ range.setEnd(t, 1);
+ sel.addRange(range);
+ p.parentNode.focus();
+
+ SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", window);
+ onSpellCheck(p.parentNode, function () {
+ sendKey('DOWN'); // now after "1"
+ sendKey('DOWN'); // now below the P element
+ sendKey('UP'); // now before the "1"
+ sendKey('UP'); // now before the "A"
+ sendKey('UP'); // now before the "A"
+ sendKey('UP'); // now before the "A"
+ document.documentElement.classList.remove("reftest-wait");
+ });
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug558663.html b/layout/base/tests/bug558663.html
new file mode 100644
index 000000000..ecf0fc6c6
--- /dev/null
+++ b/layout/base/tests/bug558663.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=558663
+-->
+<head>
+ <title>Test for Bug 558663</title>
+</head>
+<body>
+<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=558663">Mozilla Bug 558663</a></p>
+
+ <!-- 20x20 of red -->
+<iframe id="iframe" src="data:text/html,<img id='image' border='0' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAG0lEQVR42mP8z0A%2BYKJA76jmUc2jmkc1U0EzACKcASfOgGoMAAAAAElFTkSuQmCC'>"></iframe>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 558663 **/
+var ok = parent.ok;
+var SimpleTest = parent.SimpleTest;
+var compareSnapshots = parent.compareSnapshots;
+var snapshotWindow = parent.snapshotWindow;
+var synthesizeMouse = parent.synthesizeMouse;
+
+window.addEventListener("load", runTest, false);
+
+function checkSnapshots(s1, s2, shouldBeEqual, testName) {
+ var res = compareSnapshots(s1, s2, shouldBeEqual);
+ if (res[0]) {
+ ok(true, testName + " snapshots compare correctly");
+ } else {
+ ok(false, testName + " snapshots compare incorrectly. snapshot 1: " +
+ res[1] + " snapshot 2: " + res[2]);
+ }
+}
+
+function runTest() {
+ document.getElementById("iframe").contentWindow.document.designMode = "on";
+
+ // The editor requires the event loop to spin after you turn on design mode
+ // before it takes effect.
+ setTimeout(continueTest, 100);
+}
+
+function continueTest() {
+ var win = document.getElementById("iframe").contentWindow;
+ var doc = win.document;
+ var image = doc.getElementById("image");
+
+ // We want to test that clicking on the image and then clicking on one of the
+ // draggers doesn't make the draggers disappear.
+
+ // clean snapshot
+ var before = snapshotWindow(win);
+
+ // click to get the draggers
+ synthesizeMouse(image, 1, 1, {type: "mousedown"}, win);
+ synthesizeMouse(image, 1, 1, {type: "mouseup"}, win);
+
+ // mouse over a dragger will change its color, so move the mouse away
+ synthesizeMouse(doc.documentElement, 50, 50, {type: "mousemove"}, win);
+
+ // snapshot with hopefully draggers
+ var middle = snapshotWindow(win);
+
+ // clicking on the top left dragger shouldn't change anything
+ synthesizeMouse(image, 1, 1, {type: "mousedown"}, win);
+ synthesizeMouse(image, 1, 1, {type: "mouseup"}, win);
+
+ // mouse over a dragger will change its color, so move the mouse away
+ synthesizeMouse(doc.documentElement, 50, 50, {type: "mousemove"}, win);
+
+ // snapshot with hopefully draggers again
+ var middle2 = snapshotWindow(win);
+
+ // click outside the image (but inside the document) to unselect it
+ synthesizeMouse(doc.documentElement, 50, 50, {type: "mousedown"}, win);
+ synthesizeMouse(doc.documentElement, 50, 50, {type: "mouseup"}, win);
+
+ // and then click outside the document so we don't draw a caret
+ synthesizeMouse(document.documentElement, 1, 1, {type: "mousedown"}, window);
+ synthesizeMouse(document.documentElement, 1, 1, {type: "mouseup"}, window);
+
+ // hopefully clean snapshot
+ var end = snapshotWindow(win);
+
+ // before == end && middle == middle2 && before/end != middle/middle2
+ checkSnapshots(before, end, true, "before and after should be the same")
+ checkSnapshots(middle, middle2, true, "middle two should be the same");
+ checkSnapshots(before, middle, false, "before and middle should not be the same");
+ checkSnapshots(before, middle2, false, "before and middle2 should not be the same");
+ checkSnapshots(middle, end, false, "middle and end should not be the same");
+ checkSnapshots(middle2, end, false, "middle2 and end should not be the same");
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug583889_inner1.html b/layout/base/tests/bug583889_inner1.html
new file mode 100644
index 000000000..85f1bfe3f
--- /dev/null
+++ b/layout/base/tests/bug583889_inner1.html
@@ -0,0 +1,67 @@
+<html>
+<body>
+<iframe id="inner" style="height: 10px; width: 10px"></iframe>
+<div style="width: 1000px; height: 1000px"></div>
+<script type="application/javascript;version=1.8">
+function grabEventAndGo(event) {
+ gen.send(event);
+}
+
+function waitAsync() {
+ setTimeout(function() { gen.next() }, 0);
+}
+
+function postPos() {
+ parent.postMessage(JSON.stringify({ top: document.body.scrollTop,
+ left: document.body.scrollLeft }),
+ "*");
+}
+
+function runTest() {
+ var inner = document.getElementById("inner");
+ window.onload = grabEventAndGo;
+ // Wait for onLoad event.
+ yield;
+
+ document.body.scrollTop = 300;
+ document.body.scrollLeft = 300;
+
+ postPos();
+
+ inner.src = "bug583889_inner2.html#id1";
+ inner.onload = grabEventAndGo;
+ // Let parent process sent message.
+ // Wait for onLoad event from 'inner' iframe.
+ yield;
+
+ postPos();
+
+ inner.onload = null;
+ dump("hi\n");
+ inner.contentWindow.location = "bug583889_inner2.html#id2"
+ waitAsync();
+ // Let parent process sent message.
+ // Let 'inner' iframe update itself.
+ yield;
+
+ postPos();
+
+ inner.contentWindow.location.hash = "#id3"
+ waitAsync();
+ // Let parent process sent message.
+ // Let 'inner' iframe update itself.
+ yield;
+
+ postPos();
+
+ parent.postMessage("done", "*");
+ // Let parent process sent messages.
+ // "End" generator.
+ yield;
+}
+
+var gen = runTest();
+gen.next();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug583889_inner2.html b/layout/base/tests/bug583889_inner2.html
new file mode 100644
index 000000000..ce63f54cf
--- /dev/null
+++ b/layout/base/tests/bug583889_inner2.html
@@ -0,0 +1,5 @@
+<body>
+<a id="id1">link 1</a>
+<a id="id2">link 2</a>
+<a id="id3">link 3</a>
+</body>
diff --git a/layout/base/tests/bug585922-ref.html b/layout/base/tests/bug585922-ref.html
new file mode 100644
index 000000000..76827f202
--- /dev/null
+++ b/layout/base/tests/bug585922-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="doTest()">
+ <input type=text style="-moz-appearance: none">
+ <script>
+ function doTest() {
+ var d = document.querySelector("input");
+ d.value = "b";
+ d.focus();
+ var editor = SpecialPowers.wrap(d).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+ var sel = editor.selection;
+ var t = editor.rootElement.firstChild;
+ sel.collapse(t, 1); // put the caret at the end of the textbox
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug585922.html b/layout/base/tests/bug585922.html
new file mode 100644
index 000000000..e929d6710
--- /dev/null
+++ b/layout/base/tests/bug585922.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="doTest()">
+ <input type=text style="-moz-appearance: none">
+ <script>
+ function doTest() {
+ function enableCaret(aEnable) {
+ var selCon = editor.selectionController;
+ selCon.setCaretEnabled(aEnable);
+ }
+
+ var d = document.querySelector("input");
+ d.value = "a";
+ d.focus();
+ var editor = SpecialPowers.wrap(d).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+ var sel = editor.selection;
+ var t = editor.rootElement.firstChild;
+ sel.collapse(t, 1); // put the caret at the end of the div
+ setTimeout(function() {
+ enableCaret(false);enableCaret(true);// force a caret display
+ enableCaret(false); // hide the caret
+ t.replaceData(0, 1, "b"); // replace the text node data
+ // at this point, the selection is collapsed to offset 0
+ synthesizeQuerySelectedText(); // call nsCaret::GetGeometry
+ sel.collapse(t, 1); // put the caret at the end again
+ enableCaret(true); // show the caret again
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug597519-1-ref.html b/layout/base/tests/bug597519-1-ref.html
new file mode 100644
index 000000000..e11eb0c96
--- /dev/null
+++ b/layout/base/tests/bug597519-1-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML><html><head>
+</head>
+<body>
+<textarea spellcheck="false" style="-moz-appearance: none">ab
+</textarea>
+<script>
+ var t = document.querySelector("textarea");
+ t.focus();
+ t.selectionStart = t.selectionEnd = t.value.length;
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug597519-1.html b/layout/base/tests/bug597519-1.html
new file mode 100644
index 000000000..a33084f15
--- /dev/null
+++ b/layout/base/tests/bug597519-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<textarea maxlength="3" spellcheck="false" style="-moz-appearance: none"></textarea>
+<script>
+ var t = document.querySelector("textarea");
+ t.focus();
+
+ synthesizeKey("a", {});
+ synthesizeKey("b", {});
+ synthesizeKey("VK_RETURN", {});
+ synthesizeKey("c", {});
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-1-ref.html b/layout/base/tests/bug602141-1-ref.html
new file mode 100644
index 000000000..64cbd58c3
--- /dev/null
+++ b/layout/base/tests/bug602141-1-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML><html><head>
+</head>
+<body>
+<span contenteditable="true" spellcheck="false">navigable__</span><span id="x" contenteditable="true" spellcheck="false">navigable|unnavigable</span><br />
+<script>
+ // Position the caret after "u"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 11);
+ range.setEnd(t, 11);
+ sel.addRange(range);
+ x.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-1.html b/layout/base/tests/bug602141-1.html
new file mode 100644
index 000000000..5d3fa7bbe
--- /dev/null
+++ b/layout/base/tests/bug602141-1.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<span contenteditable="true" spellcheck="false">navigable__</span><span id="x" contenteditable="true" spellcheck="false">navigable|unnavigable</span><br />
+<script>
+ // Position the caret after "|"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 10);
+ range.setEnd(t, 10);
+ sel.addRange(range);
+ x.focus();
+
+ sendKey('RIGHT'); // Try to move the caret one position to the right
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-2-ref.html b/layout/base/tests/bug602141-2-ref.html
new file mode 100644
index 000000000..f54518a02
--- /dev/null
+++ b/layout/base/tests/bug602141-2-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML><html><head>
+</head>
+<body>
+<span id="x" contenteditable="true" spellcheck="false">navigable__|unnavigable</span><br />
+<script>
+ // Position the caret after "u"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 13);
+ range.setEnd(t, 13);
+ sel.addRange(range);
+ x.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-2.html b/layout/base/tests/bug602141-2.html
new file mode 100644
index 000000000..57dff22a7
--- /dev/null
+++ b/layout/base/tests/bug602141-2.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<span id="x" contenteditable="true" spellcheck="false">navigable__|</span><br />
+<script>
+ document.getElementById('x').appendChild(document.createTextNode('unnavigable'));
+
+ // Position the caret after "|"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 12);
+ range.setEnd(t, 12);
+ sel.addRange(range);
+ x.focus();
+
+ sendKey('RIGHT'); // Try to move the caret one position to the right
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-3-ref.html b/layout/base/tests/bug602141-3-ref.html
new file mode 100644
index 000000000..8d39318cc
--- /dev/null
+++ b/layout/base/tests/bug602141-3-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML><html><head>
+</head>
+<body>
+noteditable<span id="x" contenteditable="true" spellcheck="false">navigable|unnavigable</span><br />
+<script>
+ // Position the caret after "u"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 11);
+ range.setEnd(t, 11);
+ sel.addRange(range);
+ x.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-3.html b/layout/base/tests/bug602141-3.html
new file mode 100644
index 000000000..f1d41919a
--- /dev/null
+++ b/layout/base/tests/bug602141-3.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+noteditable<span id="x" contenteditable="true" spellcheck="false">navigable|unnavigable</span><br />
+<script>
+ // Position the caret after "|"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 10);
+ range.setEnd(t, 10);
+ sel.addRange(range);
+ x.focus();
+
+ sendKey('RIGHT'); // Try to move the caret one position to the right
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-4-ref.html b/layout/base/tests/bug602141-4-ref.html
new file mode 100644
index 000000000..c67986c5f
--- /dev/null
+++ b/layout/base/tests/bug602141-4-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML><html><head>
+</head>
+<body>
+<span>not editable</span><span id="x" contenteditable="true" spellcheck="false">navigable|unnavigable</span>
+<script>
+ // Position the caret after "u"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 11);
+ range.setEnd(t, 11);
+ sel.addRange(range);
+ x.focus();
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug602141-4.html b/layout/base/tests/bug602141-4.html
new file mode 100644
index 000000000..7db22db07
--- /dev/null
+++ b/layout/base/tests/bug602141-4.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<span>not editable</span><span id="x" contenteditable="true" spellcheck="false">navigable|unnavigable</span>
+<script>
+ // Position the caret after "|"
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ var range = document.createRange();
+ var x = document.getElementById('x');
+ var t = x.firstChild;
+ range.setStart(t, 10);
+ range.setEnd(t, 10);
+ sel.addRange(range);
+ x.focus();
+
+ sendKey('RIGHT'); // Try to move the caret one position to the right
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug612271-1.html b/layout/base/tests/bug612271-1.html
new file mode 100644
index 000000000..4c511b31e
--- /dev/null
+++ b/layout/base/tests/bug612271-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+ <textarea id="target" style="height: 100px; -moz-appearance: none" spellcheck="false"
+ onkeydown="this.style.display='block';this.style.height='200px';">foo</textarea>
+<script>
+ var t = document.querySelector("textarea");
+ t.focus();
+ t.selectionStart = t.selectionEnd = t.value.length;
+ sendKey('RETURN');
+ document.body.appendChild(document.createTextNode(t.selectionStart + " - " + t.selectionEnd));
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug612271-2.html b/layout/base/tests/bug612271-2.html
new file mode 100644
index 000000000..5c3754794
--- /dev/null
+++ b/layout/base/tests/bug612271-2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+ <textarea id="target" style="height: 100px; -moz-appearance: none" spellcheck="false"
+ onkeypress="this.style.display='block';this.style.height='200px';">foo</textarea>
+<script>
+ var t = document.querySelector("textarea");
+ t.focus();
+ t.selectionStart = t.selectionEnd = t.value.length;
+ sendKey('RETURN');
+ document.body.appendChild(document.createTextNode(t.selectionStart + " - " + t.selectionEnd));
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug612271-3.html b/layout/base/tests/bug612271-3.html
new file mode 100644
index 000000000..29be02693
--- /dev/null
+++ b/layout/base/tests/bug612271-3.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+ <textarea id="target" style="height: 100px; -moz-appearance: none" spellcheck="false"
+ onkeyup="this.style.display='block';this.style.height='200px';">foo</textarea>
+<script>
+ var t = document.querySelector("textarea");
+ t.focus();
+ t.selectionStart = t.selectionEnd = t.value.length;
+ sendKey('RETURN');
+ document.body.appendChild(document.createTextNode(t.selectionStart + " - " + t.selectionEnd));
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug612271-ref.html b/layout/base/tests/bug612271-ref.html
new file mode 100644
index 000000000..e1472c8c4
--- /dev/null
+++ b/layout/base/tests/bug612271-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript">
+ function loaded() {
+ var t = document.querySelector("textarea");
+ t.focus();
+ t.selectionStart = t.selectionEnd = 4;
+ }
+ </script>
+</head>
+<body onload="loaded()">
+ <textarea style="height: 200px; display: block; -moz-appearance: none" spellcheck="false"
+ >foo
+</textarea>
+ 4 - 4
+</body>
+</html>
diff --git a/layout/base/tests/bug613433-1.html b/layout/base/tests/bug613433-1.html
new file mode 100644
index 000000000..37e83a78b
--- /dev/null
+++ b/layout/base/tests/bug613433-1.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <style>
+ div {
+ min-height: 36px;
+ overflow-x: auto;
+ }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function test() {
+ document.querySelector("div").focus();
+ // type a character, then press backspace to delete it
+ sendChar("X");
+ sendKey("BACK_SPACE");
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="test()">
+ <div id="div1" contenteditable></div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug613433-2.html b/layout/base/tests/bug613433-2.html
new file mode 100644
index 000000000..9eb093ff4
--- /dev/null
+++ b/layout/base/tests/bug613433-2.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <style>
+ div {
+ min-height: 36px;
+ overflow-y: auto;
+ }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function test() {
+ document.querySelector("div").focus();
+ // type a character, then press backspace to delete it
+ sendChar("X");
+ sendKey("BACK_SPACE");
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="test()">
+ <div id="div1" contenteditable></div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug613433-3.html b/layout/base/tests/bug613433-3.html
new file mode 100644
index 000000000..e7d1bc560
--- /dev/null
+++ b/layout/base/tests/bug613433-3.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <style>
+ div {
+ min-height: 36px;
+ overflow: auto;
+ }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function test() {
+ document.querySelector("div").focus();
+ // type a character, then press backspace to delete it
+ sendChar("X");
+ sendKey("BACK_SPACE");
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="test()">
+ <div id="div1" contenteditable></div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug613433-ref.html b/layout/base/tests/bug613433-ref.html
new file mode 100644
index 000000000..f4a2ab3b6
--- /dev/null
+++ b/layout/base/tests/bug613433-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <style>
+ div {
+ min-height: 36px;
+ }
+ </style>
+ <script>
+ function test() {
+ document.querySelector("div").focus();
+ }
+ function focusTriggered() {
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="test()">
+ <div contenteditable onfocus="focusTriggered()"></div>
+ </body>
+</html>
diff --git a/layout/base/tests/bug613807-1-ref.html b/layout/base/tests/bug613807-1-ref.html
new file mode 100644
index 000000000..b47a572ea
--- /dev/null
+++ b/layout/base/tests/bug613807-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body onload="document.querySelector('textarea').focus()">
+<textarea id="t" rows="4" style="-moz-appearance: none"></textarea>
+</body>
+</html>
diff --git a/layout/base/tests/bug613807-1.html b/layout/base/tests/bug613807-1.html
new file mode 100644
index 000000000..145ea5603
--- /dev/null
+++ b/layout/base/tests/bug613807-1.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<textarea id="t" rows="4" style="-moz-appearance: none"></textarea>
+<script>
+ if (typeof(addLoadEvent) == 'undefined') {
+ _newCallStack = function(path) {
+ var rval = function () {
+ var callStack = arguments.callee.callStack;
+ for (var i = 0; i < callStack.length; i++) {
+ if (callStack[i].apply(this, arguments) === false) {
+ break;
+ }
+ }
+ try {
+ this[path] = null;
+ } catch (e) {
+ // pass
+ }
+ };
+ rval.callStack = [];
+ return rval;
+ };
+ function addLoadEvent(func) {
+ var existing = window["onload"];
+ var regfunc = existing;
+ if (!(typeof(existing) == 'function'
+ && typeof(existing.callStack) == "object"
+ && existing.callStack !== null)) {
+ regfunc = _newCallStack("onload");
+ if (typeof(existing) == 'function') {
+ regfunc.callStack.push(existing);
+ }
+ window["onload"] = regfunc;
+ }
+ regfunc.callStack.push(func);
+ };
+ }
+
+ addLoadEvent(function() {
+ var area = document.getElementById('t');
+ area.focus();
+
+ var domWindowUtils = SpecialPowers.getDOMWindowUtils(window);
+
+ // input raw characters
+ synthesizeCompositionChange(
+ { composition:
+ { string: "\u306D",
+ clauses: [
+ { length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }
+ ]
+ },
+ caret: { start: 1, length: 0 }
+ });
+ synthesizeCompositionChange(
+ { composition:
+ { string: "\u306D\u3053",
+ clauses: [
+ { length: 2, attr: COMPOSITION_ATTR_RAW_CLAUSE }
+ ]
+ },
+ caret: { start: 2, length: 0 }
+ });
+
+ // convert
+ synthesizeCompositionChange(
+ { composition:
+ { string: "\u732B",
+ clauses: [
+ { length: 1, attr: COMPOSITION_ATTR_SELECTED_CLAUSE }
+ ]
+ },
+ caret: { start: 1, length: 0 }
+ });
+
+ // commit
+ synthesizeComposition({ type: "compositioncommitasis" });
+
+ document.body.clientWidth;
+
+ // undo
+ synthesizeKey("Z", {accelKey: true});
+ });
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug632215-1.html b/layout/base/tests/bug632215-1.html
new file mode 100644
index 000000000..7def5962a
--- /dev/null
+++ b/layout/base/tests/bug632215-1.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body>
+ <iframe src="data:text/html,<body spellcheck=false></body>"></iframe>
+ <script>
+ onload = function() {
+ var i = document.querySelector("iframe");
+ var d = i.contentDocument;
+ var w = i.contentWindow;
+ var s = w.getSelection();
+ i.focus();
+ d.body.contentEditable = true;
+ d.body.contentEditable = false;
+ d.designMode = "off";
+ d.designMode = "on";
+ d.body.focus();
+ synthesizeKey("x", {});
+ s.collapse(d.body.firstChild, 1);
+ synthesizeKey("x", {});
+ setTimeout(function() {
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ };
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug632215-2.html b/layout/base/tests/bug632215-2.html
new file mode 100644
index 000000000..a05b942a4
--- /dev/null
+++ b/layout/base/tests/bug632215-2.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body>
+ <iframe src="data:text/html,<body contenteditable spellcheck=false></body>"></iframe>
+ <script>
+ onload = function() {
+ var i = document.querySelector("iframe");
+ var d = i.contentDocument;
+ var w = i.contentWindow;
+ var s = w.getSelection();
+ i.focus();
+ d.body.contentEditable = false;
+ d.designMode = "off";
+ d.designMode = "on";
+ d.body.focus();
+ synthesizeKey("x", {});
+ s.collapse(d.body.firstChild, 1);
+ synthesizeKey("x", {});
+ setTimeout(function() {
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ };
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug632215-ref.html b/layout/base/tests/bug632215-ref.html
new file mode 100644
index 000000000..980b5c46a
--- /dev/null
+++ b/layout/base/tests/bug632215-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <iframe src="data:text/html,<body spellcheck=false>xx</body>"></iframe>
+ <script>
+ onload = function() {
+ var i = document.querySelector("iframe");
+ var d = i.contentDocument;
+ var w = i.contentWindow;
+ d.designMode = "on";
+ i.focus();
+ d.body.focus();
+ w.getSelection().collapse(d.body.firstChild, 2);
+ };
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug633044-1-ref.html b/layout/base/tests/bug633044-1-ref.html
new file mode 100644
index 000000000..5a341c4e6
--- /dev/null
+++ b/layout/base/tests/bug633044-1-ref.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <script>
+ onload = function() {
+ var el;
+ while (el = document.querySelector("br")) {
+ el.parentNode.removeChild(el);
+ }
+ focus();
+ document.body.focus();
+ getSelection().collapse(document.body.firstChild, 0);
+ }
+ </script>
+</head>
+
+<body style="white-space:pre-wrap;" contenteditable></body></html>
diff --git a/layout/base/tests/bug633044-1.html b/layout/base/tests/bug633044-1.html
new file mode 100644
index 000000000..63ee5a781
--- /dev/null
+++ b/layout/base/tests/bug633044-1.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ onload = function() {
+ var el;
+ while (el = document.querySelector("br")) {
+ el.parentNode.removeChild(el);
+ }
+ focus();
+ document.body.focus();
+ getSelection().collapse(document.body.firstChild, 0);
+
+ var range = window.getSelection().getRangeAt(0);
+ var el = document.createTextNode(" ");
+ range.insertNode(el);
+ el.parentNode.removeChild(el);
+
+ synthesizeKey("VK_UP", {});
+ }
+ </script>
+</head>
+
+<body style="white-space:pre-wrap;" contenteditable></body></html>
diff --git a/layout/base/tests/bug634406-1-ref.html b/layout/base/tests/bug634406-1-ref.html
new file mode 100644
index 000000000..87b42a9ed
--- /dev/null
+++ b/layout/base/tests/bug634406-1-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML><html>
+<body>
+<textarea spellcheck="false" style="-moz-appearance: none">ab</textarea>
+<script>
+ var t = document.querySelector("textarea");
+ t.focus();
+ t.selectionStart = t.selectionEnd = t.value.length;
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug634406-1.html b/layout/base/tests/bug634406-1.html
new file mode 100644
index 000000000..141198b59
--- /dev/null
+++ b/layout/base/tests/bug634406-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML><html><head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<textarea spellcheck="false" style="-moz-appearance: none"></textarea>
+<script>
+ var t = document.querySelector("textarea");
+ t.focus();
+
+ synthesizeKey("a", {});
+ synthesizeKey("A", {accelKey: true});
+ synthesizeKey("VK_RIGHT", {});
+ synthesizeKey("b", {});
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug644428-1-ref.html b/layout/base/tests/bug644428-1-ref.html
new file mode 100644
index 000000000..ee193b0bb
--- /dev/null
+++ b/layout/base/tests/bug644428-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="setupCaret()">
+ <div contenteditable>a</div>
+ <script>
+ function setupCaret() {
+ var div = document.querySelector("div");
+ div.focus();
+ var sel = window.getSelection();
+ sel.collapse(div, 1);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug644428-1.html b/layout/base/tests/bug644428-1.html
new file mode 100644
index 000000000..9fe4d17fe
--- /dev/null
+++ b/layout/base/tests/bug644428-1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="setupCaret()" spellcheck="false">
+ <div contenteditable>a<span>b</span>c </div>
+ <script>
+ function setupCaret() {
+ var div = document.querySelector("div");
+ div.focus();
+ var sel = window.getSelection();
+ sel.collapse(div, 3);
+ synthesizeKey("VK_BACK_SPACE", {});
+ synthesizeKey("VK_BACK_SPACE", {});
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug646382-1-ref.html b/layout/base/tests/bug646382-1-ref.html
new file mode 100644
index 000000000..03acde5b5
--- /dev/null
+++ b/layout/base/tests/bug646382-1-ref.html
@@ -0,0 +1,17 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body onload="start()">
+ <textarea onfocus="done()" style="-moz-appearance: none">س</textarea>
+ <script>
+ var textarea = document.querySelector("textarea");
+ function start() {
+ textarea.focus();
+ }
+ function done() {
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug646382-1.html b/layout/base/tests/bug646382-1.html
new file mode 100644
index 000000000..06335befa
--- /dev/null
+++ b/layout/base/tests/bug646382-1.html
@@ -0,0 +1,22 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <textarea onfocus="typeIntoMe()" style="-moz-appearance: none"></textarea>
+ <script>
+ function start() {
+ document.querySelector("textarea").focus();
+ }
+ function typeIntoMe() {
+ setTimeout(function() {
+ synthesizeKey("س", {});
+ synthesizeKey("VK_DOWN", {});
+ synthesizeKey("VK_DOWN", {});
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug646382-2-ref.html b/layout/base/tests/bug646382-2-ref.html
new file mode 100644
index 000000000..fde995d41
--- /dev/null
+++ b/layout/base/tests/bug646382-2-ref.html
@@ -0,0 +1,14 @@
+<html class="reftest-wait">
+ <body onload="start()">
+ <textarea dir="rtl" onfocus="done()" style="-moz-appearance: none">s</textarea>
+ <script>
+ var textarea = document.querySelector("textarea");
+ function start() {
+ textarea.focus();
+ }
+ function done() {
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug646382-2.html b/layout/base/tests/bug646382-2.html
new file mode 100644
index 000000000..4852b8563
--- /dev/null
+++ b/layout/base/tests/bug646382-2.html
@@ -0,0 +1,21 @@
+<html class="reftest-wait">
+ <head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <textarea dir="rtl" onfocus="typeIntoMe()" style="-moz-appearance: none"></textarea>
+ <script>
+ function start() {
+ document.querySelector("textarea").focus();
+ }
+ function typeIntoMe() {
+ setTimeout(function() {
+ synthesizeKey("s", {});
+ synthesizeKey("VK_DOWN", {});
+ synthesizeKey("VK_DOWN", {});
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug664087-1-ref.html b/layout/base/tests/bug664087-1-ref.html
new file mode 100644
index 000000000..77de000b0
--- /dev/null
+++ b/layout/base/tests/bug664087-1-ref.html
@@ -0,0 +1,21 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <textarea rows="3" onfocus="done()" spellcheck="false" style="-moz-appearance: none">אב
+ג</textarea>
+ <script>
+ var textarea = document.querySelector("textarea");
+ function start() {
+ textarea.focus();
+ }
+ function done() {
+ synthesizeKey("VK_LEFT", {});
+ synthesizeKey("VK_LEFT", {});
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug664087-1.html b/layout/base/tests/bug664087-1.html
new file mode 100644
index 000000000..ea12bcaad
--- /dev/null
+++ b/layout/base/tests/bug664087-1.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <textarea rows="3" onfocus="typeIntoMe()" spellcheck="false" style="-moz-appearance: none"></textarea>
+ <script>
+ function start() {
+ document.querySelector("textarea").focus();
+ }
+ function typeIntoMe() {
+ setTimeout(function() {
+ synthesizeKey("א", {});
+ synthesizeKey("VK_RETURN", {});
+ synthesizeKey("ג", {});
+ synthesizeKey("VK_UP", {});
+ synthesizeKey("VK_END", {});
+ synthesizeKey("ב", {});
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug664087-2-ref.html b/layout/base/tests/bug664087-2-ref.html
new file mode 100644
index 000000000..52749fe44
--- /dev/null
+++ b/layout/base/tests/bug664087-2-ref.html
@@ -0,0 +1,21 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <textarea dir="rtl" onfocus="done()" spellcheck="false" style="-moz-appearance: none">ab
+c</textarea>
+ <script>
+ var textarea = document.querySelector("textarea");
+ function start() {
+ textarea.focus();
+ }
+ function done() {
+ synthesizeKey("VK_RIGHT", {});
+ synthesizeKey("VK_RIGHT", {});
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug664087-2.html b/layout/base/tests/bug664087-2.html
new file mode 100644
index 000000000..3baf2b165
--- /dev/null
+++ b/layout/base/tests/bug664087-2.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <textarea dir="rtl" onfocus="typeIntoMe()" spellcheck="false" style="-moz-appearance: none"></textarea>
+ <script>
+ function start() {
+ document.querySelector("textarea").focus();
+ }
+ function typeIntoMe() {
+ setTimeout(function() {
+ synthesizeKey("a", {});
+ synthesizeKey("VK_RETURN", {});
+ synthesizeKey("c", {});
+ synthesizeKey("VK_UP", {});
+ synthesizeKey("VK_END", {});
+ synthesizeKey("b", {});
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug682712-1-ref.html b/layout/base/tests/bug682712-1-ref.html
new file mode 100644
index 000000000..1e034fd91
--- /dev/null
+++ b/layout/base/tests/bug682712-1-ref.html
@@ -0,0 +1,24 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body onload="start()">
+ <iframe src="data:text/html,<body contenteditable spellcheck=false>foo bar"></iframe>
+ <script>
+ function start() {
+ var iframe = document.querySelector("iframe");
+ var win = iframe.contentWindow;
+ var doc = iframe.contentDocument;
+
+ setTimeout(function() {
+ doc.body.focus();
+
+ // Now try to set the caret without moving it
+ win.getSelection().collapse(doc.body.firstChild, 1);
+
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug682712-1.html b/layout/base/tests/bug682712-1.html
new file mode 100644
index 000000000..9effc8fce
--- /dev/null
+++ b/layout/base/tests/bug682712-1.html
@@ -0,0 +1,32 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <iframe src="data:text/html,<body contenteditable spellcheck=false>foo bar"></iframe>
+ <script>
+ function start() {
+ var iframe = document.querySelector("iframe");
+ var win = iframe.contentWindow;
+ var doc = iframe.contentDocument;
+
+ // Reframe the iframe
+ iframe.style.display = "none";
+ document.body.clientWidth;
+ iframe.style.display = "";
+ document.body.clientWidth;
+
+ setTimeout(function() {
+ doc.body.focus();
+
+ // Now try to move the caret
+ win.getSelection().collapse(doc.body.firstChild, 0);
+ synthesizeKey("VK_RIGHT", {});
+
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug687297_a.html b/layout/base/tests/bug687297_a.html
new file mode 100644
index 000000000..af0010834
--- /dev/null
+++ b/layout/base/tests/bug687297_a.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>Test companion for Bug 687297</title>
+ <style type="text/css"> * { font-size:9px; } </style>
+</head>
+<body>
+ <div id="test_content">ABCDEFG 0123456</div>
+</body>
+<script type="application/javascript">
+ window.onload = function() {
+ opener.report_size_a(document.getElementById("test_content").clientHeight);
+ window.location.href = "bug687297_b.html";
+ };
+</script>
+</html>
diff --git a/layout/base/tests/bug687297_b.html b/layout/base/tests/bug687297_b.html
new file mode 100644
index 000000000..34f682354
--- /dev/null
+++ b/layout/base/tests/bug687297_b.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
+ <title>Test companion for Bug 687297</title>
+ <style type="text/css"> * { font-size:9px; } </style>
+</head>
+<body>
+ <div id="test_content">ABCDEFG 0123456</div>
+</body>
+<script type="application/javascript">
+ window.onload = function() {
+ opener.report_size_b(document.getElementById("test_content").clientHeight);
+ window.location.href = "bug687297_c.html";
+ };
+</script>
+</html>
diff --git a/layout/base/tests/bug687297_c.html b/layout/base/tests/bug687297_c.html
new file mode 100644
index 000000000..ea029d24e
--- /dev/null
+++ b/layout/base/tests/bug687297_c.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>Test companion for Bug 687297</title>
+ <style type="text/css"> * { font-size:9px; } </style>
+</head>
+<body>
+ <div id="test_content">ABCDEFG 0123456</div>
+</body>
+<script type="application/javascript">
+ window.onload = function() {
+ opener.report_size_c(document.getElementById("test_content").clientHeight);
+ window.close();
+ };
+</script>
+</html>
diff --git a/layout/base/tests/bug746993-1-ref.html b/layout/base/tests/bug746993-1-ref.html
new file mode 100644
index 000000000..d65c6b142
--- /dev/null
+++ b/layout/base/tests/bug746993-1-ref.html
@@ -0,0 +1,20 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <iframe src="data:text/html,<body contenteditable spellcheck=false>Here's some text.<br /><br /><div></div></body>"></iframe>
+ <script>
+ function start() {
+ var iframe = document.querySelector("iframe");
+ var win = iframe.contentWindow;
+ var doc = iframe.contentDocument;
+ iframe.focus();
+ doc.body.focus();
+ win.getSelection().collapse(doc.body, 3);
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug746993-1.html b/layout/base/tests/bug746993-1.html
new file mode 100644
index 000000000..7ed2ccedc
--- /dev/null
+++ b/layout/base/tests/bug746993-1.html
@@ -0,0 +1,22 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <iframe src="data:text/html,<body contenteditable spellcheck=false><br /><div></div></body>"></iframe>
+ <script>
+ function start() {
+ var iframe = document.querySelector("iframe");
+ var win = iframe.contentWindow;
+ var doc = iframe.contentDocument;
+ iframe.focus();
+ doc.body.focus();
+ win.getSelection().collapse(doc.body, 0);
+ sendString("Here's some text.");
+ synthesizeKey("VK_RETURN", {});
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug851445_helper.html b/layout/base/tests/bug851445_helper.html
new file mode 100644
index 000000000..dc4e4002e
--- /dev/null
+++ b/layout/base/tests/bug851445_helper.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body style="height:1000px">
+<script>
+var docElement = document.documentElement;
+docElement.style.display = 'none';
+docElement.offsetTop;
+docElement.style.display = '';
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug921928_event_target_iframe_apps_oop.html b/layout/base/tests/bug921928_event_target_iframe_apps_oop.html
new file mode 100644
index 000000000..2a6a7d5a6
--- /dev/null
+++ b/layout/base/tests/bug921928_event_target_iframe_apps_oop.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test companion for bug 921928</title>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/base/tests/bug923376-ref.html b/layout/base/tests/bug923376-ref.html
new file mode 100644
index 000000000..3a60cf195
--- /dev/null
+++ b/layout/base/tests/bug923376-ref.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html class="reftest-wait"><div contenteditable>something missspelled<br>something elsed#</div>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script>
+document.body.firstChild.focus();
+SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm",
+ window);
+onSpellCheck(document.body.firstChild, function() {
+ document.documentElement.removeAttribute("class");
+});
+</script>
diff --git a/layout/base/tests/bug923376.html b/layout/base/tests/bug923376.html
new file mode 100644
index 000000000..8a12a18bd
--- /dev/null
+++ b/layout/base/tests/bug923376.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<html class="reftest-wait"><div contenteditable></div>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script>
+var div = document.body.firstChild;
+div.focus();
+SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm",
+ window);
+onSpellCheck(div, function() {
+ div.innerHTML = 'something missspelled<br>something elsed#';
+ onSpellCheck(div, function() {
+ document.documentElement.removeAttribute("class");
+ });
+});
+</script>
diff --git a/layout/base/tests/bug956530-1-ref.html b/layout/base/tests/bug956530-1-ref.html
new file mode 100644
index 000000000..d82c761bf
--- /dev/null
+++ b/layout/base/tests/bug956530-1-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <style>
+ /* eliminate the blue glow when focusing the element. */
+ input {
+ background: none;
+ border: none;
+ outline: none;
+ }
+ </style>
+ <script>
+ function test() {
+ focus();
+ var i = document.querySelector("input");
+ i.focus();
+ }
+ function finish() {
+ setTimeout(function() {
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ <body onload="setTimeout(test, 0)">
+ <input value="text text text text text"
+ onfocus="this.select(); finish();">
+ </body>
+</html>
diff --git a/layout/base/tests/bug956530-1.html b/layout/base/tests/bug956530-1.html
new file mode 100644
index 000000000..c4a223097
--- /dev/null
+++ b/layout/base/tests/bug956530-1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <style>
+ /* eliminate the blue glow when focusing the element. */
+ input {
+ background: none;
+ border: none;
+ outline: none;
+ }
+ </style>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function test() {
+ var i = document.querySelector("input");
+ i.setSelectionRange(i.value.length,i.value.length);
+ focus();
+ synthesizeMouseAtCenter(i, {});
+ setTimeout(function() {
+ synthesizeMouseAtCenter(document.body, {});
+ setTimeout(function() {
+ synthesizeMouseAtCenter(i, {});
+ }, 0);
+ }, 0);
+ }
+ function finish() {
+ setTimeout(function() {
+ document.documentElement.removeAttribute("class");
+ }, 0);
+ }
+ </script>
+ <body onload="setTimeout(test, 0)">
+ <input value="text text text text text"
+ onfocus="this.select(); finish();">
+ </body>
+</html>
diff --git a/layout/base/tests/bug966992-1-ref.html b/layout/base/tests/bug966992-1-ref.html
new file mode 100644
index 000000000..c8fff7b5e
--- /dev/null
+++ b/layout/base/tests/bug966992-1-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcases for overflow-clip-box:content-box</title>
+ <style type="text/css">
+ html,body {
+ color:black; background-color:white; font:16px monospace; padding:0; margin:7px;
+ }
+.block {
+ border:1px solid grey; height:50px; width:200px; padding:20px;
+ overflow:auto; overflow-clip-box:padding-box;
+}
+.rel { position:relative; }
+.mask1 { position:absolute; width:20px; background:white; top:0; bottom:0; right:0; }
+mask {
+ display:block;
+ position:absolute;
+ left: -1px;
+ bottom: -1px;
+ height: 25px;
+ width: 80%;
+ background:black;
+}
+ </style>
+</head>
+<body>
+
+<div style="position:relative;">
+<div contenteditable=true spellcheck=false tabindex=0 id=x class="rel block">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<span style="padding-right:20px">X</span><div class=mask1></div></div>
+<mask></mask>
+</div>
+
+<script>
+var x = document.getElementById('x');
+x.focus();
+window.getSelection().collapse(x,0);
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug966992-1.html b/layout/base/tests/bug966992-1.html
new file mode 100644
index 000000000..f630ff1c6
--- /dev/null
+++ b/layout/base/tests/bug966992-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcases for overflow-clip-box:content-box</title>
+ <style type="text/css">
+ html,body {
+ color:black; background-color:white; font:16px monospace; padding:0; margin:7px;
+ }
+.block {
+ border:1px solid grey; height:50px; width:200px; padding:20px;
+ overflow:auto; overflow-clip-box:content-box;
+}
+mask {
+ display:block;
+ position:absolute;
+ left: -1px;
+ bottom: -1px;
+ height: 25px;
+ width: 80%;
+ background:black;
+}
+ </style>
+</head>
+<body>
+
+<div style="position:relative;">
+<div contenteditable=true spellcheck=false tabindex=0 id=x class="block">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div>
+<mask></mask>
+</div>
+<script>
+var x = document.getElementById('x');
+x.focus();
+window.getSelection().collapse(x,0);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug966992-2-ref.html b/layout/base/tests/bug966992-2-ref.html
new file mode 100644
index 000000000..a619d579c
--- /dev/null
+++ b/layout/base/tests/bug966992-2-ref.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcases for overflow-clip-box:content-box</title>
+ <style type="text/css">
+ html,body {
+ color:black; background-color:white; font:16px monospace; padding:0; margin:7px;
+ }
+.block {
+ border:1px solid grey; height:50px; width:200px; padding:20px;
+ overflow:auto; overflow-clip-box:padding-box;
+ line-height:1px;
+}
+.rel { position:relative; }
+.mask1 { position:absolute; width:20px; background:white; top:0; bottom:0; right:0; }
+.mask2 { position:absolute; height:20px; background:white; top:0; left:40px; right:0; }
+mask {
+ display:block;
+ position:absolute;
+ left: -1px;
+ bottom: -1px;
+ height: 25px;
+ width: 80%;
+ background:black;
+}
+ </style>
+</head>
+<body>
+
+<div style="position:relative;">
+<div contenteditable=true spellcheck=false tabindex=0 id=x class="rel block">&nbsp;&nbsp;&nbsp;&nbsp;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<span style="padding-right:20px">X</span><div class=mask2></div><div class=mask1></div></div>
+<mask></mask>
+</div>
+
+<script>
+var x = document.getElementById('x');
+x.focus();
+window.getSelection().collapse(x,0);
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/bug966992-2.html b/layout/base/tests/bug966992-2.html
new file mode 100644
index 000000000..1a8919e55
--- /dev/null
+++ b/layout/base/tests/bug966992-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcases for overflow-clip-box:content-box</title>
+ <style type="text/css">
+ html,body {
+ color:black; background-color:white; font:16px monospace; padding:0; margin:7px;
+ }
+.block {
+ border:1px solid grey; height:50px; width:200px; padding:20px;
+ overflow:auto; overflow-clip-box:content-box;
+ line-height:1px;
+}
+.rel { position:relative; }
+mask {
+ display:block;
+ position:absolute;
+ left: -1px;
+ bottom: -1px;
+ height: 25px;
+ width: 80%;
+ background:black;
+}
+ </style>
+</head>
+<body>
+
+<div style="position:relative;">
+<div contenteditable=true spellcheck=false tabindex=0 id=x class="block">&nbsp;&nbsp;&nbsp;&nbsp;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div>
+<mask></mask>
+</div>
+<script>
+var x = document.getElementById('x');
+x.focus();
+window.getSelection().collapse(x,0);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug966992-3-ref.html b/layout/base/tests/bug966992-3-ref.html
new file mode 100644
index 000000000..cefbc4f80
--- /dev/null
+++ b/layout/base/tests/bug966992-3-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcases for overflow-clip-box:content-box</title>
+ <style type="text/css">
+ html,body {
+ color:black; background-color:white; font:16px monospace; padding:0; margin:7px;
+ }
+ div {
+ width: 100px; padding-right:50px; overflow-clip-box:padding-box;
+ overflow:hidden;
+ }
+.rel { position:relative; }
+.mask5 { position:absolute; height:40px; background:white; top:3px; left:0px; width:50px; }
+ </style>
+</head>
+<body>
+
+<div contenteditable=true spellcheck=false tabindex=0 id=x class="block"><span style="padding-right:50px">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</span></div>
+
+<script>
+var x = document.getElementById('x');
+x.focus();
+x.scrollLeft=100000
+window.getSelection().collapse(x,1);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug966992-3.html b/layout/base/tests/bug966992-3.html
new file mode 100644
index 000000000..2cc2af96a
--- /dev/null
+++ b/layout/base/tests/bug966992-3.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcases for overflow-clip-box:content-box</title>
+ <style type="text/css">
+ html,body {
+ color:black; background-color:white; font:16px monospace; padding:0; margin:7px;
+ }
+ div {
+ width: 100px; padding-right:50px; overflow-clip-box:content-box;
+ overflow:hidden;
+ }
+ </style>
+</head>
+<body>
+
+<div contenteditable=true spellcheck=false tabindex=0 id=x class="block">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div>
+
+<script>
+var x = document.getElementById('x');
+x.focus();
+x.scrollLeft=100000
+window.getSelection().collapse(x,1);
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/bug968148_inner.html b/layout/base/tests/bug968148_inner.html
new file mode 100644
index 000000000..7de693f73
--- /dev/null
+++ b/layout/base/tests/bug968148_inner.html
@@ -0,0 +1,295 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=968148
+-->
+<head>
+ <title>Test for Bug 968148</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .test {
+ width: 20px;
+ height: 20px;
+ border: 1px solid black;
+ -moz-user-select: none;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968148">Mozilla Bug 968148</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 968148, test orignally copied from test_bug582771.html.
+ * Mouse functionality converted to pointer and all steps duplicated in order to run them in parallel for two different pointer Id's
+**/
+
+function ok(condition, msg) {
+ parent.ok(condition, msg);
+}
+
+function is(a, b, msg) {
+ parent.is(a, b, msg);
+}
+
+var test1d1;
+var test1d2;
+var test2d1;
+var test2d2;
+var test1d1pointermovecount = 0;
+var test1d2pointermovecount = 0;
+var test2d1pointermovecount = 0;
+var test2d2pointermovecount = 0;
+
+var test1d1pointerlostcapture = 0;
+var test1d2pointerlostcapture = 0;
+var test2d1pointerlostcapture = 0;
+var test2d2pointerlostcapture = 0;
+var test1d1pointergotcapture = 0;
+var test1d2pointergotcapture = 0;
+var test2d1pointergotcapture = 0;
+var test2d2pointergotcapture = 0;
+var test1PointerId = 1;
+var test2PointerId = 2;
+
+function sendPointerMove(el, id) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendPointerEvent('pointermove', rect.left + 5, rect.top + 5, 0, 0, 0, false, 0, SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH, id);
+}
+
+function sendPointerDown(el, id) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendPointerEvent('pointerdown', rect.left + 5, rect.top + 5, 0, 1, 0, false, 0, SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH, id);
+}
+
+function sendPointerUp(el, id) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendPointerEvent('pointerup', rect.left + 5, rect.top + 5, 0, 1, 0, false, 0, SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH, id);
+}
+
+function log(s) {
+ document.getElementById("l").textContent += s + "\n";
+}
+
+function test1d2Listener(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test1d2, "test1d2 should have got pointermove.");
+ ++test1d2pointermovecount;
+}
+
+function test2d2Listener(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, test2d2, "test2d2 should have got pointermove.");
+ ++test2d2pointermovecount;
+}
+
+function test1d1DownListener(e) {
+ log(e.type + ", " + e.target.id);
+ test1d1.setPointerCapture(e.pointerId);
+}
+
+function test1d1MoveListener(e) {
+ log(e.type + ", " + e.target.id);
+ test1d2.setPointerCapture(e.pointerId);
+}
+
+function test2d1DownListener(e) {
+ log(e.type + ", " + e.target.id);
+ test2d1.setPointerCapture(e.pointerId);
+}
+
+function test2d1MoveListener(e) {
+ log(e.type + ", " + e.target.id);
+ test2d2.setPointerCapture(e.pointerId);
+}
+
+function test1d1PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d1pointergotcapture;
+}
+
+function test1d1PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d1pointerlostcapture;
+}
+
+function test2d1PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d1pointergotcapture;
+}
+
+function test2d1PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d1pointerlostcapture;
+}
+
+function test1d2PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d2pointergotcapture;
+}
+
+function test1d2PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d2pointerlostcapture;
+}
+
+function test2d2PointerGotCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d2pointergotcapture;
+}
+
+function test2d2PointerLostCapture(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d2pointerlostcapture;
+}
+
+function test1d1PointerMoveListener(e) {
+ log(e.type + ", " + e.target.id);
+ ++test1d1pointermovecount;
+}
+
+function test2d1PointerMoveListener(e) {
+ log(e.type + ", " + e.target.id);
+ ++test2d1pointermovecount;
+}
+
+function runTests() {
+ test1d1 = document.getElementById("test1d1");
+ test1d2 = document.getElementById("test1d2");
+ test2d1 = document.getElementById("test2d1");
+ test2d2 = document.getElementById("test2d2");
+
+ test1d2.addEventListener("pointermove", test1d2Listener, true);
+ test2d2.addEventListener("pointermove", test2d2Listener, true);
+
+ test1d1.addEventListener("gotpointercapture", test1d1PointerGotCapture, true);
+ test1d1.addEventListener("lostpointercapture", test1d1PointerLostCapture, true);
+
+ test2d1.addEventListener("gotpointercapture", test2d1PointerGotCapture, true);
+ test2d1.addEventListener("lostpointercapture", test2d1PointerLostCapture, true);
+
+ test1d2.addEventListener("gotpointercapture", test1d2PointerGotCapture, true);
+ test1d2.addEventListener("lostpointercapture", test1d2PointerLostCapture, true);
+
+ test2d2.addEventListener("gotpointercapture", test2d2PointerGotCapture, true);
+ test2d2.addEventListener("lostpointercapture", test2d2PointerLostCapture, true);
+
+ document.body.offsetLeft;
+ sendPointerMove(test1d2, test1PointerId);
+ sendPointerMove(test2d2, test2PointerId);
+ is(test1d2pointermovecount, 1, "Should have got pointermove");
+ is(test2d2pointermovecount, 1, "Should have got pointermove");
+
+ // This shouldn't enable capturing, since we're not in a right kind of
+ // event listener.
+ sendPointerDown(test1d1, test1PointerId);
+ sendPointerDown(test2d1, test2PointerId);
+
+ sendPointerMove(test1d2, test1PointerId);
+ sendPointerMove(test2d2, test2PointerId);
+
+ sendPointerUp(test1d1, test1PointerId);
+ sendPointerUp(test2d1, test2PointerId);
+
+ is(test1d2pointermovecount, 2, "Should have got pointermove");
+ is(test2d2pointermovecount, 2, "Should have got pointermove");
+
+ test1d1.addEventListener("pointerdown", test1d1DownListener, true);
+ test1d1.addEventListener("pointermove", test1d1PointerMoveListener, true);
+ test2d1.addEventListener("pointerdown", test2d1DownListener, true);
+ test2d1.addEventListener("pointermove", test2d1PointerMoveListener, true);
+
+ sendPointerDown(test1d1, test1PointerId);
+ sendPointerDown(test2d1, test2PointerId);
+ sendPointerMove(test1d2, test1PointerId);
+ sendPointerMove(test2d2, test2PointerId);
+ is(test1d2pointermovecount, 2, "Shouldn't have got pointermove");
+ is(test1d1pointermovecount, 1, "Should have got pointermove");
+ is(test1d1pointergotcapture, 1, "Should have got pointergotcapture");
+
+ is(test2d2pointermovecount, 2, "Shouldn't have got pointermove");
+ is(test2d1pointermovecount, 1, "Should have got pointermove");
+ is(test2d1pointergotcapture, 1, "Should have got pointergotcapture");
+
+ sendPointerUp(test1d1, test1PointerId);
+ sendPointerUp(test2d1, test2PointerId);
+ test1d1.removeEventListener("pointerdown", test1d1DownListener, true);
+ test1d1.removeEventListener("pointermove", test1d1PointerMoveListener, true);
+ test2d1.removeEventListener("pointerdown", test2d1DownListener, true);
+ test2d1.removeEventListener("pointermove", test2d1PointerMoveListener, true);
+
+ // Nothing should be capturing the event.
+ sendPointerMove(test1d2, test1PointerId);
+ sendPointerMove(test2d2, test2PointerId);
+
+ is(test1d2pointermovecount, 3, "Should have got pointermove");
+ is(test1d1pointerlostcapture, 1, "Should have got pointerlostcapture");
+ is(test2d2pointermovecount, 3, "Should have got pointermove");
+ is(test2d1pointerlostcapture, 1, "Should have got pointerlostcapture");
+
+ test1d1.addEventListener("pointermove", test1d1MoveListener, true);
+ test2d1.addEventListener("pointermove", test2d1MoveListener, true);
+
+ sendPointerDown(test1d1, test1PointerId);
+ sendPointerDown(test2d1, test2PointerId);
+
+ sendPointerMove(test1d1, test1PointerId); // This should call setPointerCapture to test1d2!
+ sendPointerMove(test2d1, test2PointerId); // This should call setPointerCapture to test2d2!
+
+ test1d1.removeEventListener("pointermove", test1d1MoveListener, true);
+ test1d1.addEventListener("pointermove", test1d1PointerMoveListener, true);
+
+ test2d1.removeEventListener("pointermove", test2d1MoveListener, true);
+ test2d1.addEventListener("pointermove", test2d1PointerMoveListener, true);
+
+ sendPointerMove(test1d1, test1PointerId); // This should send pointer event to test1d2.
+ sendPointerMove(test2d1, test2PointerId); // This should send pointer event to test2d2.
+
+ is(test1d1pointermovecount, 1, "Shouldn't have got pointermove");
+ is(test1d2pointermovecount, 4, "Should have got pointermove");
+ is(test1d2pointergotcapture, 1, "Should have got pointergotcapture");
+
+ is(test2d1pointermovecount, 1, "Shouldn't have got pointermove");
+ is(test2d2pointermovecount, 4, "Should have got pointermove");
+ is(test2d2pointergotcapture, 1, "Should have got pointergotcapture");
+
+ sendPointerUp(test1d1, test1PointerId);
+ sendPointerUp(test2d1, test2PointerId);
+
+ finishTest();
+}
+
+function finishTest() {
+ // Let window.onerror have a chance to fire
+ setTimeout(function() {
+ setTimeout(function() {
+ window.parent.postMessage("SimpleTest.finish();", "*");
+ }, 0);
+ }, 0);
+}
+
+window.onload = function () {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true],
+ ]
+ }, runTests);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<div class="test" id="test1d1">&nbsp;</div><br><div class="test" id="test1d2">&nbsp;</div>
+<div class="test" id="test2d1">&nbsp;</div><br><div class="test" id="test2d2">&nbsp;</div>
+<pre id="l"></pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug970964_inner.html b/layout/base/tests/bug970964_inner.html
new file mode 100644
index 000000000..a9cba2916
--- /dev/null
+++ b/layout/base/tests/bug970964_inner.html
@@ -0,0 +1,342 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=970964
+-->
+<head>
+ <title>Test for Bug 970964</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=970964">Mozilla Bug 970964</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 970964 **/
+
+function ok(condition, msg) {
+ parent.ok(condition, msg);
+}
+
+function is(a, b, msg) {
+ parent.is(a, b, msg);
+}
+
+function testtouch(aOptions) {
+ if (!aOptions)
+ aOptions = {};
+ this.identifier = aOptions.identifier || 0;
+ this.target = aOptions.target || 0;
+ this.page = aOptions.page || {x: 0, y: 0};
+ this.radius = aOptions.radius || {x: 0, y: 0};
+ this.rotationAngle = aOptions.rotationAngle || 0;
+ this.force = aOptions.force || 1;
+}
+
+function touchEvent(aOptions) {
+ if (!aOptions) {
+ aOptions = {};
+ }
+ this.ctrlKey = aOptions.ctrlKey || false;
+ this.altKey = aOptions.altKey || false;
+ this.shiftKey = aOptions.shiftKey || false;
+ this.metaKey = aOptions.metaKey || false;
+ this.touches = aOptions.touches || [];
+ this.targetTouches = aOptions.targetTouches || [];
+ this.changedTouches = aOptions.changedTouches || [];
+}
+
+function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
+ var ids = [], xs=[], ys=[], rxs = [], rys = [],
+ rotations = [], forces = [];
+
+ for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
+ for (var i = 0; i < aEvent[touchType].length; i++) {
+ if (ids.indexOf(aEvent[touchType][i].identifier) == -1) {
+ ids.push(aEvent[touchType][i].identifier);
+ xs.push(aEvent[touchType][i].page.x);
+ ys.push(aEvent[touchType][i].page.y);
+ rxs.push(aEvent[touchType][i].radius.x);
+ rys.push(aEvent[touchType][i].radius.y);
+ rotations.push(aEvent[touchType][i].rotationAngle);
+ forces.push(aEvent[touchType][i].force);
+ }
+ }
+ }
+ return windowUtils.sendTouchEvent(aType,
+ ids, xs, ys, rxs, rys,
+ rotations, forces,
+ ids.length, aModifiers, 0);
+}
+
+function getDefaultArgEvent(eventname) {
+ return new PointerEvent(eventname, {
+ bubbles: true, cancelable: true, view: window,
+ detail: 0, screenX: 0, screenY: 0, clientX: 0, clientY: 0,
+ ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
+ button: 0, relatedTarget: null, pointerId: 0
+ });
+}
+
+function getTouchEventForTarget(target, cwu, id) {
+ var bcr = target.getBoundingClientRect();
+ var touch = new testtouch({
+ page: {x: Math.round(bcr.left + bcr.width/2),
+ y: Math.round(bcr.top + bcr.height/2)},
+ target: target,
+ identifier: id,
+ });
+ var event = new touchEvent({
+ touches: [touch],
+ targetTouches: [touch],
+ changedTouches: [touch]
+ });
+ return event;
+}
+
+function runTests() {
+ var d0 = document.getElementById("d0");
+ var d1 = document.getElementById("d1");
+ var d2 = document.getElementById("d2");
+ var d3 = document.getElementById("d3");
+
+ // Test Pointer firing before any mouse/touch original source
+
+ var mouseDownTriggered = 0;
+ var pointerDownTriggered = 0;
+ var touchDownTriggered = 0;
+ var touchCancelTriggered = 0;
+ var pointerCancelTriggered = 0;
+
+ d0.onmousedown = function(e) {
+ mouseDownTriggered = 1;
+ is(pointerDownTriggered , 1, "Mouse event must be triggered after pointer event!");
+ };
+ d0.ontouchstart = function(e) {
+ touchDownTriggered = 1;
+ is(touchDownTriggered , 1, "Touch event must be triggered after pointer event!");
+ }
+ d0.ontouchcancel = function(e) {
+ touchCancelTriggered = 1;
+ is(pointerCancelTriggered, 1, "Touch cancel event must be triggered after pointer event!");
+ }
+ d0.onpointerdown = function(e) {
+ pointerDownTriggered = 1;
+ is(mouseDownTriggered, 0, "Pointer event must be triggered before mouse event!");
+ is(touchDownTriggered, 0, "Pointer event must be triggered before touch event!");
+ };
+ d0.addEventListener("pointercancel", function(ev) {
+ d0.removeEventListener("pointercancel", arguments.callee, false);
+ is(ev.pointerId, 0, "Correct default pointerId");
+ is(ev.bubbles, true, "bubbles should be true");
+ is(ev.cancelable, false, "pointercancel cancelable should be false ");
+ pointerCancelTriggered = 1;
+ is(touchCancelTriggered, 0, "Pointer event must be triggered before touch event!");
+ }, false);
+
+ // Test pointer event generated from mouse event
+ synthesizeMouse(d1, 3, 3, { type: "mousemove"});
+ synthesizeMouse(d1, 3, 3, { type: "mousedown"});
+ synthesizeMouse(d1, 3, 3, { type: "mouseup"});
+
+ // Test pointer event generated from touch event
+ pointerDownTriggered = 0;
+ mouseDownTriggered = 0;
+
+ var cwu = SpecialPowers.getDOMWindowUtils(window);
+ var event1 = getTouchEventForTarget(d1, cwu, 0);
+ sendTouchEvent(cwu, "touchmove", event1, 0);
+ sendTouchEvent(cwu, "touchstart", event1, 0);
+ // Test Touch to Pointer Cancel
+ sendTouchEvent(cwu, "touchcancel", event1, 0);
+
+ // Check Pointer enter/leave from mouse generated event
+ var mouseEnterTriggered = 0;
+ var pointerEnterTriggered = 0;
+ d2.onpointerenter = function(e) {
+ pointerEnterTriggered = 1;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ is(mouseEnterTriggered, 0, "Pointer event must be triggered before mouse event!");
+ };
+ d2.onmouseenter = function(e) {
+ mouseEnterTriggered = 1;
+ is(pointerEnterTriggered , 1, "Mouse event must be triggered after pointer event!");
+ };
+ synthesizeMouse(d2, 3, 3, { type: "mousemove"});
+ d2.onmouseenter = function(e) {}
+
+ // Test Multi Pointer enter/leave for pointers generated from Mouse and Touch at the same time
+ // Enter mouse and touch generated pointers to different elements
+ var d1enterCount = 0;
+ var d2enterCount = 0;
+ var d3enterCount = 0;
+ var d1leaveCount = 0;
+ var d2leaveCount = 0;
+ var d3leaveCount = 0;
+ var mousePointerEnterLeaveCount = 0;
+ var touchPointerEnterLeaveCount = 0;
+
+ var checkPointerType = function(pointerType) {
+ if (pointerType == "mouse") {
+ ++mousePointerEnterLeaveCount;
+ } else if (pointerType == "touch") {
+ ++touchPointerEnterLeaveCount;
+ }
+ };
+
+ d1.onpointerenter = function(e) {
+ ++d1enterCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d2.onpointerenter = function(e) {
+ ++d2enterCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d3.onpointerenter = function(e) {
+ ++d3enterCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d1.onpointerleave = function(e) {
+ ++d1leaveCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d2.onpointerleave = function(e) {
+ ++d2leaveCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+ d3.onpointerleave = function(e) {
+ ++d3leaveCount;
+ is(e.bubbles, false, "bubbles should be false");
+ is(e.cancelable, false, "cancelable should be false");
+ checkPointerType(e.pointerType);
+ };
+
+ synthesizeMouse(d1, 3, 3, { type: "mousemove"});
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d3, cwu, 3), 0);
+ is(touchPointerEnterLeaveCount, 1, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 2, "Wrong mouse enterLeave count for!");
+
+ is(d1enterCount, 1, "Wrong enter count for! d1");
+ is(d2leaveCount, 1, "Wrong leave count for! d2");
+ is(d3enterCount, 1, "Wrong enter count for! d3");
+
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d1, cwu, 3), 0);
+ synthesizeMouse(d3, 3, 3, { type: "mousemove"});
+ is(touchPointerEnterLeaveCount, 3, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 4, "Wrong mouse enterLeave count for!");
+
+ is(d3leaveCount, 1, "Wrong leave count for! d3");
+ is(d1leaveCount, 1, "Wrong leave count for! d1");
+ is(d1enterCount, 2, "Wrong enter count for! d1");
+ is(d3enterCount, 2, "Wrong enter count for! d3");
+
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d2, cwu, 3), 0);
+ synthesizeMouse(d2, 3, 3, { type: "mousemove"});
+ is(touchPointerEnterLeaveCount, 5, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 6, "Wrong mouse enterLeave count for!");
+
+ is(d1leaveCount, 2, "Wrong leave count for! d1");
+ is(d2enterCount, 2, "Wrong enter count for! d2");
+ is(d3leaveCount, 2, "Wrong leave count for! d3");
+
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d1, cwu, 3), 0);
+ synthesizeMouse(d1, 3, 3, { type: "mousemove"});
+ is(touchPointerEnterLeaveCount, 7, "Wrong touch enterLeave count for!");
+ is(mousePointerEnterLeaveCount, 8, "Wrong mouse enterLeave count for!");
+
+ is(d2leaveCount, 3, "Wrong leave count for! d2");
+ is(d1enterCount, 4, "Wrong enter count for! d1");
+
+ // Test for pointer buttons when it generated from mousemove event
+ d1.onpointermove = function(e) {
+ is(e.buttons, 0, "Buttons must be 0 on pointer generated from mousemove");
+ is(e.button, -1, "Button must be -1 on pointer generated from mousemove when no buttons pressed");
+ is(e.pointerType, "mouse", "Pointer type must be mouse");
+ };
+ cwu.sendMouseEvent("mousemove", 4, 4, 0, 0, 0, false, 0, 0);
+
+ d1.onpointermove = function(e) {
+ is(e.buttons, 1, "Buttons must be 1 on pointer generated from touch event");
+ is(e.button, 0, "Button must be 0 on pointer generated from touch eventd");
+ is(e.pointerType, "touch", "Pointer type must be touch");
+ };
+ sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d1, cwu, 2), 0);
+
+ // Test for cancel trigger pointerOut (Touch Pointer must be at d1 now)
+ pointerCancelTriggered = 0;
+ var pointerOutTriggeredForCancelEvent = 0;
+ var pointerLeaveTriggeredForCancelEvent = 0;
+ d1.onpointerout = function(e) {
+ if (pointerOutTriggeredForCancelEvent == 0) {
+ is(e.pointerId, 3, "Wrong Pointer type, should be id from Touch event");
+ is(e.pointerType, "touch", "Wrong Pointer type, should be touch type");
+ } else {
+ is(e.pointerId, 0, "Wrong Pointer type, should be id from mouse event");
+ is(e.pointerType, "mouse", "Wrong Pointer type, should be mouse type");
+ }
+ pointerOutTriggeredForCancelEvent = 1;
+ };
+ d1.onpointerleave = function(e) {
+ is(pointerOutTriggeredForCancelEvent, 1, "Pointer Out must be dispatched bedore Pointer leave");
+ if (pointerLeaveTriggeredForCancelEvent == 0) {
+ is(e.pointerId, 3, "Wrong Pointer type, should be id from Touch event");
+ is(e.pointerType, "touch", "Wrong Pointer type, should be touch type");
+ } else {
+ is(e.pointerId, 0, "Wrong Pointer type, should be id from mouse event");
+ is(e.pointerType, "mouse", "Wrong Pointer type, should be mouse type");
+ }
+ pointerLeaveTriggeredForCancelEvent = 1;
+ }
+
+ sendTouchEvent(cwu, "touchcancel", getTouchEventForTarget(d1, cwu, 3), 0);
+ is(pointerOutTriggeredForCancelEvent, 1, "Pointer Out not dispatched on PointerCancel");
+ is(pointerLeaveTriggeredForCancelEvent, 1, "Pointer Leave not dispatched on PointerCancel");
+
+ finishTest();
+}
+
+function finishTest() {
+ // Let window.onerror have a chance to fire
+ setTimeout(function() {
+ setTimeout(function() {
+ window.parent.postMessage("SimpleTest.finish();", "*");
+ }, 0);
+ }, 0);
+}
+
+window.onload = function () {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true],
+ ]
+ }, runTests);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<div id="d0">
+Test divs --
+<div id="d1">t</div><div id="d2">t</div><div id="d3">t</div>
+--
+</div>
+</body>
+</html>
diff --git a/layout/base/tests/bug976963_inner.html b/layout/base/tests/bug976963_inner.html
new file mode 100644
index 000000000..2c55fbccd
--- /dev/null
+++ b/layout/base/tests/bug976963_inner.html
@@ -0,0 +1,241 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=976963
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 976963</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ div#listener {
+ background: yellow;
+ position: absolute;
+ top: -100px;
+ }
+ div#middler {
+ background: yellow;
+ margin: 10px;
+ }
+ div#target {
+ background: yellow;
+ }
+ </style>
+ <script type="application/javascript">
+ /** Test for Bug 976963 **/
+ var All_Pointer_Events = ["pointerover", "pointerenter",
+ "pointermove",
+ "pointerdown", "pointerup",
+ "pointerout", "pointerleave",
+ "pointercancel",
+ "gotpointercapture", "lostpointercapture"];
+
+ function on_event(object, event, callback) {
+ object.addEventListener(event, callback, false);
+ }
+ function ok(check, msg) {
+ parent.ok(check, msg);
+ }
+ function is(a, b, msg) {
+ parent.is(a, b, msg);
+ }
+
+ var listener = undefined;
+ var middler = undefined;
+ var target = undefined;
+
+ var test_ListenerGotCapture = 0;
+ var test_ListenerUnwanted = 0;
+ var test_ListenerLostCapture = 0;
+ var test_ListenerAfterCapture = 0;
+ var test_MiddlerGotCapture = 0;
+ var test_MiddlerOver = 0;
+ var test_MiddlerLeave = 0;
+ var test_MiddlerUp = 0;
+ var test_MiddlerLostCapture = 0;
+ var test_TargetDown = 0;
+ var test_TargetUnwanted = 0;
+ var test_TargetUp = 0;
+
+ var captured_event = undefined;
+ var f_gotPointerCapture = false;
+ var f_lostPointerCapture = false;
+ var f_gotMiddlerPointerCapture = false;
+
+ function listenerEventHandler(event) {
+ logger("Listener: " + event.type + ". Captured_event: " + captured_event);
+ if(test_ListenerLostCapture)
+ test_ListenerAfterCapture++;
+ if (event.type == "gotpointercapture") {
+ f_gotPointerCapture = true;
+ test_ListenerGotCapture++;
+ }
+ else if (event.type == "lostpointercapture") {
+ f_lostPointerCapture = true;
+ f_gotPointerCapture = false;
+ test_ListenerLostCapture++;
+ }
+ else if (event.type == "pointermove") {
+ ok(captured_event && captured_event.pointerId == event.pointerId, "Listener: equals pointerId for lostpointercapture event");
+ if (f_gotPointerCapture) {
+ // on first event received for capture, release capture
+ logger("Listener call release");
+ ok(!!listener, "Listener should be live!");
+ ok(typeof(listener.releasePointerCapture) == "function", "Listener should have a function releasePointerCapture");
+ listener.releasePointerCapture(event.pointerId);
+ }
+ else {
+ logger("Listener.ASSERT: " + event.type);
+ test_ListenerUnwanted++;
+ // if any other events are received after releaseCapture, then the test fails
+ ok(false, event.target.id + "-" + event.type + " should be handled by target element handler");
+ }
+ }
+ else {
+ test_ListenerUnwanted++;
+ logger("Listener.ASSERT: " + event.type);
+ ok(false, event.type + "should be never handled by listener");
+ }
+ }
+
+ function middlerEventHandler(event) {
+ logger("Middler: " + event.type + ". Captured_event: " + captured_event);
+ if (event.type == "gotpointercapture") {
+ test_MiddlerGotCapture++;
+ f_gotMiddlerPointerCapture = true;
+ ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for gotpointercapture event");
+ }
+ else if (event.type == "pointerover") {
+ test_MiddlerOver++;
+ ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for pointerover event");
+ }
+ else if (event.type == "pointerleave") {
+ test_MiddlerLeave++;
+ ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for pointerleave event");
+ ok(!!listener, "Listener should be live!");
+ ok(typeof(listener.setPointerCapture) == "function", "Listener should have a function setPointerCapture");
+ listener.setPointerCapture(event.pointerId);
+ }
+ else if (event.type == "lostpointercapture") {
+ test_MiddlerLostCapture++;
+ f_gotMiddlerPointerCapture = false;
+ ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for lostpointercapture event");
+ }
+ else if (event.type == "pointerup" ) {
+ test_MiddlerUp++;
+ }
+ }
+
+ function targetEventHandler(event) {
+ logger("Target: " + event.type + ". Captured_event: " + captured_event);
+ if (f_gotPointerCapture || f_gotMiddlerPointerCapture) {
+ if (event.type != "pointerout" && event.type != "pointerleave") {
+ logger("Target.ASSERT: " + event.type + " " + event.pointerId);
+ test_TargetUnwanted++;
+ ok(false, "The Target element should not have received any events while capture is active. Event recieved:" + event.type + ". ");
+ }
+ }
+ if (event.type == "pointerdown") {
+ logger("Target.pointerdown 1: " + captured_event);
+ test_TargetDown++;
+ captured_event = event;
+ ok(!!middler, "Middler should be live!");
+ ok(typeof(middler.setPointerCapture) == "function", "Middler should have a function setPointerCapture");
+ middler.setPointerCapture(event.pointerId);
+ logger("Target.pointerdown 2: " + captured_event);
+ }
+ else if (event.type == "pointerup") {
+ ok(f_lostPointerCapture, "Target should have received pointerup");
+ ok(captured_event && captured_event.pointerId == event.pointerId, "Target: equals pointerId for lostpointercapture event");
+ test_TargetUp++; // complete test
+ }
+ }
+
+ function colorerHandler(event) {
+ if(event.type == "pointerover")
+ event.target.style.background = "red";
+ else if(event.type == "pointerout")
+ event.target.style.background = "yellow";
+ }
+
+ function setEventHandlers() {
+ listener = document.getElementById("listener");
+ middler = document.getElementById("middler");
+ target = document.getElementById("target");
+ target.style["touchAction"] = "none";
+
+ // target and listener - handle all events
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(target, All_Pointer_Events[i], targetEventHandler);
+ on_event(listener, All_Pointer_Events[i], listenerEventHandler);
+ on_event(middler, All_Pointer_Events[i], middlerEventHandler);
+ on_event(target, All_Pointer_Events[i], colorerHandler);
+ on_event(middler, All_Pointer_Events[i], colorerHandler);
+ }
+ }
+
+ function prepareTest() {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, executeTest);
+ }
+
+ function executeTest()
+ {
+ logger("executeTest");
+ setEventHandlers();
+ document.body.offsetLeft;
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
+ synthesizePointer(middler, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(middler, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
+ finishTest();
+ }
+
+ function finishTest() {
+ setTimeout(function() {
+ is(test_ListenerGotCapture, 1, "Listener should receive gotpointercapture event");
+ is(test_ListenerUnwanted, 0, "Listener should not receive any unwanted events");
+ is(test_ListenerLostCapture, 1, "Listener should receive lostpointercapture event");
+ is(test_ListenerAfterCapture, 0, "Listener should not receive any events after release pointer capture");
+ is(test_MiddlerGotCapture, 1, "Middler should receive gotpointercapture event");
+ is(test_MiddlerOver, 1, "Middler should receive pointerover event");
+ is(test_MiddlerLeave, 1, "Middler should receive pointerleave event");
+ is(test_MiddlerUp, 0, "Middler should not receive pointerup event");
+ is(test_MiddlerLostCapture, 1, "Middler should receive lostpointercapture event");
+ is(test_TargetDown, 1, "Target should receive pointerdown event");
+ is(test_TargetUnwanted, 0, "Target should not receive any event while pointer capture is active");
+ is(test_TargetUp, 1, "Target should receive pointerup event");
+ logger("finishTest");
+ parent.finishTest();
+ }, 1000);
+ }
+
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=976963">Mozilla Bug 976963</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="listener">div id=listener</div>
+ <div id="middler">div id=middler</div>
+ <div id="target">div id=target</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug977003_inner_1.html b/layout/base/tests/bug977003_inner_1.html
new file mode 100644
index 000000000..c4c7f2d84
--- /dev/null
+++ b/layout/base/tests/bug977003_inner_1.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977003
+https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
+https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bugs 977003, 1094913, 1098139</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target{ background: yellow; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var test_send_got = 0;
+ var test_got_async = 0;
+ var test_got_type = "";
+ var test_got_primary = false;
+ var test_send_lost = 0;
+ var test_lost_async = 0;
+ var test_lost_type = "";
+ var test_lost_primary = false;
+
+ function DownHandler(event) {
+ logger("Receive event: " + event.type);
+ logger("Send setPointerCapture to target");
+ target.setPointerCapture(event.pointerId);
+ logger("setPointerCapture was executed");
+ test_send_got++;
+ }
+ function GotPCHandler(event) {
+ logger("Receive event: " + event.type + "(" + event.pointerType + ")");
+ if(test_send_got)
+ test_got_async++;
+ test_got_type = event.pointerType;
+ test_got_primary = event.isPrimary;
+ logger("Send releasePointerCapture from target");
+ target.releasePointerCapture(event.pointerId);
+ logger("releasePointerCapture was executed");
+ test_send_lost++;
+ }
+ function LostPCHandler(event) {
+ logger("Received event: " + event.type + "(" + event.pointerType + ")");
+ if(test_send_lost)
+ test_lost_async++;
+ test_lost_type = event.pointerType;
+ test_lost_primary = event.isPrimary;
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ target.addEventListener("pointerdown", DownHandler, false);
+ target.addEventListener("gotpointercapture", GotPCHandler, false);
+ target.addEventListener("lostpointercapture", LostPCHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_send_got, 1, "Part 1: gotpointercapture event should be sent once");
+ parent.is(test_got_async, 1, "Part 1: gotpointercapture event should be asynchronous");
+ parent.is(test_got_type, "mouse", "Part 1: gotpointercapture event should have pointerType mouse");
+ parent.is(test_got_primary, true, "Part 1: gotpointercapture event should have isPrimary as true");
+ parent.is(test_send_lost, 1, "Part 1: lostpointercapture event should be sent once");
+ parent.is(test_lost_async, 1, "Part 1: lostpointercapture event should be asynchronous");
+ parent.is(test_lost_type, "mouse", "Part 1: lostpointercapture event should have pointerType mouse");
+ parent.is(test_lost_primary, true, "Part 1: lostpointercapture event should have isPrimary as true");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 1</a>
+ <br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1094913">Mozilla Bug 1094913</a>
+ <br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1098139">Mozilla Bug 1098139</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="target">div id=target</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug977003_inner_2.html b/layout/base/tests/bug977003_inner_2.html
new file mode 100644
index 000000000..0282bd01c
--- /dev/null
+++ b/layout/base/tests/bug977003_inner_2.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977003
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 977003</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #listener { background: yellow; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var listener = undefined;
+ var test_down_got = false;
+ var test_listener = false;
+
+ function TargetDownHandler(event) {
+ logger("Target receive event: " + event.type);
+ logger("Send setPointerCapture to listener");
+ listener.setPointerCapture(event.pointerId);
+ logger("Send releasePointerCapture from listener");
+ listener.releasePointerCapture(event.pointerId);
+ logger("set/release was executed");
+ test_down_got = true;
+ }
+ function ListenerHandler(event) {
+ logger("Receive event on Listener: " + event.type);
+ test_listener = true;
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetDownHandler, false);
+ listener.addEventListener("gotpointercapture", ListenerHandler, false);
+ listener.addEventListener("lostpointercapture", ListenerHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_down_got, true, "Part 2: pointerdown event should be received by target");
+ parent.is(test_listener, false, "Part 2: listener should not receive any events");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 2</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="listener">div id=listener</div>
+ <div id="target">div id=target</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug977003_inner_3.html b/layout/base/tests/bug977003_inner_3.html
new file mode 100644
index 000000000..f332f8a43
--- /dev/null
+++ b/layout/base/tests/bug977003_inner_3.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977003
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 977003</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #mediator, #listener { background: yellow; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var mediator = undefined;
+ var listener = undefined;
+ var test_down_got = false;
+ var test_mediator_got = false;
+ var test_mediator_lost = false;
+ var test_listener = false;
+
+ function TargetDownHandler(event) {
+ logger("Target receive event: " + event.type);
+ logger("Send pointerCapture to Mediator");
+ mediator.setPointerCapture(event.pointerId);
+ logger("setPointerCapture was executed");
+ test_down_got = true;
+ }
+ function MediatorGotPCHandler(event) {
+ logger("Mediator receive event: " + event.type);
+ logger("Try send setPointerCapture on listener");
+ listener.setPointerCapture(event.pointerId);
+ logger("Try send releasePointerCapture from listener");
+ listener.releasePointerCapture(event.pointerId);
+ test_mediator_got = true;
+ }
+ function MediatorLostPCHandler(event) {
+ logger("Mediator receive event: " + event.type);
+ test_mediator_lost = true;
+ }
+ function ListenerHandler(event) {
+ logger("Receive event on Listener: " + event.type);
+ test_listener = true;
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ mediator = document.getElementById("mediator");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetDownHandler, false);
+ mediator.addEventListener("gotpointercapture", MediatorGotPCHandler, false);
+ mediator.addEventListener("lostpointercapture", MediatorLostPCHandler, false);
+ listener.addEventListener("gotpointercapture", ListenerHandler, false);
+ listener.addEventListener("lostpointercapture", ListenerHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
+ synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointermove"});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_down_got, true, "Part 3: pointerdown event should be received");
+ parent.is(test_mediator_got, true, "Part 3: gotpointercapture event should be received by Mediator");
+ parent.is(test_mediator_lost, true, "Part 3: lostpointercapture event should be received by Mediator");
+ parent.is(test_listener, false, "Part 3: listener should not receive any events");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 3</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="listener">div id=listener</div>
+ <div id="mediator">div id=mediator</div>
+ <div id="target">div id=target</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug977003_inner_4.html b/layout/base/tests/bug977003_inner_4.html
new file mode 100644
index 000000000..be0865cc4
--- /dev/null
+++ b/layout/base/tests/bug977003_inner_4.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977003
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 977003</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #mediator, #listener { background: yellow; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var mediator = undefined;
+ var listener = undefined;
+ var test_down_got = false;
+ var test_mediator_got = false;
+ var test_mediator_lost = false;
+ var test_listener_got = false;
+ var test_listener_lost = false;
+
+ function TargetDownHandler(event) {
+ logger("Target receive event: " + event.type);
+ logger("Send pointerCapture to Mediator");
+ mediator.setPointerCapture(event.pointerId);
+ logger("setPointerCapture was executed");
+ test_down_got = true;
+ }
+ function MediatorGotPCHandler(event) {
+ logger("Mediator receive event: " + event.type);
+ logger("Try send setPointerCapture on listener");
+ listener.setPointerCapture(event.pointerId);
+ logger("Try send releasePointerCapture from Mediator");
+ mediator.releasePointerCapture(event.pointerId);
+ test_mediator_got = true;
+ }
+ function MediatorLostPCHandler(event) {
+ logger("Mediator receive event: " + event.type);
+ test_mediator_lost = true;
+ }
+ function ListenerGotHandler(event) {
+ test_listener_got = true;
+ }
+ function ListenerLostHandler(event) {
+ test_listener_lost = true;
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ mediator = document.getElementById("mediator");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetDownHandler, false);
+ mediator.addEventListener("gotpointercapture", MediatorGotPCHandler, false);
+ mediator.addEventListener("lostpointercapture", MediatorLostPCHandler, false);
+ listener.addEventListener("gotpointercapture", ListenerGotHandler, false);
+ listener.addEventListener("lostpointercapture", ListenerLostHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
+ synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointermove"});
+ synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointerup"});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_down_got, true, "Part 4: pointerdown event should be received");
+ parent.is(test_mediator_got, true, "Part 4: gotpointercapture event should be received by Mediator");
+ parent.is(test_mediator_lost, true, "Part 4: lostpointercapture event should be received by Mediator");
+ parent.is(test_listener_got, true, "Part 4: gotpointercapture event should be received by listener");
+ parent.is(test_listener_lost, true, "Part 4: lostpointercapture event should be received by listener");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 4</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="listener">div id=listener</div>
+ <div id="mediator">div id=mediator</div>
+ <div id="target">div id=target</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug977003_inner_5.html b/layout/base/tests/bug977003_inner_5.html
new file mode 100644
index 000000000..70fc5ba40
--- /dev/null
+++ b/layout/base/tests/bug977003_inner_5.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977003
+https://bugzilla.mozilla.org/show_bug.cgi?id=1073563
+https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
+https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bugs 977003, 1073563, 1094913, 1098139</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #listener { background: yellow; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var listener = undefined;
+ var test_down_target = false;
+ var test_got_listener = false;
+ var test_got_type = "";
+ var test_got_primary = false;
+ var test_lost_listener = false;
+ var test_lost_type = "";
+ var test_move_listener = false;
+ var test_listener = false;
+ var test_lost_primary = false;
+
+ function TargetDownHandler(event) {
+ logger("Target receive event: " + event.type);
+ logger("Send setPointerCapture to listener");
+ listener.setPointerCapture(event.pointerId);
+ logger("setPointerCapture was executed");
+ test_down_target = true;
+ }
+ function ListenerGotPCHandler(event) {
+ logger("Receive event on Listener: " + event.type + "(" + event.pointerType + ")");
+ listener.releasePointerCapture(event.pointerId);
+ test_got_listener = true;
+ test_got_type = event.pointerType;
+ test_got_primary = event.isPrimary;
+ }
+ function ListenerLostPCHandler(event) {
+ logger("Receive event on Listener: " + event.type + "(" + event.pointerType + ")");
+ test_lost_listener = true;
+ test_lost_type = event.pointerType;
+ test_lost_primary = event.isPrimary;
+ }
+ function ListenerMoveHandler(event) {
+ logger("Receive event on Listener: " + event.type);
+ test_move_listener = true;
+ }
+ function ListenerHandler(event) {
+ logger("Receive event on Listener: " + event.type);
+ test_listener = true;
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetDownHandler, false);
+ listener.addEventListener("gotpointercapture", ListenerGotPCHandler, false);
+ listener.addEventListener("lostpointercapture", ListenerLostPCHandler, false);
+ listener.addEventListener("pointerover", ListenerHandler, false);
+ listener.addEventListener("pointermove", ListenerMoveHandler, false);
+ listener.addEventListener("pointerup", ListenerHandler, false);
+ listener.addEventListener("pointerout", ListenerHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_down_target, true, "Part 5: pointerdown event should be received by target");
+ parent.is(test_got_listener, true, "Part 5: listener should receive gotpointercapture event");
+ parent.is(test_got_type, "touch", "Part 5: gotpointercapture event should have pointerType touch");
+ parent.is(test_got_primary, true, "Part 5: gotpointercapture event should have isPrimary as true");
+ parent.is(test_lost_listener, true, "Part 5: listener should receive lostpointercapture event");
+ parent.is(test_lost_type, "touch", "Part 5: lostpointercapture event should have pointerType touch");
+ parent.is(test_lost_primary, true, "Part 5: lostpointercapture event should have isPrimary as true");
+ parent.is(test_move_listener, true, "Part 5: gotpointercapture should be triggered by pointermove");
+ parent.is(test_listener, false, "Part 5: listener should not receive any other events");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 5</a>
+ <br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1073563">Mozilla Bug 1073563</a>
+ <br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1094913">Mozilla Bug 1094913</a>
+ <br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1098139">Mozilla Bug 1098139</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="listener">div id=listener</div>
+ <div id="target">div id=target</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug977003_inner_6.html b/layout/base/tests/bug977003_inner_6.html
new file mode 100644
index 000000000..12424b1f2
--- /dev/null
+++ b/layout/base/tests/bug977003_inner_6.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977003
+https://bugzilla.mozilla.org/show_bug.cgi?id=1073563
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bugs 977003, 1073563</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #target, #listener { background: yellow; }
+ </style>
+ <script type="application/javascript">
+ var target = undefined;
+ var listener = undefined;
+ var test_target = false;
+ var test_move = false;
+ var test_listener = false;
+ var receive_lostpointercapture = false;
+
+ function TargetDownHandler(event) {
+ logger("Target receive event: " + event.type);
+ logger("Send setPointerCapture to listener");
+ listener.setPointerCapture(event.pointerId);
+ logger("set/release was executed");
+ test_target = true;
+ }
+ function ListenerHandler(event) {
+ logger("Receive event on Listener: " + event.type);
+ if("gotpointercapture" == event.type) {
+ logger("Send releasePointerCapture from listener");
+ listener.releasePointerCapture(event.pointerId);
+ } else if(event.type == "lostpointercapture") {
+ // Set/release pointer capture in the event listeners of got/lostpointercapture won't take effect immediately
+ parent.is(receive_lostpointercapture, false, "Part 6: listener should receive only one lostpointercapture");
+ if (!receive_lostpointercapture) {
+ receive_lostpointercapture = true;
+ logger("Send setPointerCapture to listener");
+ listener.setPointerCapture(event.pointerId);
+ }
+ } else if(event.type == "pointermove") {
+ test_move = true;
+ } else {
+ test_listener = true;
+ }
+ }
+ function logger(message) {
+ console.log(message);
+ var log = document.getElementById('log');
+ log.innerHTML = message + "<br>" + log.innerHTML;
+ }
+
+ function prepareTest() {
+ parent.turnOnPointerEvents(executeTest);
+ }
+ function executeTest()
+ {
+ logger("executeTest");
+ target = document.getElementById("target");
+ listener = document.getElementById("listener");
+ target.addEventListener("pointerdown", TargetDownHandler, false);
+ listener.addEventListener("gotpointercapture", ListenerHandler, false);
+ listener.addEventListener("pointerdown", ListenerHandler, false);
+ listener.addEventListener("pointerover", ListenerHandler, false);
+ listener.addEventListener("pointermove", ListenerHandler, false);
+ listener.addEventListener("pointerup", ListenerHandler, false);
+ listener.addEventListener("pointerout", ListenerHandler, false);
+ listener.addEventListener("lostpointercapture", ListenerHandler, false);
+ var rect = target.getBoundingClientRect();
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
+ synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
+ finishTest();
+ }
+ function finishTest() {
+ parent.is(test_target, true, "Part 6: pointerdown event should be received by target");
+ // PE level 2 defines that the pending pointer capture is processed when firing next pointer events.
+ // In this test case, pointer capture release is processed when firing pointermove
+ parent.is(test_move, true, "Part 6: gotpointercapture should be triggered by pointermove");
+ parent.is(test_listener, false, "Part 6: no other pointerevents should be fired before gotpointercapture");
+ logger("finishTest");
+ parent.finishTest();
+ }
+ </script>
+</head>
+<body onload="prepareTest()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 6</a>
+ <br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1073563">Mozilla Bug 1073563</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <div id="listener">div id=listener</div>
+ <div id="target">div id=target</div>
+ <pre id="log">
+ </pre>
+</body>
+</html>
diff --git a/layout/base/tests/bug989012-1-ref.html b/layout/base/tests/bug989012-1-ref.html
new file mode 100644
index 000000000..f1b922b11
--- /dev/null
+++ b/layout/base/tests/bug989012-1-ref.html
@@ -0,0 +1,21 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<img alt="IMAGE">bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ // Set the caret right before "bar"
+ sel.collapse(div.lastChild, 0);
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug989012-1.html b/layout/base/tests/bug989012-1.html
new file mode 100644
index 000000000..5bc9a2061
--- /dev/null
+++ b/layout/base/tests/bug989012-1.html
@@ -0,0 +1,24 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<img alt="IMAGE">bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ sel.collapse(div, 0);
+ // Press Right four times to set the caret right before "bar"
+ for (var i = 0; i < 4; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug989012-2-ref.html b/layout/base/tests/bug989012-2-ref.html
new file mode 100644
index 000000000..246ad5307
--- /dev/null
+++ b/layout/base/tests/bug989012-2-ref.html
@@ -0,0 +1,26 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ span:before {
+ content: "IMAGE";
+ }
+ </style>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<span></span>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ // Set the caret right before "bar"
+ sel.collapse(div.lastChild, 0);
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug989012-2.html b/layout/base/tests/bug989012-2.html
new file mode 100644
index 000000000..32b43418e
--- /dev/null
+++ b/layout/base/tests/bug989012-2.html
@@ -0,0 +1,29 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ span:before {
+ content: "IMAGE";
+ }
+ </style>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<span></span>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ sel.collapse(div, 0);
+ // Press Right four times to set the caret right before "bar"
+ for (var i = 0; i < 4; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug989012-3-ref.html b/layout/base/tests/bug989012-3-ref.html
new file mode 100644
index 000000000..29b08b991
--- /dev/null
+++ b/layout/base/tests/bug989012-3-ref.html
@@ -0,0 +1,28 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ img {
+ border: solid 1px red;
+ mid-width: 1em;
+ display: inline-block;
+ }
+ </style>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<img>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ // Set the caret right before "bar"
+ sel.collapse(div.lastChild, 0);
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/bug989012-3.html b/layout/base/tests/bug989012-3.html
new file mode 100644
index 000000000..6510e7d62
--- /dev/null
+++ b/layout/base/tests/bug989012-3.html
@@ -0,0 +1,31 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ img {
+ border: solid 1px red;
+ mid-width: 1em;
+ display: inline-block;
+ }
+ </style>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<img>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ sel.collapse(div, 0);
+ // Press Right four times to set the caret right before "bar"
+ for (var i = 0; i < 4; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/base/tests/chrome/animated.gif b/layout/base/tests/chrome/animated.gif
new file mode 100644
index 000000000..b2895487b
--- /dev/null
+++ b/layout/base/tests/chrome/animated.gif
Binary files differ
diff --git a/layout/base/tests/chrome/blue-32x32.png b/layout/base/tests/chrome/blue-32x32.png
new file mode 100644
index 000000000..deefd19b2
--- /dev/null
+++ b/layout/base/tests/chrome/blue-32x32.png
Binary files differ
diff --git a/layout/base/tests/chrome/bug1041200_window.html b/layout/base/tests/chrome/bug1041200_window.html
new file mode 100644
index 000000000..e098e1d92
--- /dev/null
+++ b/layout/base/tests/chrome/bug1041200_window.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 1041200</title>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
+</head>
+<body>
+<iframe style="width:700px; height:500px; margin-top:200px;" id="ourFrame"></iframe>
+<script>
+var SpecialPowers = window.opener.wrappedJSObject.SpecialPowers;
+var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
+var ok = window.opener.wrappedJSObject.ok;
+var info = window.opener.wrappedJSObject.info;
+
+var viewer =
+ SpecialPowers.wrap(ourFrame).contentWindow
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .QueryInterface(SpecialPowers.Ci.nsIDocShell)
+ .contentViewer;
+viewer.fullZoom = 2;
+
+SimpleTest.waitForExplicitFinish();
+
+window.onload = function() {
+ window.waitForAllPaintsFlushed(function () {
+ // Supply random key to ensure load actually happens
+ ourFrame.src = "data:text/html,<body onload='parent.childLoaded()' style='background:lime'><p>Hello<p>Hello<p>Hello<p>Hello<p>Hello<p>" + Math.random();
+ }, document.getElementById("ourFrame").contentDocument);
+};
+
+window.childLoaded = function() {
+ setTimeout(function() {
+ window.waitForAllPaintsFlushed(function(x1, y1, x2, y2) {
+ ok(x2 - x1 >= 700 && y2 - y1 >= 500,
+ "expected to see invalidate of entire frame, got " + [x1,y1,x2,y2].join(','));
+ SimpleTest.finish();
+ window.close();
+ });
+ }, 0);
+};
+</script>
+
diff --git a/layout/base/tests/chrome/bug495648.rdf b/layout/base/tests/chrome/bug495648.rdf
new file mode 100644
index 000000000..b7045aa70
--- /dev/null
+++ b/layout/base/tests/chrome/bug495648.rdf
@@ -0,0 +1,214 @@
+<?xml version="1.0"?>
+<RDF:RDF xmlns:NS1="http://sitedelta.schierla.de/SD-rdf#"
+ xmlns:NC="http://home.netscape.com/NC-rdf#"
+ xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=19&amp;btnG=Suche&amp;meta="
+ NC:name="19 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Bag RDF:about="urn:root:bag">
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=1&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=2&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=3&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=4&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=5&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=6&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=7&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=8&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=9&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=10&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=11&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=12&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=13&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=14&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=15&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=16&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=17&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=18&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=19&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=20&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=21&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=22&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=23&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=24&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=25&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=26&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=27&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=28&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=29&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=30&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=31&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=32&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=33&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=34&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=35&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=36&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=37&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=38&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=39&amp;btnG=Suche&amp;meta="/>
+ <RDF:li RDF:resource="http://www.google.de/search?hl=de&amp;q=40&amp;btnG=Suche&amp;meta="/>
+ </RDF:Bag>
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=2&amp;btnG=Suche&amp;meta="
+ NC:name="2 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=12&amp;btnG=Suche&amp;meta="
+ NC:name="12 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=5&amp;btnG=Suche&amp;meta="
+ NC:name="5 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=6&amp;btnG=Suche&amp;meta="
+ NC:name="6 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=22&amp;btnG=Suche&amp;meta="
+ NC:name="22 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=17&amp;btnG=Suche&amp;meta="
+ NC:name="17 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="urn:root">
+ <NC:links RDF:resource="urn:root:bag"/>
+ </RDF:Description>
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=8&amp;btnG=Suche&amp;meta="
+ NC:name="8 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=1&amp;btnG=Suche&amp;meta="
+ NC:name="1 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=16&amp;btnG=Suche&amp;meta="
+ NC:name="16 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=21&amp;btnG=Suche&amp;meta="
+ NC:name="21 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=20&amp;btnG=Suche&amp;meta="
+ NC:name="20 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=9&amp;btnG=Suche&amp;meta="
+ NC:name="9 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=11&amp;btnG=Suche&amp;meta="
+ NC:name="11 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=14&amp;btnG=Suche&amp;meta="
+ NC:name="14 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=23&amp;btnG=Suche&amp;meta="
+ NC:name="23 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=24&amp;btnG=Suche&amp;meta="
+ NC:name="24 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=18&amp;btnG=Suche&amp;meta="
+ NC:name="18 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www0.pafnet.de/user/322033"
+ NC:name="pafnet - You2_xD"
+ NS1:nextScan="1243707104073"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=3&amp;btnG=Suche&amp;meta="
+ NC:name="3 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=7&amp;btnG=Suche&amp;meta="
+ NC:name="7 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=15&amp;btnG=Suche&amp;meta="
+ NC:name="15 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=4&amp;btnG=Suche&amp;meta="
+ NC:name="4 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=13&amp;btnG=Suche&amp;meta="
+ NC:name="13 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=10&amp;btnG=Suche&amp;meta="
+ NC:name="10 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=25&amp;btnG=Suche&amp;meta="
+ NC:name="25 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=26&amp;btnG=Suche&amp;meta="
+ NC:name="26 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=27&amp;btnG=Suche&amp;meta="
+ NC:name="27 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=28&amp;btnG=Suche&amp;meta="
+ NC:name="28 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=29&amp;btnG=Suche&amp;meta="
+ NC:name="29 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=30&amp;btnG=Suche&amp;meta="
+ NC:name="30 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=31&amp;btnG=Suche&amp;meta="
+ NC:name="31 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=32&amp;btnG=Suche&amp;meta="
+ NC:name="32 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=33&amp;btnG=Suche&amp;meta="
+ NC:name="33 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=34&amp;btnG=Suche&amp;meta="
+ NC:name="34 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=35&amp;btnG=Suche&amp;meta="
+ NC:name="35 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=36&amp;btnG=Suche&amp;meta="
+ NC:name="36 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=37&amp;btnG=Suche&amp;meta="
+ NC:name="37 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=38&amp;btnG=Suche&amp;meta="
+ NC:name="38 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=39&amp;btnG=Suche&amp;meta="
+ NC:name="39 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+ <RDF:Description RDF:about="http://www.google.de/search?hl=de&amp;q=40&amp;btnG=Suche&amp;meta="
+ NC:name="40 - Google-Suche"
+ NS1:nextScan="0"
+ NS1:status="0" />
+</RDF:RDF>
diff --git a/layout/base/tests/chrome/bug551434_childframe.html b/layout/base/tests/chrome/bug551434_childframe.html
new file mode 100644
index 000000000..3d7bd6c13
--- /dev/null
+++ b/layout/base/tests/chrome/bug551434_childframe.html
@@ -0,0 +1,4 @@
+<script>
+var gKeyDownChild = 0, gKeyPressChild = 0, gKeyUpChild = 0;
+</script>
+<input id='i4' onkeydown="gKeyDownChild++" onkeypress="gKeyPressChild++" onkeyup="gKeyUpChild++; this.parentNode.removeChild(this);">
diff --git a/layout/base/tests/chrome/chrome.ini b/layout/base/tests/chrome/chrome.ini
new file mode 100644
index 000000000..2f6ca0ba8
--- /dev/null
+++ b/layout/base/tests/chrome/chrome.ini
@@ -0,0 +1,49 @@
+[DEFAULT]
+skip-if = os == 'android'
+support-files =
+ animated.gif
+ blue-32x32.png
+ bug495648.rdf
+ bug551434_childframe.html
+ chrome_content_integration_window.xul
+ chrome_over_plugin_window.xul
+ default_background_window.xul
+ dialog_with_positioning_window.xul
+ no_clip_iframe_subdoc.html
+ no_clip_iframe_window.xul
+ printpreview_bug396024_helper.xul
+ printpreview_bug482976_helper.xul
+ printpreview_helper.xul
+ file_bug1018265.xul
+
+[test_bug396367-1.html]
+[test_bug396367-2.html]
+[test_bug420499.xul]
+[test_bug458898.html]
+[test_bug495648.xul]
+[test_bug504311.xul]
+[test_bug514660.xul]
+[test_bug533845.xul]
+[test_bug551434.html]
+[test_bug708062.html]
+[test_bug812817.xul]
+[test_bug847890_paintFlashing.html]
+[test_bug1018265.xul]
+[test_bug1041200.xul]
+support-files=bug1041200_window.html
+[test_chrome_content_integration.xul]
+[test_chrome_over_plugin.xul]
+[test_default_background.xul]
+[test_dialog_with_positioning.html]
+tags = openwindow
+[test_fixed_bg_scrolling_repaints.html]
+[test_leaf_layers_partition_browser_window.xul]
+skip-if = (!debug) || (toolkit == "cocoa") || (os == "linux") # Disabled on Mac and Linux because of Bug 992311
+[test_no_clip_iframe.xul]
+[test_prerendered_transforms.html]
+[test_printpreview.xul]
+skip-if = os == "linux" && bits == 32 # Disabled on Linux32 for bug 1278957
+[test_printpreview_bug396024.xul]
+[test_printpreview_bug482976.xul]
+[test_scrolling_repaints.html]
+[test_will_change.html]
diff --git a/layout/base/tests/chrome/chrome_content_integration_window.xul b/layout/base/tests/chrome/chrome_content_integration_window.xul
new file mode 100644
index 000000000..23cd21e6e
--- /dev/null
+++ b/layout/base/tests/chrome/chrome_content_integration_window.xul
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<window title="Content/chrome integration subwindow"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTests()"
+ style="background:black; -moz-appearance:none;">
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <stack style="height:300px; width:200px;">
+ <!-- the bottom 100px is a strip of black that should be vixible through the content iframe -->
+ <vbox style="background:pink; border-bottom:100px solid black"/>
+ <!-- the middle 100px is a strip of black in the content iframe -->
+ <!-- the bottom 100px of the iframe is transparent, the top 100px is yellow -->
+ <iframe type="content" style="border:none;"
+ transparent="transparent"
+ src="data:text/html,&lt;div style='position:absolute;left:0;top:0;width:100%;height:100px;background:yellow;border-bottom:100px solid black'&gt;"/>
+ <!-- the top 100px is a strip of black above the content iframe -->
+ <vbox style="border-top:100px solid black;"/>
+ </stack>
+
+ <script type="application/javascript">
+ <![CDATA[
+ var imports = [ "SimpleTest", "is", "isnot", "ok", "SpecialPowers" ];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ function runTests() {
+ var testCanvas = snapshotWindow(window);
+
+ var refCanvas = snapshotWindow(window);
+ var ctx = refCanvas.getContext('2d');
+ ctx.fillStyle = "black";
+ ctx.fillRect(0, 0, refCanvas.width, refCanvas.height);
+
+ var comparison = compareSnapshots(testCanvas, refCanvas, true);
+ ok(comparison[0], "Rendering OK, got " + comparison[1] + ", expected " + comparison[2]);
+
+ var tester = window.SimpleTest;
+ window.close();
+ tester.finish();
+ }
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/chrome_over_plugin_window.xul b/layout/base/tests/chrome/chrome_over_plugin_window.xul
new file mode 100644
index 000000000..54c18fd56
--- /dev/null
+++ b/layout/base/tests/chrome/chrome_over_plugin_window.xul
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<window title="Content/chrome integration subwindow"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTests()">\
+ <!-- We're mainly testing that a) translucent chrome elements cause the plugin to be clipped away and
+ b) translucent content elements do NOT cause the plugin to be clipped away -->
+ <stack style="height:100px; width:150px;">
+ <iframe type="content" style="border:none;" id="f"
+ src="data:text/html,&lt;embed id='e' type='application/x-test' wmode='window'
+ style='position:absolute;left:0;top:0;width:100px;height:100px'&gt;&lt;/embed&gt;
+ &lt;div style='position:absolute;left:0;top:80px;width:100px;height:10px;background:rgba(0,0,128,0.5)'&gt;&lt;/div&gt;
+ &lt;div style='position:absolute;left:0;top:90px;width:100px;height:10px;background:blue'&gt;&lt;/div&gt;
+ "/>
+ <vbox>
+ <vbox style="height:25px; background:yellow;"/> <!-- plugin should be covered here -->
+ <vbox style="height:25px; background:rgba(0,128,0,0.5);"/> <!-- plugin should be covered here -->
+ <vbox style="height:50px;"/> <!-- plugin should be visible here -->
+ </vbox>
+ </stack>
+
+ <script type="application/javascript">
+ <![CDATA[
+ var imports = [ "SimpleTest", "is", "isnot", "ok", "todo" ];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ var plugin;
+ function waitForPaint() {
+ if (plugin.getPaintCount() < 1) {
+ setTimeout(waitForPaint, 0);
+ return;
+ }
+
+ if (plugin.hasWidget()) {
+ is(plugin.getClipRegionRectCount(), 1, "plugin clip rect count");
+ var left = plugin.getEdge(0);
+ var top = plugin.getEdge(1);
+ is(plugin.getClipRegionRectEdge(0,0) - left, 0, "plugin clip rect left");
+ // our two vboxes with backgrounds should cause the top of the plugin to be clipped
+ is(plugin.getClipRegionRectEdge(0,1) - top, 50, "plugin clip rect top");
+ is(plugin.getClipRegionRectEdge(0,2) - left, 100, "plugin clip rect right");
+ // of the two content DIVs, the first one should not cause the plugin to be clipped because
+ // it's transparent. The second one should cause the plugin to be clipped.
+ is(plugin.getClipRegionRectEdge(0,3) - top, 90, "plugin clip rect bottom");
+ } else {
+ todo(false, "Test only tests windowed plugins");
+ }
+
+ var tester = window.SimpleTest;
+ window.close();
+ tester.finish();
+ }
+
+ function runTests() {
+ plugin = document.getElementById("f").contentDocument.getElementById("e").wrappedJSObject;
+ waitForPaint();
+ }
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/default_background_window.xul b/layout/base/tests/chrome/default_background_window.xul
new file mode 100644
index 000000000..110dd8c15
--- /dev/null
+++ b/layout/base/tests/chrome/default_background_window.xul
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTests()">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <iframe type="content" id="f" src="about:blank" style="border:1px solid black;"/>
+
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ var imports = [ "SimpleTest", "is", "isnot", "ok" ];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ function snapshot(win) {
+ var el = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+ el.width = win.innerWidth;
+ el.height = win.innerHeight;
+
+ var ctx = el.getContext("2d");
+ ctx.drawWindow(win, 0, 0,
+ win.innerWidth, win.innerHeight,
+ "rgba(0,0,0,0)", 0);
+ return el;
+ }
+
+ var color = '#2468AC';
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ prefs.setCharPref('browser.display.background_color', color);
+
+ function runTests() {
+ var f = document.getElementById("f");
+
+ var testCanvas = snapshot(f.contentWindow);
+ prefs.clearUserPref('browser.display.background_color');
+
+ var refCanvas = snapshot(f.contentWindow);
+ var ctx = refCanvas.getContext('2d');
+ ctx.fillStyle = color;
+ ctx.fillRect(0, 0, refCanvas.width, refCanvas.height);
+
+ var comparison = compareSnapshots(testCanvas, refCanvas, true);
+ ok(comparison[0], "Rendering OK, got " + comparison[1] + ", expected " + comparison[2]);
+
+ var tester = window.SimpleTest;
+ window.close();
+ tester.finish();
+ }
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/dialog_with_positioning_window.xul b/layout/base/tests/chrome/dialog_with_positioning_window.xul
new file mode 100644
index 000000000..6b94fefdf
--- /dev/null
+++ b/layout/base/tests/chrome/dialog_with_positioning_window.xul
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="setTimeout(runTest, 0)">
+ <vbox>
+ <text value="powered by example.com" style="padding: 16px;"/>
+ </vbox>
+ <hbox id="t" style="position: fixed; right: 16px; bottom: 16px;">
+ <button label="OK"/>
+ </hbox>
+<script><![CDATA[
+var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
+var SpecialPowers = window.opener.wrappedJSObject.SpecialPowers;
+var is = window.opener.wrappedJSObject.is;
+var ok = window.opener.wrappedJSObject.ok;
+
+// We run this off a setTimeout from onload, because the XUL window
+// only does its intrinsic-height layout after the load event has
+// finished
+function runTest() {
+ var t = document.getElementById("t");
+ var tBottom = t.getBoundingClientRect().bottom;
+ is(tBottom, document.documentElement.getBoundingClientRect().bottom - 16,
+ "check fixed-pos element t bottom positioned correctly");
+ ok(tBottom < 200, "fixed-pos element t bottom must be sane, less than 200 (got " + tBottom + ")");
+ window.close();
+ SimpleTest.finish();
+}
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/file_bug1018265.xul b/layout/base/tests/chrome/file_bug1018265.xul
new file mode 100644
index 000000000..91944c5b4
--- /dev/null
+++ b/layout/base/tests/chrome/file_bug1018265.xul
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1018265
+-->
+<window title="Mozilla Bug 1018265"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="setTimeout(run, 0);">
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 1018265 **/
+
+ var testcontent = null;
+
+ function run() {
+ testcontent = document.getElementById("testcontent");
+ shouldHaveTwoNonHiddenContentViewers();
+ testcontent.setAttribute("src", "foobarpage");
+ setTimeout(errorPageLoaded, 2500)
+ }
+
+ function errorPageLoaded() {
+ testcontent.addEventListener("pageshow", didGoBack, true);
+ setTimeout("testcontent.contentWindow.history.back();", 0);
+ }
+
+ function didGoBack(e) {
+ testcontent.removeEventListener("pageshow", didGoBack, true);
+ shouldHaveTwoNonHiddenContentViewers();
+ opener.done();
+ window.close();
+ }
+
+ function getContentViewer(win) {
+ return win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDocShell).contentViewer;
+ }
+
+ function shouldHaveTwoNonHiddenContentViewers() {
+ opener.is(getContentViewer(testcontent.contentWindow).isHidden, false, "Top level ContentViewer should not be hidden.");
+ opener.is(getContentViewer(testcontent.contentWindow.frames[0]).isHidden, false, " Iframe's ContentViewer should not be hidden.");
+ }
+ ]]>
+ </script>
+
+ <browser type="content" id="testcontent" flex="1" src="data:text/html,&lt;iframe&gt;&lt;/iframe&gt;"/>
+</window>
diff --git a/layout/base/tests/chrome/no_clip_iframe_subdoc.html b/layout/base/tests/chrome/no_clip_iframe_subdoc.html
new file mode 100644
index 000000000..b00b48be6
--- /dev/null
+++ b/layout/base/tests/chrome/no_clip_iframe_subdoc.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="margin:0; background:lime;">
+<div id="d" style="position:relative; top:-50px; width:150px; height:250px; background:yellow;"></div>
+<div id="p" style="margin-top:-50px; width:150px; height:50px;"></div>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/no_clip_iframe_window.xul b/layout/base/tests/chrome/no_clip_iframe_window.xul
new file mode 100644
index 000000000..960477e9e
--- /dev/null
+++ b/layout/base/tests/chrome/no_clip_iframe_window.xul
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTests()">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
+
+ <div id="container" xmlns="http://www.w3.org/1999/xhtml" style="height:400px; overflow:auto; background:gray">
+ <div style="height:0">
+ <iframe type="content" id="f" src="no_clip_iframe_subdoc.html"
+ style="margin-top:50px; border:1px solid black; width:100px; height:100px;"/>
+ </div>
+ <div id="ref" style="background:gray;">
+ <div style="border:1px solid black; margin-top:50px; width:100px; height:100px;">
+ <div id="ref-d" style="background:lime; height:250px; width:150px;">
+ <div style="position:relative; top:-50px; width:150px; height:100%; background:yellow;"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ <vbox flex="1"/>
+
+ <script type="application/javascript">
+ <![CDATA[
+ var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror" ];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ var Ci = Components.interfaces;
+ var frame = document.getElementById("f");
+ var fl = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
+ is(fl.clipSubdocument, true, "clipSubdocument should default to true");
+ fl.clipSubdocument = false;
+ is(fl.clipSubdocument, false, "clipSubdocument should have been set to false");
+
+ function runTests() {
+ var ref = document.getElementById("ref");
+ frame.contentWindow.scrollTo(0,0);
+
+ ref.style.visibility = "hidden";
+ var testCanvas = snapshotWindow(window);
+ ref.style.visibility = "";
+ var refCanvas = snapshotWindow(window);
+ var comparison = compareSnapshots(testCanvas, refCanvas, true);
+ ok(comparison[0], "Basic overflow drawing; got " + comparison[1] + ", expected " + comparison[2]);
+
+ document.getElementById("container").style.height = "200px";
+ ref.style.visibility = "hidden";
+ testCanvas = snapshotWindow(window);
+ ref.style.visibility = "";
+ refCanvas = snapshotWindow(window);
+ comparison = compareSnapshots(testCanvas, refCanvas, true);
+ ok(comparison[0], "Drawing with vertical scrollbar to show overflow area computation; got " +
+ comparison[1] + ", expected " + comparison[2]);
+
+ frame.contentDocument.getElementById("d").style.height = "350px";
+ document.getElementById("ref-d").style.height = "350px";
+ ref.style.visibility = "hidden";
+ testCanvas = snapshotWindow(window);
+ ref.style.visibility = "";
+ refCanvas = snapshotWindow(window);
+ comparison = compareSnapshots(testCanvas, refCanvas, true);
+ ok(comparison[0], "testing dynamic overflow area change affecting scrollbar; got " +
+ comparison[1] + ", expected " + comparison[2]);
+
+ // Now do invalidation tests
+ ref.style.visibility = "hidden";
+ document.getElementById("container").style.height = "400px";
+ waitForAllPaintsFlushed(function() {
+ frame.contentWindow.scrollTo(0,80);
+ waitForAllPaintsFlushed(function(x1, y1, x2, y2) {
+ ok(x1 <= 1 && x2 >= 151 && y1 <= 0 && y2 >= 400,
+ "Entire scrolled region is painted: " + x1 + "," + y1 + "," + x2 + "," + y2);
+ frame.contentDocument.getElementById("p").style.background = "cyan";
+ waitForAllPaintsFlushed(function(x1, y1, x2, y2) {
+ ok(x1 <= 1 && x2 >= 151 && y1 <= 271 && y2 >= 320,
+ "Entire updated region is painted: " + x1 + "," + y1 + "," + x2 + "," + y2);
+
+ var tester = window.SimpleTest;
+ window.close();
+ tester.finish();
+ }, frame.contentDocument);
+ });
+ });
+ }
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/printpreview_bug396024_helper.xul b/layout/base/tests/chrome/printpreview_bug396024_helper.xul
new file mode 100644
index 000000000..8fe2609f5
--- /dev/null
+++ b/layout/base/tests/chrome/printpreview_bug396024_helper.xul
@@ -0,0 +1,123 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=396024
+-->
+<window title="Mozilla Bug 396024" onload="run()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<iframe id="i" src="about:blank" type="content"></iframe>
+<iframe src="about:blank" type="content"></iframe>
+<script type="application/javascript">
+<![CDATA[
+var is = window.opener.wrappedJSObject.is;
+var ok = window.opener.wrappedJSObject.ok;
+var todo = window.opener.wrappedJSObject.todo;
+var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
+var gWbp;
+function printpreview() {
+ gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint);
+ var listener = {
+ onLocationChange: function(webProgress, request, location, flags) { },
+ onProgressChange: function(webProgress, request, curSelfProgress,
+ maxSelfProgress, curTotalProgress,
+ maxTotalProgress) { },
+ onSecurityChange: function(webProgress, request, state) { },
+ onStateChange: function(webProgress, request, stateFlags, status) { },
+ onStatusChange: function(webProgress, request, status, message) { },
+ QueryInterface: function(iid) {
+ if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
+ iid.equals(Components.interfaces.nsISupportsWeakReference))
+ return this;
+ throw Components.results.NS_NOINTERFACE;
+ }
+ }
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ prefs.setBoolPref('print.show_print_progress', false);
+ //XXX I would have thought this would work, instead I'm forced to use prefs service
+ gWbp.globalPrintSettings.showPrintProgress = false;
+ gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
+ prefs.clearUserPref('print.show_print_progress');
+}
+
+function exitprintpreview() {
+ window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
+}
+
+function finish() {
+ SimpleTest.finish();
+ window.close();
+}
+
+function run()
+{
+/** Test for Bug 396024 **/
+ var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
+ .getService(Components.interfaces.nsIPrintSettingsService);
+
+ try {
+ Components.classes["@mozilla.org/gfx/printerenumerator;1"]
+ .getService(Components.interfaces.nsIPrinterEnumerator);
+ } catch(e) {
+ todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there");
+ finish();
+ return;
+ }
+
+ if (printService.defaultPrinterName != '') {
+ printpreview();
+ ok(gWbp.doingPrintPreview, "Should be doing print preview");
+ exitprintpreview();
+ ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore1");
+ printpreview();
+ setTimeout(run2, 0)
+ } else {
+ todo(false, "No printer seems installed on this machine, that is necessary for this test");
+ finish();
+ }
+}
+
+function run2() {
+ var loadhandler = function() {
+ document.getElementById("i").removeEventListener("load", arguments.callee, true);
+ setTimeout(run3, 0);
+ };
+ document.getElementById("i").addEventListener("load", loadhandler, true);
+ window.frames[0].location.reload();
+}
+
+function run3() {
+ gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint);
+ ok(gWbp.doingPrintPreview, "Should be doing print preview");
+ exitprintpreview();
+ setTimeout(run4, 0);
+}
+
+function run4() {
+ var i = document.getElementById("i");
+ var x = i.parentNode.removeChild(i);
+ var loadhandler = function() {
+ document.getElementById("i").removeEventListener("load", loadhandler, true);
+ setTimeout(run5, 0);
+ };
+ x.addEventListener("load", loadhandler, true);
+ document.documentElement.getBoundingClientRect();
+ document.documentElement.appendChild(x);
+ gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint);
+ ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore2");
+}
+
+function run5() {
+ //XXX this shouldn't be necessary, see bug 405555
+ printpreview();
+ exitprintpreview();
+ finish(); //should not have crashed after all of this
+}
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/printpreview_bug482976_helper.xul b/layout/base/tests/chrome/printpreview_bug482976_helper.xul
new file mode 100644
index 000000000..34c2d658e
--- /dev/null
+++ b/layout/base/tests/chrome/printpreview_bug482976_helper.xul
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=482976
+-->
+<window title="Mozilla Bug 482976" onload="run1()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<iframe src="about:blank" type="content"></iframe>
+<iframe src="about:blank" type="content"></iframe>
+<script type="application/javascript">
+<![CDATA[
+var is = window.opener.wrappedJSObject.is;
+var ok = window.opener.wrappedJSObject.ok;
+var todo = window.opener.wrappedJSObject.todo;
+var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
+var gWbp;
+function printpreview() {
+ gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint);
+ var listener = {
+ onLocationChange: function(webProgress, request, location, flags) { },
+ onProgressChange: function(webProgress, request, curSelfProgress,
+ maxSelfProgress, curTotalProgress,
+ maxTotalProgress) { },
+ onSecurityChange: function(webProgress, request, state) { },
+ onStateChange: function(webProgress, request, stateFlags, status) { },
+ onStatusChange: function(webProgress, request, status, message) { },
+ QueryInterface: function(iid) {
+ if (iid.equals(Components.interfaces.nsIWebProgessListener) ||
+ iid.equals(Components.interfaces.nsISupportsWeakReference))
+ return this;
+ throw Components.results.NS_NOINTERFACE;
+ }
+ }
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ prefs.setBoolPref('print.show_print_progress', false);
+ //XXX I would have thought this would work, instead I'm forced to use prefs service
+ gWbp.globalPrintSettings.showPrintProgress = false;
+ gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
+ prefs.clearUserPref('print.show_print_progress');
+}
+
+function exitprintpreview() {
+ window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
+}
+
+function finish() {
+ SimpleTest.finish();
+ window.close();
+}
+
+function run1()
+{
+/** Test for Bug 482976 **/
+ var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
+ .getService(Components.interfaces.nsIPrintSettingsService);
+
+ try {
+ Components.classes["@mozilla.org/gfx/printerenumerator;1"]
+ .getService(Components.interfaces.nsIPrinterEnumerator);
+ } catch(e) {
+ todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there");
+ finish();
+ return;
+ }
+
+ if (printService.defaultPrinterName != '') {
+ printpreview();
+ ok(gWbp.doingPrintPreview, "Should be doing print preview");
+ exitprintpreview();
+ ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore");
+ } else {
+ todo(false, "No printer seems installed on this machine, that is necessary for this test");
+ }
+ finish();
+}
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/printpreview_helper.xul b/layout/base/tests/chrome/printpreview_helper.xul
new file mode 100644
index 000000000..96d835b9a
--- /dev/null
+++ b/layout/base/tests/chrome/printpreview_helper.xul
@@ -0,0 +1,274 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window onload="runTests()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<iframe height="200" width="600" type="content"></iframe>
+<iframe height="200" width="600" type="content"></iframe>
+<script type="application/javascript">
+<![CDATA[
+var is = window.opener.wrappedJSObject.is;
+var isnot = window.opener.wrappedJSObject.isnot;
+var ok = window.opener.wrappedJSObject.ok;
+var todo = window.opener.wrappedJSObject.todo;
+var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
+var gWbp;
+var ctx1;
+var ctx2;
+var counter = 0;
+
+var file = Components.classes["@mozilla.org/file/directory_service;1"]
+ .getService(Components.interfaces.nsIProperties)
+ .get("TmpD", Components.interfaces.nsILocalFile);
+filePath = file.path;
+
+function printpreview() {
+ gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint);
+ var listener = {
+ onLocationChange: function(webProgress, request, location, flags) { },
+ onProgressChange: function(webProgress, request, curSelfProgress,
+ maxSelfProgress, curTotalProgress,
+ maxTotalProgress) { },
+ onSecurityChange: function(webProgress, request, state) { },
+ onStateChange: function(webProgress, request, stateFlags, status) { },
+ onStatusChange: function(webProgress, request, status, message) { },
+ QueryInterface: function(iid) {
+ if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
+ iid.equals(Components.interfaces.nsISupportsWeakReference))
+ return this;
+ throw Components.results.NS_NOINTERFACE;
+ }
+ }
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ prefs.setBoolPref('print.show_print_progress', false);
+ //XXX I would have thought this would work, instead I'm forced to use prefs service
+ gWbp.globalPrintSettings.showPrintProgress = false;
+ var before = 0;
+ var after = 0;
+ function beforeprint() { ++before; }
+ function afterprint() { ++after; }
+ window.frames[0].addEventListener("beforeprint", beforeprint, true);
+ window.frames[0].addEventListener("afterprint", afterprint, true);
+ gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
+ is(before, 1, "Should have called beforeprint listener!");
+ is(after, 1, "Should have called afterprint listener!");
+ window.frames[0].removeEventListener("beforeprint", beforeprint, true);
+ window.frames[0].removeEventListener("afterprint", afterprint, true);
+ prefs.clearUserPref('print.show_print_progress');
+}
+
+function exitprintpreview() {
+ window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
+}
+
+function finish() {
+ SimpleTest.finish();
+ window.close();
+}
+
+function runTests()
+{
+ var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
+ .getService(Components.interfaces.nsIPrintSettingsService);
+
+ try {
+ Components.classes["@mozilla.org/gfx/printerenumerator;1"]
+ .getService(Components.interfaces.nsIPrinterEnumerator);
+ } catch(e) {
+ todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there");
+ finish();
+ return;
+ }
+
+ if (printService.defaultPrinterName != '') {
+ startTest1();
+ } else {
+ todo(false, "No printer seems installed on this machine, that is necessary for this test");
+ finish();
+ }
+}
+
+function compareCanvases() {
+ return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindowUtils)
+ .compareCanvases(document.getElementsByTagName("canvas")[0],
+ document.getElementsByTagName("canvas")[1],
+ {}) == 0;
+}
+
+function addHTMLContent(parent) {
+ var n = parent.ownerDocument.createElement("div");
+ parent.appendChild(n);
+ var s = "<iframe width='500' height='40' src='data:text/plain,ThisIsAnIframeCreatedDuringPrintPreview'></iframe>";
+ s += "<table>";
+ for (var i = 1; i < 501; ++i) {
+ s += "<tr><td>Cell A" + i + "</td><td>Cell B" + i + "</td><td>Cell C" + i + "</td></tr>";
+ }
+ s += "</table>";
+ n.innerHTML = s;
+}
+
+function startTest1() {
+ ctx1 = document.getElementsByTagName("canvas")[0].getContext("2d");
+ ctx2 = document.getElementsByTagName("canvas")[1].getContext("2d");
+ window.frames[0].document.body.innerHTML = "<div> </div><div>" + counter + " timers</div><div> </div>";
+
+ // Note this timeout is needed so that we can check that timers run
+ // after print preview, but not during it.
+ window.frames[0].wrappedJSObject.counter = counter;
+ window.frames[0].counterTimeout = "document.body.firstChild.nextSibling.innerHTML = ++counter + ' timers';" +
+ "window.setTimeout(counterTimeout, 0);";
+ window.frames[0].setTimeout(window.frames[0].counterTimeout, 0);
+ window.frames[0].document.body.firstChild.innerHTML = "Print preview";
+
+ printpreview();
+ ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
+ window.frames[0].document.body.firstChild.innerHTML = "Galley presentation";
+
+ // Add some elements.
+ addHTMLContent(window.frames[0].document.body.lastChild);
+ // Delete them.
+ window.frames[0].document.body.lastChild.innerHTML = "";
+ // And readd.
+ addHTMLContent(window.frames[0].document.body.lastChild);
+
+ setTimeout(finalizeTest1, 1000);
+}
+
+function finalizeTest1() {
+ ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
+ exitprintpreview();
+ ok(compareCanvases(), "Canvas should be the same!");
+ counter = window.frames[0].counter;
+ // This timeout is needed so that we can check that timers do run after
+ // print preview.
+ setTimeout(runTest2, 1000);
+}
+
+function runTest2() {
+ isnot(window.frames[0].document.body.firstChild.nextSibling.textContent, "0 timers", "Timers should have run!");
+ isnot(window.frames[0].counter, 0, "Timers should have run!");
+ counter = window.frames[0].counter;
+ window.frames[0].counterTimeout = "";
+ setTimeout(runTest3, 0);
+}
+
+var elementIndex = 0;
+var compareEmptyElement = true;
+var emptyFormElements =
+ ["<input type='text'>",
+ "<input type='password'>",
+ "<input type='file'>",
+ "<input type='button'>",
+ "<input type='submit'>",
+ "<input type='reset'>",
+ "<input type='checkbox'>",
+ "<input type='radio'>",
+ "<select></select>",
+ "<select size='5'></select>",
+ "<textarea></textarea>"];
+
+var formElements =
+ ["<input type='text' value='text'>",
+ "<input type='password' value='password'>",
+ "<input type='file' value='" + filePath + "'>",
+ "<input type='button' value='button'>",
+ "<input type='submit' value='submit button'>",
+ "<input type='reset' value='reset button'>",
+ "<input type='checkbox' checked>",
+ "<input type='radio' checked>",
+ "<select><option>option1</option></select>",
+ "<select size='5'><option>1</option><option>2</option><option>3</option></select>",
+ "<textarea value='textarea'>textarea</textarea>"];
+
+function runTest3() {
+ if (compareEmptyElement) {
+ var currentIndex = elementIndex;
+ ++elementIndex;
+ if (elementIndex >= emptyFormElements.length) {
+ elementIndex = 0;
+ compareEmptyElement = false;
+ }
+ compareFormElementPrint(emptyFormElements[currentIndex], emptyFormElements[currentIndex], true);
+ return;
+ } else if (elementIndex < emptyFormElements.length) {
+ var currentIndex = elementIndex;
+ ++elementIndex;
+ compareFormElementPrint(emptyFormElements[currentIndex], formElements[currentIndex], false);
+ return;
+ }
+
+ setTimeout(runTest4, 0)
+}
+
+function compareFormElementPrint(el1, el2, equals) {
+ window.frames[0].document.body.innerHTML = el1;
+ window.frames[0].document.body.firstChild.value =
+ window.frames[0].document.body.firstChild.getAttribute('value');
+ printpreview();
+ ctx1.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
+ exitprintpreview();
+ window.frames[0].document.body.innerHTML = el2;
+ window.frames[0].document.body.firstChild.value =
+ window.frames[0].document.body.firstChild.getAttribute('value');
+ printpreview();
+ ctx2.drawWindow(window.frames[1], 0, 0, 400, 400, "rgb(256,256,256)");
+ exitprintpreview();
+ is(compareCanvases(), equals,
+ "Comparing print preview didn't succeed [" + el1 + " : " + el2 + "]");
+ setTimeout(runTest3, 100);
+}
+
+// This is a crash test for bug 539060.
+function runTest4() {
+ window.frames[0].document.body.innerHTML =
+ "<iframe style='display: none;' src='data:text/html,<iframe>'></iframe>";
+ setTimeout(runTest4end, 500);
+}
+
+function runTest4end() {
+ printpreview();
+ exitprintpreview();
+
+ runTest5();
+}
+
+// This is a crash test for bug 595337
+function runTest5() {
+ window.frames[0].document.body.innerHTML =
+ '<iframe style="position: fixed; visibility: hidden; bottom: 10em;"></iframe>' +
+ '<input contenteditable="true" style="display: table; page-break-before: left; width: 10000px;">';
+ printpreview();
+ exitprintpreview();
+
+ setTimeout(runTest6, 0);
+}
+
+// Crash test for bug 878037
+function runTest6() {
+ window.frames[0].document.body.innerHTML =
+ '<style> li { list-style-image: url("animated.gif"); } </style>' +
+ '<li>Firefox will crash if you try and print this page</li>';
+
+ setTimeout(runTest6end, 500);
+}
+
+function runTest6end() {
+ printpreview();
+ exitprintpreview();
+
+ finish();
+}
+
+]]></script>
+<table style="border: 1px solid black;" xmlns="http://www.w3.org/1999/xhtml">
+<tr><th>Print preview canvas 1</th><th>Print preview canvas 2</th></tr>
+<tr>
+<td><canvas height="400" width="400"></canvas></td>
+<td><canvas height="400" width="400"></canvas></td>
+</tr></table>
+</window>
diff --git a/layout/base/tests/chrome/test_bug1018265.xul b/layout/base/tests/chrome/test_bug1018265.xul
new file mode 100644
index 000000000..5787be72c
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug1018265.xul
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1018265
+-->
+<window title="Mozilla Bug 1018265"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="run()">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 1018265 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ function run() {
+ window.open("file_bug1018265.xul", "contentViewerTest", "chrome,width=100,height=100");
+ }
+
+ function done() {
+ ok(true, "done");
+ setTimeout("SimpleTest.finish()", 0);
+ }
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1018265"
+ target="_blank">Mozilla Bug 1018265</a>
+ </body>
+</window>
diff --git a/layout/base/tests/chrome/test_bug1041200.xul b/layout/base/tests/chrome/test_bug1041200.xul
new file mode 100644
index 000000000..e85349697
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug1041200.xul
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+ // Run the test in a separate window so that the test runs as a chrome
+ // window
+ window.open("bug1041200_window.html", "bug1041200",
+ "chrome,width=800,height=800");
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/test_bug396367-1.html b/layout/base/tests/chrome/test_bug396367-1.html
new file mode 100644
index 000000000..bf24161ca
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug396367-1.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=396367
+-->
+<head>
+ <title>Test for Bug 396367</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+
+ function finish() {
+ ok(true, "didn't crash");
+ var docviewer = getdocviewer();
+ docviewer.textZoom = 1;
+ SimpleTest.finish();
+ }
+
+ function getdocviewer() {
+ var navigator1 = top.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation);
+ var docShell = navigator1.QueryInterface(Components.interfaces.nsIDocShell);
+ var docviewer = docShell.contentViewer;
+ return docviewer;
+ }
+ </script>
+</head>
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=396367">Mozilla Bug 396367</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+
+<input>
+<script>document.body.setAttribute('style', 'display: -moz-box; overflow: scroll;');</script>
+<script>
+var docviewer = getdocviewer();
+docviewer.textZoom=Math.floor(10*Math.random())/4+0.2;
+document.documentElement.offsetHeight;
+setTimeout(finish, 0);
+</script>
+
+
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_bug396367-2.html b/layout/base/tests/chrome/test_bug396367-2.html
new file mode 100644
index 000000000..94f218a0d
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug396367-2.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=396367
+-->
+<head>
+ <title>Test for Bug 396367</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <style>select::after { content:"m"; }</style>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+
+ function finish() {
+ ok(true, "didn't crash");
+ var docviewer = getdocviewer();
+ docviewer.textZoom = 1;
+ SimpleTest.finish();
+ }
+
+ function getdocviewer() {
+ var navigator1 = top.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation);
+ var docShell = navigator1.QueryInterface(Components.interfaces.nsIDocShell);
+ var docviewer = docShell.contentViewer;
+ return docviewer;
+ }
+ </script>
+</head>
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=396367">Mozilla Bug 396367</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+
+<div style="overflow: scroll; float: left;">
+
+<select></select>
+
+<li style="display: table-cell;">
+
+<script>
+var docviewer = getdocviewer();
+docviewer.textZoom=Math.floor(10*Math.random())/4+0.2;
+document.documentElement.offsetHeight;
+setTimeout(finish, 0);
+</script>
+</li>
+</div>
+
+
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_bug420499.xul b/layout/base/tests/chrome/test_bug420499.xul
new file mode 100644
index 000000000..fb20c417a
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug420499.xul
@@ -0,0 +1,129 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=420499
+-->
+<window title="Mozilla Bug 420499" onload="setTimeout(focusInput, 500);"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+
+
+ <menu id="menu" label="Menu">
+ <menupopup id="file-popup">
+ <!-- <textbox id="some-text" maxlength="10" value="some text"/> -->
+ <menu label="submenu">
+ <menupopup id="file-popup-inner">
+
+ <menuitem label="Item1"/>
+ <menuitem label="Item2"/>
+ <textbox id="some-text" maxlength="10" value="some more text"/>
+ </menupopup>
+ </menu>
+ <menuitem label="Item3"/>
+ <menuitem label="Item4"/>
+ </menupopup>
+ </menu>
+
+ <popupset>
+ <popup id="contextmenu">
+ <menuitem label="Cut"/>
+ <menuitem label="Copy"/>
+ <menuitem label="Paste"/>
+ </popup>
+ <tooltip id="tooltip" orient="vertical">
+ <description value="This is a tooltip"/>
+ </tooltip>
+ </popupset>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml" bgcolor="white">
+
+ <p id="par1">Paragraph 1</p>
+ <p id="par2">Paragraph 2</p>
+ <p id="par3">Paragraph 3</p>
+ <p id="par4">Paragraph 4</p>
+ <p id="par5">Paragraph 5</p>
+
+ <input type="text" id="text-input" maxlength="10" value="some more text"/> <br />
+
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=420499"
+ target="_blank">Mozilla Bug 420499</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+ /** Test for Bug 420499 **/
+ SimpleTest.waitForExplicitFinish();
+
+ function getSelectionController() {
+ return document.docShell
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsISelectionDisplay)
+ .QueryInterface(Components.interfaces.nsISelectionController);
+ }
+
+ function isCaretVisible() {
+ window.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
+ var docShell = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .QueryInterface(Components.interfaces.nsIDocShell);
+ var selCon = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsISelectionDisplay)
+ .QueryInterface(Components.interfaces.nsISelectionController);
+ return selCon.caretVisible;
+ }
+
+ function focusInput() {
+ ok(!isCaretVisible(), "Caret shouldn't be visible");
+ $("text-input").focus();
+ ok(isCaretVisible(), "Caret should be visible when input focused");
+ window.addEventListener("popupshown", popupMenuShownHandler, false);
+ $("menu").open = true;
+ }
+
+ function popupMenuShownHandler() {
+ window.removeEventListener("popupshown", popupMenuShownHandler, false);
+ ok(!isCaretVisible(), "Caret shouldn't be visible when menu open");
+ window.addEventListener("popuphidden", ensureParagraphFocused, false);
+ $("menu").open = false;
+ }
+
+ function ensureParagraphFocused() {
+ window.removeEventListener("popuphidden", ensureParagraphFocused, false);
+ ok(isCaretVisible(), "Caret should have returned to previous focus");
+ window.addEventListener("popupshown", popupMenuShownHandler2, false);
+ $("contextmenu").openPopup($('text-input'), "topleft" , -1 , -1 , true, true);
+ }
+
+ function popupMenuShownHandler2() {
+ window.removeEventListener("popupshown", popupMenuShownHandler2, false);
+ ok(isCaretVisible(), "Caret should be visible when context menu open");
+ window.addEventListener("popuphidden", ensureParagraphFocused2, false);
+ document.getElementById("contextmenu").hidePopup();
+ }
+
+ function ensureParagraphFocused2() {
+ window.removeEventListener("popuphidden", ensureParagraphFocused2, false);
+ ok(isCaretVisible(), "Caret should still be visible");
+ window.addEventListener("popupshown", tooltipShownHandler, false);
+ $("tooltip").openPopup($('text-input'), "topleft" , -1 , -1 , false, true);
+ }
+
+ function tooltipShownHandler() {
+ window.removeEventListener("popupshown", tooltipShownHandler, false);
+ ok(isCaretVisible(), "Caret should be visible when tooltip is visible");
+ window.addEventListener("popuphidden", ensureParagraphFocused3, false);
+ document.getElementById("tooltip").hidePopup();
+ }
+
+ function ensureParagraphFocused3() {
+ window.removeEventListener("popuphidden", ensureParagraphFocused2, false);
+ ok(isCaretVisible(), "Caret should still be visible");
+ SimpleTest.finish();
+ }
+ ]]></script>
+</window>
diff --git a/layout/base/tests/chrome/test_bug458898.html b/layout/base/tests/chrome/test_bug458898.html
new file mode 100644
index 000000000..90261b4ce
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug458898.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=458898
+-->
+<head>
+ <title>Test for Bug 458898</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=458898">Mozilla Bug 458898</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+var win = window.openDialog("data:text/html,<div style='height:200px; width:100px;'>");
+
+function loaded() {
+ var disableWindowResizePref = "dom.disable_window_move_resize";
+ SpecialPowers.pushPrefEnv({"set":[[disableWindowResizePref, false]]}, function() {
+ win.sizeToContent();
+ ok(win.innerWidth >= 100, "innerWidth: " + win.innerWidth + " >= 100 ?");
+ ok(win.innerHeight >= 200, "innerHeight: " + win.innerHeight + " >= 200 ?");
+ win.close();
+ SimpleTest.finish();
+ });
+}
+
+win.addEventListener("load", loaded, false);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_bug495648.xul b/layout/base/tests/chrome/test_bug495648.xul
new file mode 100644
index 000000000..186417a0d
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug495648.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=495648
+-->
+<window title="Mozilla Bug 495648"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=495648"
+ target="_blank">Mozilla Bug 495648</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.expectAssertions(15, 24);
+
+ /** Test for Bug 495648 **/
+ var uri = window.location.href.replace(/test_bug495648.xul/, "bug495648.rdf");
+
+ function doTest() {
+ var list = document.getElementById('l');
+ var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
+ var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
+ var rdf = rdfService.GetDataSourceBlocking(uri);
+ list.database.AddDataSource(rdf);
+ list.builder.rebuild();
+ is(list.itemCount, 40, "Unexpected item count");
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+
+ ]]>
+ </script>
+<listbox flex="1" id="l" seltype="multiple" datasources="rdf:null" ref="urn:root" sortResource="http://home.netscape.com/NC-rdf#name" sortDirection="ascending">
+<template>
+<rule><conditions><content uri="?uri" /><triple subject="?uri" predicate="http://home.netscape.com/NC-rdf#links" object="?links" /><member container="?links" child="?child" /><triple subject="?child" predicate="http://home.netscape.com/NC-rdf#name" object="?name" /></conditions><bindings><binding subject="?child" predicate="http://sitedelta.schierla.de/SD-rdf#status" object="?status" /></bindings><action><listitem label="?name" class="listitem-iconic" status="?status" uri="?child" /></action></rule>
+</template>
+</listbox>
+</window>
diff --git a/layout/base/tests/chrome/test_bug504311.xul b/layout/base/tests/chrome/test_bug504311.xul
new file mode 100644
index 000000000..1b640fdd8
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug504311.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=504311
+-->
+<window title="Mozilla Bug 504311"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="doTest()">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=504311"
+ target="_blank">Mozilla Bug 504311</a>
+</body>
+ <!-- test code goes here -->
+<script type="application/javascript">
+<![CDATA[
+SimpleTest.waitForExplicitFinish();
+
+function doTest()
+{
+ var tb = document.getElementById("tb01");
+ var inputField = tb.inputField;
+ var editor = inputField.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
+ editor = editor.QueryInterface(Components.interfaces.nsIPlaintextEditor);
+ editor.wrapWidth = -1;
+
+ ok(true, "Didn't crash");
+ SimpleTest.finish();
+}
+]]></script>
+<textbox id="tb01" multiline="true"/>
+</window>
diff --git a/layout/base/tests/chrome/test_bug514660.xul b/layout/base/tests/chrome/test_bug514660.xul
new file mode 100644
index 000000000..e7c504bcf
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug514660.xul
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=514660
+-->
+<window title="Mozilla Bug 504311"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="doTest()">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=514660"
+ target="_blank">Mozilla Bug 514660</a>
+<textarea></textarea>
+</body>
+ <!-- test code goes here -->
+<script type="application/javascript">
+<![CDATA[
+SimpleTest.waitForExplicitFinish();
+
+function doTest()
+{
+ var viewer = window
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .QueryInterface(Components.interfaces.nsIDocShell)
+ .contentViewer;
+ viewer.authorStyleDisabled = true;
+
+ document.documentElement.getBoundingClientRect();
+ ok(true, "Didn't crash");
+
+ viewer.authorStyleDisabled = false;
+
+ SimpleTest.finish();
+}
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/test_bug533845.xul b/layout/base/tests/chrome/test_bug533845.xul
new file mode 100644
index 000000000..2cee7af05
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug533845.xul
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=533845
+-->
+<window title="Mozilla Bug 533845"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="doTest()">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<panel id="panel" width="50" height="50" onpopupshown="continueTest()">
+ <iframe type="content" id="contentFrame" src="data:text/html,&lt;html&gt;&lt;body onclick='document.body.textContent=1'&gt;This is a panel!&lt;/body&gt;&lt;/html&gt;" width="500" height="500"/>
+</panel>
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=533845"
+ target="_blank">Mozilla Bug 533845</a>
+</body>
+ <!-- test code goes here -->
+<script type="application/javascript">
+<![CDATA[
+SimpleTest.waitForExplicitFinish();
+
+function doTest() {
+ document.getElementById('panel').showPopup();
+}
+
+function continueTest() {
+ var ifrwindow = document.getElementById("contentFrame").contentWindow;
+ ifrwindow.focus();
+ var utils = ifrwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindowUtils);
+ var rect = ifrwindow.document.body.getBoundingClientRect();
+ var x = rect.left + (rect.width/2);
+ var y = rect.top + (rect.height/2);
+ utils.sendMouseEvent("mousedown", x, y, 0, 1, 0);
+ utils.sendMouseEvent("mouseup", x, y, 0, 1, 0);
+ is(ifrwindow.document.body.textContent, "1", "Should have got a click event!");
+ SimpleTest.finish();
+}
+
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/test_bug551434.html b/layout/base/tests/chrome/test_bug551434.html
new file mode 100644
index 000000000..10691c53a
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug551434.html
@@ -0,0 +1,97 @@
+<html>
+<head>
+ <title>Test for Bug 551434</title>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+</div>
+<pre id="test">
+<input id="i1" onkeydown="gKeyDown1++; $('i2').focus();" onkeypress="gKeyPress1++;" onkeyup="gKeyUp1++;"/>
+<input id="i2" onkeydown="gKeyDown2++;" onkeypress="gKeyPress2++;" onkeyup="gKeyUp2++;"/>
+
+<input id="i3" onkeydown="gKeyDown3++; frames[0].document.getElementById('i4').focus();"
+ onkeypress="gKeyPress3++;" onkeyup="gKeyUp3++;"/>
+<iframe id="iframe" src="http://example.org/chrome/layout/base/tests/chrome/bug551434_childframe.html"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var gKeyDown1 = 0, gKeyPress1 = 0, gKeyUp1 = 0;
+var gKeyDown2 = 0, gKeyPress2 = 0, gKeyUp2 = 0;
+var gKeyDown3 = 0, gKeyPress3 = 0, gKeyUp3 = 0;
+
+function runTest()
+{
+ $("i1").focus();
+
+ // key events should not be retargeted when the focus changes to an
+ // element in the same document.
+ synthesizeKey("a", { type: "keydown", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_B });
+ is(document.activeElement, $("i2"), "input 2 in focused");
+
+ synthesizeKey("a", { type: "keyup", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_B });
+
+ is(gKeyDown1, 1, "keydown on input 1");
+ is(gKeyPress1, 0, "keypress on input 1");
+ is(gKeyUp1, 0, "keyup on input 1");
+ is(gKeyDown2, 0, "keydown on input 2");
+ is(gKeyPress2, 1, "keypress on input 2");
+ is(gKeyUp2, 1, "keyup on input 2");
+
+ is($("i1").value, "", "input 1 value");
+ is($("i2").value, "a", "input 2 value");
+
+ // key events should however be retargeted when the focus changes to an
+ // element in the a content document from a chrome document.
+ $("i3").focus();
+
+ var childWinObj = frames[0].wrappedJSObject;
+
+ synthesizeKey("b", { code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B });
+ is(gKeyDown3, 1, "keydown on input 3");
+ is(gKeyPress3, 1, "keypress on input 3");
+ is(gKeyUp3, 1, "keyup on input 3");
+ is(childWinObj.gKeyDownChild, 0, "keydown on input 4");
+ is(childWinObj.gKeyPressChild, 0, "keypress on input 4");
+ is(childWinObj.gKeyUpChild, 0, "keyup on input 4");
+
+ var i4 = frames[0].document.getElementById("i4");
+ is($("i3").value, "b", "input 3 value");
+ is(i4.value, "", "input 4 value");
+
+ is(document.activeElement, $("iframe"), "parent focus");
+ is(frames[0].document.activeElement, i4, "child focus");
+
+ // key events should also be retargeted when the focus changes to an
+ // element in a chrome document from a content document.
+ i4.addEventListener("keydown", () => $("i3").focus(), false);
+
+ synthesizeKey("c", { code: "KeyC", keyCode: KeyboardEvent.DOM_VK_C });
+
+ is(gKeyDown3, 1, "keydown on input 3");
+ is(gKeyPress3, 1, "keypress on input 3");
+ is(gKeyUp3, 1, "keyup on input 3");
+ is(childWinObj.gKeyDownChild, 1, "keydown on input 4");
+ is(childWinObj.gKeyPressChild, 1, "keypress on input 4");
+ is(childWinObj.gKeyUpChild, 1, "keyup on input 4");
+
+ is($("i3").value, "b", "input 3 value");
+ is(i4.value, "c", "input 4 value");
+
+ is(document.activeElement, $("i3"), "parent focus");
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForFocus(runTest);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/chrome/test_bug708062.html b/layout/base/tests/chrome/test_bug708062.html
new file mode 100644
index 000000000..dcf4481ea
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug708062.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=708062
+-->
+<head>
+ <title>Test for Bug 708062</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body onload="doTest()">
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=708062">Mozilla Bug 708062</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<iframe id="f" style="width:100px;"
+ src="data:text/html,A<div id='d' style='position:fixed;width:170px;top:0;right:0;height:1px;background:yellow;'>"></iframe>
+<pre id="test">
+
+<script>
+function isBoundingClientRect(e, r, msg) {
+ var BCR = e.getBoundingClientRect();
+ is([BCR.left, BCR.top, BCR.right, BCR.bottom].join(','), r, msg);
+}
+
+function doTest() {
+ var f = document.getElementById('f');
+
+ var navigator1 = f.contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation);
+ var docShell = navigator1.QueryInterface(Components.interfaces.nsIDocShell);
+ var docviewer = docShell.contentViewer;
+
+ var d = f.contentDocument.getElementById('d');
+
+ isBoundingClientRect(d, "-70,0,100,1", "initial rect");
+ docviewer.fullZoom = 2;
+ isBoundingClientRect(d, "-120,0,50,1", "after zooming in");
+ docviewer.fullZoom = 1;
+ isBoundingClientRect(d, "-70,0,100,1", "after zooming back out");
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_bug812817.xul b/layout/base/tests/chrome/test_bug812817.xul
new file mode 100644
index 000000000..d9e1d59ed
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug812817.xul
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=812817
+-->
+<window title="Mozilla Bug 812817"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="doTest()">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<panel id="panel" width="200" height="200" onpopupshown="continueTest()">
+</panel>
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=812817"
+ target="_blank">Mozilla Bug 812817</a>
+</body>
+ <!-- test code goes here -->
+<script type="application/javascript">
+<![CDATA[
+SimpleTest.waitForExplicitFinish();
+
+var panel = document.getElementById('panel');
+function doTest() {
+ panel.openPopup(null, '', 500, 500, false, false, null);
+}
+
+function continueTest() {
+ panel.style.background = "url(blue-32x32.png)";
+ setTimeout(function() {
+ ok(true, "Didn't crash");
+ SimpleTest.finish();
+ }, 50);
+}
+
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/test_bug847890_paintFlashing.html b/layout/base/tests/chrome/test_bug847890_paintFlashing.html
new file mode 100644
index 000000000..9653e48d9
--- /dev/null
+++ b/layout/base/tests/chrome/test_bug847890_paintFlashing.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Tests for paint flashing</title>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
+
+ <script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function startTest() {
+ waitForAllPaintsFlushed(function () {
+ var before = snapshotWindow(window, false);
+ SpecialPowers.getDOMWindowUtils(window).paintFlashing = true;
+ document.body.innerHTML = "bar";
+ waitForAllPaintsFlushed(function () {
+ document.body.innerHTML = "foo";
+ waitForAllPaintsFlushed(function () {
+ var after = snapshotWindow(window, false);
+ ok(compareSnapshots(before, after, false)[0], "windows are different");
+ SpecialPowers.getDOMWindowUtils(window).paintFlashing = false;
+ SimpleTest.finish();
+ });
+ });
+ });
+ }
+ </script>
+</head>
+<body onload="startTest()">foo</body>
+</html>
diff --git a/layout/base/tests/chrome/test_chrome_content_integration.xul b/layout/base/tests/chrome/test_chrome_content_integration.xul
new file mode 100644
index 000000000..94878447a
--- /dev/null
+++ b/layout/base/tests/chrome/test_chrome_content_integration.xul
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/chrome-harness.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+ // Run the test in a separate window so that the test runs as a chrome
+ // window
+ var root = getRootDirectory(window.location.href);
+ window.open(root + "chrome_content_integration_window.xul", "chrome_content_integration",
+ "chrome,width=200,height=300");
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/test_chrome_over_plugin.xul b/layout/base/tests/chrome/test_chrome_over_plugin.xul
new file mode 100644
index 000000000..9d352bdfa
--- /dev/null
+++ b/layout/base/tests/chrome/test_chrome_over_plugin.xul
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+ // Run the test in a separate window so that the test runs as a chrome
+ // window
+ SpecialPowers.setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ var w = window.open("chrome_over_plugin_window.xul", "chrome_over_plugin",
+ "chrome,width=200,height=300");
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/test_default_background.xul b/layout/base/tests/chrome/test_default_background.xul
new file mode 100644
index 000000000..e278e58b6
--- /dev/null
+++ b/layout/base/tests/chrome/test_default_background.xul
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+ // Run the test in a separate window so that the test runs as a chrome
+ // window
+ window.open("default_background_window.xul", "default_background",
+ "chrome,width=200,height=300");
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/test_dialog_with_positioning.html b/layout/base/tests/chrome/test_dialog_with_positioning.html
new file mode 100644
index 000000000..048197a42
--- /dev/null
+++ b/layout/base/tests/chrome/test_dialog_with_positioning.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test positioning of fixed-pos/abs-pos elements in a XUL dialog</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var root = getRootDirectory(window.location.href);
+window.openDialog(root + "dialog_with_positioning_window.xul", "dialog_with_positioning",
+ "dialog,chrome");
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_fixed_bg_scrolling_repaints.html b/layout/base/tests/chrome/test_fixed_bg_scrolling_repaints.html
new file mode 100644
index 000000000..0cd9b9abb
--- /dev/null
+++ b/layout/base/tests/chrome/test_fixed_bg_scrolling_repaints.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that we don't get unnecessary repaints with fixed backgrounds</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<!-- Need a timeout here to allow paint unsuppression before we start the test -->
+<body onload="setTimeout(startTest,0)" style="background:url(blue-32x32.png) top left no-repeat fixed; background-size: 100px 2000px; overflow:hidden;">
+<div style="height: 2048px"></div>
+
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+function startTest() {
+ // Do a scroll to ensure we trigger activity heuristics.
+ document.documentElement.scrollTop = 1;
+ waitForAllPaintsFlushed(function () {
+ document.documentElement.scrollTop = 0;
+ waitForAllPaintsFlushed(function () {
+ // Clear paint state and scroll down
+ utils.checkAndClearPaintedState(document.documentElement);
+ document.documentElement.scrollTop = 100;
+ waitForAllPaintsFlushed(function () {
+ // Make sure nothing painted
+ var painted = utils.checkAndClearPaintedState(document.documentElement);
+ is(painted, false, "Fixed background should not have been painted when scrolled");
+ SimpleTest.finish();
+ });
+ });
+ });
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_leaf_layers_partition_browser_window.xul b/layout/base/tests/chrome/test_leaf_layers_partition_browser_window.xul
new file mode 100644
index 000000000..c3cce54e5
--- /dev/null
+++ b/layout/base/tests/chrome/test_leaf_layers_partition_browser_window.xul
@@ -0,0 +1,114 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ var winLowerThanVista = navigator.platform.indexOf("Win") == 0;
+ if (winLowerThanVista) {
+ var version = Components.classes["@mozilla.org/system-info;1"]
+ .getService(Components.interfaces.nsIPropertyBag2)
+ .getProperty("version");
+ winLowerThanVista = parseFloat(version) < 6.0;
+ }
+
+ var tests = [{maximize: false}, {maximize: true}];
+ var testIndex = 0;
+ var win;
+
+ function testInfo() {
+ return tests[testIndex].maximize ? " (maximized)" : " (non-maximized)";
+ }
+
+ function doTest(evt) {
+ var initialCount = win.mozPaintCount;
+
+ function nextStep() {
+ if (win.mozPaintCount == initialCount || win.isMozAfterPaintPending) {
+ SimpleTest.info("Waiting for mozPaintCount (= " + initialCount + ") to increase" + testInfo());
+ // Do not use SimpleTest.executeSoon() here: give a little more time.
+ setTimeout(nextStep, 100);
+ return;
+ }
+
+ isnot(win.mozPaintCount, initialCount, "mozPaintCount has increased" + testInfo());
+
+ function testLeafLayersPartitionWindow() {
+ var success = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindowUtils)
+ .leafLayersPartitionWindow();
+ // "[leafLayersPartitionWindow()] Always returns true in non-DEBUG builds."
+ // To prevent random failures on Windows, try to run this again after a timeout.
+ if (!success && navigator.platform.indexOf("Win") >= 0) {
+ setTimeout(testLeafLayersPartitionWindow, 100);
+ return;
+ }
+ ok(success,
+ "Leaf layers should form a non-overlapping partition of the browser window" + testInfo() +
+ (success ? "" : ". [Set MOZ_DUMP_PAINT_LIST=1 env var to investigate.]"));
+
+ win.close();
+ ++testIndex;
+ nextTest();
+ }
+ testLeafLayersPartitionWindow();
+ }
+
+ if (tests[testIndex].maximize) {
+ function resizeListener() {
+ win.removeEventListener("resize", resizeListener, true);
+ // We want a paint after resize.
+ initialCount = win.mozPaintCount;
+ SimpleTest.executeSoon(nextStep);
+ }
+ win.addEventListener("resize", resizeListener, true);
+ SimpleTest.info("Maximizing test " + testIndex + " window" + testInfo());
+ Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator)
+ .getMostRecentWindow("navigator:browser")
+ .maximize();
+ } else {
+ SimpleTest.executeSoon(nextStep);
+ }
+ }
+
+ function nextTest() {
+ if (testIndex >= tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ if (winLowerThanVista && !tests[testIndex].maximize) {
+ ok(true, "Skipping non-maximized test " + testIndex + " on winLowerThanVista since the resizer causes overlapping layers");
+ ++testIndex;
+ nextTest();
+ return;
+ }
+
+ window.focus();
+ // Run the test in a separate window so we get a clean browser window.
+ win = window.open("data:text/html,<html style='overflow:scroll'>",
+ "", "scrollbars=yes,toolbar,menubar,width=500,height=500");
+ setTimeout(setupWindow, 0);
+ }
+
+ function setupWindow() {
+ win.addEventListener("load", doTest, false);
+ win.focus();
+ }
+
+ nextTest();
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/test_no_clip_iframe.xul b/layout/base/tests/chrome/test_no_clip_iframe.xul
new file mode 100644
index 000000000..b8e74d8ea
--- /dev/null
+++ b/layout/base/tests/chrome/test_no_clip_iframe.xul
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+ // Run the test in a separate window so that the test runs as a chrome
+ // window
+ window.open("no_clip_iframe_window.xul", "no_clip_iframe",
+ "chrome,width=200,height=400");
+ ]]>
+ </script>
+</window>
diff --git a/layout/base/tests/chrome/test_prerendered_transforms.html b/layout/base/tests/chrome/test_prerendered_transforms.html
new file mode 100644
index 000000000..86893303a
--- /dev/null
+++ b/layout/base/tests/chrome/test_prerendered_transforms.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that active transformed elements coming into view are prerendered so we don't have to redraw constantly</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body onload="startTest()">
+<div>
+<div id="t" style="position:absolute; left:0; top:500px; -moz-transform: translatex(-100px); width:200px; height:100px; background:yellow;">
+ <div style="text-align:right">Hello</div>
+ <div style="text-align:left">Kitty</div>
+</div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var t = document.getElementById("t");
+var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+function startTest() {
+ // Do a couple of transform changes to ensure we've triggered activity heuristics
+ waitForAllPaintsFlushed(function () {
+ t.style.MozTransform = "translatex(-75px)";
+ waitForAllPaintsFlushed(function () {
+ t.style.MozTransform = "translatex(-50px)";
+ waitForAllPaintsFlushed(function () {
+ // Clear paint state now and move again.
+ utils.checkAndClearPaintedState(t);
+ // Don't move to 0 since that might trigger some special case that turns off transforms.
+ t.style.MozTransform = "translatex(-1px)";
+ waitForAllPaintsFlushed(function () {
+ var painted = utils.checkAndClearPaintedState(t);
+ is(painted, false, "Transformed element should not have been painted");
+ SimpleTest.finish();
+ });
+ });
+ });
+ });
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_printpreview.xul b/layout/base/tests/chrome/test_printpreview.xul
new file mode 100644
index 000000000..6a63791f2
--- /dev/null
+++ b/layout/base/tests/chrome/test_printpreview.xul
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<body xmlns="http://www.w3.org/1999/xhtml">
+</body>
+ <!-- test code goes here -->
+<script type="application/javascript">
+<![CDATA[
+SimpleTest.waitForExplicitFinish();
+window.open("printpreview_helper.xul", "printpreview", "chrome,width=100,height=100");
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/test_printpreview_bug396024.xul b/layout/base/tests/chrome/test_printpreview_bug396024.xul
new file mode 100644
index 000000000..eb086d35a
--- /dev/null
+++ b/layout/base/tests/chrome/test_printpreview_bug396024.xul
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=396024
+-->
+<window title="Mozilla Bug 369024"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=396024"
+ target="_blank">Mozilla Bug 396024</a>
+</body>
+ <!-- test code goes here -->
+<script type="application/javascript">
+<![CDATA[
+SimpleTest.waitForExplicitFinish();
+window.open("printpreview_bug396024_helper.xul", "bug396024", "chrome,width=100,height=100");
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/test_printpreview_bug482976.xul b/layout/base/tests/chrome/test_printpreview_bug482976.xul
new file mode 100644
index 000000000..52918d5ba
--- /dev/null
+++ b/layout/base/tests/chrome/test_printpreview_bug482976.xul
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=482976
+-->
+<window title="Mozilla Bug 482976"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=482976"
+ target="_blank">Mozilla Bug 482976</a>
+</body>
+ <!-- test code goes here -->
+<script type="application/javascript">
+<![CDATA[
+SimpleTest.waitForExplicitFinish();
+window.open("printpreview_bug482976_helper.xul", "bug482976", "chrome,width=100,height=100");
+]]></script>
+</window>
diff --git a/layout/base/tests/chrome/test_scrolling_repaints.html b/layout/base/tests/chrome/test_scrolling_repaints.html
new file mode 100644
index 000000000..ff62aa5db
--- /dev/null
+++ b/layout/base/tests/chrome/test_scrolling_repaints.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that we don't get unnecessary repaints due to subpixel shifts</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<!-- Need a timeout here to allow paint unsuppression before we start the test -->
+<body onload="setTimeout(startTest,0)">
+<div id="t" style="width:400px; height:100px; background:yellow; overflow:hidden">
+ <div style="height:40px;"></div>
+ <div id="e" style="height:30px; background:lime"></div>
+ <div style="height:60.4px; background:pink"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var t = document.getElementById("t");
+var e = document.getElementById("e");
+var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+function startTest() {
+ // Do a scroll to ensure we trigger activity heuristics.
+ waitForAllPaintsFlushed(function () {
+ t.scrollTop = 5;
+ // Scroll down as far as we can, to put our rendering layer at a subpixel offset within the layer
+ waitForAllPaintsFlushed(function () {
+ t.scrollTop = 1000;
+ waitForAllPaintsFlushed(function () {
+ // Clear paint state now and scroll again.
+ utils.checkAndClearPaintedState(e);
+ // scroll up a little bit. This should not cause anything to be repainted.
+ t.scrollTop = t.scrollTop - 10;
+ waitForAllPaintsFlushed(function () {
+ var painted = utils.checkAndClearPaintedState(e);
+ is(painted, false, "Fully-visible scrolled element should not have been painted");
+ SimpleTest.finish();
+ });
+ });
+ });
+ });
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/chrome/test_will_change.html b/layout/base/tests/chrome/test_will_change.html
new file mode 100644
index 000000000..fb8122b0b
--- /dev/null
+++ b/layout/base/tests/chrome/test_will_change.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Tests for MozAfterPaint</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
+ <style>
+ #checkOpacityRepaint {
+ will-change: opacity;
+ }
+ #checkTransformRepaint {
+ will-change: transform;
+ }
+ div {
+ width: 100px;
+ height: 100px;
+ background: radial-gradient(ellipse at center, #87e0fd 0%,#53cbf1 40%,#05abe0 100%);
+ }
+ </style>
+</head>
+<body>
+ <div id="checkRepaint">
+ Check repaint without will-change
+ </div>
+ <div id="checkOpacityRepaint">
+ Check repaint with will-change
+ </div>
+ <div id="checkTransformRepaint">
+ Check repaint with will-change
+ </div>
+</body>
+<script>
+
+var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+var initialPaintCount = 0;
+
+function test_checkRepaint(next) {
+ var element = document.getElementById("checkRepaint");
+ waitForAllPaintsFlushed(function () {
+ utils.checkAndClearPaintedState(element);
+ element.style.opacity = "0.5";
+ waitForAllPaintsFlushed(function () {
+ var painted = utils.checkAndClearPaintedState(element);
+ // *** We check that this repaints because the test is relying
+ // on this property. If this is broken then this test wont
+ // be reliable check for will-change.
+ is(painted, true, "element should have been painted");
+ next();
+ });
+ });
+}
+
+function test_checkOpacityRepaint(next) {
+ var element = document.getElementById("checkOpacityRepaint");
+ waitForAllPaintsFlushed(function () {
+ utils.checkAndClearPaintedState(element);
+ element.style.opacity = "0.5";
+ waitForAllPaintsFlushed(function () {
+ var painted = utils.checkAndClearPaintedState(element);
+ // BasicLayers' heuristics are so that even with will-change:opacity,
+ // we can still have repaints.
+ if (utils.layerManagerType != "Basic") {
+ is(painted, false, "will-change checkOpacityRepaint element should not have been painted");
+ }
+ next();
+ });
+ });
+}
+
+function test_checkTransformRepaint(next) {
+ var element = document.getElementById("checkTransformRepaint");
+ waitForAllPaintsFlushed(function () {
+ utils.checkAndClearPaintedState(element);
+ element.style.transform = "translateY(-5px)";
+ waitForAllPaintsFlushed(function () {
+ var painted = utils.checkAndClearPaintedState(element);
+ // BasicLayers' heuristics are so that even with will-change:transform,
+ // we can still have repaints.
+ if (utils.layerManagerType != "Basic") {
+ is(painted, false, "will-change checkTransformRepaint element should not have been painted");
+ }
+ next();
+ });
+ });
+}
+
+SimpleTest.waitForExplicitFinish();
+test_checkRepaint(function(){
+ test_checkOpacityRepaint(function(){
+ test_checkTransformRepaint(function(){
+ SimpleTest.finish();
+ });
+ });
+});
+
+</script>
+</html>
diff --git a/layout/base/tests/file_bug607529.html b/layout/base/tests/file_bug607529.html
new file mode 100644
index 000000000..9fbd7f393
--- /dev/null
+++ b/layout/base/tests/file_bug607529.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<script>
+ window.onerror = function(msg, url, line) {
+ var myMsg = JSON.stringify({msg: msg, url: url, line: line, error: true});
+ opener.postMessage(myMsg, "*");
+ }
+
+ var report = false;
+
+ function g() {
+ if (report) {
+ opener.postMessage("callbackHappened", "*");
+ }
+ window.requestAnimationFrame(g);
+ }
+ g();
+
+ window.onload = function() {
+ opener.postMessage("loaded", "*");
+ }
+
+ addEventListener("pagehide", function f(e) {
+ if (!e.persisted && !report) {
+ opener.postMessage("notcached", "*");
+ }
+ }, false);
+
+ addEventListener("pageshow", function f(e) {
+ if (e.persisted) {
+ opener.postMessage("revived", "*");
+ }
+ }, false);
+
+ window.onmessage = function (e) {
+ if (e.data == "report") {
+ report = true;
+ }
+ };
+
+</script>
diff --git a/layout/base/tests/file_bug842853.html b/layout/base/tests/file_bug842853.html
new file mode 100644
index 000000000..12bb56506
--- /dev/null
+++ b/layout/base/tests/file_bug842853.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcase for bug </title>
+<link rel="stylesheet" href="file_bug842853.sjs">
+</head>
+<body>
+
+<a href="#anchor">Click to scroll to anchor</a><div style="height:5000px"></div><a name="anchor">FAIL</a>
+<script>window.parent.runTest()</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/file_bug842853.sjs b/layout/base/tests/file_bug842853.sjs
new file mode 100644
index 000000000..1586aaf48
--- /dev/null
+++ b/layout/base/tests/file_bug842853.sjs
@@ -0,0 +1,14 @@
+var timer;
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache, must-revalidate", false);
+ response.setHeader("Content-Type", "text/css", false);
+ response.write("body { background:lime; color:red; }");
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.finish();
+ }, 500, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
diff --git a/layout/base/tests/image_rgrg-256x256.png b/layout/base/tests/image_rgrg-256x256.png
new file mode 100644
index 000000000..e6fba3daa
--- /dev/null
+++ b/layout/base/tests/image_rgrg-256x256.png
Binary files differ
diff --git a/layout/base/tests/image_rrgg-256x256.png b/layout/base/tests/image_rrgg-256x256.png
new file mode 100644
index 000000000..7f6351565
--- /dev/null
+++ b/layout/base/tests/image_rrgg-256x256.png
Binary files differ
diff --git a/layout/base/tests/input-invalid-ref.html b/layout/base/tests/input-invalid-ref.html
new file mode 100644
index 000000000..4b34c9a2f
--- /dev/null
+++ b/layout/base/tests/input-invalid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <input value="foo" style="background-color:red">
+ </body>
+</html>
+
diff --git a/layout/base/tests/input-maxlength-invalid-change.html b/layout/base/tests/input-maxlength-invalid-change.html
new file mode 100644
index 000000000..4056682a4
--- /dev/null
+++ b/layout/base/tests/input-maxlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with maxlength is invalid if the user edits and it's too long -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" maxlength="2" value="fooo">
+ </body>
+</html>
diff --git a/layout/base/tests/input-maxlength-ui-invalid-change.html b/layout/base/tests/input-maxlength-ui-invalid-change.html
new file mode 100644
index 000000000..609838f16
--- /dev/null
+++ b/layout/base/tests/input-maxlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with maxlength is -moz-ui-invalid if the user edits and it's too long -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" maxlength="2" value="fooo">
+ </body>
+</html>
diff --git a/layout/base/tests/input-maxlength-ui-valid-change.html b/layout/base/tests/input-maxlength-ui-valid-change.html
new file mode 100644
index 000000000..4cd332182
--- /dev/null
+++ b/layout/base/tests/input-maxlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with maxlength is -moz-ui-valid if the user edits and it's not too long -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+ input.blur();
+ input.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" maxlength="3" value="foooo">
+ </body>
+</html>
diff --git a/layout/base/tests/input-maxlength-valid-before-change.html b/layout/base/tests/input-maxlength-valid-before-change.html
new file mode 100644
index 000000000..8662e8f5f
--- /dev/null
+++ b/layout/base/tests/input-maxlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with maxlength is valid until the user edits it, even if it's too long -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ </head>
+ <body onload="document.documentElement.className=''">
+ <input id="input" maxlength="2" value="foo">
+ </body>
+</html>
+
diff --git a/layout/base/tests/input-maxlength-valid-change.html b/layout/base/tests/input-maxlength-valid-change.html
new file mode 100644
index 000000000..bf02a8040
--- /dev/null
+++ b/layout/base/tests/input-maxlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with maxlength is valid if the user edits and it's not too long -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+ input.blur();
+ input.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" maxlength="3" value="foooo">
+ </body>
+</html>
diff --git a/layout/base/tests/input-minlength-invalid-change.html b/layout/base/tests/input-minlength-invalid-change.html
new file mode 100644
index 000000000..cc2107e3d
--- /dev/null
+++ b/layout/base/tests/input-minlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with minlength is invalid if the user edits and it's too short -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('o', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" minlength="4" value="fo">
+ </body>
+</html>
diff --git a/layout/base/tests/input-minlength-ui-invalid-change.html b/layout/base/tests/input-minlength-ui-invalid-change.html
new file mode 100644
index 000000000..cf00703ad
--- /dev/null
+++ b/layout/base/tests/input-minlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with minlength is -moz-ui-invalid if the user edits and it's too short -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('o', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" minlength="4" value="fo">
+ </body>
+</html>
diff --git a/layout/base/tests/input-minlength-ui-valid-change.html b/layout/base/tests/input-minlength-ui-valid-change.html
new file mode 100644
index 000000000..830c4acfa
--- /dev/null
+++ b/layout/base/tests/input-minlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with minlength is -moz-ui-valid if the user edits and it's not too short -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('o', {}); // so that it becomes invalid first
+ input.blur();
+ input.focus();
+ synthesizeKey('o', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" minlength="3" value="f">
+ </body>
+</html>
diff --git a/layout/base/tests/input-minlength-valid-before-change.html b/layout/base/tests/input-minlength-valid-before-change.html
new file mode 100644
index 000000000..21e692792
--- /dev/null
+++ b/layout/base/tests/input-minlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with minlength is valid until the user edits it, even if it's too short -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ </head>
+ <body onload="document.documentElement.className=''">
+ <input id="input" minlength="5" value="foo">
+ </body>
+</html>
+
diff --git a/layout/base/tests/input-minlength-valid-change.html b/layout/base/tests/input-minlength-valid-change.html
new file mode 100644
index 000000000..40a282682
--- /dev/null
+++ b/layout/base/tests/input-minlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: input with minlength is valid if the user edits and it's not too short -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var input = document.getElementById('input');
+ input.setSelectionRange(input.value.length, input.value.length)
+ input.focus();
+ synthesizeKey('o', {}); // so that it becomes invalid first
+ input.blur();
+ input.focus();
+ synthesizeKey('o', {});
+ input.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <input id="input" minlength="3" value="f">
+ </body>
+</html>
diff --git a/layout/base/tests/input-ui-valid-ref.html b/layout/base/tests/input-ui-valid-ref.html
new file mode 100644
index 000000000..76d938667
--- /dev/null
+++ b/layout/base/tests/input-ui-valid-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <input value="foo" style="background-color:green">
+ </body>
+</html>
diff --git a/layout/base/tests/input-valid-ref.html b/layout/base/tests/input-valid-ref.html
new file mode 100644
index 000000000..ec01bb98f
--- /dev/null
+++ b/layout/base/tests/input-valid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <input value="foo" style="background-color:green">
+ </body>
+</html>
+
diff --git a/layout/base/tests/marionette/manifest.ini b/layout/base/tests/marionette/manifest.ini
new file mode 100644
index 000000000..98428ccf5
--- /dev/null
+++ b/layout/base/tests/marionette/manifest.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+run-if = buildapp == 'browser'
+
+[test_accessiblecaret_cursor_mode.py]
+[test_accessiblecaret_selection_mode.py]
diff --git a/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
new file mode 100644
index 000000000..e330e4d70
--- /dev/null
+++ b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
@@ -0,0 +1,298 @@
+# -*- coding: utf-8 -*-
+# 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/.
+
+import string
+
+from marionette_driver.by import By
+from marionette_driver.marionette import Actions
+from marionette_driver.selection import SelectionManager
+from marionette_harness.marionette_test import (
+ MarionetteTestCase,
+ parameterized,
+)
+
+
+class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
+ '''Test cases for AccessibleCaret under cursor mode.
+
+ We call the blinking cursor (nsCaret) as cursor, and call AccessibleCaret as
+ caret for short.
+
+ '''
+ # Element IDs.
+ _input_id = 'input'
+ _input_padding_id = 'input-padding'
+ _textarea_id = 'textarea'
+ _textarea_one_line_id = 'textarea-one-line'
+ _contenteditable_id = 'contenteditable'
+
+ # Test html files.
+ _cursor_html = 'test_carets_cursor.html'
+
+ def setUp(self):
+ # Code to execute before every test is running.
+ super(AccessibleCaretCursorModeTestCase, self).setUp()
+ self.caret_tested_pref = 'layout.accessiblecaret.enabled'
+ self.caret_timeout_ms_pref = 'layout.accessiblecaret.timeout_ms'
+ self.hide_carets_for_mouse = 'layout.accessiblecaret.hide_carets_for_mouse_input'
+ self.prefs = {
+ self.caret_tested_pref: True,
+ self.caret_timeout_ms_pref: 0,
+ self.hide_carets_for_mouse: False,
+ }
+ self.marionette.set_prefs(self.prefs)
+ self.actions = Actions(self.marionette)
+
+ def open_test_html(self, test_html):
+ self.marionette.navigate(self.marionette.absolute_url(test_html))
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_move_cursor_to_the_right_by_one_character(self, el_id):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ target_content = sel.content
+ target_content = target_content[:1] + content_to_add + target_content[1:]
+
+ # Get first caret (x, y) at position 1 and 2.
+ el.tap()
+ sel.move_cursor_to_front()
+ cursor0_x, cursor0_y = sel.cursor_location()
+ first_caret0_x, first_caret0_y = sel.first_caret_location()
+ sel.move_cursor_by_offset(1)
+ first_caret1_x, first_caret1_y = sel.first_caret_location()
+
+ # Tap the front of the input to make first caret appear.
+ el.tap(cursor0_x, cursor0_y)
+
+ # Move first caret.
+ self.actions.flick(el, first_caret0_x, first_caret0_y,
+ first_caret1_x, first_caret1_y).perform()
+
+ self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+ self.assertEqual(target_content, sel.content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_move_cursor_to_end_by_dragging_caret_to_bottom_right_corner(self, el_id):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ target_content = sel.content + content_to_add
+
+ # Tap the front of the input to make first caret appear.
+ el.tap()
+ sel.move_cursor_to_front()
+ el.tap(*sel.cursor_location())
+
+ # Move first caret to the bottom-right corner of the element.
+ src_x, src_y = sel.first_caret_location()
+ dest_x, dest_y = el.size['width'], el.size['height']
+ self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
+
+ self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+ self.assertEqual(target_content, sel.content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_move_cursor_to_front_by_dragging_caret_to_front(self, el_id):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ target_content = content_to_add + sel.content
+
+ # Get first caret location at the front.
+ el.tap()
+ sel.move_cursor_to_front()
+ dest_x, dest_y = sel.first_caret_location()
+
+ # Tap to make first caret appear. Note: it's strange that when the caret
+ # is at the end, the rect of the caret in <textarea> cannot be obtained.
+ # A bug perhaps.
+ el.tap()
+ sel.move_cursor_to_end()
+ sel.move_cursor_by_offset(1, backward=True)
+ el.tap(*sel.cursor_location())
+ src_x, src_y = sel.first_caret_location()
+
+ # Move first caret to the front of the input box.
+ self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
+
+ self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+ self.assertEqual(target_content, sel.content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_dragging_caret_to_top_left_corner_after_timeout(self, el_id):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ non_target_content = content_to_add + sel.content
+
+ # Set caret timeout to be 1 second.
+ timeout = 1
+ self.marionette.set_pref(self.caret_timeout_ms_pref, timeout * 1000)
+
+ # Set a 3x timeout margin to prevent intermittent test failures.
+ timeout *= 3
+
+ # Tap to make first caret appear. Note: it's strange that when the caret
+ # is at the end, the rect of the caret in <textarea> cannot be obtained.
+ # A bug perhaps.
+ el.tap()
+ sel.move_cursor_to_end()
+ sel.move_cursor_by_offset(1, backward=True)
+ el.tap(*sel.cursor_location())
+
+ # Wait until first caret disappears, then pretend to move it to the
+ # top-left corner of the input box.
+ src_x, src_y = sel.first_caret_location()
+ dest_x, dest_y = 0, 0
+ self.actions.wait(timeout).flick(el, src_x, src_y, dest_x, dest_y).perform()
+
+ self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+ self.assertNotEqual(non_target_content, sel.content)
+
+ def test_caret_not_appear_when_typing_in_scrollable_content(self):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, self._input_id)
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ non_target_content = content_to_add + sel.content + string.ascii_letters
+
+ el.tap()
+ sel.move_cursor_to_end()
+
+ # Insert a long string to the end of the <input>, which triggers
+ # ScrollPositionChanged event.
+ el.send_keys(string.ascii_letters)
+
+ # The caret should not be visible. If it does appear wrongly due to the
+ # ScrollPositionChanged event, we can drag it to the front of the
+ # <input> to change the cursor position.
+ src_x, src_y = sel.first_caret_location()
+ dest_x, dest_y = 0, 0
+ self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
+
+ # The content should not be inserted at the front of the <input>.
+ el.send_keys(content_to_add)
+
+ self.assertNotEqual(non_target_content, sel.content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_input_padding_id, el_id=_input_padding_id)
+ @parameterized(_textarea_one_line_id, el_id=_textarea_one_line_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_caret_not_jump_when_dragging_to_editable_content_boundary(self, el_id):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ non_target_content = sel.content + content_to_add
+
+ # Goal: the cursor position is not changed after dragging the caret down
+ # on the Y-axis.
+ el.tap()
+ sel.move_cursor_to_front()
+ el.tap(*sel.cursor_location())
+ x, y = sel.first_caret_location()
+
+ # Drag the caret down by 50px, and insert '!'.
+ self.actions.flick(el, x, y, x, y + 50).perform()
+ self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+ self.assertNotEqual(non_target_content, sel.content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_input_padding_id, el_id=_input_padding_id)
+ @parameterized(_textarea_one_line_id, el_id=_textarea_one_line_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_caret_not_jump_to_front_when_dragging_up_to_editable_content_boundary(self, el_id):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ non_target_content = content_to_add + sel.content
+
+ # Goal: the cursor position is not changed after dragging the caret down
+ # on the Y-axis.
+ el.tap()
+ sel.move_cursor_to_end()
+ sel.move_cursor_by_offset(1, backward=True)
+ el.tap(*sel.cursor_location())
+ x, y = sel.first_caret_location()
+
+ # Drag the caret up by 50px, and insert '!'.
+ self.actions.flick(el, x, y, x, y - 50).perform()
+ self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+ self.assertNotEqual(non_target_content, sel.content)
+
+ def test_drag_caret_from_front_to_end_across_columns(self):
+ self.open_test_html('test_carets_columns.html')
+ el = self.marionette.find_element(By.ID, 'columns-inner')
+ sel = SelectionManager(el)
+ content_to_add = '!'
+ target_content = sel.content + content_to_add
+
+ # Goal: the cursor position can be changed by dragging the caret from
+ # the front to the end of the content.
+
+ # Tap to make the cursor appear.
+ before_image_1 = self.marionette.find_element(By.ID, 'before-image-1')
+ before_image_1.tap()
+
+ # Tap the front of the content to make first caret appear.
+ sel.move_cursor_to_front()
+ el.tap(*sel.cursor_location())
+ src_x, src_y = sel.first_caret_location()
+ dest_x, dest_y = el.size['width'], el.size['height']
+
+ # Drag the first caret to the bottom-right corner of the element.
+ self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
+
+ self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+ self.assertEqual(target_content, sel.content)
+
+ def test_move_cursor_to_front_by_dragging_caret_to_front_br_element(self):
+ self.open_test_html(self._cursor_html)
+ el = self.marionette.find_element(By.ID, self._contenteditable_id)
+ sel = SelectionManager(el)
+ content_to_add_1 = '!'
+ content_to_add_2 = '\n\n'
+ target_content = content_to_add_1 + content_to_add_2 + sel.content
+
+ # Goal: the cursor position can be changed by dragging the caret from
+ # the end of the content to the front br element. Because we cannot get
+ # caret location if it's on a br element, we need to get the first caret
+ # location then adding the new lines.
+
+ # Get first caret location at the front.
+ el.tap()
+ sel.move_cursor_to_front()
+ dest_x, dest_y = sel.first_caret_location()
+
+ # Append new line to the front of the content.
+ el.send_keys(content_to_add_2);
+
+ # Tap to make first caret appear.
+ el.tap()
+ sel.move_cursor_to_end()
+ sel.move_cursor_by_offset(1, backward=True)
+ el.tap(*sel.cursor_location())
+ src_x, src_y = sel.first_caret_location()
+
+ # Move first caret to the front of the input box.
+ self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
+
+ self.actions.key_down(content_to_add_1).key_up(content_to_add_1).perform()
+ self.assertEqual(target_content, sel.content)
diff --git a/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py b/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
new file mode 100644
index 000000000..2cc93dd74
--- /dev/null
+++ b/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
@@ -0,0 +1,632 @@
+# -*- coding: utf-8 -*-
+# 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/.
+
+import re
+
+from marionette_driver.by import By
+from marionette_driver.marionette import Actions
+from marionette_driver.selection import SelectionManager
+from marionette_harness.marionette_test import (
+ MarionetteTestCase,
+ SkipTest,
+ parameterized
+)
+
+
+def skip_if_not_rotatable(target):
+ def wrapper(self, *args, **kwargs):
+ if not self.marionette.session_capabilities.get('rotatable'):
+ raise SkipTest('skipping due to device not rotatable')
+ return target(self, *args, **kwargs)
+ return wrapper
+
+
+class AccessibleCaretSelectionModeTestCase(MarionetteTestCase):
+ '''Test cases for AccessibleCaret under selection mode.'''
+ # Element IDs.
+ _input_id = 'input'
+ _input_padding_id = 'input-padding'
+ _textarea_id = 'textarea'
+ _textarea2_id = 'textarea2'
+ _textarea_one_line_id = 'textarea-one-line'
+ _textarea_rtl_id = 'textarea-rtl'
+ _contenteditable_id = 'contenteditable'
+ _contenteditable2_id = 'contenteditable2'
+ _content_id = 'content'
+ _content2_id = 'content2'
+ _non_selectable_id = 'non-selectable'
+
+ # Test html files.
+ _selection_html = 'test_carets_selection.html'
+ _multipleline_html = 'test_carets_multipleline.html'
+ _multiplerange_html = 'test_carets_multiplerange.html'
+ _longtext_html = 'test_carets_longtext.html'
+ _iframe_html = 'test_carets_iframe.html'
+ _display_none_html = 'test_carets_display_none.html'
+
+ def setUp(self):
+ # Code to execute before every test is running.
+ super(AccessibleCaretSelectionModeTestCase, self).setUp()
+ self.carets_tested_pref = 'layout.accessiblecaret.enabled'
+ self.prefs = {
+ 'layout.word_select.eat_space_to_next_word': False,
+ self.carets_tested_pref: True,
+ }
+ self.marionette.set_prefs(self.prefs)
+ self.actions = Actions(self.marionette)
+
+ def open_test_html(self, test_html):
+ self.marionette.navigate(self.marionette.absolute_url(test_html))
+
+ def word_offset(self, text, ordinal):
+ 'Get the character offset of the ordinal-th word in text.'
+ tokens = re.split(r'(\S+)', text) # both words and spaces
+ spaces = tokens[0::2] # collect spaces at odd indices
+ words = tokens[1::2] # collect word at even indices
+
+ if ordinal >= len(words):
+ raise IndexError('Only %d words in text, but got ordinal %d' %
+ (len(words), ordinal))
+
+ # Cursor position of the targeting word is behind the the first
+ # character in the word. For example, offset to 'def' in 'abc def' is
+ # between 'd' and 'e'.
+ offset = len(spaces[0]) + 1
+ offset += sum(len(words[i]) + len(spaces[i + 1]) for i in range(ordinal))
+ return offset
+
+ def test_word_offset(self):
+ text = ' ' * 3 + 'abc' + ' ' * 3 + 'def'
+
+ self.assertTrue(self.word_offset(text, 0), 4)
+ self.assertTrue(self.word_offset(text, 1), 10)
+ with self.assertRaises(IndexError):
+ self.word_offset(text, 2)
+
+ def word_location(self, el, ordinal):
+ '''Get the location (x, y) of the ordinal-th word in el.
+
+ The ordinal starts from 0.
+
+ Note: this function has a side effect which changes focus to the
+ target element el.
+
+ '''
+ sel = SelectionManager(el)
+ offset = self.word_offset(sel.content, ordinal)
+
+ # Move the blinking cursor to the word.
+ el.tap()
+ sel.move_cursor_to_front()
+ sel.move_cursor_by_offset(offset)
+ x, y = sel.cursor_location()
+
+ return x, y
+
+ def rect_relative_to_window(self, el):
+ '''Get element's bounding rectangle.
+
+ This function is similar to el.rect, but the coordinate is relative to
+ the top left corner of the window instead of the document.
+
+ '''
+ return self.marionette.execute_script('''
+ let rect = arguments[0].getBoundingClientRect();
+ return {x: rect.x, y:rect.y, width: rect.width, height: rect.height};
+ ''', script_args=[el])
+
+ def long_press_on_location(self, el, x=None, y=None):
+ '''Long press the location (x, y) to select a word.
+
+ If no (x, y) are given, it will be targeted at the center of the
+ element. On Windows, those spaces after the word will also be selected.
+ This function sends synthesized eMouseLongTap to gecko.
+
+ '''
+ rect = self.rect_relative_to_window(el)
+ target_x = rect['x'] + (x if x is not None else rect['width'] // 2)
+ target_y = rect['y'] + (y if y is not None else rect['height'] // 2)
+
+ self.marionette.execute_script('''
+ let Ci = Components.interfaces;
+ let utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ utils.sendTouchEventToWindow('touchstart', [0],
+ [arguments[0]], [arguments[1]],
+ [1], [1], [0], [1], 1, 0);
+ utils.sendMouseEventToWindow('mouselongtap', arguments[0], arguments[1],
+ 0, 1, 0);
+ utils.sendTouchEventToWindow('touchend', [0],
+ [arguments[0]], [arguments[1]],
+ [1], [1], [0], [1], 1, 0);
+ ''', script_args=[target_x, target_y], sandbox='system')
+
+ def long_press_on_word(self, el, wordOrdinal):
+ x, y = self.word_location(el, wordOrdinal)
+ self.long_press_on_location(el, x, y)
+
+ def to_unix_line_ending(self, s):
+ """Changes all Windows/Mac line endings in s to UNIX line endings."""
+
+ return s.replace('\r\n', '\n').replace('\r', '\n')
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ @parameterized(_content_id, el_id=_content_id)
+ def test_long_press_to_select_a_word(self, el_id):
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ self._test_long_press_to_select_a_word(el)
+
+ def _test_long_press_to_select_a_word(self, el):
+ sel = SelectionManager(el)
+ original_content = sel.content
+ words = original_content.split()
+ self.assertTrue(len(words) >= 2, 'Expect at least two words in the content.')
+ target_content = words[0]
+
+ # Goal: Select the first word.
+ self.long_press_on_word(el, 0)
+
+ # Ignore extra spaces selected after the word.
+ self.assertEqual(target_content, sel.selected_content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ @parameterized(_content_id, el_id=_content_id)
+ def test_drag_carets(self, el_id):
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ original_content = sel.content
+ words = original_content.split()
+ self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
+
+ # Goal: Select all text after the first word.
+ target_content = original_content[len(words[0]):]
+
+ # Get the location of the carets at the end of the content for later
+ # use.
+ el.tap()
+ sel.select_all()
+ end_caret_x, end_caret_y = sel.second_caret_location()
+
+ self.long_press_on_word(el, 0)
+
+ # Drag the second caret to the end of the content.
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform()
+
+ # Drag the first caret to the previous position of the second caret.
+ self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform()
+
+ self.assertEqual(target_content, sel.selected_content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ @parameterized(_content_id, el_id=_content_id)
+ def test_drag_swappable_carets(self, el_id):
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ original_content = sel.content
+ words = original_content.split()
+ self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
+
+ target_content1 = words[0]
+ target_content2 = original_content[len(words[0]):]
+
+ # Get the location of the carets at the end of the content for later
+ # use.
+ el.tap()
+ sel.select_all()
+ end_caret_x, end_caret_y = sel.second_caret_location()
+
+ self.long_press_on_word(el, 0)
+
+ # Drag the first caret to the end and back to where it was
+ # immediately. The selection range should not be collapsed.
+ caret1_x, caret1_y = sel.first_caret_location()
+ self.actions.flick(el, caret1_x, caret1_y, end_caret_x, end_caret_y)\
+ .flick(el, end_caret_x, end_caret_y, caret1_x, caret1_y).perform()
+ self.assertEqual(target_content1, sel.selected_content)
+
+ # Drag the first caret to the end.
+ caret1_x, caret1_y = sel.first_caret_location()
+ self.actions.flick(el, caret1_x, caret1_y, end_caret_x, end_caret_y).perform()
+ self.assertEqual(target_content2, sel.selected_content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ @parameterized(_content_id, el_id=_content_id)
+ def test_minimum_select_one_character(self, el_id):
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ self._test_minimum_select_one_character(el)
+
+ @parameterized(_textarea2_id, el_id=_textarea2_id)
+ @parameterized(_contenteditable2_id, el_id=_contenteditable2_id)
+ @parameterized(_content2_id, el_id=_content2_id)
+ def test_minimum_select_one_character2(self, el_id):
+ self.open_test_html(self._multipleline_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ self._test_minimum_select_one_character(el)
+
+ def _test_minimum_select_one_character(self, el, x=None, y=None):
+ sel = SelectionManager(el)
+ original_content = sel.content
+ words = original_content.split()
+ self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
+
+ # Get the location of the carets at the end of the content for later
+ # use.
+ sel.select_all()
+ end_caret_x, end_caret_y = sel.second_caret_location()
+ el.tap()
+
+ # Goal: Select the first character.
+ target_content = original_content[0]
+
+ if x and y:
+ # If we got x and y from the arguments, use it as a hint of the
+ # location of the first word
+ pass
+ else:
+ x, y = self.word_location(el, 0)
+ self.long_press_on_location(el, x, y)
+
+ # Drag the second caret to the end of the content.
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform()
+
+ # Drag the second caret to the position of the first caret.
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform()
+
+ self.assertEqual(target_content, sel.selected_content)
+
+ @parameterized(_input_id + '_to_' + _textarea_id,
+ el1_id=_input_id, el2_id=_textarea_id)
+ @parameterized(_input_id + '_to_' + _contenteditable_id,
+ el1_id=_input_id, el2_id=_contenteditable_id)
+ @parameterized(_input_id + '_to_' + _content_id,
+ el1_id=_input_id, el2_id=_content_id)
+ @parameterized(_textarea_id + '_to_' + _input_id,
+ el1_id=_textarea_id, el2_id=_input_id)
+ @parameterized(_textarea_id + '_to_' + _contenteditable_id,
+ el1_id=_textarea_id, el2_id=_contenteditable_id)
+ @parameterized(_textarea_id + '_to_' + _content_id,
+ el1_id=_textarea_id, el2_id=_content_id)
+ @parameterized(_contenteditable_id + '_to_' + _input_id,
+ el1_id=_contenteditable_id, el2_id=_input_id)
+ @parameterized(_contenteditable_id + '_to_' + _textarea_id,
+ el1_id=_contenteditable_id, el2_id=_textarea_id)
+ @parameterized(_contenteditable_id + '_to_' + _content_id,
+ el1_id=_contenteditable_id, el2_id=_content_id)
+ @parameterized(_content_id + '_to_' + _input_id,
+ el1_id=_content_id, el2_id=_input_id)
+ @parameterized(_content_id + '_to_' + _textarea_id,
+ el1_id=_content_id, el2_id=_textarea_id)
+ @parameterized(_content_id + '_to_' + _contenteditable_id,
+ el1_id=_content_id, el2_id=_contenteditable_id)
+ def test_long_press_changes_focus_from(self, el1_id, el2_id):
+ '''Test the focus could be changed from el1 to el2 by long press.
+
+ If the focus is changed to e2 successfully, the carets should appear and
+ could be dragged.
+
+ '''
+ # Goal: Tap to focus el1, and then select the first character on
+ # el2.
+
+ # We want to collect the location of the first word in el2 here
+ # since self.word_location() has the side effect which would
+ # change the focus.
+ self.open_test_html(self._selection_html)
+ el1 = self.marionette.find_element(By.ID, el1_id)
+ el2 = self.marionette.find_element(By.ID, el2_id)
+ x, y = self.word_location(el2, 0)
+ el1.tap()
+ self._test_minimum_select_one_character(el2, x=x, y=y)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_focus_not_changed_by_long_press_on_non_selectable(self, el_id):
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ non_selectable = self.marionette.find_element(By.ID, self._non_selectable_id)
+
+ # Goal: Focus remains on the editable element el after long pressing on
+ # the non-selectable element.
+ sel = SelectionManager(el)
+ self.long_press_on_word(el, 0)
+ self.long_press_on_location(non_selectable)
+ active_sel = SelectionManager(self.marionette.get_active_element())
+ self.assertEqual(sel.content, active_sel.content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_textarea_id, el_id=_textarea_id)
+ @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ @parameterized(_content_id, el_id=_content_id)
+ def test_handle_tilt_when_carets_overlap_each_other(self, el_id):
+ '''Test tilt handling when carets overlap to each other.
+
+ Let the two carets overlap each other. If they are set to tilted
+ successfully, tapping the tilted carets should not cause the selection
+ to be collapsed and the carets should be draggable.
+
+ '''
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ original_content = sel.content
+ words = original_content.split()
+ self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
+
+ # Goal: Select the first word.
+ self.long_press_on_word(el, 0)
+ target_content = sel.selected_content
+
+ # Drag the first caret to the position of the second caret to trigger
+ # carets overlapping.
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform()
+
+ # We make two hit tests targeting the left edge of the left tilted caret
+ # and the right edge of the right tilted caret. If either of the hits is
+ # missed, selection would be collapsed and both carets should not be
+ # draggable.
+ (caret3_x, caret3_y), (caret4_x, caret4_y) = sel.carets_location()
+
+ # The following values are from ua.css and all.js
+ caret_width = float(self.marionette.get_pref('layout.accessiblecaret.width'))
+ caret_margin_left = float(self.marionette.get_pref('layout.accessiblecaret.margin-left'))
+ tilt_right_margin_left = 0.41 * caret_width
+ tilt_left_margin_left = -0.39 * caret_width
+
+ left_caret_left_edge_x = caret3_x + caret_margin_left + tilt_left_margin_left
+ el.tap(left_caret_left_edge_x + 2, caret3_y)
+
+ right_caret_right_edge_x = (caret4_x + caret_margin_left +
+ tilt_right_margin_left + caret_width)
+ el.tap(right_caret_right_edge_x - 2, caret4_y)
+
+ # Drag the first caret back to the initial selection, the first word.
+ self.actions.flick(el, caret3_x, caret3_y, caret1_x, caret1_y).perform()
+
+ self.assertEqual(target_content, sel.selected_content)
+
+ def test_drag_caret_over_non_selectable_field(self):
+ '''Test dragging the caret over a non-selectable field.
+
+ The selected content should exclude non-selectable elements and the
+ second caret should appear in last range's position.
+
+ '''
+ self.open_test_html(self._multiplerange_html)
+ body = self.marionette.find_element(By.ID, 'bd')
+ sel3 = self.marionette.find_element(By.ID, 'sel3')
+ sel4 = self.marionette.find_element(By.ID, 'sel4')
+ sel6 = self.marionette.find_element(By.ID, 'sel6')
+
+ # Select target element and get target caret location
+ self.long_press_on_word(sel4, 3)
+ sel = SelectionManager(body)
+ end_caret_x, end_caret_y = sel.second_caret_location()
+
+ self.long_press_on_word(sel6, 0)
+ end_caret2_x, end_caret2_y = sel.second_caret_location()
+
+ # Select start element
+ self.long_press_on_word(sel3, 3)
+
+ # Drag end caret to target location
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(body, caret2_x, caret2_y, end_caret_x, end_caret_y, 1).perform()
+ self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
+ 'this 3\nuser can select this')
+
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(body, caret2_x, caret2_y, end_caret2_x, end_caret2_y, 1).perform()
+ self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
+ 'this 3\nuser can select this 4\nuser can select this 5\nuser')
+
+ # Drag first caret to target location
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(body, caret1_x, caret1_y, end_caret_x, end_caret_y, 1).perform()
+ self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
+ '4\nuser can select this 5\nuser')
+
+ def test_drag_swappable_caret_over_non_selectable_field(self):
+ self.open_test_html(self._multiplerange_html)
+ body = self.marionette.find_element(By.ID, 'bd')
+ sel3 = self.marionette.find_element(By.ID, 'sel3')
+ sel4 = self.marionette.find_element(By.ID, 'sel4')
+ sel = SelectionManager(body)
+
+ self.long_press_on_word(sel4, 3)
+ (end_caret1_x, end_caret1_y), (end_caret2_x, end_caret2_y) = sel.carets_location()
+
+ self.long_press_on_word(sel3, 3)
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+
+ # Drag the first caret down, which will across the second caret.
+ self.actions.flick(body, caret1_x, caret1_y, end_caret1_x, end_caret1_y).perform()
+ self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
+ '3\nuser can select')
+
+ # The old second caret becomes the first caret. Drag it down again.
+ self.actions.flick(body, caret2_x, caret2_y, end_caret2_x, end_caret2_y).perform()
+ self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
+ 'this')
+
+ def test_drag_caret_to_beginning_of_a_line(self):
+ '''Bug 1094056
+ Test caret visibility when caret is dragged to beginning of a line
+ '''
+ self.open_test_html(self._multiplerange_html)
+ body = self.marionette.find_element(By.ID, 'bd')
+ sel1 = self.marionette.find_element(By.ID, 'sel1')
+ sel2 = self.marionette.find_element(By.ID, 'sel2')
+
+ # Select the first word in the second line
+ self.long_press_on_word(sel2, 0)
+ sel = SelectionManager(body)
+ (start_caret_x, start_caret_y), (end_caret_x, end_caret_y) = sel.carets_location()
+
+ # Select target word in the first line
+ self.long_press_on_word(sel1, 2)
+
+ # Drag end caret to the beginning of the second line
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(body, caret2_x, caret2_y, start_caret_x, start_caret_y).perform()
+
+ # Drag end caret back to the target word
+ self.actions.flick(body, start_caret_x, start_caret_y, caret2_x, caret2_y).perform()
+
+ self.assertEqual(self.to_unix_line_ending(sel.selected_content), 'select')
+
+ @skip_if_not_rotatable
+ def test_caret_position_after_changing_orientation_of_device(self):
+ '''Bug 1094072
+ If positions of carets are updated correctly, they should be draggable.
+ '''
+ self.open_test_html(self._longtext_html)
+ body = self.marionette.find_element(By.ID, 'bd')
+ longtext = self.marionette.find_element(By.ID, 'longtext')
+
+ # Select word in portrait mode, then change to landscape mode
+ self.marionette.set_orientation('portrait')
+ self.long_press_on_word(longtext, 12)
+ sel = SelectionManager(body)
+ (p_start_caret_x, p_start_caret_y), (p_end_caret_x, p_end_caret_y) = sel.carets_location()
+ self.marionette.set_orientation('landscape')
+ (l_start_caret_x, l_start_caret_y), (l_end_caret_x, l_end_caret_y) = sel.carets_location()
+
+ # Drag end caret to the start caret to change the selected content
+ self.actions.flick(body, l_end_caret_x, l_end_caret_y,
+ l_start_caret_x, l_start_caret_y).perform()
+
+ # Change orientation back to portrait mode to prevent affecting
+ # other tests
+ self.marionette.set_orientation('portrait')
+
+ self.assertEqual(self.to_unix_line_ending(sel.selected_content), 'o')
+
+ def test_select_word_inside_an_iframe(self):
+ '''Bug 1088552
+ The scroll offset in iframe should be taken into consideration properly.
+ In this test, we scroll content in the iframe to the bottom to cause a
+ huge offset. If we use the right coordinate system, selection should
+ work. Otherwise, it would be hard to trigger select word.
+ '''
+ self.open_test_html(self._iframe_html)
+ iframe = self.marionette.find_element(By.ID, 'frame')
+
+ # switch to inner iframe and scroll to the bottom
+ self.marionette.switch_to_frame(iframe)
+ self.marionette.execute_script(
+ 'document.getElementById("bd").scrollTop += 999')
+
+ # long press to select bottom text
+ body = self.marionette.find_element(By.ID, 'bd')
+ sel = SelectionManager(body)
+ self._bottomtext = self.marionette.find_element(By.ID, 'bottomtext')
+ self.long_press_on_location(self._bottomtext)
+
+ self.assertNotEqual(self.to_unix_line_ending(sel.selected_content), '')
+
+ def test_carets_initialized_in_display_none(self):
+ '''Test AccessibleCaretEventHub is properly initialized on a <html> with
+ display: none.
+
+ '''
+ self.open_test_html(self._display_none_html)
+ html = self.marionette.find_element(By.ID, 'html')
+ content = self.marionette.find_element(By.ID, 'content')
+
+ # Remove 'display: none' from <html>
+ self.marionette.execute_script(
+ 'arguments[0].style.display = "unset";',
+ script_args=[html]
+ )
+
+ # If AccessibleCaretEventHub is initialized successfully, select a word
+ # should work.
+ self._test_long_press_to_select_a_word(content)
+
+ def test_long_press_to_select_when_partial_visible_word_is_selected(self):
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, self._input_id)
+ sel = SelectionManager(el)
+
+ # To successfully select the second word while the first word is being
+ # selected, use sufficient spaces between 'a' and 'b' to avoid the
+ # second caret covers on the second word.
+ original_content = 'aaaaaaaa bbbbbbbb'
+ el.clear()
+ el.send_keys(original_content)
+ words = original_content.split()
+
+ # We cannot use self.long_press_on_word() directly since it has will
+ # change the cursor position which affects this test. We have to store
+ # the position of word 0 and word 1 before long-pressing to select the
+ # word.
+ word0_x, word0_y = self.word_location(el, 0)
+ word1_x, word1_y = self.word_location(el, 1)
+
+ self.long_press_on_location(el, word0_x, word0_y)
+ self.assertEqual(words[0], sel.selected_content)
+
+ self.long_press_on_location(el, word1_x, word1_y)
+ self.assertEqual(words[1], sel.selected_content)
+
+ self.long_press_on_location(el, word0_x, word0_y)
+ self.assertEqual(words[0], sel.selected_content)
+
+ # If the second carets is visible, it can be dragged to the position of
+ # the first caret. After that, selection will contain only the first
+ # character.
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+ self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform()
+ self.assertEqual(words[0][0], sel.selected_content)
+
+ @parameterized(_input_id, el_id=_input_id)
+ @parameterized(_input_padding_id, el_id=_input_padding_id)
+ @parameterized(_textarea_one_line_id, el_id=_textarea_one_line_id)
+ @parameterized(_contenteditable_id, el_id=_contenteditable_id)
+ def test_carets_not_jump_when_dragging_to_editable_content_boundary(self, el_id):
+ self.open_test_html(self._selection_html)
+ el = self.marionette.find_element(By.ID, el_id)
+ sel = SelectionManager(el)
+ original_content = sel.content
+ words = original_content.split()
+ self.assertTrue(len(words) >= 3, 'Expect at least three words in the content.')
+
+ # Goal: the selection is not changed after dragging the caret on the
+ # Y-axis.
+ target_content = words[1]
+
+ self.long_press_on_word(el, 1)
+ (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
+
+ # Drag the first caret up by 50px.
+ self.actions.flick(el, caret1_x, caret1_y, caret1_x, caret1_y - 50).perform()
+ self.assertEqual(target_content, sel.selected_content)
+
+ # Drag the second caret down by 50px.
+ self.actions.flick(el, caret2_x, caret2_y, caret2_x, caret2_y + 50).perform()
+ self.assertEqual(target_content, sel.selected_content)
diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini
new file mode 100644
index 000000000..279b0af8a
--- /dev/null
+++ b/layout/base/tests/mochitest.ini
@@ -0,0 +1,316 @@
+[DEFAULT]
+# Android: SLOW_DIRECTORY;
+skip-if = toolkit == 'android'
+support-files =
+ Ahem.ttf
+ border_radius_hit_testing_iframe.html
+ preserve3d_sorting_hit_testing_iframe.html
+ preserve3d_sorting_hit_testing2_iframe.html
+ image_rgrg-256x256.png
+ image_rrgg-256x256.png
+ bug369950-subframe.xml
+ file_bug842853.sjs
+ file_bug842853.html
+ ../../../dom/plugins/test/mochitest/plugin-utils.js
+ bug558663.html
+ bug956530-1.html
+ bug956530-1-ref.html
+ bug989012-1.html
+ bug989012-1-ref.html
+ bug989012-2.html
+ bug989012-2-ref.html
+ bug989012-3.html
+ bug989012-3-ref.html
+ bug1061468.html
+ bug1061468-ref.html
+ bug1097242-1.html
+ bug1097242-1-ref.html
+ bug1109968-1-ref.html
+ bug1109968-1.html
+ bug1109968-2-ref.html
+ bug1109968-2.html
+ bug1123067-1.html
+ bug1123067-2.html
+ bug1123067-3.html
+ bug1123067-ref.html
+ bug1132768-1.html
+ bug1132768-1-ref.html
+ bug1237236-1.html
+ bug1237236-1-ref.html
+ bug1237236-2.html
+ bug1237236-2-ref.html
+ bug1258308-1.html
+ bug1258308-1-ref.html
+ bug1258308-2.html
+ bug1258308-2-ref.html
+ bug1259949-1.html
+ bug1259949-1-ref.html
+ bug1259949-2.html
+ bug1259949-2-ref.html
+ bug1263288.html
+ bug1263288-ref.html
+ selection-utils.js
+ multi-range-user-select.html
+ multi-range-user-select-ref.html
+ multi-range-script-select.html
+ multi-range-script-select-ref.html
+ transformed_scrolling_repaints_3_window.html
+
+[test_preserve3d_sorting_hit_testing.html]
+[test_preserve3d_sorting_hit_testing2.html]
+[test_after_paint_pref.html]
+[test_bug370436.html]
+[test_bug993936.html]
+[test_border_radius_hit_testing.html]
+[test_bug66619.html]
+[test_bug93077-1.html]
+[test_bug93077-2.html]
+[test_bug93077-3.html]
+[test_bug93077-4.html]
+[test_bug93077-5.html]
+[test_bug93077-6.html]
+[test_bug114649.html]
+[test_bug369950.html]
+skip-if = true # Bug 492575
+[test_bug386575.xhtml]
+[test_bug388019.html]
+[test_bug394057.html]
+[test_bug399284.html]
+[test_bug399951.html]
+[test_bug404209.xhtml]
+[test_bug416896.html]
+[test_bug423523.html]
+[test_bug449781.html]
+[test_bug450930.xhtml]
+skip-if = buildapp == 'b2g' || true # bug 934301
+support-files = bug450930.xhtml
+[test_bug465448.xul]
+[test_bug469170.html]
+[test_bug471126.html]
+[test_bug435293-scale.html]
+[test_bug435293-interaction.html]
+[test_bug435293-skew.html]
+[test_reftests_with_caret.html]
+support-files =
+ bug106855-1.html
+ bug106855-2.html
+ bug106855-1-ref.html
+ bug240933-1.html
+ bug240933-2.html
+ bug240933-1-ref.html
+ bug389321-1.html
+ bug389321-1-ref.html
+ bug389321-2.html
+ bug389321-2-ref.html
+ bug389321-3.html
+ bug389321-3-ref.html
+ bug482484.html
+ bug482484-ref.html
+ bug503399.html
+ bug503399-ref.html
+ bug512295-1.html
+ bug512295-1-ref.html
+ bug512295-2.html
+ bug512295-2-ref.html
+ bug585922.html
+ bug585922-ref.html
+ bug597519-1.html
+ bug597519-1-ref.html
+ bug602141-1.html
+ bug602141-1-ref.html
+ bug602141-2.html
+ bug602141-2-ref.html
+ bug602141-3.html
+ bug602141-3-ref.html
+ bug602141-4.html
+ bug602141-4-ref.html
+ bug612271-1.html
+ bug612271-2.html
+ bug612271-3.html
+ bug612271-ref.html
+ bug613433-1.html
+ bug613433-2.html
+ bug613433-3.html
+ bug613433-ref.html
+ bug613807-1.html
+ bug613807-1-ref.html
+ bug632215-1.html
+ bug632215-2.html
+ bug632215-ref.html
+ bug633044-1.html
+ bug633044-1-ref.html
+ bug634406-1.html
+ bug634406-1-ref.html
+ bug644428-1.html
+ bug644428-1-ref.html
+ bug646382-1.html
+ bug646382-1-ref.html
+ bug646382-2.html
+ bug646382-2-ref.html
+ bug664087-1.html
+ bug664087-1-ref.html
+ bug664087-2.html
+ bug664087-2-ref.html
+ bug682712-1.html
+ bug682712-1-ref.html
+ bug746993-1.html
+ bug746993-1-ref.html
+ bug923376.html
+ bug923376-ref.html
+ bug966992-1.html
+ bug966992-1-ref.html
+ bug966992-2.html
+ bug966992-2-ref.html
+ bug966992-3.html
+ bug966992-3-ref.html
+ bug1007065-1.html
+ bug1007065-1-ref.html
+ bug1007067-1.html
+ bug1007067-1-ref.html
+ bug1082486-1.html
+ bug1082486-1-ref.html
+ bug1082486-2.html
+ bug1082486-2-ref.html
+ bug1263357-1.html
+ bug1263357-1-ref.html
+ bug1263357-2.html
+ bug1263357-2-ref.html
+ bug1263357-3.html
+ bug1263357-3-ref.html
+ bug1263357-4.html
+ bug1263357-4-ref.html
+ bug1263357-5.html
+ bug1263357-5-ref.html
+ input-maxlength-valid-before-change.html
+ input-maxlength-valid-change.html
+ input-maxlength-invalid-change.html
+ input-minlength-valid-before-change.html
+ input-minlength-valid-change.html
+ input-minlength-invalid-change.html
+ input-maxlength-ui-valid-change.html
+ input-maxlength-ui-invalid-change.html
+ input-minlength-ui-valid-change.html
+ input-minlength-ui-invalid-change.html
+ input-valid-ref.html
+ input-invalid-ref.html
+ textarea-maxlength-valid-before-change.html
+ textarea-maxlength-valid-change.html
+ textarea-maxlength-invalid-change.html
+ textarea-minlength-valid-before-change.html
+ textarea-minlength-valid-change.html
+ textarea-minlength-invalid-change.html
+ textarea-maxlength-ui-valid-change.html
+ textarea-maxlength-ui-invalid-change.html
+ textarea-minlength-ui-valid-change.html
+ textarea-minlength-ui-invalid-change.html
+ textarea-valid-ref.html
+ textarea-invalid-ref.html
+[test_bug514127.html]
+[test_bug518777.html]
+[test_bug548545.xhtml]
+[test_bug558663.html]
+[test_bug559499.html]
+[test_bug569520.html]
+[test_bug582181-1.html]
+[test_bug582181-2.html]
+[test_bug588174.html]
+[test_bug607529.html]
+support-files = file_bug607529.html
+[test_bug667512.html]
+[test_bug677878.html]
+[test_bug696020.html]
+[test_event_target_radius.html]
+[test_event_target_iframe_oop.html]
+skip-if = e10s # bug 1020135, nested oop iframes not supported
+support-files = bug921928_event_target_iframe_apps_oop.html
+[test_mozPaintCount.html]
+skip-if = toolkit == 'android'
+[test_scroll_event_ordering.html]
+[test_scroll_selection_into_view.html]
+support-files=scroll_selection_into_view_window.html
+[test_scroll_snapping.html]
+skip-if = buildapp == 'android' # bug 1041833
+[test_scroll_snapping_scrollbars.html]
+skip-if = buildapp == 'android' # bug 1041833
+[test_bug583889.html]
+support-files = bug583889_inner1.html bug583889_inner2.html
+[test_bug582771.html]
+[test_bug968148.html]
+support-files = bug968148_inner.html
+[test_bug603550.html]
+skip-if = toolkit == 'android' #TIMED_OUT
+[test_bug629838.html]
+skip-if = toolkit == 'android'
+[test_bug646757.html]
+[test_bug718809.html]
+[test_bug725426.html]
+[test_bug731777.html]
+[test_bug761572.html]
+[test_bug770106.html]
+[test_remote_frame.html]
+[test_bug842853.html]
+[test_bug842853-2.html]
+[test_bug849219.html]
+[test_bug851485.html]
+[test_bug851445.html]
+support-files = bug851445_helper.html
+[test_bug970964.html]
+support-files = bug970964_inner.html
+[test_bug976963.html]
+support-files = bug976963_inner.html
+[test_bug977003.html]
+support-files =
+ bug977003_inner_1.html
+ bug977003_inner_2.html
+ bug977003_inner_3.html
+ bug977003_inner_4.html
+ bug977003_inner_5.html
+ bug977003_inner_6.html
+[test_emulateMedium.html]
+[test_getClientRects_emptytext.html]
+[test_bug858459.html]
+
+# because of bug 469208.
+[test_bug332655-1.html]
+skip-if = toolkit == 'android'
+[test_bug332655-2.html]
+[test_bug499538-1.html]
+[test_bug749186.html]
+[test_bug644768.html]
+[test_flush_on_paint.html]
+skip-if = true || (toolkit == 'android') || (toolkit == "cocoa") # Bug 688128, bug 539356
+[test_getBoxQuads_convertPointRectQuad.html]
+[test_bug687297.html]
+support-files =
+ bug687297_a.html
+ bug687297_b.html
+ bug687297_c.html
+[test_bug990340.html]
+[test_bug1080360.html]
+support-files = bug1080360_inner.html
+[test_bug1078327.html]
+support-files = bug1078327_inner.html
+[test_bug1080361.html]
+support-files = bug1080361_inner.html
+[test_frame_reconstruction_for_pseudo_elements.html]
+[test_bug1093686.html]
+support-files = bug1093686_inner.html
+[test_bug1120705.html]
+skip-if = buildapp == 'android' || os == 'mac' || toolkit == 'gtk2' || toolkit == 'gtk3' # android does not have clickable scrollbars, mac does not have scrollbar down and up buttons, gtk may or may not have scrollbar buttons depending on theme
+[test_bug1153130.html]
+support-files = bug1153130_inner.html
+[test_bug1162990.html]
+support-files =
+ bug1162990_inner_1.html
+ bug1162990_inner_2.html
+[test_bug1226904.html]
+support-files = bug1226904.html
+[test_bug1246622.html]
+[test_bug1278021.html]
+[test_transformed_scrolling_repaints.html]
+[test_transformed_scrolling_repaints_2.html]
+[test_transformed_scrolling_repaints_3.html]
+[test_frame_reconstruction_scroll_restore.html]
+[test_resize_flush.html]
+support-files =
+ resize_flush_iframe.html
diff --git a/layout/base/tests/multi-range-script-select-ref.html b/layout/base/tests/multi-range-script-select-ref.html
new file mode 100644
index 000000000..cf42ee79b
--- /dev/null
+++ b/layout/base/tests/multi-range-script-select-ref.html
@@ -0,0 +1,173 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1129078</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="selection-utils.js"></script>
+
+<style type="text/css">
+@font-face {
+ font-family: Ahem;
+ src: url("Ahem.ttf");
+}
+html,body { margin:0; padding: 0; }
+body,pre { font-family: Ahem; font-size: 20px; }
+</style>
+</head>
+<body>
+
+<pre id="select">
+2af45494-ak7e-11e4-a0c6-a7e7
+38222880-bj6d-11e4-8064-fb7b
+3d649ae4-ci5c-11e4-995d-17b2
+434351bc-dh4b-11e4-9971-4fc8
+4dc0e0b4-eg4a-11e4-8c28-5319
+a96319c8-ad7d-11e4-b312-039c
+</pre>
+
+<pre id="log" style="border:1px solid green"></pre>
+
+<script>
+
+var sel = window.getSelection();
+var e = document.querySelector('#select');
+function setupSelectionPrev3() {
+ addChildRanges([[0,150,0,160], [0,65,0,70], [0,15,0,15]], e);
+ sel.extend(e.firstChild, 10); // to get eDirPrevious direction
+}
+function setupSelectionPrev2() {
+ addChildRanges([[0,150,0,160], [0,70,0,70]], e);
+ sel.extend(e.firstChild, 65); // to get eDirPrevious direction
+}
+function setupSelectionPrev1() {
+ addChildRanges([[0,160,0,160]], e);
+ sel.extend(e.firstChild, 150); // to get eDirPrevious direction
+}
+
+function setupSelectionNext3() {
+ addChildRanges([[0,10,0,15], [0,65,0,70], [0,150,0,160]], e);
+}
+function setupSelectionNext2() {
+ addChildRanges([[0,10,0,15], [0,65,0,70]], e);
+}
+function setupSelectionNext2b() {
+ addChildRanges([[0,15,0,80], [0,150,0,160]], e);
+}
+function setupSelectionNext1() {
+ addChildRanges([[0,10,0,15]], e);
+}
+function setupSelectionNext1b() {
+ addChildRanges([[0,15,0,170]], e);
+}
+function setupSelectionNext1c() {
+ addChildRanges([[0,150,0,160]], e);
+}
+
+function runTest() {
+ var hash = window.location.hash
+ var op = hash.substring(6,8);
+ var test = hash.substring(0,6);
+ if (hash.substring(0,5) == "#prev") {
+ if (test == "#prev1") {
+ setupSelectionPrev3();
+ if (op == "SL") {
+ sel.extend(e.firstChild, 8);
+ } else if (op == "SR") {
+ sel.extend(e.firstChild, 12);
+ } else if (op == "AD") {
+ addChildRanges([[0,1,0,2]], e);
+ } else {
+ sel.extend(e.firstChild, 1);
+ }
+ } else if (test == "#prev2") {
+ setupSelectionPrev3();
+ sel.extend(e.firstChild, 13);
+ } else if (test == "#prev3") {
+ if (op == "S_") {
+ setupSelectionPrev3();
+ sel.extend(e.firstChild, 20);
+ } else if (op == "SA") {
+ setupSelectionPrev3();
+ sel.extend(e.firstChild, 20);
+ }
+ } else if (test == "#prev4") {
+ addChildRanges([[0,67,0,70], [0,150,0,160], [0,15,0,67]], e);
+ } else if (test == "#prev5") {
+ if (op == "S_") {
+ setupSelectionNext2b();
+ } else if (op == "SA") {
+ setupSelectionNext2b();
+ }
+ } else if (test == "#prev6") {
+ addChildRanges([[0,152,0,160], [0,15,0,152]], e);
+ } else if (test == "#prev7") {
+ if (op == "AD") {
+ setupSelectionPrev3();
+ addChildRanges([[0,168,0,170]], e);
+ } else if (op == "S_") {
+ setupSelectionNext1b();
+ } else if (op == "SA") {
+ setupSelectionNext1b();
+ }
+ }
+ } else {
+ if (test == "#next1") {
+ if (op == "SL") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 158);
+ } else if (op == "SR") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 162);
+ } else if (op == "AD") {
+ setupSelectionNext3();
+ addChildRanges([[0,1,0,2]], e);
+ } else if (op == "S_") {
+ setupSelectionNext1c();
+ sel.extend(e.firstChild, 1);
+ } else if (op == "SA") {
+ setupSelectionNext1c();
+ sel.extend(e.firstChild, 1);
+ }
+ } else if (test == "#next2") {
+ addChildRanges([[0,10,0,13], [0,150,0,151]], e);
+ sel.extend(e.firstChild, 13);
+ } else if (test == "#next3") {
+ if (op == "S_") {
+ addChildRanges([[0,10,0,15], [0,150,0,151]], e);
+ sel.extend(e.firstChild, 20);
+ } else if (op == "SA") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 20);
+ }
+ } else if (test == "#next4") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 67);
+ } else if (test == "#next5") {
+ if (op == "S_") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 80);
+ } else if (op == "SA") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 80);
+ }
+ } else if (test == "#next6") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 152);
+ } else if (test == "#next7") {
+ setupSelectionNext3();
+ if (op == "AD") {
+ addChildRanges([[0,168,0,170]], e);
+ } else {
+ sel.extend(e.firstChild, 170);
+ }
+ }
+ }
+ document.documentElement.removeAttribute("class");
+}
+
+SimpleTest.waitForFocus(runTest);
+
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/multi-range-script-select.html b/layout/base/tests/multi-range-script-select.html
new file mode 100644
index 000000000..b9bcaeab8
--- /dev/null
+++ b/layout/base/tests/multi-range-script-select.html
@@ -0,0 +1,185 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1129078</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="selection-utils.js"></script>
+
+<style type="text/css">
+@font-face {
+ font-family: Ahem;
+ src: url("Ahem.ttf");
+}
+html,body { margin:0; padding: 0; }
+body,pre { font-family: Ahem; font-size: 20px; }
+</style>
+</head>
+<body>
+
+<pre id="select">
+2af45494-ak7e-11e4-a0c6-a7e7
+38222880-bj6d-11e4-8064-fb7b
+3d649ae4-ci5c-11e4-995d-17b2
+434351bc-dh4b-11e4-9971-4fc8
+4dc0e0b4-eg4a-11e4-8c28-5319
+a96319c8-ad7d-11e4-b312-039c
+</pre>
+
+<pre id="log" style="border:1px solid green"></pre>
+
+<script>
+window.info = parent.info;
+window.is = parent.is;
+window.isnot = parent.isnot;
+window.ok = parent.ok;
+
+function setupPrevSelection() {
+ var sel = window.getSelection();
+ var e = document.querySelector('#select');
+ addChildRanges([[0,150,0,160], [0,65,0,70], [0,15,0,15]], e);
+ sel.extend(e.firstChild, 10); // to get eDirPrevious direction
+}
+
+function setupNextSelection() {
+ var sel = window.getSelection();
+ var e = document.querySelector('#select');
+ addChildRanges([[0,10,0,15], [0,65,0,70], [0,150,0,160]], e);
+}
+
+var ops = {
+ S_ : shiftClick,
+ SA : shiftAccelClick,
+ AD : accelDragSelect,
+ SL : keyLeft,
+ SR : keyRight
+}
+
+function runTest() {
+ var e = document.querySelector('#select');
+ var hash = window.location.hash
+ if (hash.substring(0,5)=="#prev")
+ setupPrevSelection();
+ else
+ setupNextSelection();
+ var op = hash.substring(6,8);
+ var action = ops[op];
+ var test = hash.substring(0,6);
+ if (hash.substring(0,5) == "#prev") {
+ if (test == "#prev1") {
+ if (action == keyLeft) {
+ keyLeft({shiftKey:true}, 2)
+ checkRanges([[0,8,0,15], [0,65,0,70], [0,150,0,160]], e);
+ } else if (action == keyRight) {
+ keyRight({shiftKey:true}, 2)
+ checkRanges([[0,12,0,15], [0,65,0,70], [0,150,0,160]], e);
+ } else if (action == accelDragSelect) {
+ accelDragSelect(e, 30, 50);
+ checkRanges([[0,1,0,2], [0,10,0,15], [0,65,0,70], [0,150,0,160]], e);
+ } else {
+ action(e, 30);
+ checkRanges([[0,1,0,15], [0,65,0,70], [0,150,0,160]], e);
+ }
+ } else if (test == "#prev2") {
+ action(e, 260);
+ checkRanges([[0,13,0,15], [0,65,0,70], [0,150,0,160]], e);
+ } else if (test == "#prev3") {
+ action(e, 400);
+ if (action == shiftClick)
+ checkRanges([[0,15,0,20], [0,65,0,70], [0,150,0,160]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,15,0,20], [0,65,0,70], [0,150,0,160]], e);
+ } else if (test == "#prev4") {
+ action(e, 180, 65);
+ if (action == shiftClick)
+ checkRanges([[0,15,0,67], [0,67,0,70], [0,150,0,160]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,15,0,67], [0,67,0,70], [0,150,0,160]], e);
+ } else if (test == "#prev5") {
+ action(e, 440, 65);
+ if (action == shiftClick)
+ checkRanges([[0,15,0,80], [0,150,0,160]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,15,0,80], [0,150,0,160]], e);
+ } else if (test == "#prev6") {
+ action(e, 140, 125);
+ if (action == shiftClick)
+ checkRanges([[0,15,0,152], [0,152,0,160]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,15,0,152], [0,152,0,160]], e);
+ } else if (test == "#prev7") {
+ if (action == accelDragSelect) {
+ accelDragSelect(e, 460, 500, 125);
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,160], [0,168,0,170]], e);
+ } else if (action == shiftClick) {
+ action(e, 500, 125);
+ checkRanges([[0,15,0,170]], e);
+ } else if (action == shiftAccelClick) {
+ action(e, 500, 125);
+ checkRanges([[0,15,0,170]], e);
+ }
+ }
+ } else {
+ if (test == "#next1") {
+ if (action == keyLeft) {
+ keyLeft({shiftKey:true}, 2)
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,158]], e);
+ } else if (action == keyRight) {
+ keyRight({shiftKey:true}, 2)
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,162]], e);
+ } else if (action == accelDragSelect) {
+ accelDragSelect(e, 30, 50);
+ checkRanges([[0,1,0,2], [0,10,0,15], [0,65,0,70], [0,150,0,160]], e);
+ } else {
+ action(e, 30);
+ checkRanges([[0,1,0,150]], e);
+ }
+ } else if (test == "#next2") {
+ action(e, 260);
+ checkRanges([[0,10,0,13], [0,13,0,150]], e);
+ } else if (test == "#next3") {
+ action(e, 400);
+ if (action == shiftClick)
+ checkRanges([[0,10,0,15], [0,20,0,150]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,10,0,15], [0,20,0,150]], e);
+ } else if (test == "#next4") {
+ action(e, 180, 65);
+ if (action == shiftClick)
+ checkRanges([[0,10,0,15], [0,65,0,67], [0,67,0,150]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,10,0,15], [0,65,0,67], [0,67,0,150]], e);
+ } else if (test == "#next5") {
+ action(e, 440, 65);
+ if (action == shiftClick)
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,80,0,150]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,80,0,150]], e);
+ } else if (test == "#next6") {
+ action(e, 140, 125);
+ if (action == shiftClick)
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,152]], e);
+ else if (action == shiftAccelClick)
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,152]], e);
+ } else if (test == "#next7") {
+ if (action == accelDragSelect) {
+ accelDragSelect(e, 460, 500, 125);
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,160], [0,168,0,170]], e);
+ } else if (action == shiftClick) {
+ action(e, 500, 125);
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,170]], e);
+ } else if (action == shiftAccelClick) {
+ action(e, 500, 125);
+ checkRanges([[0,10,0,15], [0,65,0,70], [0,150,0,170]], e);
+ }
+ }
+ }
+ document.documentElement.removeAttribute("class");
+}
+
+SimpleTest.waitForFocus(runTest);
+
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/multi-range-user-select-ref.html b/layout/base/tests/multi-range-user-select-ref.html
new file mode 100644
index 000000000..812bae047
--- /dev/null
+++ b/layout/base/tests/multi-range-user-select-ref.html
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1129078</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="selection-utils.js"></script>
+
+<style type="text/css">
+@font-face {
+ font-family: Ahem;
+ src: url("Ahem.ttf");
+}
+html,body { margin:0; padding: 0; }
+body,pre { font-family: Ahem; font-size: 20px; }
+</style>
+</head>
+<body>
+
+<pre id="select">
+2af45494-ak7e-11e4-a0c6-a7e7
+38222880-bj6d-11e4-8064-fb7b
+3d649ae4-ci5c-11e4-995d-17b2
+434351bc-dh4b-11e4-9971-4fc8
+4dc0e0b4-eg4a-11e4-8c28-5319
+a96319c8-ad7d-11e4-b312-039c
+</pre>
+
+<pre id="log" style="border:1px solid green"></pre>
+
+<script>
+
+var sel = window.getSelection();
+var e = document.querySelector('#select');
+function setupSelectionPrev3() {
+ addChildRanges([[0,150,0,160], [0,65,0,70], [0,15,0,15]], e);
+ sel.extend(e.firstChild, 10); // to get eDirPrevious direction
+}
+function setupSelectionPrev2() {
+ addChildRanges([[0,150,0,160], [0,70,0,70]], e);
+ sel.extend(e.firstChild, 65); // to get eDirPrevious direction
+}
+function setupSelectionPrev1() {
+ addChildRanges([[0,160,0,160]], e);
+ sel.extend(e.firstChild, 150); // to get eDirPrevious direction
+}
+
+function setupSelectionNext3() {
+ addChildRanges([[0,10,0,15], [0,65,0,70], [0,150,0,160]], e);
+}
+function setupSelectionNext2() {
+ addChildRanges([[0,10,0,15], [0,65,0,70]], e);
+}
+function setupSelectionNext2b() {
+ addChildRanges([[0,15,0,80], [0,150,0,160]], e);
+}
+function setupSelectionNext1() {
+ addChildRanges([[0,10,0,15]], e);
+}
+function setupSelectionNext1b() {
+ addChildRanges([[0,15,0,170]], e);
+}
+function setupSelectionNext1c() {
+ addChildRanges([[0,150,0,160]], e);
+}
+
+function runTest() {
+ sel = window.getSelection();
+ sel.removeAllRanges();
+ document.body.offsetHeight;
+ var hash = window.location.hash
+ var op = hash.substring(6,8);
+ var test = hash.substring(0,6);
+ if (hash.substring(0,5) == "#prev") {
+ if (test == "#prev1") {
+ setupSelectionPrev3();
+ if (op == "SL") {
+ sel.extend(e.firstChild, 8);
+ } else if (op == "SR") {
+ sel.extend(e.firstChild, 12);
+ } else if (op == "AD") {
+ addChildRanges([[0,1,0,2]], e);
+ } else {
+ sel.extend(e.firstChild, 1);
+ }
+ } else if (test == "#prev2") {
+ setupSelectionPrev3();
+ sel.extend(e.firstChild, 14); // now eDirNext
+ sel.extend(e.firstChild, 13); // now eDirPrevious again
+ } else if (test == "#prev3") {
+ setupSelectionPrev2();
+ sel.extend(e.firstChild, 20);
+ } else if (test == "#prev4") {
+ setupSelectionPrev2();
+ sel.extend(e.firstChild, 68); // now eDirNext
+ sel.extend(e.firstChild, 67); // now eDirPrevious again
+ } else if (test == "#prev5") {
+ setupSelectionPrev1();
+ sel.extend(e.firstChild, 80);
+ } else if (test == "#prev6") {
+ setupSelectionPrev1();
+ sel.extend(e.firstChild, 153); // now eDirNext
+ sel.extend(e.firstChild, 152); // now eDirPrevious again
+ } else if (test == "#prev7") {
+ if (op == "AD") {
+ setupSelectionPrev3();
+ addChildRanges([[0,168,0,170]], e);
+ } else {
+ addChildRanges([[0,160,0,170]], e);
+ }
+ } else if (test == "#prev8") {
+ if (op == "AD") {
+ addChildRanges([[0,150,0,155], [0,68,0,70]], e);
+ }
+ }
+ } else {
+ if (test == "#next1") {
+ if (op == "SL") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 158);
+ } else if (op == "SR") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 162);
+ } else if (op == "AD") {
+ setupSelectionNext3();
+ addChildRanges([[0,1,0,2]], e);
+ } else {
+ setupSelectionNext1();
+ sel.extend(e.firstChild, 1);
+ }
+ } else if (test == "#next2") {
+ setupSelectionNext1();
+ sel.extend(e.firstChild, 13);
+ } else if (test == "#next3") {
+ setupSelectionNext1();
+ sel.extend(e.firstChild, 20);
+ } else if (test == "#next4") {
+ setupSelectionNext2();
+ sel.extend(e.firstChild, 67);
+ } else if (test == "#next5") {
+ setupSelectionNext2();
+ sel.extend(e.firstChild, 80);
+ } else if (test == "#next6") {
+ setupSelectionNext3();
+ sel.extend(e.firstChild, 152);
+ } else if (test == "#next7") {
+ setupSelectionNext3();
+ if (op == "AD") {
+ addChildRanges([[0,168,0,170]], e);
+ } else {
+ sel.extend(e.firstChild, 170);
+ }
+ } else if (test == "#next8") {
+ if (op == "AD") {
+ addChildRanges([[0,68,0,70], [0,150,0,155]], e);
+ }
+ }
+ }
+ document.documentElement.removeAttribute("class");
+}
+
+SimpleTest.waitForFocus(function(){setTimeout(runTest,0)});
+
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/multi-range-user-select.html b/layout/base/tests/multi-range-user-select.html
new file mode 100644
index 000000000..9da8f9398
--- /dev/null
+++ b/layout/base/tests/multi-range-user-select.html
@@ -0,0 +1,223 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1129078</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="selection-utils.js"></script>
+
+<style type="text/css">
+@font-face {
+ font-family: Ahem;
+ src: url("Ahem.ttf");
+}
+html,body { margin:0; padding: 0; }
+body,pre { font-family: Ahem; font-size: 20px; }
+span { -moz-user-select:none; }
+x { -moz-user-select:text; }
+</style>
+</head>
+<body>
+
+<pre id="select">
+2af45494-a<x>k7e-1</x><span id="span2">1e4-a0c6-a7e7
+38222880-bj6d-11e4-8064-fb7b
+3d649ae</span><x>4-ci5</x><span id="span3">c-11e4-995d-17b2
+434351bc-dh4b-11e4-9971-4fc8
+4dc0e0b4-eg4a-11e4-8c28-5319
+a9631</span><x>9c8-ad7d-1</x>1e4-b312-039c
+</pre>
+
+<pre id="log" style="border:1px solid green"></pre>
+
+<script>
+window.info = parent.info;
+window.is = parent.is;
+window.isnot = parent.isnot;
+window.ok = parent.ok;
+
+var sel = window.getSelection();
+
+function enableSelection(id) {
+ var span = document.getElementById(id);
+ span.style.MozUserSelect = 'text';
+}
+
+function setupPrevSelection() {
+ var e = document.querySelector('#select');
+ dragSelectPoints(e, 300, 125, 200, 5);
+}
+
+function setupNextSelection() {
+ var e = document.querySelector('#select');
+ dragSelectPoints(e, 199, 5, 300, 125);
+}
+
+var ops = {
+ S_ : shiftClick,
+ SA : shiftAccelClick,
+ AD : accelDragSelect,
+ SL : keyLeft,
+ SR : keyRight
+}
+
+function runTest() {
+ sel = window.getSelection();
+ sel.removeAllRanges();
+ document.body.offsetHeight;
+ var e = document.querySelector('#select');
+ var hash = window.location.hash
+ if (hash.substring(0,5)=="#prev")
+ setupPrevSelection();
+ else
+ setupNextSelection();
+ var op = hash.substring(6,8);
+ var action = ops[op];
+ var test = hash.substring(0,6);
+ if (hash.substring(0,5) == "#prev") {
+ if (test == "#prev1") {
+ if (action == keyLeft) {
+ keyLeft({shiftKey:true}, 2)
+ checkRanges([[0,8,-1,2], [3,0,-1,4], [5,0,6,0]], e);
+ } else if (action == keyRight) {
+ keyRight({shiftKey:true}, 2)
+ checkRanges([[e.childNodes[1].firstChild,2,-1,2], [3,0,-1,4], [5,0,6,0]], e);
+ } else if (action == accelDragSelect) {
+ accelDragSelect(e, 30, 50);
+ checkRanges([[0,1,0,2], [e.childNodes[1].firstChild,0,-1,2], [3,0,-1,4], [5,0,6,0]], e);
+ } else {
+ action(e, 30);
+ checkRanges([[0,1,-1,2], [3,0,-1,4], [5,0,6,0]], e);
+ }
+ } else if (test == "#prev2") {
+ action(e, 260);
+ checkRangeCount(3, e);
+ checkRange(0, [0,3,-2,2], e.childNodes[1]);
+ checkRange(1, [3,0,-1,4], e);
+ checkRange(2, [5,0,6,0], e);
+ } else if (test == "#prev3") {
+ enableSelection('span2');
+ action(e, 400);
+ checkRangeCount(2, e);
+ checkRange(0, [0,5,-2,4], e.childNodes[2]);
+ checkRange(1, [5,0,6,0], e);
+ } else if (test == "#prev4") {
+ action(e, 180, 65);
+ checkRangeCount(2, e);
+ checkRange(0, [0,2,-2,4], e.childNodes[3]);
+ checkRange(1, [5,0,6,0], e);
+ } else if (test == "#prev5") {
+ enableSelection('span3');
+ action(e, 440, 65);
+ checkRangeCount(1, e);
+ checkRangePoints(0, [e.childNodes[4].firstChild,10,e.childNodes[6],0], e);
+ } else if (test == "#prev6") {
+ action(e, 140, 125);
+ checkRangeCount(1, e);
+ checkRangePoints(0, [e.childNodes[5].firstChild,2,e.childNodes[6],0], e);
+ } else if (test == "#prev7") {
+ if (action == accelDragSelect) {
+ accelDragSelect(e, 460, 500, 125);
+ checkRanges([[e.childNodes[1].firstChild,0,-1,2], [3,0,-1,4], [5,0,6,0], [6,8,6,10]], e);
+ } else {
+ action(e, 500, 125);
+ checkRanges([[6,0,6,10]], e);
+ }
+ } else if (test == "#prev8") {
+ if (action == accelDragSelect) {
+ sel.removeAllRanges();
+ var e = document.querySelector('#select');
+ synthesizeMouse(e, 200, 125, {type: "mousedown", accelKey: true});
+ synthesizeMouse(e, 200, 120, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 100, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 80, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 210, 60, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 60, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 60, {type: "mouseup", accelKey: true});
+ var x3t = e.childNodes[3].firstChild;
+ var x5 = e.childNodes[5];
+ checkRanges([[x3t,3,-1,4], [x5,0,x5.firstChild,5]], e);
+ }
+ }
+ } else {
+ if (test == "#next1") {
+ if (action == keyLeft) {
+ keyLeft({shiftKey:true}, 2)
+ checkRanges([[0,10,-1,2], [3,0,-1,4], [5,0,e.childNodes[5].firstChild,8]], e);
+ } else if (action == keyRight) {
+ keyRight({shiftKey:true}, 2)
+ checkRanges([[0,10,-1,2], [3,0,-1,4], [5,0,6,2]], e);
+ } else if (action == accelDragSelect) {
+ accelDragSelect(e, 30, 50);
+ checkRanges([[0,1,0,2], [0,10,-1,2], [3,0,-1,4], [5,0,e.childNodes[5].firstChild,10]], e);
+ } else {
+ action(e, 30);
+ checkRanges([[0,1,0,10]], e);
+ }
+ } else if (test == "#next2") {
+ action(e, 260);
+ checkRangeCount(1, e);
+ checkRangePoints(0, [e.childNodes[0],10,e.childNodes[1].firstChild,3], e);
+ } else if (test == "#next3") {
+ enableSelection('span2');
+ action(e, 400);
+ checkRangeCount(1, e);
+ checkRangePoints(0, [e.childNodes[0],10,e.childNodes[2].firstChild,5], e);
+ } else if (test == "#next4") {
+ action(e, 180, 65);
+ checkRangeCount(2, e);
+ checkRange(0, [0,10,-1,2], e);
+ checkRange(1, [-1,0,0,2], e.childNodes[3]);
+ } else if (test == "#next5") {
+ enableSelection('span3');
+ action(e, 440, 65);
+ checkRangeCount(2, e);
+ checkRange(0, [0,10,-1,2], e);
+ checkRangePoints(1, [e.childNodes[3],0,e.childNodes[4].firstChild,10], e);
+ } else if (test == "#next6") {
+ action(e, 140, 125);
+ checkRangeCount(3, e);
+ checkRange(0, [0,10,-1,2], e);
+ checkRange(1, [3,0,-1,4], e);
+ checkRange(2, [-1,0,0,2], e.childNodes[5]);
+ } else if (test == "#next7") {
+ if (action == keyRight) {
+ keyRight({shiftKey:true}, 2)
+ checkRanges([[0,10,-1,2], [3,0,-1,4], [5,0,6,2]], e);
+ } else if (action == accelDragSelect) {
+ accelDragSelect(e, 460, 500, 125);
+ checkRanges([[0,10,-1,2], [3,0,-1,4], [5,0,e.childNodes[5].firstChild,10], [6,8,6,10]], e);
+ } else {
+ action(e, 500, 125);
+ checkRangeCount(3, e);
+ checkRange(0, [0,10,-1,2], e);
+ checkRange(1, [3,0,-1,4], e);
+ checkRangePoints(2, [e.childNodes[5],0,e.childNodes[6],10], e);
+ }
+ } else if (test == "#next8") {
+ if (action == accelDragSelect) {
+ sel.removeAllRanges();
+ var e = document.querySelector('#select');
+ synthesizeMouse(e, 200, 60, {type: "mousedown", accelKey: true});
+ synthesizeMouse(e, 180, 60, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 80, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 100, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 120, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 190, 125, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 125, {type: "mousemove", accelKey: true});
+ synthesizeMouse(e, 200, 125, {type: "mouseup", accelKey: true});
+ var x3t = e.childNodes[3].firstChild;
+ var x5 = e.childNodes[5];
+ checkRanges([[x3t,3,-1,4], [x5,0,x5.firstChild,5]], e);
+ }
+ }
+ }
+ document.documentElement.removeAttribute("class");
+}
+
+SimpleTest.waitForFocus(function(){setTimeout(runTest,0)});
+
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/preserve3d_sorting_hit_testing2_iframe.html b/layout/base/tests/preserve3d_sorting_hit_testing2_iframe.html
new file mode 100644
index 000000000..e9fa71977
--- /dev/null
+++ b/layout/base/tests/preserve3d_sorting_hit_testing2_iframe.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<style>
+body {
+ background: #333;
+ overflow: hidden;
+}
+
+::-webkit-scrollbar {
+ display: none;
+}
+
+div {
+ margin: 0;
+ padding: 0;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d;
+ position: absolute;
+}
+
+#container {
+ font-family: UnifrakturMaguntia;
+ width: 350px;
+ height: 70%;
+ max-height: 500px;
+ -webkit-perspective: 5000px;
+ perspective: 5000px;
+ transform: translate(-50%, -50%) rotateY(20deg);
+}
+
+#container p {
+ padding: 0 5px 0 5px;
+}
+
+#container hr {
+ margin: 0 20px 0 20px;
+}
+
+#content {
+ -ms-overflow-style: none;
+ overflow: -moz-scrollbars-none;
+ overflow-y: scroll;
+ height: 100%;
+ background: #fefee0;
+}
+
+
+#lorem {
+ font-size: 7em;
+ float: left;
+ color: red;
+ border: 1px solid black;
+ margin-right: 5px;
+}
+
+#tree {
+ float: right;
+ width: 10em;
+ height: 10em;
+ border: 1px solid black;
+ margin: 0 5px 0 2px;
+}
+</style>
+</head>
+<body>
+ <div id="container">
+ <div id="content">
+ <p>
+ <span id="lorem">L</span>orem ipsum dolor sit amet, consectetur adipiscing elit. Integer sagittis nisi urna, a ultrices est facilisis a. Morbi porttitor vulputate odio, eu lacinia nisi. Suspendisse felis sapien, facilisis nec ex in, blandit tincidunt tellus. Sed at commodo nunc. In nibh lectus, facilisis nec magna nec, bibendum egestas nunc. Nam varius lorem in fringilla cursus. Integer dignissim, lectus vitae sodales molestie, libero purus malesuada arcu, vitae facilisis nunc dolor non mi. In nunc tortor, tempor non pharetra vitae, mattis a purus. Nulla rhoncus vitae metus vel ornare. Nunc augue dui, suscipit ac urna vel, consectetur volutpat ipsum. Nunc ac nulla ut enim laoreet placerat. Sed luctus aliquam purus, sollicitudin blandit dui blandit id. Aenean venenatis risus dolor, at viverra urna aliquam non. Morbi sit amet pellentesque justo, eget viverra augue.
+ </p>
+ <p>&nbsp;&nbsp;&nbsp;&nbsp;
+ Praesent posuere ultricies orci sit amet lacinia. Suspendisse lacinia scelerisque risus, sodales egestas turpis cursus sed. Proin sed mollis mauris, vitae ultricies nibh. Nulla bibendum leo a mauris luctus, sit amet iaculis arcu blandit. Etiam pulvinar, odio et rutrum egestas, elit mi maximus ex, id elementum est tortor id turpis. Duis rhoncus et lorem vel maximus. Aenean at justo sagittis, aliquet eros eget, iaculis magna. Nam non orci congue, dapibus dui eget, sagittis nisl. Phasellus venenatis id est et tempor. Aenean condimentum tristique nibh sit amet varius. Vestibulum et lectus quis eros dapibus consectetur nec auctor dolor. Sed euismod eu felis aliquam fermentum. Donec lacinia fringilla erat, at eleifend velit tempus at.
+ </p>
+ <hr>
+ <p>&nbsp;&nbsp;&nbsp;&nbsp;
+ Cras justo turpis, vulputate eget venenatis sit amet, bibendum quis dolor. Cras at interdum libero. Quisque convallis rutrum magna in ultrices. Donec ut magna dolor. Mauris pulvinar ut sapien a posuere. Sed nisi elit, tincidunt vitae magna eu, dapibus suscipit purus. Maecenas tincidunt mollis eros et dictum. Duis est nulla, rhoncus tincidunt velit at, venenatis elementum velit. Phasellus lobortis sem tellus, id sodales quam dignissim nec. Phasellus pulvinar metus ex, nec gravida nunc elementum vel. Ut mattis varius fringilla. Phasellus imperdiet sit amet risus a elementum. Donec pulvinar ante sit amet massa blandit ullamcorper. Donec vitae malesuada nisl, et laoreet sem.
+ </p>
+ <p>&nbsp;&nbsp;&nbsp;&nbsp;
+ Suspendisse bibendum elit blandit arcu vulputate, nec hendrerit dui vehicula. Vestibulum porta finibus odio vitae maximus. Duis in vulputate risus. Donec mattis turpis ex, vitae semper sem ultrices eu. Aliquam in ex blandit erat ultrices sollicitudin. Vestibulum porta nisl in porttitor rutrum. Integer consectetur porttitor ligula facilisis malesuada. Proin placerat enim sed lacus commodo mollis nec eu arcu. In hac habitasse platea dictumst. Curabitur luctus est risus, sit amet fringilla nunc condimentum vel. Integer mauris lorem, molestie ut nisl sit amet, pellentesque mollis quam. Aliquam posuere purus non nisi molestie semper.
+ </p>
+ <hr>
+ <p>&nbsp;&nbsp;&nbsp;&nbsp;
+ Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris facilisis nisi diam, eu pulvinar ex sollicitudin sed. Maecenas sed eros id quam suscipit ultricies ut tincidunt quam. Donec iaculis, justo at fringilla laoreet, quam sem dapibus urna, ut eleifend odio eros et ligula. Proin urna ante, condimentum vitae sollicitudin sit amet, egestas ac nunc. Aenean sapien velit, porta a eros quis, iaculis dignissim felis. Suspendisse mollis vulputate metus vel interdum. Aliquam hendrerit elementum erat, sit amet commodo velit suscipit et. Sed semper sem at mauris rhoncus, id efficitur arcu molestie. Nam feugiat lorem pretium, consectetur felis et, fringilla dolor. Nunc dui velit, elementum non hendrerit nec, sagittis vitae odio. Curabitur nec leo tincidunt, pellentesque metus at, condimentum risus.
+ </p>
+ </div>
+ </div>
+</body>
+
+<script type="application/javascript">
+ window.onload = function() {
+ opener.child_opened(document);
+ };
+</script>
+
+</html>
diff --git a/layout/base/tests/preserve3d_sorting_hit_testing_iframe.html b/layout/base/tests/preserve3d_sorting_hit_testing_iframe.html
new file mode 100644
index 000000000..01e605911
--- /dev/null
+++ b/layout/base/tests/preserve3d_sorting_hit_testing_iframe.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<title>preserve-3d hit testing</title>
+<style>
+ #stage {
+ }
+
+ #parent {
+ -moz-transform-style: preserve-3d;
+ }
+
+ #big {
+ width: 1000px;
+ height: 1000px;
+ background-color: #995C7F;
+ -moz-transform: translate3d(0px, 0px, 350px) rotatey(45deg);
+ }
+
+ #small {
+ width: 100px;
+ height: 100px;
+ background-color: #835A99;
+ -moz-transform: translate3d(600px, 200px, 350px);
+ }
+
+</style>
+<body>
+ <div id="stage">
+ <div id="parent">
+ <div id="small"></div>
+ <div id="big"></div>
+ </div>
+ </div>
diff --git a/layout/base/tests/resize_flush_iframe.html b/layout/base/tests/resize_flush_iframe.html
new file mode 100644
index 000000000..37555a514
--- /dev/null
+++ b/layout/base/tests/resize_flush_iframe.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+ <style>
+ body {
+ background-color: red;
+ }
+
+ @media (min-width: 250px) {
+ body {
+ background-color: green;
+ }
+ }
+ </style>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/base/tests/scroll_selection_into_view_window.html b/layout/base/tests/scroll_selection_into_view_window.html
new file mode 100644
index 000000000..46fbb0d19
--- /dev/null
+++ b/layout/base/tests/scroll_selection_into_view_window.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for scrolling selection into view</title>
+</head>
+<body onload="opener.doTest();">
+
+<div id="c1" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:200px; left:0;">
+ <div style="height:400px;"></div>
+ <div><span id="target1"
+ style="display:inline-block; vertical-align:top; height:20px;"></span>
+ </div>
+ <div style="height:400px;"></div>
+</div>
+<div id="c2" style="overflow:hidden; width:200px; height:200px; position:absolute; top:200px; left:200px;">
+ <div style="height:400px;"></div>
+ <div><span id="target2"
+ style="display:inline-block; vertical-align:top; height:20px;"></span>
+ </div>
+ <div style="height:400px;"></div>
+</div>
+<div id="c3" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:200px; left:400px;">
+ <div style="height:400px;"></div>
+ <div><span id="target3"
+ style="display:inline-block; vertical-align:top; height:300px;"></span>
+ </div>
+ <div style="height:400px;"></div>
+</div>
+<div id="c4" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:200px; left:600px;">
+ <iframe id="target4" style="border:none; width:100%; height:1100px; display:block;"
+ src="data:text/html,
+ <body style='margin:0; overflow:hidden;'>
+ <div style='height:400px;'></div>
+ <div><span id='target4'
+ style='display:inline-block; vertical-align:top; height:300px;'></span>
+ </div>
+ <div style='height:400px;'></div>">
+ </iframe>
+</div>
+<div id="c5" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:0;">
+ <div style="-moz-transform:translateY(400px); transform:translateY(400px)">
+ <span id="target5" style="display:inline-block; vertical-align:top; height:20px;"></span>
+ </div>
+ <div style="height:800px;"></div>
+</div>
+<div id="c6" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:200px;">
+ <div style="height:200px"></div>
+ <div style="height:100px; -moz-transform:scale(2); transform:scale(2)">
+ <span id="target6" style="display:inline-block; vertical-align:top; height:20px;"></span>
+ </div>
+ <div style="height:800px;"></div>
+</div>
+<div id="c7" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:400px;">
+ <div style="overflow:auto; height:200px; -moz-transform:translateY(400px); transform:translateY(400px)">
+ <div style="height:200px;"></div>
+ <div>
+ <span id="target7" style="display:inline-block; vertical-align:top; height:20px;"></span>
+ </div>
+ <div style="height:800px;"></div>
+ </div>
+ <div style="height:800px;"></div>
+</div>
+
+</body>
+
+</html>
diff --git a/layout/base/tests/selection-utils.js b/layout/base/tests/selection-utils.js
new file mode 100644
index 000000000..a14ff0d81
--- /dev/null
+++ b/layout/base/tests/selection-utils.js
@@ -0,0 +1,154 @@
+// -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
+// vim: set ts=2 sw=2 et tw=78:
+function clearSelection(w)
+{
+ var sel = (w ? w : window).getSelection();
+ sel.removeAllRanges();
+}
+
+function getNode(e, index) {
+ if (!(typeof index==='number')) return index;
+ if (index >= 0) return e.childNodes[index];
+ while (++index != 0) e = e.parentNode;
+ return e;
+}
+
+function dragSelectPointsWithData()
+{
+ var event = arguments[0];
+ var e = arguments[1];
+ var x1 = arguments[2];
+ var y1 = arguments[3];
+ var x2 = arguments[4];
+ var y2 = arguments[5];
+ dir = x2 > x1 ? 1 : -1;
+ event['type'] = "mousedown";
+ synthesizeMouse(e, x1, y1, event);
+ event['type'] = "mousemove";
+ synthesizeMouse(e, x1 + dir, y1, event);
+ for (var i = 6; i < arguments.length; ++i)
+ synthesizeMouse(e, arguments[i], y1, event);
+ synthesizeMouse(e, x2 - dir, y2, event);
+ event['type'] = "mouseup";
+ synthesizeMouse(e, x2, y2, event);
+}
+
+function dragSelectPoints()
+{
+ var args = Array.prototype.slice.call(arguments);
+ dragSelectPointsWithData.apply(this, [{}].concat(args));
+}
+
+function dragSelect()
+{
+ var args = Array.prototype.slice.call(arguments);
+ var e = args.shift();
+ var x1 = args.shift();
+ var x2 = args.shift();
+ dragSelectPointsWithData.apply(this, [{},e,x1,5,x2,5].concat(args));
+}
+
+function accelDragSelect()
+{
+ var args = Array.prototype.slice.call(arguments);
+ var e = args.shift();
+ var x1 = args.shift();
+ var x2 = args.shift();
+ var y = args.length != 0 ? args.shift() : 5;
+ dragSelectPointsWithData.apply(this, [{accelKey: true},e,x1,y,x2,y].concat(args));
+}
+
+function shiftClick(e, x, y)
+{
+ function pos(p) { return (typeof p === "undefined") ? 5 : p }
+ synthesizeMouse(e, pos(x), pos(y), { shiftKey: true });
+}
+
+function keyRepeat(key,data,repeat)
+{
+ while (repeat-- > 0)
+ synthesizeKey(key, data);
+}
+
+function keyRight(data)
+{
+ var repeat = arguments.length > 1 ? arguments[1] : 1;
+ keyRepeat("VK_RIGHT", data, repeat);
+}
+
+function keyLeft(data)
+{
+ var repeat = arguments.length > 1 ? arguments[1] : 1;
+ keyRepeat("VK_LEFT", data, repeat);
+}
+
+function shiftAccelClick(e, x, y)
+{
+ function pos(p) { return (typeof p === "undefined") ? 5 : p }
+ synthesizeMouse(e, pos(x), pos(y), { shiftKey: true, accelKey: true });
+}
+
+function accelClick(e, x, y)
+{
+ function pos(p) { return (typeof p === "undefined") ? 5 : p }
+ synthesizeMouse(e, pos(x), pos(y), { accelKey: true });
+}
+
+function addChildRanges(arr, e)
+{
+ var sel = window.getSelection();
+ for (i = 0; i < arr.length; ++i) {
+ var data = arr[i];
+ var r = new Range()
+ r.setStart(getNode(e, data[0]), data[1]);
+ r.setEnd(getNode(e, data[2]), data[3]);
+ sel.addRange(r);
+ }
+}
+
+function checkText(text, e)
+{
+ var sel = window.getSelection();
+ is(sel.toString(), text, e.id + ": selected text")
+}
+
+function checkRangeText(text, index)
+{
+ var r = window.getSelection().getRangeAt(index);
+ is(r.toString(), text, e.id + ": range["+index+"].toString()")
+}
+
+function checkRangeCount(n, e)
+{
+ var sel = window.getSelection();
+ is(sel.rangeCount, n, e.id + ": Selection range count");
+}
+
+function checkRangePoints(i, expected, e) {
+ var sel = window.getSelection();
+ if (i >= sel.rangeCount) return;
+ var r = sel.getRangeAt(i);
+ is(r.startContainer, expected[0], e.id + ": range.startContainer");
+ is(r.startOffset, expected[1], e.id + ": range.startOffset");
+ is(r.endContainer, expected[2], e.id + ": range.endContainer");
+ is(r.endOffset, expected[3], e.id + ": range.endOffset");
+}
+
+function checkRange(i, expected, e) {
+ var sel = window.getSelection();
+ if (i >= sel.rangeCount) return;
+ var r = sel.getRangeAt(i);
+ is(r.startContainer, getNode(e, expected[0]), e.id + ": range["+i+"].startContainer");
+ is(r.startOffset, expected[1], e.id + ": range["+i+"].startOffset");
+ is(r.endContainer, getNode(e, expected[2]), e.id + ": range["+i+"].endContainer");
+ is(r.endOffset, expected[3], e.id + ": range["+i+"].endOffset");
+}
+
+function checkRanges(arr, e)
+{
+ checkRangeCount(arr.length, e);
+ for (i = 0; i < arr.length; ++i) {
+ var expected = arr[i];
+ checkRange(i, expected, e);
+ }
+}
diff --git a/layout/base/tests/test_after_paint_pref.html b/layout/base/tests/test_after_paint_pref.html
new file mode 100644
index 000000000..33a8c7162
--- /dev/null
+++ b/layout/base/tests/test_after_paint_pref.html
@@ -0,0 +1,111 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=608030
+-->
+<head>
+ <title>Test for MozAfterPaint pref Bug 608030</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=608030">Mozilla Bug 608030</a>
+<div id="display" style="width: 10em; height: 5em; background-color: red"></div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 608030 **/
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+window.addEventListener("load", step0, false);
+
+is(SpecialPowers.getBoolPref("dom.send_after_paint_to_content"), true, "pref defaults to true in mochitest harness");
+
+function print_rect(rect) {
+ return "(top=" + rect.top + ",left=" + rect.left + ",width=" + rect.width + ",height=" + rect.height + ")";
+}
+
+function print_event(event) {
+ var res = "boundingClientRect=" + print_rect(event.boundingClientRect);
+ var rects = event.clientRects;
+ for (var i = 0; i < rects.length; ++i) {
+ res += " clientRects[" + i + "]=" + print_rect(rects[i]);
+ }
+ return res;
+}
+
+function step0(event) {
+ // Wait until we get the MozAfterPaint following the load event
+ // before starting.
+ ok(true, "loaded");
+ window.addEventListener("MozAfterPaint", step1, false);
+
+ // Ensure a MozAfterPaint event is fired
+ div.style.backgroundColor = "yellow";
+}
+
+var start;
+var div = document.getElementById("display");
+
+function step1(event)
+{
+ ok(true, "step1 reached: " + print_event(event));
+ window.removeEventListener("MozAfterPaint", step1, false);
+
+ start = Date.now();
+
+ window.addEventListener("MozAfterPaint", step2, false);
+
+ div.style.backgroundColor = "blue";
+}
+
+function step2(event)
+{
+ ok(true, "step2 reached: " + print_event(event));
+ window.removeEventListener("MozAfterPaint", step2, false);
+
+ var end = Date.now();
+ var timeout = 3 * Math.max(end - start, 300);
+
+ ok(true, "got MozAfterPaint (timeout for next step is " + timeout + "ms)");
+
+ // Set the pref for our second test
+
+ // When there was previously another page in our window, we seem to
+ // get duplicate events, simultaneously, so we need to register our
+ // next listener after a zero timeout.
+ SpecialPowers.pushPrefEnv({'set': [['dom.send_after_paint_to_content', false]]}, function() {setTimeout(step3, 0, timeout);});
+}
+function step3(timeout)
+{
+ ok(true, "step3 reached");
+ window.addEventListener("MozAfterPaint", failstep, false);
+
+ div.style.backgroundColor = "fuchsia";
+
+ setTimeout(step4, timeout);
+}
+
+function failstep(event)
+{
+ ok(true, "failstep reached: " + print_event(event));
+ ok(false, "got MozAfterPaint when we should not have");
+}
+
+function step4()
+{
+ ok(true, "step4 reached"); // If we didn't get the failure in failstep,
+ // then we passed.
+
+ window.removeEventListener("MozAfterPaint", failstep, false);
+
+ // Set the pref back in its initial state.
+ SpecialPowers.pushPrefEnv({'set': [['dom.send_after_paint_to_content', true]]}, SimpleTest.finish);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_border_radius_hit_testing.html b/layout/base/tests/test_border_radius_hit_testing.html
new file mode 100644
index 000000000..abb7a07db
--- /dev/null
+++ b/layout/base/tests/test_border_radius_hit_testing.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=595652
+-->
+<head>
+ <title>Test for Bug 595652</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595652">Mozilla Bug 595652</a>
+<iframe src="border_radius_hit_testing_iframe.html" id="iframe" height="600" width="500" style="border:none"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 595652 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run() {
+ var iframe = document.getElementById("iframe");
+
+ var doc = iframe.contentDocument;
+
+ var container = doc.body;
+ var one = doc.getElementById("one");
+ var two = doc.getElementById("two").firstChild;
+
+ //container.addEventListener("click", function(event) { alert(event.clientX + "," + event.clientY) }, false);
+
+ function check(x, y, expected_element, description)
+ {
+ is(doc.elementFromPoint(x, y), expected_element,
+ "point (" + x + ", " + y + "): " + description);
+ }
+
+ check(42, 6, container, "outside top left corner of #one");
+ check(11, 21, container, "outside top left corner of #one");
+ check(476, 10, container, "outside top right corner of #one");
+ check(495, 28, container, "outside top right corner of #one");
+ check(483, 197, container, "outside bottom right corner of #one");
+ check(497, 175, container, "outside bottom right corner of #one");
+ check(29, 182, container, "outside bottom left corner of #one");
+ check(73, 198, container, "outside bottom left corner of #one");
+
+ check(95, 2, one, "inside top left corner of #one (curved quadrant)");
+ check(16, 27, one, "inside top left corner of #one (curved quadrant)");
+ check(87, 37, one, "inside top left corner of #one (curved quadrant)");
+ check(465, 10, one, "inside top right corner of #one (curved quadrant)");
+ check(489, 33, one, "inside top right corner of #one (curved quadrant)");
+ check(443, 56, one, "inside top right corner of #one (curved quadrant)");
+ check(493, 167, one, "inside bottom right corner of #one (curved quadrant)");
+ check(476, 188, one, "inside bottom right corner of #one (curved quadrant)");
+ check(462, 144, one, "inside bottom right corner of #one (curved quadrant)");
+ check(74, 186, one, "inside bottom left corner of #one (curved quadrant)");
+ check(16, 153, one, "inside bottom left corner of #one (curved quadrant)");
+ check(112, 124, one, "inside bottom left corner of #one (curved quadrant)");
+
+ check(250, 1, one, "along top edge of #one");
+ check(250, 199, one, "along bottom edge of #one");
+ check(1, 100, one, "along left edge of #one");
+ check(499, 100, one, "along right edge of #one");
+ check(250, 100, one, "in center of #one");
+
+ check(2, 52, one, "inside top left corner of #one (left edge, outside ellipse)");
+ check(82, 52, one, "inside top left corner of #one (left edge, inside ellipse)");
+
+ check(42, 306, container, "outside top left corner of #two");
+ check(11, 321, container, "outside top left corner of #two");
+ check(476, 310, container, "outside top right corner of #two");
+ check(495, 328, container, "outside top right corner of #two");
+ check(483, 497, container, "outside bottom right corner of #two");
+ check(497, 475, container, "outside bottom right corner of #two");
+ check(29, 482, container, "outside bottom left corner of #two");
+ check(73, 498, container, "outside bottom left corner of #two");
+
+ check(95, 302, two, "inside top left corner of #two (curved quadrant)");
+ check(16, 327, two, "inside top left corner of #two (curved quadrant)");
+ check(87, 337, two, "inside top left corner of #two (curved quadrant)");
+ check(465, 310, two, "inside top right corner of #two (curved quadrant)");
+ check(489, 333, two, "inside top right corner of #two (curved quadrant)");
+ check(443, 356, two, "inside top right corner of #two (curved quadrant)");
+ check(493, 467, two, "inside bottom right corner of #two (curved quadrant)");
+ check(476, 488, two, "inside bottom right corner of #two (curved quadrant)");
+ check(462, 444, two, "inside bottom right corner of #two (curved quadrant)");
+ check(74, 486, two, "inside bottom left corner of #two (curved quadrant)");
+ check(16, 453, two, "inside bottom left corner of #two (curved quadrant)");
+ check(112, 424, two, "inside bottom left corner of #two (curved quadrant)");
+
+ check(250, 301, two, "along top edge of #two");
+ check(250, 499, two, "along bottom edge of #two");
+ check(1, 400, two, "along left edge of #two");
+ check(499, 400, two, "along right edge of #two");
+ check(250, 400, two, "in center of #two");
+
+ check(2, 352, two, "inside top left corner of #two (left edge, outside ellipse)");
+ check(82, 352, two, "inside top left corner of #two (left edge, inside ellipse)");
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug1078327.html b/layout/base/tests/test_bug1078327.html
new file mode 100644
index 000000000..ed0bc3bec
--- /dev/null
+++ b/layout/base/tests/test_bug1078327.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1078327
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1078327</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var iframe = undefined;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ iframe = document.getElementById("testFrame");
+ turnOnPointerEvents(startTest);
+ }
+ function turnOnPointerEvents(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, callback);
+ }
+ function startTest() {
+ iframe.src = "bug1078327_inner.html";
+ }
+ function finishTest() {
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug1080360.html b/layout/base/tests/test_bug1080360.html
new file mode 100644
index 000000000..f51d0b521
--- /dev/null
+++ b/layout/base/tests/test_bug1080360.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1080360
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1080360</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var iframe = undefined;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ iframe = document.getElementById("testFrame");
+ turnOnPointerEvents(startTest);
+ }
+ function turnOnPointerEvents(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, callback);
+ }
+ function startTest() {
+ iframe.src = "bug1080360_inner.html";
+ }
+ function finishTest() {
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug1080361.html b/layout/base/tests/test_bug1080361.html
new file mode 100644
index 000000000..91d42ddce
--- /dev/null
+++ b/layout/base/tests/test_bug1080361.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1080361
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1080361</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var iframe = undefined;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+ iframe = document.getElementById("testFrame");
+ turnOnPointerEvents(startTest);
+ }
+ function turnOnPointerEvents(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, callback);
+ }
+ function startTest() {
+ iframe.src = "bug1080361_inner.html";
+ }
+ function finishTest() {
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug1093686.html b/layout/base/tests/test_bug1093686.html
new file mode 100644
index 000000000..7b63f0ba5
--- /dev/null
+++ b/layout/base/tests/test_bug1093686.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1093686
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Testing effect of listener on body with respect to event retargeting</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var iframe = undefined;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ iframe = document.getElementById("testFrame");
+ turnOnEventRetargeting(startTest);
+ }
+ function turnOnEventRetargeting(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["ui.mouse.radius.enabled", true],
+ ["ui.mouse.radius.inputSource.touchOnly", false],
+ ["ui.mouse.radius.leftmm", 8],
+ ["ui.mouse.radius.topmm", 12],
+ ["ui.mouse.radius.rightmm", 8],
+ ["ui.mouse.radius.bottommm", 4]
+ ]
+ }, callback);
+ }
+ function startTest() {
+ iframe.src = "bug1093686_inner.html";
+ }
+ function finishTest() {
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug1120705.html b/layout/base/tests/test_bug1120705.html
new file mode 100644
index 000000000..c3cc343ac
--- /dev/null
+++ b/layout/base/tests/test_bug1120705.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 1120705</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<p id="display"></p>
+<select id="sel">
+ <option value="1">1</option>
+ <option value="2">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="11">11</option>
+ <option value="12">12</option>
+ <option value="13">13</option>
+ <option value="14">14</option>
+ <option value="15">15</option>
+ <option value="16">16</option>
+ <option value="17">17</option>
+ <option value="18">18</option>
+ <option value="19">19</option>
+ <option value="20">20</option>
+</select>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+
+function clickDownButton() {
+ var sel = document.getElementById("sel");
+ var scrollbar_width = sel.offsetWidth - sel.clientWidth;
+ synthesizeMouse(sel,
+ sel.offsetWidth - scrollbar_width / 2,
+ sel.offsetHeight - scrollbar_width / 2,
+ { type: "mousedown" });
+
+ synthesizeMouse(sel,
+ sel.offsetWidth - scrollbar_width / 2,
+ sel.offsetHeight - scrollbar_width / 2,
+ { type: "mouseup" });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+
+addLoadEvent(function() {
+ SpecialPowers.pushPrefEnv({
+ "set": [["general.smoothScroll", false],
+ ["toolkit.scrollbox.verticalScrollDistance", 3]]},
+ function() {
+ var sel = document.getElementById("sel");
+ sel.size = 2;
+ sel.scrollTo(0, 0);
+ clickDownButton();
+ window.requestAnimationFrame(function() {
+ var restricted_top = sel.scrollTop;
+ isnot(restricted_top, 0,
+ "Expected to scroll when clicking scrollbar button");
+ sel.size = 10;
+ sel.scrollTo(0, 0);
+ clickDownButton();
+ window.requestAnimationFrame(function() {
+ isnot(sel.scrollTop, restricted_top,
+ "Scrollbar button scrolling should be limited by page size");
+ SimpleTest.finish();
+ });
+ });
+ });
+});
+</script>
+</pre>
+</body>
+
+</html>
+
diff --git a/layout/base/tests/test_bug114649.html b/layout/base/tests/test_bug114649.html
new file mode 100644
index 000000000..ac11c2aba
--- /dev/null
+++ b/layout/base/tests/test_bug114649.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=114649
+-->
+<head>
+ <title>Test for Bug 114649</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=114649">Mozilla Bug 114649</a>
+<iframe id="display" style="width: 500px; height: 500px;"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 114649 **/
+
+var gIFrame;
+var gCurrentWidth = 500;
+var gGotEventsAt = [];
+var gInterval;
+
+function run() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+
+ gIFrame = document.getElementById("display");
+
+ var subdoc = gIFrame.contentDocument;
+ subdoc.open();
+ subdoc.write("<body onresize='window.parent.handle_child_resize()'>");
+ subdoc.close();
+
+ gInterval = window.setInterval(do_a_resize, 50);
+}
+
+function do_a_resize()
+{
+ // decrease the width by 10 until we hit 400, then stop
+ gCurrentWidth -= 10;
+ gIFrame.style.width = gCurrentWidth + "px";
+
+ if (gCurrentWidth == 400) {
+ window.clearInterval(gInterval);
+ window.setTimeout(check_for_resize_events, 250);
+ return;
+ }
+}
+
+function handle_child_resize()
+{
+ gGotEventsAt.push(gCurrentWidth);
+}
+
+function check_for_resize_events()
+{
+ ok(gGotEventsAt.length >= 2, "got continuous events");
+ isnot(gGotEventsAt[0], 400, "got continuous events");
+ is(gGotEventsAt[gGotEventsAt.length - 1], 400, "got last event");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug1153130.html b/layout/base/tests/test_bug1153130.html
new file mode 100644
index 000000000..c5482629e
--- /dev/null
+++ b/layout/base/tests/test_bug1153130.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1153130
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1153130</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var iframe = undefined;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ iframe = document.getElementById("testFrame");
+ turnOnPointerEvents(startTest);
+ }
+ function turnOnPointerEvents(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, callback);
+ }
+ function startTest() {
+ iframe.src = "bug1153130_inner.html";
+ }
+ function finishTest() {
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug1162990.html b/layout/base/tests/test_bug1162990.html
new file mode 100644
index 000000000..1b6c59851
--- /dev/null
+++ b/layout/base/tests/test_bug1162990.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1162990
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1162990</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var iframe;
+ var number = 0;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ iframe = document.getElementById("testFrame");
+ turnOnPointerEvents(finishTest);
+ }
+ function turnOnPointerEvents(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, callback);
+ }
+ function finishTest() {
+ // Try to run several tests named as bug1162990_inner_<number>.html
+ if(++number < 3)
+ iframe.src = "bug1162990_inner_" + number + ".html";
+ else
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug1226904.html b/layout/base/tests/test_bug1226904.html
new file mode 100644
index 000000000..caac899ab
--- /dev/null
+++ b/layout/base/tests/test_bug1226904.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=684759
+-->
+<head>
+ <title>Test for Bug 684759</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1226904">Mozilla Bug 1226904</a>
+<iframe src="bug1226904.html" id="iframe" height="1000" width="1000" style="border:none"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1226904 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run() {
+ var iframe = document.getElementById("iframe");
+ var doc = iframe.contentDocument;
+ var container = doc.getElementById("container");
+ var separator = doc.getElementById("separator");
+ var transformed = doc.getElementById("transformed");
+
+ function check(x, y, expected_element, description)
+ {
+ is(doc.elementFromPoint(x, y), expected_element,
+ "point (" + x + ", " + y + "): " + description);
+ }
+
+ check(600, 200, separator, "Separator object should be at right side");
+ check(900, 200, container, "Check bounds of separator object");
+ check(200, 600, transformed, "Transformed object should be at left side");
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug1246622.html b/layout/base/tests/test_bug1246622.html
new file mode 100644
index 000000000..78d51b145
--- /dev/null
+++ b/layout/base/tests/test_bug1246622.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test for Bug 1246622</title>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+ #grandparent {
+ position: absolute;
+ height: 100px;
+ width: 100px;
+ left: 400px;
+ transform-style: preserve-3d;
+ }
+
+ #parent {
+ transform: translateX(0px);
+ }
+
+ #child {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ transform-style: preserve-3d;
+ }
+ </style>
+</head>
+<body>
+<div id="grandparent">
+ <div id="parent">
+ <div id="child"></div>
+ </div>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1246622 **/
+
+is(document.elementFromPoint(450,50), document.getElementById("child"), "Able to hit transformed object");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug1278021.html b/layout/base/tests/test_bug1278021.html
new file mode 100644
index 000000000..f17ec9cf6
--- /dev/null
+++ b/layout/base/tests/test_bug1278021.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test for Bug 1278021</title>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style type="text/css">
+ #parent {
+ transform-style: preserve-3d;
+ }
+
+ #firstchild {
+ width: 100%;
+ height: 226px;
+ background-color: blue;
+ }
+
+ #secondchild {
+ display: block;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ }
+</style>
+</head>
+<body>
+<div id="parent">
+ <div id="firstchild"></div>
+ <div id="secondchild"></div>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1278021 **/
+
+is(document.elementFromPoint(50,50), document.getElementById("secondchild"), "Able to hit transformed object");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug332655-1.html b/layout/base/tests/test_bug332655-1.html
new file mode 100644
index 000000000..8110cbfd3
--- /dev/null
+++ b/layout/base/tests/test_bug332655-1.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=332655
+-->
+<head>
+ <title>Test for Bug 332655</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332655">Mozilla Bug 332655</a>
+<p id="display"></p>
+<div id="content">
+<input type="text" id="testInput"
+ style="-moz-appearance: none"> <!-- bug 1204897 workaround -->
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 332655 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function test() {
+ var textInput = $("testInput");
+ var s1, s2, s3, equal, str1, str2;
+
+ textInput.focus();
+ synthesizeKey("a", { });
+ synthesizeKey("b", { });
+ synthesizeKey(" ", { });
+ synthesizeKey("\u05d0", { });
+ synthesizeKey("\u05d1", { });
+ s1 = snapshotWindow(window);
+
+ synthesizeKey(" ", { });
+ s2 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s2, true);
+ ok(equal, "space after LTR + RTL shouldn't change direction: expected " +
+ str1 + " but got " + str2);
+
+ synthesizeKey("VK_BACK_SPACE", { });
+ s3 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s3, true);
+ ok(equal, "backspace should restore the status quo: expected " + str1 +
+ " but got " + str2);
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug332655-2.html b/layout/base/tests/test_bug332655-2.html
new file mode 100644
index 000000000..b4dac3691
--- /dev/null
+++ b/layout/base/tests/test_bug332655-2.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=332655
+-->
+<head>
+ <title>Test for Bug 332655</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332655">Mozilla Bug 332655</a>
+<p id="display"></p>
+<div id="content">
+<input type="text" id="testInput"
+ style="-moz-appearance: none"> <!-- bug 1234659 workaround -->
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 332655 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function repeatKey(key, repetitions) {
+ for (var i = 0; i < 4; ++i) {
+ synthesizeKey(key, {});
+ }
+}
+
+function test() {
+ var textInput = $("testInput");
+ var s1, s2, s3, equal, str1, str2;
+
+ textInput.focus();
+ synthesizeKey("\u05d0", { });
+ synthesizeKey("a", { });
+ synthesizeKey("b", { });
+ synthesizeKey(" ", { });
+ synthesizeKey("\u05d1", { });
+ synthesizeKey("\u05d2", { });
+ s1 = snapshotWindow(window);
+
+ // 4 LEFT to get to the beginning of the line: HOME doesn't work on OS X
+ repeatKey("VK_LEFT", 4);
+ synthesizeKey("VK_BACK_SPACE", { });
+ synthesizeKey("\u05d0", { });
+ s2 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s2, true);
+ ok(equal, "deleting and inserting RTL char at beginning of line shouldn't change: expected " +
+ str1 + " but got " + str2);
+
+ textInput.select();
+ synthesizeKey("a", { });
+ synthesizeKey("b", { });
+ synthesizeKey(" ", { });
+ synthesizeKey("\u05d1", { });
+ synthesizeKey("\u05d2", { });
+ // 4 LEFT to get to the beginning of the line: HOME doesn't work on OS X
+ repeatKey("VK_LEFT", 4);
+ synthesizeKey("\u05d0", { });
+
+ s3 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s3, true);
+ ok(equal, "the order entering Bidi text shouldn't change rendering: expected " +
+ str1 + " but got " + str2);
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug369950.html b/layout/base/tests/test_bug369950.html
new file mode 100644
index 000000000..374996103
--- /dev/null
+++ b/layout/base/tests/test_bug369950.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=369950
+-->
+<head>
+ <title>Test for Bug 369950</title>
+ <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=369950">Mozilla Bug 369950</a>
+<p id="display">
+ <iframe id="i" src="bug369950-subframe.xml" width="200" height="100"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 369950 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+ // Can't just run our code here, because we might not have painting
+ // unsuppressed yet. Do it async.
+ SimpleTest.executeSoon(doTheTest);
+});
+
+function doTheTest() {
+ // do a layout flush
+ var rect = $("i").getBoundingClientRect();
+ var rect2 = $("i").contentDocument.documentElement.getBoundingClientRect();
+
+ // And do the rest of it later
+ SimpleTest.executeSoon(reallyDoTheTest);
+}
+
+function reallyDoTheTest() {
+ var rect = $("i").getBoundingClientRect();
+ var rect2 = $("i").contentDocument.documentElement.getBoundingClientRect();
+
+ // We want coords relative to the iframe, so subtract off rect2.left/top.
+ // 7px is a guess to get us from the bottom of the iframe into the scrollbar
+ // groove for the horizontal scrollbar on the bottom.
+ synthesizeMouse($("i").contentDocument.documentElement,
+ -rect2.left + rect.width / 2, rect.height - rect2.top - 7,
+ {}, $("i").contentWindow);
+ // Scroll is async, so give it time
+ SimpleTest.executeSoon(checkScroll);
+};
+
+function checkScroll() {
+ // do a layout flush
+ var rect = $("i").getBoundingClientRect();
+ // And do the rest of it later
+ SimpleTest.executeSoon(reallyCheckScroll);
+}
+
+function reallyCheckScroll() {
+ var rect = $("i").getBoundingClientRect();
+ var rect2 = $("i").contentDocument.documentElement.getBoundingClientRect();
+ isnot($("i").contentWindow.scrollX, 0, "Clicking scrollbar should scroll");
+
+ // Not doing things below here, since avoiding the scroll arrows
+ // cross-platform is a huge pain.
+ SimpleTest.finish();
+ return;
+
+ // 8px horizontal offset is a guess to get us into the scr
+ synthesizeMouse($("i").contentDocument.documentElement, -rect2.left + 8,
+ rect.height - rect2.top - 7, {}, $("i").contentWindow);
+ // Scroll is async, so give it time
+ SimpleTest.executeSoon(finishUp);
+}
+
+function finishUp() {
+ is($("i").contentWindow.scrollX, 0, "Clicking scrollbar should scroll back");
+ SimpleTest.finish();
+};
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug370436.html b/layout/base/tests/test_bug370436.html
new file mode 100644
index 000000000..a3e8471bb
--- /dev/null
+++ b/layout/base/tests/test_bug370436.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=370436
+-->
+<head>
+ <title>Test for Bug 370436</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script class="testbody" type="application/javascript">
+<!--
+words = new Array()
+
+function expandStringOffsetToWord(data, offset)
+{
+ if (data == undefined) return "";
+
+ var m1 = data.substr(0, offset).match(/\w+$/) || "";
+ var m2 = data.substr(offset).match(/^\w+/) || "";
+ return m1 + m2;
+}
+
+function onContextMenu(e)
+{
+ var node = SpecialPowers.wrap(e).rangeParent;
+ var offset = e.rangeOffset;
+
+ var word = expandStringOffsetToWord(node.data, offset);
+ words.push(word);
+}
+
+function startTest()
+{
+ ta = document.getElementById('blah');
+ ta.focus();
+ ta.selectionStart = ta.selectionEnd = ta.value.length;
+
+// Note: This test, intentionally or by accident, relies on sending button '0'
+// with contextMenu, which triggers some key-equiv stuff in
+// PresShell::AdjustContextMenuKeyEvent.
+var mouseParams = { type: 'contextmenu', button: 0 };
+
+ /* Put cursor at start and middle of "sheep" */
+ synthesizeKey("VK_UP", {})
+ synthesizeMouse(ta, 0, 0, mouseParams);
+ synthesizeKey("VK_RIGHT", {})
+ synthesizeMouse(ta, 0, 0, mouseParams);
+ synthesizeKey("VK_RIGHT", {})
+ synthesizeMouse(ta, 0, 0, mouseParams);
+
+ /* Put cursor at the end of "hello" */
+ synthesizeKey("VK_UP", {})
+ synthesizeMouse(ta, 0, 0, mouseParams);
+ synthesizeKey("VK_RIGHT", {})
+ synthesizeKey("VK_RIGHT", {})
+ synthesizeKey("VK_RIGHT", {})
+ synthesizeMouse(ta, 0, 0, mouseParams);
+ synthesizeKey("VK_RIGHT", {})
+ synthesizeMouse(ta, 0, 0, mouseParams);
+
+ /* Put cursor on "welcome" */
+ synthesizeKey("VK_UP", {})
+ synthesizeMouse(ta, 0, 0, mouseParams);
+
+ is(words.pop(), "welcome", "Word 1 selected correctly");
+ is(words.pop(), "world" , "Word 2 selected correctly");
+ is(words.pop(), "hello" , "Word 3 selected correctly");
+ is(words.pop(), "hello" , "Word 4 selected correctly");
+ is(words.pop(), "sheep" , "Word 5 selected correctly");
+ is(words.pop(), "sheep" , "Word 6 selected correctly");
+ is(words.pop(), "sheep" , "Word 7 selected correctly");
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish()
+SimpleTest.waitForFocus(startTest)
+-->
+</script>
+
+<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=370436">Mozilla Bug 370436</a></p>
+
+<textarea id="blah" rows="10" cols="80" oncontextmenu="onContextMenu(event); return false;">
+welcome
+hello world
+sheep
+</textarea>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug386575.xhtml b/layout/base/tests/test_bug386575.xhtml
new file mode 100644
index 000000000..d9a278eff
--- /dev/null
+++ b/layout/base/tests/test_bug386575.xhtml
@@ -0,0 +1,46 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=386575
+-->
+<head>
+ <title>Test for Bug 386575</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386575">Mozilla Bug 386575</a>
+<p id="display">
+
+
+<!-- the image is http://dxr.mozilla.org/mozilla-central/source/layout/reftests/bugs/solidblue.png -->
+<!-- solidblue.png is a 16x16 image -->
+<table>
+ <tbody>
+ <div style="height:20px; min-height:100%">
+ <img src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%08%06%00%00%00%1F%F3%FFa%00%00%00%01sRGB%00%AE%CE%1C%E9%00%00%00%04gAMA%00%00%B1%8F%0B%FCa%05%00%00%00%20cHRM%00%00z%26%00%00%80%84%00%00%FA%00%00%00%80%E8%00%00u0%00%00%EA%60%00%00%3A%98%00%00%17p%9C%BAQ%3C%00%00%00%18tEXtSoftware%00Paint.NET%20v3.01%1C%AE%24E%00%00%00'IDAT8Ocd%10%AE%FF%CF%40%11%00%19%40%09%A6H3%D8%F5%94%D8%3Ej%00%24%F6F%03q4%0C%80%E9%00%00%D6%11y%92%15%8F%DC%CE%00%00%00%00IEND%AEB%60%82" style="height: 80%" />
+ </div>
+ </tbody>
+</table>
+
+
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 386575 **/
+
+
+SimpleTest.waitForExplicitFinish();
+ok(true,"This is an assertion test");
+SimpleTest.finish();
+
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug388019.html b/layout/base/tests/test_bug388019.html
new file mode 100644
index 000000000..c695822aa
--- /dev/null
+++ b/layout/base/tests/test_bug388019.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=388019
+-->
+<head>
+ <title>Test for Bug 388019</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388019">Mozilla Bug 388019</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 388019 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run()
+{
+ var oldY = window.scrollY;
+ window.location.hash="#abc";
+ var newY = window.scrollY;
+ isnot(oldY, newY, "we scroll at all");
+ ok(oldY + 4000 < newY, "we scroll at least 4000 pixels");
+ window.scrollTo(0, 0); // make the results visible
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+
+<div style="height:4000px"></div>
+<a name="abc"></a>You should see this text if you click on the link.
+<div style="height:4000px"></div>
+
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug394057.html b/layout/base/tests/test_bug394057.html
new file mode 100644
index 000000000..f36d73904
--- /dev/null
+++ b/layout/base/tests/test_bug394057.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html lang="en">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=394057
+-->
+<head>
+ <title>Test for Bug 394057</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <style type="text/css">
+
+ #display { background: yellow; color: black; font-family: serif; }
+
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=394057">Mozilla Bug 394057</a>
+<table id="display"><tr><td>MmMmMm...iiiIIIlll---</td></tr></table>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 394057 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var tableElement = document.getElementById("display");
+
+var CC = SpecialPowers.Cc;
+var CI = SpecialPowers.Ci;
+
+var fe =
+ CC["@mozilla.org/gfx/fontenumerator;1"].createInstance(CI.nsIFontEnumerator);
+var serifFonts = fe.EnumerateFonts("x-western", "serif", {});
+var monospaceFonts = fe.EnumerateFonts("x-western", "monospace", {});
+
+function table_width_for_font(font) {
+ tableElement.style.fontFamily = '"' + font + '"';
+ var result = tableElement.offsetWidth;
+ tableElement.style.fontFamily = "";
+ return result;
+}
+
+var serifIdx = 0;
+var monospaceIdx = 0;
+var monospaceWidth, serifWidth;
+monospaceWidth = table_width_for_font(monospaceFonts[monospaceIdx]);
+for (serifIdx in serifFonts) {
+ serifWidth = table_width_for_font(serifFonts[serifIdx]);
+ if (serifWidth != monospaceWidth)
+ break;
+}
+if (serifWidth == monospaceWidth) {
+ for (monospaceIdx in monospaceFonts) {
+ monospaceWidth = table_width_for_font(monospaceFonts[monospaceIdx]);
+ if (serifWidth != monospaceWidth)
+ break;
+ }
+}
+
+isnot(serifWidth, monospaceWidth,
+ "can't find serif and monospace fonts of different width");
+
+SpecialPowers.pushPrefEnv({'set': [['font.name.serif.x-western', serifFonts[serifIdx]]]}, step2);
+
+var serifWidthFromPref;
+function step2() {
+ serifWidthFromPref = tableElement.offsetWidth;
+ SpecialPowers.pushPrefEnv({'set': [['font.name.serif.x-western', monospaceFonts[monospaceIdx]]]}, step3);
+}
+var monospaceWidthFromPref;
+function step3() {
+ monospaceWidthFromPref = tableElement.offsetWidth;
+
+ is(serifWidthFromPref, serifWidth,
+ "changing font pref should change width of table (serif)");
+ is(monospaceWidthFromPref, monospaceWidth,
+ "changing font pref should change width of table (monospace)");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug399284.html b/layout/base/tests/test_bug399284.html
new file mode 100644
index 000000000..09d729742
--- /dev/null
+++ b/layout/base/tests/test_bug399284.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=399284
+-->
+<head>
+ <title>Test for Bug 399284</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=399284">Mozilla Bug 399284</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 399284 **/
+const testContent = "<p id='testPara'>The quick brown fox jumps over the lazy dog";
+
+var decoders = [
+ "Big5",
+ "Big5-HKSCS",
+ "EUC-JP",
+ "EUC-KR",
+ "gb18030",
+ "IBM866",
+ "ISO-2022-JP",
+ "ISO-8859-3",
+ "ISO-8859-4",
+ "ISO-8859-5",
+ "ISO-8859-6",
+ "ISO-8859-7",
+ "ISO-8859-8",
+ "ISO-8859-8-I",
+ "ISO-8859-10",
+ "ISO-8859-13",
+ "ISO-8859-14",
+ "ISO-8859-15",
+ "ISO-8859-16",
+ "ISO-8859-2",
+ "KOI8-R",
+ "KOI8-U",
+ "Shift_JIS",
+ "windows-1250",
+ "windows-1251",
+ "windows-1252",
+ "windows-1253",
+ "windows-1254",
+ "windows-1255",
+ "windows-1256",
+ "windows-1257",
+ "windows-1258",
+ "windows-874",
+ "x-mac-cyrillic",
+ "UTF-8",
+ "UTF-16LE",
+ "UTF-16BE"
+];
+
+var decoder;
+for (var i = 0; i < decoders.length; i++) {
+ var decoder = decoders[i];
+ var data;
+
+ // encode the content for non-ASCII compatible encodings
+ if (decoder == "UTF-16BE")
+ data = encodeUTF16BE(testContent);
+ else if (decoder == "UTF-16LE")
+ data = encodeUTF16LE(testContent);
+ else
+ data = encodeURI(testContent);
+ var dataURI = "data:text/html;charset=" + decoder + "," + data;
+
+ var testFrame = document.createElement("iframe");
+ frameID = decoder;
+ testFrame.setAttribute("id", frameID);
+ var testFrameObj = document.body.appendChild(testFrame);
+ testFrameObj.setAttribute("onload", "testFontSize('" + decoder + "')");
+ testFrameObj.contentDocument.location.assign(dataURI);
+}
+
+function encodeUTF16BE(string)
+{
+ var encodedString = "";
+ for (i = 0; i < string.length; ++i) {
+ encodedString += "%00";
+ encodedString += encodeURI(string.charAt(i));
+ }
+ return encodedString;
+}
+
+function encodeUTF16LE(string)
+{
+ var encodedString = "";
+ for (i = 0; i < string.length; ++i) {
+ encodedString += encodeURI(string.charAt(i));
+ encodedString += "%00";
+ }
+ return encodedString;
+}
+
+function testFontSize(frame)
+{
+ var iframeDoc = $(frame).contentDocument;
+ var size = parseInt(iframeDoc.defaultView.
+ getComputedStyle(iframeDoc.getElementById("testPara"),
+ null).
+ getPropertyValue("font-size"));
+ ok(size > 0, "font size assigned for " + frame);
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug399951.html b/layout/base/tests/test_bug399951.html
new file mode 100644
index 000000000..0d7ac83cc
--- /dev/null
+++ b/layout/base/tests/test_bug399951.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=399951
+-->
+<head>
+ <title>Test for Bug 399951</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body style="direction: rtl" onload="document.body.style.direction = 'ltr';">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=399951">Mozilla Bug 399951</a>
+<div style="white-space: pre;">
+.i
+ h
+ f
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ function test()
+{
+/** Test for Bug 399951 **/
+ ok(true, "Should not crash");
+ SimpleTest.finish();
+}
+
+ SimpleTest.requestFlakyTimeout("untriaged");
+ setTimeout(test, 500);
+ SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug404209.xhtml b/layout/base/tests/test_bug404209.xhtml
new file mode 100644
index 000000000..104fdc69e
--- /dev/null
+++ b/layout/base/tests/test_bug404209.xhtml
@@ -0,0 +1,47 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=404209
+-->
+<head>
+ <title>Test for Bug 404209</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <style type="text/css">
+ div::first-letter { color: green; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=404209">Mozilla Bug 404209</a>
+<table id="table" dir="rtl"><div><span id="v"><span><tfoot></tfoot>abcd</span></span></div></table>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+function boom1()
+{
+ document.getElementById("table").style.borderRight = "1px solid magenta";
+ setTimeout(boom2, 400);
+}
+
+function boom2()
+{
+ var v = document.getElementById("v");
+ var newTD = document.createElementNS("http://www.w3.org/1999/xhtml", "td");
+ newTD.setAttribute("width", "13%");
+ v.insertBefore(newTD, v.firstChild);
+ setTimeout(lastTest, 400);
+}
+
+function lastTest()
+{
+/** Test for Bug 404209 **/
+ ok(true, "Should not crash");
+ SimpleTest.finish();
+}
+
+ SimpleTest.requestFlakyTimeout("untriaged");
+ setTimeout(boom1, 400);
+ SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug416896.html b/layout/base/tests/test_bug416896.html
new file mode 100644
index 000000000..d77423275
--- /dev/null
+++ b/layout/base/tests/test_bug416896.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=416896
+-->
+<head>
+ <title>Test for Bug 416896</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <link rel="stylesheet" type="text/css" id="l"
+ href="data:text/css,a { color: green }"/>
+ <style type="text/css" id="i"> a { color: blue; } </style>
+
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=416896">Mozilla Bug 416896</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 416896 **/
+ var inlineSheet = $("i").sheet;
+ isnot(inlineSheet, null, "Should have sheet here");
+
+ var linkedSheet = $("l").sheet;
+ isnot(linkedSheet, null, "Should have sheet here");
+
+ var domUtils = SpecialPowers.Cc["@mozilla.org/inspector/dom-utils;1"]
+ .getService(SpecialPowers.Ci.inIDOMUtils);
+ const nsIDOMCSSStyleRule = SpecialPowers.Ci["nsIDOMCSSStyleRule"];
+ var inspectedRules = domUtils.getCSSStyleRules(document.links[0]);
+
+ var seenInline = false;
+ var seenLinked = false;
+
+ for (var i = 0; i < inspectedRules.Count(); ++i)
+ {
+ var rule =
+ SpecialPowers.unwrap(inspectedRules.GetElementAt(i).QueryInterface(nsIDOMCSSStyleRule));
+ var sheet = rule.parentStyleSheet;
+ if (sheet == inlineSheet) {
+ is(sheet.href, null, "It's an inline sheet");
+ is(seenInline, false, "Only one inline rule matches");
+ seenInline = true;
+ } else {
+ isnot(sheet.href, null, "Shouldn't have null href here");
+ if (sheet == linkedSheet) {
+ is(seenLinked, false, "Only one linked rule matches");
+ seenLinked = true;
+ }
+ }
+ }
+
+ is(seenLinked, true, "Didn't find the linked rule?");
+ is(seenInline, true, "Didn't find the inline rule?");
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug423523.html b/layout/base/tests/test_bug423523.html
new file mode 100644
index 000000000..c1fedf9ae
--- /dev/null
+++ b/layout/base/tests/test_bug423523.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=423523
+-->
+<head>
+ <title>Test for Bug 423523</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body onload="setTimeout(runtests, 200)">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=423523">Mozilla Bug 423523</a>
+<p id="display"></p>
+
+ <table>
+ <tbody><tr>
+ <td class="tdABB" id="tdTo">
+ <p id="par1">Some text...</p></td>
+ <td>
+ <div id="div1" style="border: 1px solid silver; width: 250px;" contenteditable="true">This is some editable text.</div>
+ </td></tr>
+ </tbody></table>
+
+
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 423523 **/
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+
+
+ function divIsFocused() {
+ // Check if div is directly focused.
+ var divNode = document.getElementById("div1");
+ if (window.getSelection().focusNode == divNode) {
+ return true;
+ }
+ // Check if one of the div's children has focus.
+ var node = window.getSelection().focusNode;
+ var childNodes = divNode.childNodes;
+ for (var i=0; i<childNodes.length; i++) {
+ if (childNodes[i] == node) {
+ return true;
+ }
+ }
+ // Not focused (at least not the first gen kids, and
+ // that's ok for this test).
+ return false;
+ }
+
+ function selectionOffsetIs(expectedOffset) {
+ return window.getSelection().focusOffset == expectedOffset;
+ }
+
+ function sendMouseClick() {
+ var rect=document.getElementById('div1').getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendMouseEvent('mousedown', rect.left+1, rect.top+1, 0, 1, 0);
+ utils.sendMouseEvent('mouseup', rect.left+1, rect.top+1, 0, 1, 0);
+ }
+
+ function runtests() {
+ sendMouseClick();
+ window.getSelection().collapse(document.getElementById("div1").firstChild, 0);
+ ok(divIsFocused(), "Div should be focused [0].");
+
+ ok(divIsFocused(), "Div should be focused [1].");
+ ok(selectionOffsetIs(0), "Caret should be at offset 0");
+
+ synthesizeKey("VK_LEFT", { });
+ ok(divIsFocused(), "Div should be focused [2].");
+ ok(selectionOffsetIs(0), "Caret should be at offset 0");
+
+ synthesizeKey("VK_RIGHT", { });
+ ok(divIsFocused(), "Div should be focused [3].");
+ ok(selectionOffsetIs(1), "Caret should be at offset 1");
+
+ synthesizeKey("VK_LEFT", { });
+ ok(divIsFocused(), "Div should be focused [4].");
+ ok(selectionOffsetIs(0), "Caret should be at offset 0");
+
+ ok(divIsFocused(), "Div should be focused [5].");
+ ok(selectionOffsetIs(0), "Caret should be at offset 0");
+ sendMouseClick();
+
+ ok(divIsFocused(), "Div should be focused [6].");
+ ok(selectionOffsetIs(0), "Caret should be at offset 0");
+ synthesizeKey("VK_LEFT", { });
+
+ ok(divIsFocused(), "Div should be focused [7].");
+ ok(selectionOffsetIs(0), "Caret should be at offset 0");
+ SimpleTest.finish();
+ }
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug435293-interaction.html b/layout/base/tests/test_bug435293-interaction.html
new file mode 100644
index 000000000..d004d7d59
--- /dev/null
+++ b/layout/base/tests/test_bug435293-interaction.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=435293
+-->
+<head>
+ <title>Test for Bug 435293</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style>
+ #test1 {
+ background: green;
+ height: 100px;
+ width: 100px;
+ -moz-transform: skew(30deg, 60deg) scale(2, 5) rotate(45deg) translate(2%, 50px);
+ -moz-transform-origin: 100% 50%;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435293">Mozilla Bug 435293</a>
+<div id="content">
+ <div id="test1" onclick="testFinish();">
+ test
+ </div>
+
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+runtests();
+
+function runtests() {
+ function doClick() {
+ sendMouseEvent({type: 'click'}, 'test1');
+ }
+ setTimeout(doClick, 300);
+}
+
+function testFinish(){
+ ok(1, "We can still interact with the item after it is transformed");
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug435293-scale.html b/layout/base/tests/test_bug435293-scale.html
new file mode 100644
index 000000000..91777af3c
--- /dev/null
+++ b/layout/base/tests/test_bug435293-scale.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=435293
+-->
+<head>
+ <title>Test for Bug 435293</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style>
+ .test {
+ background: green;
+ height: 100px;
+ width: 100px;
+ }
+ #test1 {
+ -moz-transform: scalex(0.5);
+ }
+ #test2 {
+ -moz-transform: scaley(0.5);
+ }
+ #test3 {
+ -moz-transform: scale(0.5, 0.5);
+ }
+ #test4 {
+ -moz-transform: scale(0.5, 0.5, 0.5);
+ }
+ #test5 {
+ -moz-transform: scale(80%, none);
+ }
+ #test6 {
+ -moz-transform: scale(640000, 0.0000000000000000001);
+ }
+ #test7 {
+ -moz-transform: scale(2em, 4px);
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435293">Mozilla Bug 435293</a>
+<p id="display"></p>
+<div id="content">
+ <div id="test1" class="test">
+ test
+ </div>
+ <p id="test2" class="test">
+ test
+ </p>
+ <div id="test3" class="test">
+ test
+ </div>
+ <div id="test4" class="test">
+ test
+ </div>
+ <div id="test5" class="test">
+ test
+ </div>
+ <div id="test6" class="test">
+ test
+ </div>
+ <div id="test7" class="test">
+ test
+ </div>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+runtests();
+
+function runtests() {
+ var style = window.getComputedStyle(document.getElementById("test1"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(0.5, 0, 0, 1, 0, 0)",
+ "Scalex proper matrix is applied");
+
+ style = window.getComputedStyle(document.getElementById("test2"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(1, 0, 0, 0.5, 0, 0)",
+ "Scaley proper matrix is applied");
+
+ style = window.getComputedStyle(document.getElementById("test3"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(0.5, 0, 0, 0.5, 0, 0)",
+ "Scale proper matrix is applied");
+
+ style = window.getComputedStyle(document.getElementById("test4"), "");
+ is(style.getPropertyValue("-moz-transform"), "none",
+ "Three dimensional scale should be ignored");
+
+ style = window.getComputedStyle(document.getElementById("test5"), "");
+ is(style.getPropertyValue("-moz-transform"), "none",
+ "Percent values in scale should be ignored");
+
+ style = window.getComputedStyle(document.getElementById("test6"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(640000, 0, 0, 1e-19, 0, 0)",
+ "Ensure wacky values are accepted");
+
+ style = window.getComputedStyle(document.getElementById("test7"), "");
+ is(style.getPropertyValue("-moz-transform"), "none",
+ "No unit values allowed in scale");
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug435293-skew.html b/layout/base/tests/test_bug435293-skew.html
new file mode 100644
index 000000000..287fdc085
--- /dev/null
+++ b/layout/base/tests/test_bug435293-skew.html
@@ -0,0 +1,173 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=435293
+-->
+<head>
+ <title>Test for Bug 435293</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style>
+ /* Skewed boxes can get very big. The .pane wrapper prevents them
+ from obscuring the test results. */
+ .pane {
+ height: 300px;
+ width: 300px;
+ float: left;
+ overflow: auto;
+ border: 1px solid black;
+ }
+ .test {
+ background: green;
+ height: 100px;
+ width: 100px;
+ margin: 100px;
+ }
+
+ /* Radian units are not used in this test because our CSS
+ implementation stores all dimensional values in single-
+ precision floating point, which makes it impossible to
+ hit mathematically interesting angles with radians.
+ Degrees and grads do not suffer this problem. */
+ #test1 {
+ -moz-transform: skewx(30deg);
+ }
+ #test2 {
+ -moz-transform: skewy(60deg);
+ }
+ #test3 {
+ -moz-transform: skew(45deg, 45deg);
+ }
+ #test4 {
+ -moz-transform: skew(360deg, 45deg);
+ }
+ #test5 {
+ -moz-transform: skew(45deg, 150grad);
+ }
+ #test6 {
+ -moz-transform: skew(80%, 78px);
+ }
+ #test7 {
+ -moz-transform: skew(2em, 40ex);
+ }
+ #test8 {
+ -moz-transform: skew(-45deg, -465deg);
+ }
+ #test9 {
+ -moz-transform: skew(30deg, 30deg, 30deg);
+ }
+
+ /* approach the singularity from the negative side */
+ #test10 {
+ -moz-transform: skew(50grad, 90.001deg);
+ }
+ #test11 {
+ -moz-transform: skew(300grad, 90.001deg);
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435293">Mozilla Bug 435293</a>
+<p id="display"></p>
+<div id="content">
+ <div class="pane"><div id="test1" class="test">test</div></div>
+ <div class="pane"><p id="test2" class="test">test</p></div>
+ <div class="pane"><div id="test3" class="test">test</div></div>
+ <div class="pane"><div id="test4" class="test">test</div></div>
+ <div class="pane"><div id="test5" class="test">test</div></div>
+ <div class="pane"><div id="test6" class="test">test</div></div>
+ <div class="pane"><div id="test7" class="test">test</div></div>
+ <div class="pane"><div id="test8" class="test">test</div></div>
+ <div class="pane"><div id="test9" class="test">test</div></div>
+ <div class="pane"><div id="test10" class="test">test</div></div>
+ <div class="pane"><div id="test11" class="test">test</div></div>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+runtests();
+
+function runtests() {
+ // For test 1 we need to handle the contingency that different systems may
+ // round differently. We will parse out the values and compare them
+ // individually. The matrix should be: matrix(1, 0, 0.57735, 1, 0, 0)
+ var style = window.getComputedStyle(document.getElementById("test1"), "");
+ var tformStyle = style.getPropertyValue("-moz-transform");
+ var tformValues = tformStyle.substring(tformStyle.indexOf('(') + 1,
+ tformStyle.indexOf(')')).split(',');
+ is((+tformValues[0]), 1, "Test1: skewx: param 0 is 1");
+ is((+tformValues[1]), 0, "Test1: skewx: param 1 is 0");
+ ok(verifyRounded(tformValues[2], 0.57735), "Test1: skewx: Rounded param 2 is in bounds");
+ is((+tformValues[3]), 1, "Test1: skewx: param 3 is 1");
+ is((+tformValues[4]), 0, "Test1: skewx: param 4 is 0");
+ is((+tformValues[5]), 0, "Test1: skewx: param 5 is 0");
+
+ // Again, handle rounding for test 2, proper matrix should be:
+ // matrix(1, 1.73205, 0, 1, 0, 0)
+ style = window.getComputedStyle(document.getElementById("test2"), "");
+ tformStyle = style.getPropertyValue("-moz-transform");
+ tformValues = tformStyle.substring(tformStyle.indexOf('(') + 1,
+ tformStyle.indexOf(')')).split(',');
+ is((+tformValues[0]), 1, "Test2: skewy: param 0 is 1");
+ ok(verifyRounded(tformValues[1], 1.73205), "Test2: skewy: Rounded param 1 is in bounds");
+ is((+tformValues[2]), 0, "Test2: skewy: param 2 is 0");
+ is((+tformValues[3]), 1, "Test2: skewy: param 3 is 1");
+ is((+tformValues[4]), 0, "Test2: skewy: param 4 is 0");
+ is((+tformValues[5]), 0, "Test2: skewy: param 5 is 0");
+
+ style = window.getComputedStyle(document.getElementById("test3"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(1, 1, 1, 1, 0, 0)",
+ "Test3: Skew proper matrix is applied");
+
+ style = window.getComputedStyle(document.getElementById("test4"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(1, 1, 0, 1, 0, 0)",
+ "Test4: Skew angle wrap: proper matrix is applied");
+
+ style = window.getComputedStyle(document.getElementById("test5"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(1, -1, 1, 1, 0, 0)",
+ "Test5: Skew mixing deg and grad");
+
+ style = window.getComputedStyle(document.getElementById("test6"), "");
+ is(style.getPropertyValue("-moz-transform"), "none",
+ "Test6: Skew with invalid units");
+
+ style = window.getComputedStyle(document.getElementById("test7"), "");
+ is(style.getPropertyValue("-moz-transform"), "none",
+ "Test7: Skew with more invalid units");
+
+ // Test 8: skew with negative degrees, here again we must handle rounding.
+ // The matrix should be: matrix(1, 3.73206, -1, 1, 0, 0)
+ style = window.getComputedStyle(document.getElementById("test8"), "");
+ tformStyle = style.getPropertyValue("-moz-transform");
+ tformValues = tformStyle.substring(tformStyle.indexOf('(') + 1,
+ tformStyle.indexOf(')')).split(',');
+ is((+tformValues[0]), 1, "Test8: Test skew with negative degrees-param 0 is 1");
+ ok(verifyRounded(tformValues[1], 3.73206), "Test8: Rounded param 1 is in bounds");
+ is((+tformValues[2]), -1, "Test8: param 2 is -1");
+ is((+tformValues[3]), 1, "Test8: param 3 is 1");
+ is((+tformValues[4]), 0, "Test8: param 4 is 0");
+ is((+tformValues[5]), 0, "Test8: param 5 is 0");
+
+ style = window.getComputedStyle(document.getElementById("test9"), "");
+ is(style.getPropertyValue("-moz-transform"), "none",
+ "Test9: Skew in 3d should be ignored");
+
+ style = window.getComputedStyle(document.getElementById("test10"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(1, -10000, 1, 1, 0, 0)",
+ "Test10: Skew with nearly infinite numbers");
+
+ style = window.getComputedStyle(document.getElementById("test11"), "");
+ is(style.getPropertyValue("-moz-transform"), "matrix(1, -10000, 10000, 1, 0, 0)",
+ "Test11: Skew with more infinite numbers");
+}
+
+// Verifies that aVal is +/- 0.00001 of aTrueVal
+// Returns true if so, false if not
+function verifyRounded(aVal, aTrueVal) {
+ return (Math.abs(aVal - aTrueVal).toFixed(5) <= 0.00001);
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug449781.html b/layout/base/tests/test_bug449781.html
new file mode 100644
index 000000000..ad32793b2
--- /dev/null
+++ b/layout/base/tests/test_bug449781.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=449781
+-->
+<head>
+ <title>Test for Bug 449781</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=449781">Mozilla Bug 449781</a>
+<p id="display">Canary</p>
+<iframe src="about:blank" id="ourFrame" style="visibility: hidden">
+</iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+var s1, s2, s3, s4;
+
+/** Test for Bug 449781 **/
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ s1 = snapshotWindow(window);
+
+ $("ourFrame").style.display = "none";
+ is($("ourFrame").offsetWidth, 0, "Unexpected width after hiding");
+ $("ourFrame").style.display = "";
+ is($("ourFrame").clientWidth, 300, "Unexpected width after showing");
+
+ s2 = snapshotWindow(window);
+
+ var equal, str1, str2;
+ [equal, str1, str2] = compareSnapshots(s1, s2, true);
+ ok(equal, "Show/hide should have no effect",
+ "got " + str1 + " but expected " + str2);
+
+ var viewer =
+ SpecialPowers.wrap($("ourFrame")).contentWindow
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .QueryInterface(SpecialPowers.Ci.nsIDocShell)
+ .contentViewer;
+ viewer.fullZoom = 2;
+
+ s3 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s3, true);
+ ok(equal, "Zoom should have no effect",
+ "got " + str1 + " but expected " + str2);
+
+ $("display").style.display = "none";
+
+ s4 = snapshotWindow(window);
+ [equal, str1, str2] = compareSnapshots(s3, s4, true);
+ ok(!equal, "Should be able to see the canary");
+
+ SimpleTest.finish();
+});
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug450930.xhtml b/layout/base/tests/test_bug450930.xhtml
new file mode 100644
index 000000000..7162fc123
--- /dev/null
+++ b/layout/base/tests/test_bug450930.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=450930
+-->
+<head>
+ <title>Test for Bug 450930 (MozAfterPaint)</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript"><![CDATA[
+
+/** Test for Bug 450930 **/
+SimpleTest.waitForExplicitFinish();
+var subwindow = window.open("./bug450930.xhtml", "bug450930", "width=800,height=1000");
+
+function finishTests() {
+ subwindow.close();
+ SimpleTest.finish();
+}
+
+]]></script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug465448.xul b/layout/base/tests/test_bug465448.xul
new file mode 100644
index 000000000..8a09158fa
--- /dev/null
+++ b/layout/base/tests/test_bug465448.xul
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
+
+<window title="Bug 465448"
+ onload="loaded()"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+
+<script><![CDATA[
+SimpleTest.waitForExplicitFinish();
+var loadedCalled = false;
+var win = window.open("data:text/html,<body onload='window.opener.loaded()'><div style='height:200px; width:100px;'>", "_blank", "width=600,height=600");
+
+function loaded() {
+ if (!loadedCalled) {
+ loadedCalled = true;
+ return;
+ }
+ win.sizeToContent();
+ win.sizeToContent();
+ win.sizeToContent();
+ win.sizeToContent();
+ win.sizeToContent();
+ win.sizeToContent();
+ ok(win.innerWidth >= 100, "innerWidth");
+ ok(win.innerHeight >= 200, "innerHeight");
+ win.close();
+ SimpleTest.finish();
+}
+]]></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+</window>
diff --git a/layout/base/tests/test_bug469170.html b/layout/base/tests/test_bug469170.html
new file mode 100644
index 000000000..13f79d39c
--- /dev/null
+++ b/layout/base/tests/test_bug469170.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=469170
+-->
+<head>
+ <title>Test for Bug 469170</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTest();">
+<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469170">Mozilla Bug 469170</a></p>
+
+<iframe id="source" width="50" height="50"
+ src="data:text/html,%3Chtml%3E%3C%2Fhtml%3E"></iframe>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 469170 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+ var source = document.getElementById('source').contentWindow;
+ rect = { left: 0, top: 0,
+ width: source.innerWidth, height: source.innerHeight };
+ var canvas = SpecialPowers.snapshotRect(source, rect, "transparent");
+ var context = canvas.getContext("2d");
+
+ var components = [ "red", "green", "blue", "alpha" ];
+
+ var data = context.getImageData(0, 0, canvas.width, canvas.height).data;
+ var failed = false;
+ for (var i = 0; i < data.length; i++) {
+ if (data[i] != 0) {
+ is(data[i], 0, "pixel " + Math.floor(i/4) + " " + components[i%4]);
+ failed = true;
+ }
+ }
+ if (!failed) {
+ ok(!failed, "all pixels fully transparent");
+ }
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug471126.html b/layout/base/tests/test_bug471126.html
new file mode 100644
index 000000000..df7479e50
--- /dev/null
+++ b/layout/base/tests/test_bug471126.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=471126
+-->
+<head>
+ <title>Test for Bug 471126</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=471126">Mozilla Bug 471126</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 471126 **/
+
+function test()
+{
+ var selection = window.getSelection();
+ selection.collapse(document.documentElement, 0);
+ document.documentElement.addEventListener("click", function(){ var foo = window; }, false);
+}
+test();
+ok(true, "Shouldn't leak");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug499538-1.html b/layout/base/tests/test_bug499538-1.html
new file mode 100644
index 000000000..054ce726e
--- /dev/null
+++ b/layout/base/tests/test_bug499538-1.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=499538
+-->
+<head>
+ <title>Test for Bug 499538</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=499538">Mozilla Bug 499538</a>
+<p id="display"></p>
+<div id="content">
+<input type="text" id="testInput" style="-moz-appearance:none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 499538 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function test() {
+ var textInput = $("testInput");
+ var s1, s2, s3, equal, str1, str2;
+
+ textInput.focus();
+ synthesizeKey("a", { });
+ synthesizeKey(" ", { });
+ synthesizeKey("\u0639", { });
+ synthesizeKey("\u063A", { });
+ synthesizeKey(" ", { });
+ synthesizeKey("b", { });
+ s1 = snapshotWindow(window);
+
+ textInput.select();
+ synthesizeKey("a", { });
+ synthesizeKey(" ", { });
+ synthesizeKey(" ", { });
+ synthesizeKey("b", { });
+ synthesizeKey("VK_LEFT", { });
+ synthesizeKey("VK_LEFT", { });
+ synthesizeKey("\u0639", { });
+ synthesizeKey("\u063A", { });
+ s2 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s2, true);
+ ok(equal, "Arabic text between English words not connected: expected " +
+ str1 + " but got " + str2);
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug514127.html b/layout/base/tests/test_bug514127.html
new file mode 100644
index 000000000..a8ca40f59
--- /dev/null
+++ b/layout/base/tests/test_bug514127.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=514127
+-->
+<head>
+ <title>Test for Bug 514127</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTest();">
+<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=514127">Mozilla Bug 514127</a></p>
+
+<!--
+iframe source is
+<html><body style='background: rgb(0,0,255); width: 100px; height: 50100px;'></body></html>
+-->
+<iframe id="source" width="50" height="50"
+ src="data:text/html,%3Chtml%3E%3Cbody%20style%3D%27background%3A%20rgb%280%2C0%2C255%29%3B%20width%3A%20100px%3B%20height%3A%2050100px%3B%27%3E%3C%2Fbody%3E%3C%2Fhtml%3E"></iframe>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 514127 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+
+ var source = document.getElementById('source').contentWindow;
+ var canvasWidth = 50;
+ var canvasHeight = 50;
+
+ rect = { left: 25, top: 50000,
+ width: canvasWidth, height: canvasHeight };
+ var canvas = SpecialPowers.snapshotRect(source, rect, "transparent");
+ var context = canvas.getContext("2d");
+
+ var data = context.getImageData(0, 0, canvasWidth, canvasHeight).data;
+ var failed = false;
+ for (var i = 0; i < data.length; i+=4) {
+ if (data[i] != 0 || data[i+1] != 0 || data[i+2] != 255 || data[i+3] != 255) {
+ failed = true;
+ break;
+ }
+ }
+ ok(!failed, "all pixels blue");
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug518777.html b/layout/base/tests/test_bug518777.html
new file mode 100644
index 000000000..298f18d24
--- /dev/null
+++ b/layout/base/tests/test_bug518777.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=518777
+-->
+<head>
+ <title>Test for Bug 518777</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+ <script>
+ SimpleTest.waitForExplicitFinish();
+
+ function dotest() {
+ var canvasWidth = 50;
+ var canvasHeight = 50;
+ var source = document.getElementById("source").contentWindow;
+ rect = { left: 25, top: 25,
+ width: canvasWidth, height: canvasHeight };
+ var canvas = SpecialPowers.snapshotRect(source, rect, "transparent");
+ var context = canvas.getContext("2d");
+
+ var data = context.getImageData(0, 0, canvasWidth, canvasHeight).data;
+ var i;
+ for (i = 0; i < data.length; i += 4) {
+ if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 255 || data[i + 3] != 255)
+ break;
+ }
+ ok(i >= data.length, "all pixels blue");
+
+ SimpleTest.finish();
+ }
+ </script>
+</head>
+<body>
+<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=518777">Mozilla Bug 518777</a></p>
+
+<!--
+iframe source is
+<html><body onload='window.scrollTo(0,99999999); document.documentElement.offsetWidth; window.parent.dotest();' style='background: rgb(0,0,255); width: 100px; height: 50100px;'></body></html>
+-->
+<iframe id="source" width="50" height="50"
+ src="data:text/html,%3Chtml%3E%3Cbody%20onload%3D%27window.scrollTo%280%2C99999999%29%3B%20document.documentElement.offsetWidth%3B%20window.parent.dotest%28%29%3B%27%20style%3D%27background%3A%20rgb%280%2C0%2C255%29%3B%20width%3A%20100px%3B%20height%3A%2050100px%3B%27%3E%3C%2Fbody%3E%3C%2Fhtml%3E"></iframe>
+
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug548545.xhtml b/layout/base/tests/test_bug548545.xhtml
new file mode 100644
index 000000000..039a07de4
--- /dev/null
+++ b/layout/base/tests/test_bug548545.xhtml
@@ -0,0 +1,47 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=548545
+-->
+<head>
+ <title>Test for Bug 548545</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <style type="text/css">
+ #content { margin: 1em; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=548545">Mozilla Bug 548545</a>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+/** Test for Bug 548545 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var content = document.getElementById("content");
+
+var CC = SpecialPowers.Cc;
+var CI = SpecialPowers.Ci;
+
+var fe =
+ CC["@mozilla.org/gfx/fontenumerator;1"].createInstance(CI.nsIFontEnumerator);
+var allFonts = fe.EnumerateFonts(null, null, {});
+
+var idx = 0;
+var list = "";
+for (idx in allFonts) {
+ list += allFonts[idx] + "<br/>";
+}
+content.innerHTML = list;
+
+ok(true,"Loaded the font list");
+SimpleTest.finish();
+
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug558663.html b/layout/base/tests/test_bug558663.html
new file mode 100644
index 000000000..2e20deec3
--- /dev/null
+++ b/layout/base/tests/test_bug558663.html
@@ -0,0 +1,37 @@
+<!-- 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/. -->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Bug 558663 test</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ iframe {
+ width: 600px;
+ height: 400px;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="container"></div>
+ </body>
+ <script>
+ if (navigator.platform.startsWith("Linux")) {
+ // For e10s issue of bug 966157
+ SimpleTest.expectAssertions(0, 2);
+ }
+ SimpleTest.waitForExplicitFinish();
+ // AccessibleCaret's pref is checked only when PresShell is initialized. To turn
+ // off the pref, we test bug 558663 in an iframe.
+ SpecialPowers.pushPrefEnv({"set": [['layout.accessiblecaret.enabled', false]]}, function() {
+ var iframe = document.createElement("iframe");
+ iframe.src = "bug558663.html";
+ document.getElementById('container').appendChild(iframe);
+ });
+ </script>
+</html>
diff --git a/layout/base/tests/test_bug559499.html b/layout/base/tests/test_bug559499.html
new file mode 100644
index 000000000..e7c81b282
--- /dev/null
+++ b/layout/base/tests/test_bug559499.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html style="background:yellow">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=559499
+-->
+<head>
+ <title>Test for Bug 559499</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body style="position:relative; z-index:-1; padding-top:100px;">
+<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=559499">Mozilla Bug 514127</a></p>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 559499 **/
+
+is(document.elementFromPoint(50, 50), document.body, "Able to hit body");
+document.documentElement.style.display = "table";
+is(document.elementFromPoint(50, 50), document.body, "Able to hit body (table)");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug569520.html b/layout/base/tests/test_bug569520.html
new file mode 100644
index 000000000..cd6e5ad86
--- /dev/null
+++ b/layout/base/tests/test_bug569520.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=569520
+-->
+<head>
+ <title>Test for Bug 569520</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=569520">Mozilla Bug 569520</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 569520 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var start = window.performance.now();
+var firstListenerArg;
+var secondListenerArg;
+var thirdListenerTime;
+
+// callback arg is in the same timeline as performance.now()
+function thirdListener(t) {
+ thirdListenerTime = t;
+
+ ok(secondListenerArg >= firstListenerArg, // callback args from consecutive requestAnimationFrame
+ "Second listener should fire after first listener");
+
+ ok(thirdListenerTime >= secondListenerArg,
+ "Third listener should fire after second listener");
+
+ ok(firstListenerArg >= start, "First listener should fire after start");
+
+ SimpleTest.finish();
+}
+
+// callback arg is from requestAnimationFrame and comparable to performance.now()
+function secondListener(t) {
+ secondListenerArg = t;
+ requestAnimationFrame(thirdListener);
+}
+
+function firstListener(t) {
+ firstListenerArg = t;
+ requestAnimationFrame(secondListener);
+}
+
+addLoadEvent(function() {
+ setTimeout(function() {
+ requestAnimationFrame(firstListener);
+ }, 100);
+ });
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug582181-1.html b/layout/base/tests/test_bug582181-1.html
new file mode 100644
index 000000000..c2cd399bd
--- /dev/null
+++ b/layout/base/tests/test_bug582181-1.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=582181
+-->
+<head>
+ <title>Test for Bug 582181</title>
+ <meta charset="utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=582181">Mozilla Bug 582181</a>
+<p id="display"></p>
+<div id="content" dir="rtl">
+<textarea rows="4" style="resize: none" id="testInput">فارسی
+[[en:Farsi]]</textarea>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 582181 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function test() {
+ var textInput = $("testInput");
+ var s1, s2, s3, equal, str1, str2;
+
+ s1 = snapshotWindow(window);
+
+ textInput.focus();
+ synthesizeKey("VK_DOWN", { });
+ synthesizeKey("VK_DOWN", { });
+ synthesizeKey("VK_RETURN", { });
+ textInput.blur();
+ s2 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s2, true);
+ ok(equal, "enter after text shouldn't change rendering: expected " +
+ str1 + " but got " + str2);
+
+ textInput.focus();
+ synthesizeKey("VK_BACK_SPACE", { });
+ textInput.blur();
+ s3 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s3, true);
+ ok(equal, "backspace shouldn't change rendering: expected " + str1 +
+ " but got " + str2);
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug582181-2.html b/layout/base/tests/test_bug582181-2.html
new file mode 100644
index 000000000..9577991ae
--- /dev/null
+++ b/layout/base/tests/test_bug582181-2.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=582181
+-->
+<head>
+ <title>Test for Bug 582181</title>
+ <meta charset="utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=582181">Mozilla Bug 582181</a>
+<p id="display"></p>
+<div id="content" dir="rtl">
+<textarea rows="5" id="testInput" style="resize:none">Blah blah
+فلان فلان
+&lt;ref&gt;ooo&lt;/ref&gt;
+&lt;references /&gt;</textarea>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 582181 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function test() {
+ var textInput = $("testInput");
+ var s1, s2, s3, equal, str1, str2;
+
+ s1 = snapshotWindow(window);
+
+ textInput.focus();
+ synthesizeKey("VK_DOWN", { });
+ synthesizeKey("VK_DOWN", { });
+ synthesizeKey("VK_DOWN", { });
+ synthesizeKey("VK_DOWN", { });
+ synthesizeKey("VK_BACK_SPACE", { });
+ textInput.blur();
+ s2 = snapshotWindow(window);
+
+ [unequal, str1, str2] = compareSnapshots(s1, s2, false);
+ ok(unequal, "backspace after text should change rendering: got " + str2);
+
+ textInput.focus();
+ synthesizeKey(">", { });
+ textInput.blur();
+ s3 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s3, true);
+ ok(equal, "entering '>' should restore original rendering: expected " + str1 +
+ " but got " + str2);
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug582771.html b/layout/base/tests/test_bug582771.html
new file mode 100644
index 000000000..17781643c
--- /dev/null
+++ b/layout/base/tests/test_bug582771.html
@@ -0,0 +1,128 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=582771
+-->
+<head>
+ <title>Test for Bug 582771</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .test {
+ width: 20px;
+ height: 20px;
+ border: 1px solid black;
+ -moz-user-select: none;
+ }
+ </style>
+</head>
+<body onload="setTimeout('runTest()', 0)">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=582771">Mozilla Bug 582771</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 582771 **/
+
+SimpleTest.waitForExplicitFinish();
+var d1;
+var d2;
+var d1mousemovecount = 0;
+var d2mousemovecount = 0;
+
+function sendMouseMove(el) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendMouseEvent('mousemove', rect.left + 5, rect.top + 5, 0, 0, 0);
+}
+
+function sendMouseDown(el) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendMouseEvent('mousedown', rect.left + 5, rect.top + 5, 0, 1, 0);
+}
+
+function sendMouseUp(el) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendMouseEvent('mouseup', rect.left + 5, rect.top + 5, 0, 1, 0);
+}
+
+function log(s) {
+ document.getElementById("l").textContent += s + "\n";
+}
+
+function d2Listener(e) {
+ log(e.type + ", " + e.target.id);
+ is(e.target, d2, "d2 should have got mousemove.");
+ ++d2mousemovecount;
+}
+
+function d1Listener(e) {
+ log(e.type + ", " + e.target.id);
+ d1.setCapture(true);
+}
+
+function d1Listener2(e) {
+ log(e.type + ", " + e.target.id);
+ d2.setCapture(true);
+}
+
+function d1MouseMoveListener(e) {
+ log(e.type + ", " + e.target.id);
+ ++d1mousemovecount;
+}
+
+function runTest() {
+ d1 = document.getElementById("d1");
+ d2 = document.getElementById("d2");
+ d2.addEventListener("mousemove", d2Listener, true);
+ document.body.offsetLeft;
+ sendMouseMove(d2);
+ is(d2mousemovecount, 1, "Should have got mousemove");
+
+ // This shouldn't enable capturing, since we're not in a right kind of
+ // event listener.
+ d1.setCapture(true);
+ sendMouseDown(d1);
+ sendMouseMove(d2);
+ sendMouseUp(d1);
+ is(d2mousemovecount, 2, "Should have got mousemove");
+
+ d1.addEventListener("mousedown", d1Listener, true);
+ d1.addEventListener("mousemove", d1MouseMoveListener, true);
+ sendMouseDown(d1);
+ sendMouseMove(d2);
+ is(d2mousemovecount, 2, "Shouldn't have got mousemove");
+ is(d1mousemovecount, 1, "Should have got mousemove");
+ sendMouseUp(d1);
+ d1.removeEventListener("mousedown", d1Listener, true);
+ d1.removeEventListener("mousemove", d1MouseMoveListener, true);
+
+ // Nothing should be capturing the event.
+ sendMouseMove(d2);
+ is(d2mousemovecount, 3, "Should have got mousemove");
+
+
+ d1.addEventListener("mousemove", d1Listener2, true);
+ sendMouseDown(d1);
+ sendMouseMove(d1); // This should call setCapture to d2!
+ d1.removeEventListener("mousemove", d1Listener2, true);
+ d1.addEventListener("mousemove", d1MouseMoveListener, true);
+ sendMouseMove(d1); // This should send mouse event to d2.
+ is(d1mousemovecount, 1, "Shouldn't have got mousemove");
+ is(d2mousemovecount, 4, "Should have got mousemove");
+ sendMouseUp(d1);
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+<div class="test" id="d1">&nbsp;</div><br><div class="test" id="d2">&nbsp;</div>
+<pre id="l"></pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug583889.html b/layout/base/tests/test_bug583889.html
new file mode 100644
index 000000000..163c0f1db
--- /dev/null
+++ b/layout/base/tests/test_bug583889.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=583889
+-->
+<head>
+ <title>Test for Bug 583889</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583889">Mozilla Bug 583889</a>
+<iframe id="inner" style="width: 10px; height: 10px;"></iframe>
+<pre id="test">
+<script type="application/javascript;version=1.8">
+
+/** Test for Bug 583889 **/
+SimpleTest.waitForExplicitFinish();
+
+function grabEventAndGo(event) {
+ gen.send(event);
+}
+
+function runTest() {
+ window.onload = grabEventAndGo;
+ // Wait for onLoad event.
+ yield;
+
+ var inner = $("inner");
+ inner.src = "bug583889_inner1.html";
+ window.onmessage = grabEventAndGo;
+ // Wait for message from 'inner' iframe.
+ event = yield;
+
+ while (event.data != "done") {
+ data = JSON.parse(event.data);
+ is(data.top, 300, "should remain at same top");
+ is(data.left, 300, "should remain at same left");
+
+ // Wait for message from 'inner' iframe.
+ event = yield;
+ }
+
+ // finish(), yet let the test actually end first, to be safe.
+ SimpleTest.executeSoon(SimpleTest.finish);
+ // "End" generator.
+ yield;
+}
+
+var gen = runTest();
+gen.next();
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug588174.html b/layout/base/tests/test_bug588174.html
new file mode 100644
index 000000000..cd6e5ad86
--- /dev/null
+++ b/layout/base/tests/test_bug588174.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=569520
+-->
+<head>
+ <title>Test for Bug 569520</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=569520">Mozilla Bug 569520</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 569520 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var start = window.performance.now();
+var firstListenerArg;
+var secondListenerArg;
+var thirdListenerTime;
+
+// callback arg is in the same timeline as performance.now()
+function thirdListener(t) {
+ thirdListenerTime = t;
+
+ ok(secondListenerArg >= firstListenerArg, // callback args from consecutive requestAnimationFrame
+ "Second listener should fire after first listener");
+
+ ok(thirdListenerTime >= secondListenerArg,
+ "Third listener should fire after second listener");
+
+ ok(firstListenerArg >= start, "First listener should fire after start");
+
+ SimpleTest.finish();
+}
+
+// callback arg is from requestAnimationFrame and comparable to performance.now()
+function secondListener(t) {
+ secondListenerArg = t;
+ requestAnimationFrame(thirdListener);
+}
+
+function firstListener(t) {
+ firstListenerArg = t;
+ requestAnimationFrame(secondListener);
+}
+
+addLoadEvent(function() {
+ setTimeout(function() {
+ requestAnimationFrame(firstListener);
+ }, 100);
+ });
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug603550.html b/layout/base/tests/test_bug603550.html
new file mode 100644
index 000000000..0df24f28b
--- /dev/null
+++ b/layout/base/tests/test_bug603550.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=603550
+-->
+<head>
+ <title>Test for Bug 603550</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .test {
+ width: 20px;
+ height: 20px;
+ border: 1px solid black;
+ -moz-user-select: none;
+ }
+ </style>
+</head>
+<body onload="setTimeout('runTest()', 0)">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=603550">Mozilla Bug 603550</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 603550 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function sendMouseMoveFaraway(el) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendMouseEvent('mousemove', rect.left + 5000, rect.top + 5000, 0, 0, 0);
+}
+
+function sendMouseDown(el) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendMouseEvent('mousedown', rect.left + 5, rect.top + 5, 0, 1, 0);
+}
+
+function sendMouseUp(el) {
+ var rect = el.getBoundingClientRect();
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.sendMouseEvent('mouseup', rect.left + 5, rect.top + 5, 0, 1, 0);
+}
+
+function fireEvent(target, event) {
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ utils.dispatchDOMEventViaPresShell(target, event, true);
+}
+
+function fireDrop(element) {
+ var ds = SpecialPowers.Cc["@mozilla.org/widget/dragservice;1"].
+ getService(SpecialPowers.Ci.nsIDragService);
+
+ ds.startDragSession();
+
+ var event = document.createEvent("DragEvent");
+ event.initDragEvent("dragover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null);
+ fireEvent(element, event);
+
+ event = document.createEvent("DragEvent");
+ event.initDragEvent("drop", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null);
+ fireEvent(element, event);
+
+ ds.endDragSession(false);
+ ok(!ds.getCurrentSession(), "There shouldn't be a drag session anymore!");
+}
+
+function runTest() {
+ var d1 = document.getElementById("d1");
+ var didGetMouseMove = false;
+ sendMouseDown(d1);
+ document.addEventListener("mousemove",
+ function (e) {
+ didGetMouseMove = (e.target == document);
+ },
+ true);
+ sendMouseMoveFaraway(d1);
+ ok(didGetMouseMove, "Should have got mousemove!");
+ sendMouseUp(d1);
+
+ didGetMouseMove = false;
+ document.addEventListener("mousedown",
+ function (e) {
+ e.preventDefault();
+ },
+ true);
+ sendMouseDown(d1);
+ sendMouseMoveFaraway(d1);
+ ok(didGetMouseMove, "Should have got mousemove! (2)");
+ sendMouseUp(d1);
+
+ didGetMouseMove = false;
+ sendMouseDown(d1);
+ fireDrop(d1);
+ sendMouseMoveFaraway(d1);
+ ok(!didGetMouseMove, "Shouldn't have got mousemove!");
+
+
+
+ SimpleTest.finish();
+}
+
+
+</script>
+</pre>
+<div class="test" id="d1">&nbsp;</div>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug607529.html b/layout/base/tests/test_bug607529.html
new file mode 100644
index 000000000..332996084
--- /dev/null
+++ b/layout/base/tests/test_bug607529.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=607529
+-->
+<head>
+ <title>Test for Bug 607529</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=607529">Mozilla Bug 607529</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+
+ /* General idea: Open a new window (needed because we don't bfcache
+ subframes) that uses requestAnimationFrame, navigate it, navigate it
+ back, and verify that the animations are still running. */
+
+ var doneOneLoad = false;
+
+ /** Test for Bug 607529 **/
+ var done = false;
+ window.onmessage = function(e) {
+ isnot(e.data, "notcached", "Should never end up not being cached");
+
+ if (e.data == "loaded" && !doneOneLoad) {
+ doneOneLoad = true;
+ w.location = "data:text/html,<script>window.onload = function() { opener.postMessage('goback', '*'); }</" + "script>";
+ }
+ else if (e.data == "goback") {
+ w.history.back();
+ }
+ else if (e.data == "revived") {
+ w.postMessage("report", "*");
+ }
+ else if (e.data == "callbackHappened") {
+ // We might get this message more than once, if the other page queues up
+ // more than one callbackHappened message before we manage to close it.
+ // Protect against calling SimpleTest.finish() more than once.
+ if (!done) {
+ w.close();
+ window.onmessage = null;
+ SimpleTest.finish();
+ done = true;
+ }
+ } else {
+ var msg = JSON.parse(e.data);
+ if (msg.error) {
+ window.onerror(msg.msg, msg.url, msg.line);
+ }
+ }
+ };
+
+ var w = window.open("file_bug607529.html");
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug629838.html b/layout/base/tests/test_bug629838.html
new file mode 100644
index 000000000..34f12fc16
--- /dev/null
+++ b/layout/base/tests/test_bug629838.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Tests for MozAfterPaint</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <script type="application/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display">
+<embed type="application/x-test" width="100" height="100" id="p"
+ drawmode="solid" color="FF00FF00"></embed>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var initialPaintCount, afterPaintCount;
+var color = 0;
+
+function onAfterPaint () {
+ afterPaintCount += 1;
+}
+
+function startTest() {
+ setTimeout(function () {
+ afterPaintCount = 0;
+ initialPaintCount = window.mozPaintCount;
+ window.addEventListener("MozAfterPaint", onAfterPaint, true);
+ doBackgroundFlicker();
+ }, 500);
+}
+
+document.addEventListener("DOMContentLoaded", startTest, true);
+
+// Unfortunately we cannot reliably assert that mozPaintCount and afterPaintCount increment perfectly
+// in sync, because they can diverge in the presence of OS-triggered paints or system load.
+// Instead, wait for a minimum number of afterPaint events to at least ensure that they are being fired.
+const minimumAfterPaintsToPass = 10;
+
+function doPluginFlicker() {
+ ok(true, "Plugin color iteration " + color +
+ ", afterpaint count: " + afterPaintCount +
+ ", mozpaint count: " + window.mozPaintCount);
+ if (afterPaintCount >= minimumAfterPaintsToPass) {
+ ok(true, "afterPaintCount incremented enough from plugin color changes.");
+ SimpleTest.finish();
+ return;
+ }
+
+ color = (color + 1) % 256;
+ var str = color.toString(16);
+ if (str.length < 2) {
+ str = "0" + str;
+ }
+ str = "FF" + str + str + str;
+ document.getElementById("p").setColor(str);
+ setTimeout(doPluginFlicker, 0);
+}
+
+function doBackgroundFlicker() {
+ ok(true, "Background color iteration " + color +
+ ", afterpaint count: " + afterPaintCount +
+ ", mozpaint count: " + window.mozPaintCount);
+ if (afterPaintCount >= minimumAfterPaintsToPass) {
+ ok(true, "afterPaintCount incremented enough from background color changes.");
+ afterPaintCount = 0;
+ initialPaintCount = window.mozPaintCount;
+ doPluginFlicker();
+ return;
+ }
+
+ color = (color + 1) % 256;
+ document.body.style.backgroundColor = "rgb(" + color + "," + color + "," + color + ")";
+ setTimeout(doBackgroundFlicker, 0);
+}
+
+</script>
+</pre>
+
+<div style="height:4000px"></div>
+<a id="first" href="http://www.mozilla.org/">first<br>link</a>
+<a id="second" href="http://www.mozilla.org/">second link</a>
+<a id="third" href="http://www.mozilla.org/">third<br>link</a>
+<div style="height:4000px"></div>
+
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug644768.html b/layout/base/tests/test_bug644768.html
new file mode 100644
index 000000000..297cd1c3b
--- /dev/null
+++ b/layout/base/tests/test_bug644768.html
@@ -0,0 +1,62 @@
+<!-- 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/. -->
+
+<!DOCTYPE html>
+<html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=644768
+ -->
+ <head>
+ <title>Test for Bug 644768</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body onload="test()">
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=644768">Mozilla Bug 644768</a>
+ <p id="display"></p>
+ <div id="content">
+ <!-- test text is
+ == زادروزها ==
+ * [[۱۳۰۷]]
+ -->
+ <textarea id="testInput" dir="rtl" cols="80" rows="25" style="-moz-appearance:none">
+
+== &#x0632;&#x0627;&#x062F;&#x0631;&#x0648;&#x0632;&#x0647;&#x0627; ==
+* [[&#x06F1;&#x06F3;&#x06F0;&#x06F7;]]</textarea>
+ </div>
+ <pre id="test">
+ <script class="testbody" type="text/javascript">
+
+ /** Test for Bug 644768 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ function test() {
+ var textInput = $("testInput");
+ var s1, s2, equal, str1, str2;
+
+ textInput.focus();
+ s1 = snapshotWindow(window);
+
+ synthesizeKey("VK_UP", { });
+ synthesizeKey("VK_UP", { });
+ synthesizeKey("VK_UP", { });
+ synthesizeKey("VK_DELETE", { });
+ synthesizeKey("VK_RETURN", { });
+ // Bug 1016184: Touch caret will hide due to key event.
+ s2 = snapshotWindow(window);
+
+ [equal, str1, str2] = compareSnapshots(s1, s2, true);
+ ok(equal, "newline before bidi text shouldn't change direction: expected " +
+ str1 + " but got " + str2);
+
+ SimpleTest.finish();
+ }
+
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug646757.html b/layout/base/tests/test_bug646757.html
new file mode 100644
index 000000000..f4a1ffcf2
--- /dev/null
+++ b/layout/base/tests/test_bug646757.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=646757
+-->
+<head>
+ <title>Test for Bug 646757</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body style="margin:0" id="body">
+<div style="height:20.3px; width:400px; background:pink" id="d1"></div>
+<div style="height:20px; width:400px; background:yellow" id="d2"></div>
+<div style="height:9.7px; width:400px;" id="space1"></div>
+<div style="height:20.7px; width:400px; background:pink" id="d3"></div>
+<div style="height:20px; width:400px; background:yellow" id="d4"></div>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=646757">Mozilla Bug 646757</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+function testPoint(x, y, id) {
+ is(document.elementFromPoint(x, y).id, id,
+ "checking element at " + x + "," + y);
+}
+
+/** Test for Bug 646757 **/
+testPoint(200, 20, "d1");
+testPoint(200, 20.2, "d1");
+testPoint(200, 20.4, "d2");
+testPoint(200, 21, "d2");
+
+testPoint(200, 70, "d3");
+testPoint(200, 70.6, "d3");
+testPoint(200, 70.8, "d4");
+testPoint(200, 71, "d4");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug66619.html b/layout/base/tests/test_bug66619.html
new file mode 100644
index 000000000..663556c0e
--- /dev/null
+++ b/layout/base/tests/test_bug66619.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=66619
+-->
+<head>
+ <title>Test for Bug 66619</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=66619">Mozilla Bug 66619</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 66619 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run()
+{
+ is(window.scrollY, 0, "window should initially be at top");
+
+ document.getElementById("first").focus();
+ var first = window.scrollY;
+ isnot(first, 0, "we scrolled to first anchor");
+ ok(first + window.innerHeight > 4000,
+ "we scrolled enough to show the anchor");
+
+ window.scrollTo(0, 0);
+ document.getElementById("second").focus();
+ var second = window.scrollY;
+
+ window.scrollTo(0, 0);
+ document.getElementById("third").focus();
+ var third = window.scrollY;
+
+ is(second, first, "we scrolled the second line of the anchor into view");
+ isnot(third, second, "we scrolled the second line of the anchor into view");
+ ok(third > second, "we scrolled the second line of the anchor into view");
+
+ window.scrollTo(0, 0); // make the results visible
+ SimpleTest.finish();
+}
+
+
+</script>
+</pre>
+
+<div style="height:4000px"></div>
+<a id="first" href="http://www.mozilla.org/">first<br>link</a>
+<a id="second" href="http://www.mozilla.org/">second link</a>
+<a id="third" href="http://www.mozilla.org/">third<br>link</a>
+<div style="height:4000px"></div>
+
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug667512.html b/layout/base/tests/test_bug667512.html
new file mode 100644
index 000000000..600b6d0f6
--- /dev/null
+++ b/layout/base/tests/test_bug667512.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=667512
+-->
+<head>
+ <title>Test for Bug 667512</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<table contenteditable="true"><tbody><tr><td id="b"><br id="a"></td></tr></tbody></table>
+<span style="display: list-item;direction: rtl;"></span>
+<script type="application/javascript">
+
+/** Test for Bug 667512 **/
+function appendElements() {
+ window.focus();
+ window.getSelection().collapse(document.documentElement, 0);
+
+ var x=document.getElementById('a');
+ x.parentNode.removeChild(x);
+
+ var x=document.getElementById('b');
+ x.parentNode.removeChild(x);
+
+ synthesizeKey("VK_LEFT", {});
+ synthesizeKey("VK_RIGHT", {});
+
+ ok(true, "Should not crash!");
+ SimpleTest.finish();
+}
+
+addLoadEvent(appendElements);
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/layout/base/tests/test_bug677878.html b/layout/base/tests/test_bug677878.html
new file mode 100644
index 000000000..cb9e05a26
--- /dev/null
+++ b/layout/base/tests/test_bug677878.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677878
+-->
+<head>
+ <title>Test for Bug 677878</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style>
+ #test1 {
+ background: green;
+ height: 100px;
+ width: 100px;
+ -moz-transform: scale(20, 20);
+ -moz-transform-origin: 0 0%;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677878">Mozilla Bug 677878</a>
+<div id="content">
+ <div id="test1">
+ <div id="test2" onclick="testFinish();">
+ test
+ </div>
+ </div>
+
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+runtests();
+
+function runtests() {
+ function doClick() {
+ document.getElementById("test2").addEventListener("mousedown", testFinish, true);
+ // Don't target the center because the center could actually be outside the
+ // viewport.
+ synthesizeMouse(document.getElementById("test2"), 10, 10, { type: "mousedown" })
+ }
+ setTimeout(doClick, 300);
+}
+
+function testFinish(event){
+ ok(true, "We can still interact with the item after it is transformed");
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug687297.html b/layout/base/tests/test_bug687297.html
new file mode 100644
index 000000000..6ec9aaf4f
--- /dev/null
+++ b/layout/base/tests/test_bug687297.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=687297
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 687297</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SpecialPowers.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=687297">Mozilla Bug 687297</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+ <script class="testbody" type="text/javascript">
+ /** Test for Bug 687297 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ var size_a=0, size_b=0, size_c=0;
+
+ window.report_size_a = function(s) {
+ size_a = s;
+ };
+
+ window.report_size_b = function(s) {
+ size_b = s;
+ };
+
+ window.report_size_c = function(s) {
+ size_c = s;
+
+ isnot(size_a, size_b, "Font sizes are changing with global language-specific minimum font size");
+ is(size_c, size_a, "Font sizes are equal, propagating only the presentation-level base minimum font size");
+
+ SimpleTest.finish();
+ };
+
+ SpecialPowers.pushPrefEnv(
+ {'set':[["font.minimum-size.ja", 120]]},
+ function() {
+ window.open("bug687297_a.html", '_blank');
+ }
+ );
+
+ </script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug696020.html b/layout/base/tests/test_bug696020.html
new file mode 100644
index 000000000..41bd2d8b0
--- /dev/null
+++ b/layout/base/tests/test_bug696020.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=696020
+-->
+<head>
+ <title>Test for Bug 696020</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696020">Mozilla Bug 696020</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 696020 **/
+
+
+function startTest() {
+ var testFrame = document.getElementById("tf").contentWindow;
+ testFrame.focus();
+ var didHandleKeyEvent = false;
+ testFrame.addEventListener("keypress",
+ function(e) {
+ is(e.target, testFrame.document.body,
+ "Body element should be event target for key events!");
+ didHandleKeyEvent = true;
+ });
+ synthesizeKey("A", {}, testFrame);
+ ok(didHandleKeyEvent, "Should have handled a key event!");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(startTest)
+
+
+</script>
+</pre>
+<iframe id="tf"></iframe>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug718809.html b/layout/base/tests/test_bug718809.html
new file mode 100644
index 000000000..33075347d
--- /dev/null
+++ b/layout/base/tests/test_bug718809.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=718809
+-->
+<head>
+ <title>Test for Bug 718809</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+</head>
+<body style=margin:0>
+<div style="background:blue;height:50px;width:100px; -moz-transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 10, 1); -moz-transform-origin:0 0"></div>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=718809">Mozilla Bug 718809</a>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ var rect = document.querySelector("div").getBoundingClientRect();
+
+ is(rect.top, 0, "Incorrect bounding rect");
+ is(rect.left, 0, "Incorrect bounding rect");
+ is(rect.right, 100, "Incorrect bounding rect");
+ is(rect.bottom, 50, "Incorrect bounding rect");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/layout/base/tests/test_bug725426.html b/layout/base/tests/test_bug725426.html
new file mode 100644
index 000000000..f02030362
--- /dev/null
+++ b/layout/base/tests/test_bug725426.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=725426
+-->
+<title>Test for bug 725426</title>
+<script src=/tests/SimpleTest/SimpleTest.js></script>
+<link rel=stylesheet href=/tests/SimpleTest/test.css>
+<body style=margin:0>
+<div style="-moz-transform: perspective(200px)">
+<div style="-moz-transform: translatez(-100px);
+width:100px;height:100px;background:blue">
+</div></div>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725426">
+Mozilla Bug 725426</a>
+<pre id=test>
+<script class=testbody>
+var rect = document.querySelector("div>div").getBoundingClientRect();
+is(rect.top, 0, "Incorrect bounding rect top");
+is(rect.right, 100, "Incorrect bounding rect top");
+is(rect.bottom, 100, "Incorrect bounding rect top");
+is(rect.left, 0, "Incorrect bounding rect top");
+</script>
+</pre>
diff --git a/layout/base/tests/test_bug731777.html b/layout/base/tests/test_bug731777.html
new file mode 100644
index 000000000..190a28dfb
--- /dev/null
+++ b/layout/base/tests/test_bug731777.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 731777</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #container {
+ position: relative;
+ height: 300px;
+ width: 300px;
+ margin: 50px 100px;
+ border: 2px solid blue;
+ background-color: #044B0A;
+
+ -moz-perspective: 500px;
+ overflow:hidden;
+ }
+
+ #inner {
+ margin: 0px;
+ width: 480px;
+ border: 2px solid blue;
+ height: 220px;
+ background-color: #844BCA;
+
+ -moz-transform: rotateY(91deg) translateX(0px) translateZ(0px);
+ transition: 5s;
+ }
+
+ </style>
+</head>
+<body>
+<div id="container">
+ <div id="inner"></div>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 731777 **/
+
+is(document.elementFromPoint(325,170), document.getElementById("inner"), "Able to hit transformed object");
+is(document.elementFromPoint(405,170), document.getElementById("inner"), "Able to hit transformed object");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug749186.html b/layout/base/tests/test_bug749186.html
new file mode 100644
index 000000000..94e11f365
--- /dev/null
+++ b/layout/base/tests/test_bug749186.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=749186
+Note that this is a crashtest, but because of the special privileges
+required, it needs to be run as a mochitest. Thus, the expected
+behavior of this test is that it actually loads and doesn't crash the
+browser.
+-->
+ <head>
+ <title>Test for Bug 749186 (Crashtest)</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script>
+ function endTest() {
+ ok(true, 'test finished without crashing');
+ SimpleTest.finish();
+ }
+
+ function removeBoldStyle() {
+ document.getElementById('b').removeAttribute('style');
+ SpecialPowers.pushPrefEnv({'set': [['font.size.inflation.emPerLine', 0]]},endTest);
+ }
+
+ function startTest() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+ SpecialPowers.pushPrefEnv({'set': [['font.size.inflation.emPerLine', 8]]},removeBoldStyle);
+ }
+
+ startTest();
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=749186">Bug 749186</a>
+ <iframe id="a" style="display: none;"></iframe>
+ <div id="b" style="display: inline;"></div>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug761572.html b/layout/base/tests/test_bug761572.html
new file mode 100644
index 000000000..02a3cfb66
--- /dev/null
+++ b/layout/base/tests/test_bug761572.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=761572
+-->
+<head>
+ <title>Test for Bug 761572</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=761572">Mozilla Bug 761572</a>
+<div id="content">
+ <div id="d" style="background:lime; width:50px; height:50px" onmouseup="doUp()" onclick="doClick()"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var d = document.getElementById("d");
+
+function doUp() {
+ d.style.display = "none";
+}
+function doClick() {
+ ok(true, "Check click received");
+ SimpleTest.finish();
+}
+
+function doTest() {
+ // synthesizes a mousedown/mouseup pair
+ synthesizeMouse(d, 10, 10, {});
+}
+
+SimpleTest.waitForFocus(doTest);
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug770106.html b/layout/base/tests/test_bug770106.html
new file mode 100644
index 000000000..ff440f738
--- /dev/null
+++ b/layout/base/tests/test_bug770106.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 770106</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<span id="s">Hello</span>
+<button><div style="pointer-events:none; position:relative; width:100px; background:yellow; left:-100px;">Kitty</div></button>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 770106 **/
+
+var sRect = s.getBoundingClientRect();
+is(document.elementFromPoint(sRect.left + sRect.width/2, sRect.top + sRect.height/2),
+ document.getElementById("s"), "Correct object selected");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug842853-2.html b/layout/base/tests/test_bug842853-2.html
new file mode 100644
index 000000000..2b777abfc
--- /dev/null
+++ b/layout/base/tests/test_bug842853-2.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=842853
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 842853</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 842853 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function verifyAfterLoad() {
+ var e = document.getElementsByTagName('iframe')[0];
+ var win = e.contentWindow;
+ if (win.location.hash != '') {
+ is(win.scrollY,500);
+ SimpleTest.finish();
+ return;
+ }
+}
+
+function runTest() {
+ var e = document.getElementsByTagName('iframe')[0];
+ var win = e.contentWindow;
+ if (win.location.hash != '') {
+ return;
+ }
+ win.location.hash='#anchor'
+ win.scrollTo(0,500);
+ e.setAttribute("onload","verifyAfterLoad()");
+ win.location.reload()
+}
+
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=842853">Mozilla Bug 842853</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+<iframe src="file_bug842853.html"></iframe>
+<script>
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug842853.html b/layout/base/tests/test_bug842853.html
new file mode 100644
index 000000000..2f9a1d11d
--- /dev/null
+++ b/layout/base/tests/test_bug842853.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=842853
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 842853</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 842853 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+ var win = e.contentWindow;
+ if (win.location.hash != '') {
+ is(win.scrollY,500);
+ SimpleTest.finish();
+ return;
+ }
+ win.location.hash='#anchor'
+ win.scrollTo(0,500);
+ win.location.reload()
+}
+
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=842853">Mozilla Bug 842853</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+<script>
+
+var e = document.createElement('iframe');
+var url = 'data:text/html,<a href="%23anchor">Click to scroll to anchor</a><div style="height:5000px"></div><a name="anchor">FAIL</a>'
+e.setAttribute('src',url);
+e.setAttribute('onload','runTest()');
+document.body.appendChild(e);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug849219.html b/layout/base/tests/test_bug849219.html
new file mode 100644
index 000000000..666f418b4
--- /dev/null
+++ b/layout/base/tests/test_bug849219.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=849219
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 849219</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 849219 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+ var win = e.contentWindow;
+ if (win.location.hash != '') {
+ is(win.scrollY,0);
+ SimpleTest.finish();
+ return;
+ }
+ win.location.hash='#anchor'
+ win.scrollTo(0,0);
+ win.location.reload()
+}
+
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=849219">Mozilla Bug 849219</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+<script>
+
+var e = document.createElement('iframe');
+var url = 'data:text/html,<a href="%23anchor">Click to scroll to anchor</a><div style="height:5000px"></div><a name="anchor">FAIL</a>'
+e.setAttribute('src',url);
+e.setAttribute('onload','runTest()');
+document.body.appendChild(e);
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug851445.html b/layout/base/tests/test_bug851445.html
new file mode 100644
index 000000000..5dd79dfae
--- /dev/null
+++ b/layout/base/tests/test_bug851445.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=851445
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 851445</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=851445">Mozilla Bug 851445</a>
+<p id="display"></p>
+<iframe id="f" style="width:400px; height:400px;"></iframe>
+<script>
+SimpleTest.waitForExplicitFinish();
+
+function handleLoad() {
+ f.contentWindow.scrollTo(0,100);
+ function handleLoad2() {
+ // Verify that the scroll position was retained
+ is(f.contentWindow.scrollY, 100);
+ SimpleTest.finish();
+ }
+ f.onload = handleLoad2;
+ f.contentWindow.location.reload();
+}
+
+f.src = "bug851445_helper.html?" + Math.random();
+f.onload = handleLoad;
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug851485.html b/layout/base/tests/test_bug851485.html
new file mode 100644
index 000000000..8be136b84
--- /dev/null
+++ b/layout/base/tests/test_bug851485.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=851485
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 851485</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 851485 **/
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+function delayedVerifyScroll(win) {
+ ok(win.scrollY > 3000);
+ SimpleTest.finish();
+}
+
+function verifyScroll(event) {
+ var win = event.target.defaultView;
+ win.onscroll = "";
+ setTimeout(function(){delayedVerifyScroll(win)},500)
+}
+
+function clickLink(link,win) {
+ win.document.body.offsetHeight;
+ synthesizeMouseAtCenter(link, {type: "mousedown"}, win);
+ synthesizeMouseAtCenter(link, {type: "mouseup"}, win);
+ sendMouseEvent({type: "click"}, link, win);
+}
+
+function verifyAfterLoad() {
+ var e = document.getElementsByTagName('iframe')[0];
+ var win = e.contentWindow;
+ if (win.location.hash != '') {
+ is(win.scrollY,500);
+ var link = win.document.getElementsByTagName('a')[0];
+ win.onscroll = verifyScroll;
+ clickLink(link,win);
+ return;
+ }
+}
+
+function runTest() {
+ var e = document.getElementsByTagName('iframe')[0];
+ var win = e.contentWindow;
+ if (win.location.hash != '') {
+ return;
+ }
+ win.location.hash='#anchor'
+ win.scrollTo(0,500);
+ e.setAttribute("onload","verifyAfterLoad()");
+ win.location.reload()
+}
+
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=851485">Mozilla Bug 851485</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+<iframe src="file_bug842853.html"></iframe>
+<script>
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug858459.html b/layout/base/tests/test_bug858459.html
new file mode 100644
index 000000000..2f594aa78
--- /dev/null
+++ b/layout/base/tests/test_bug858459.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=858459
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 858459</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 858459 **/
+
+var result = "";
+var timeout = null;
+var clicks = 0;
+const EXPECTED_RESULT = "change select";
+
+function logEvent(ev,msg) {
+ result += ev.type + ' ' + msg;
+ ++clicks;
+ if (result.length > EXPECTED_RESULT.length)
+ finishTest();
+}
+
+document.onclick = function(event) { logEvent(event,"document"); }
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+function finishTest() {
+ if (!timeout) return;
+ clearTimeout(timeout);
+ timeout = null;
+ is(result,EXPECTED_RESULT,"");
+ SimpleTest.finish();
+}
+
+function runTest() {
+ // Need a timeout to check that an event has _not_ occurred.
+ timeout = setTimeout(finishTest, 5000);
+ synthesizeMouseAtCenter(document.getElementById('test858459'), { });
+}
+
+ </script>
+</head>
+<body onload="SimpleTest.waitForFocus(runTest)">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=858459">Mozilla Bug 858459</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test"><div><select id="test858459" size=4 onclick="logEvent(event,'select');" onchange="logEvent(event,'select');var div = document.querySelector('#test div'); div.innerHTML='<p>'+div.innerHTML; document.body.offsetHeight;"><option>1111111111111111<option>2<option>3</select></div>
+
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug93077-1.html b/layout/base/tests/test_bug93077-1.html
new file mode 100644
index 000000000..16fad6b2a
--- /dev/null
+++ b/layout/base/tests/test_bug93077-1.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=93077
+-->
+<head>
+ <title>Test for Bug 93077</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #filler { height: 200cm; background: papayawhip; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=93077">Mozilla Bug 93077</a>
+<p id="display"></p>
+<div id=filler>...</div>
+<p id=below></p>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 93077 **/
+["#top", "#TOP", "#Top"].forEach(function(fragid) {
+ document.getElementById("below").scrollIntoView()
+ isnot(window.scrollY, 0)
+ location.hash = fragid
+ is(window.scrollY, 0)
+})
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug93077-2.html b/layout/base/tests/test_bug93077-2.html
new file mode 100644
index 000000000..24e17b735
--- /dev/null
+++ b/layout/base/tests/test_bug93077-2.html
@@ -0,0 +1,32 @@
+<!-- Testing quirks mode. -->
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=93077
+-->
+<head>
+ <title>Test for Bug 93077</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #filler { height: 200cm; background: papayawhip; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=93077">Mozilla Bug 93077</a>
+<p id="display"></p>
+<div id=filler>...</div>
+<p id=below></p>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 93077 **/
+["#top", "#TOP", "#Top"].forEach(function(fragid) {
+ document.getElementById("below").scrollIntoView()
+ isnot(window.scrollY, 0)
+ location.hash = fragid
+ is(window.scrollY, 0)
+})
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug93077-3.html b/layout/base/tests/test_bug93077-3.html
new file mode 100644
index 000000000..0c37be986
--- /dev/null
+++ b/layout/base/tests/test_bug93077-3.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=93077
+-->
+<head>
+ <title>Test for Bug 93077</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #filler { height: 200cm; background: papayawhip; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=93077">Mozilla Bug 93077</a>
+<p id="display"></p>
+<div id=filler>...</div>
+<p id=below></p>
+<p id=top>Top</p>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 93077 **/
+["#TOP", "#Top"].forEach(function(fragid) {
+ document.getElementById("below").scrollIntoView()
+ isnot(window.scrollY, 0)
+ location.hash = fragid
+ is(window.scrollY, 0)
+})
+location.hash = "#top"
+isnot(window.scrollY, 0)
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug93077-4.html b/layout/base/tests/test_bug93077-4.html
new file mode 100644
index 000000000..ea624086a
--- /dev/null
+++ b/layout/base/tests/test_bug93077-4.html
@@ -0,0 +1,35 @@
+<!-- Testing quirks mode. -->
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=93077
+-->
+<head>
+ <title>Test for Bug 93077</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #filler { height: 200cm; background: papayawhip; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=93077">Mozilla Bug 93077</a>
+<p id="display"></p>
+<div id=filler>...</div>
+<p id=below></p>
+<p><a name=top>Top</a></p>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 93077 **/
+["#TOP", "#Top"].forEach(function(fragid) {
+ document.getElementById("below").scrollIntoView()
+ isnot(window.scrollY, 0)
+ location.hash = fragid
+ is(window.scrollY, 0)
+})
+location.hash = "#top"
+isnot(window.scrollY, 0)
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug93077-5.html b/layout/base/tests/test_bug93077-5.html
new file mode 100644
index 000000000..ffe9233cf
--- /dev/null
+++ b/layout/base/tests/test_bug93077-5.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=93077
+-->
+<head>
+ <title>Test for Bug 93077</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #filler { height: 200cm; background: papayawhip; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=93077">Mozilla Bug 93077</a>
+<p id="display"></p>
+<div id=filler>...</div>
+<p id=below></p>
+<p id=TOP>Top</p>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 93077 **/
+["#top", "#Top"].forEach(function(fragid) {
+ document.getElementById("below").scrollIntoView()
+ isnot(window.scrollY, 0)
+ location.hash = fragid
+ is(window.scrollY, 0)
+})
+location.hash = "#TOP"
+isnot(window.scrollY, 0)
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug93077-6.html b/layout/base/tests/test_bug93077-6.html
new file mode 100644
index 000000000..08cdb6c7f
--- /dev/null
+++ b/layout/base/tests/test_bug93077-6.html
@@ -0,0 +1,35 @@
+<!-- Testing quirks mode. -->
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=93077
+-->
+<head>
+ <title>Test for Bug 93077</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #filler { height: 200cm; background: papayawhip; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=93077">Mozilla Bug 93077</a>
+<p id="display"></p>
+<div id=filler>...</div>
+<p id=below></p>
+<p><a name=TOP>Top</a></p>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 93077 **/
+["#top", "#Top"].forEach(function(fragid) {
+ document.getElementById("below").scrollIntoView()
+ isnot(window.scrollY, 0)
+ location.hash = fragid
+ is(window.scrollY, 0)
+})
+location.hash = "#TOP"
+isnot(window.scrollY, 0)
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_bug968148.html b/layout/base/tests/test_bug968148.html
new file mode 100644
index 000000000..3cab8b073
--- /dev/null
+++ b/layout/base/tests/test_bug968148.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=968148
+-->
+<head>
+ <title>Test for Bug 968148</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript;version=1.7">
+ function setRemoteFrame() {
+ var iframe = document.getElementById("testFrame");
+ iframe.src = "bug968148_inner.html";
+
+ function messageListener(event) {
+ eval(event.data);
+ }
+
+ window.addEventListener("message", messageListener, false);
+ }
+
+ function runTest() {
+ SimpleTest.waitForExplicitFinish();
+
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, setRemoteFrame);
+ }
+ </script>
+</head>
+<body onload="runTest();">
+ <iframe id="testFrame" height="500" width="500"></iframe>
+</body>
+
diff --git a/layout/base/tests/test_bug970964.html b/layout/base/tests/test_bug970964.html
new file mode 100644
index 000000000..461911598
--- /dev/null
+++ b/layout/base/tests/test_bug970964.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=970964
+-->
+<head>
+ <title>Test for Bug 970964</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript;version=1.7">
+ function setRemoteFrame() {
+ var iframe = document.getElementById("testFrame");
+ iframe.src = "bug970964_inner.html";
+
+ function messageListener(event) {
+ eval(event.data);
+ }
+
+ window.addEventListener("message", messageListener, false);
+ }
+
+ function runTest() {
+ SimpleTest.waitForExplicitFinish();
+
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, setRemoteFrame);
+ }
+ </script>
+</head>
+<body onload="runTest();">
+ <iframe id="testFrame" height="500" width="500"></iframe>
+</body>
+
diff --git a/layout/base/tests/test_bug976963.html b/layout/base/tests/test_bug976963.html
new file mode 100644
index 000000000..4b8da3a6e
--- /dev/null
+++ b/layout/base/tests/test_bug976963.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=976963
+-->
+ <head>
+ <meta charset="utf-8">
+ <meta name="author" content="Maksim Lebedev" />
+ <title>Test for Bug 976963</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true],
+ ["layout.reflow.synthMouseMove", false]
+ ]
+ }, startTest);
+ }
+ function startTest() {
+ var iframe = document.getElementById("testFrame");
+ iframe.src = "bug976963_inner.html";
+ }
+ function finishTest() {
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug977003.html b/layout/base/tests/test_bug977003.html
new file mode 100644
index 000000000..f6bca6975
--- /dev/null
+++ b/layout/base/tests/test_bug977003.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977003
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 977003</title>
+ <meta name="author" content="Maksim Lebedev" />
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var number = 0;
+ var iframe = undefined;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ iframe = document.getElementById("testFrame");
+ turnOnPointerEvents(finishTest);
+ }
+ function turnOnPointerEvents(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.w3c_pointer_events.enabled", true]
+ ]
+ }, callback);
+ }
+ function finishTest() {
+ // Try to run several tests named as bug977003_inner_<number>.html
+ if(++number < 7)
+ iframe.src = "bug977003_inner_" + number + ".html";
+ else
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
diff --git a/layout/base/tests/test_bug990340.html b/layout/base/tests/test_bug990340.html
new file mode 100644
index 000000000..8d9984fbe
--- /dev/null
+++ b/layout/base/tests/test_bug990340.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=990340
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 990340</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 990340 **/
+
+ function testbug990340() {
+ ok(document.querySelector('#bug990340 span').clientHeight < 100,
+ "'height' is in transition")
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=990340">Mozilla Bug 990340</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<style type="text/css">
+
+#bug990340::before {
+ content: ":before";
+}
+
+#bug990340 span {
+ display: inline-block;
+ border:1px solid blue;
+ height: 20px;
+ transition: height 30s;
+}
+
+#bug990340.s span {
+ height: 100px;
+}
+</style>
+<div id="bug990340" style="overflow:scroll">
+ <span>Transition height</span>
+</div>
+</pre>
+
+<script>
+document.body.offsetHeight;
+document.querySelector('#bug990340').className='s';
+testbug990340()
+</script>
+
+</body>
+</html>
diff --git a/layout/base/tests/test_bug993936.html b/layout/base/tests/test_bug993936.html
new file mode 100644
index 000000000..9d62831ea
--- /dev/null
+++ b/layout/base/tests/test_bug993936.html
@@ -0,0 +1,161 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=993936
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 993936</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 993936 **/
+
+var currentId = 0;
+var evictedTouchesCount = 0;
+
+function testtouch(aOptions) {
+ if (!aOptions)
+ aOptions = {};
+ this.identifier = aOptions.identifier || 0;
+ this.target = aOptions.target || 0;
+ this.page = aOptions.page || {x: 0, y: 0};
+ this.radius = aOptions.radius || {x: 0, y: 0};
+ this.rotationAngle = aOptions.rotationAngle || 0;
+ this.force = aOptions.force || 1;
+}
+
+function touchEvent(aOptions) {
+ if (!aOptions) {
+ aOptions = {};
+ }
+ this.ctrlKey = aOptions.ctrlKey || false;
+ this.altKey = aOptions.altKey || false;
+ this.shiftKey = aOptions.shiftKey || false;
+ this.metaKey = aOptions.metaKey || false;
+ this.touches = aOptions.touches || [];
+ this.targetTouches = aOptions.targetTouches || [];
+ this.changedTouches = aOptions.changedTouches || [];
+}
+
+function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
+ var ids = [], xs=[], ys=[], rxs = [], rys = [],
+ rotations = [], forces = [];
+
+ for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
+ for (var i = 0; i < aEvent[touchType].length; i++) {
+ if (ids.indexOf(aEvent[touchType][i].identifier) == -1) {
+ ids.push(aEvent[touchType][i].identifier);
+ xs.push(aEvent[touchType][i].page.x);
+ ys.push(aEvent[touchType][i].page.y);
+ rxs.push(aEvent[touchType][i].radius.x);
+ rys.push(aEvent[touchType][i].radius.y);
+ rotations.push(aEvent[touchType][i].rotationAngle);
+ forces.push(aEvent[touchType][i].force);
+ }
+ }
+ }
+ return windowUtils.sendTouchEvent(aType,
+ ids, xs, ys, rxs, rys,
+ rotations, forces,
+ ids.length, aModifiers, 0);
+}
+
+function getSingleTouchEventForTarget(target, cwu) {
+ currentId++;
+ var bcr = target.getBoundingClientRect();
+ var touch = new testtouch({
+ page: {x: Math.round(bcr.left + bcr.width/2),
+ y: Math.round(bcr.top + bcr.height/2)},
+ target: target,
+ identifier: currentId,
+ });
+ var event = new touchEvent({
+ touches: [touch],
+ targetTouches: [touch],
+ changedTouches: [touch]
+ });
+ return event;
+}
+
+function getMultiTouchEventForTarget(target, cwu) {
+ currentId++;
+ var bcr = target.getBoundingClientRect();
+ var touch1 = new testtouch({
+ page: {x: Math.round(bcr.left + bcr.width/2),
+ y: Math.round(bcr.top + bcr.height/2)},
+ target: target,
+ identifier: currentId,
+ });
+ currentId++;
+ var touch2 = new testtouch({
+ page: {x: Math.round(bcr.left + bcr.width),
+ y: Math.round(bcr.top + bcr.height)},
+ target: target,
+ identifier: currentId,
+ });
+ var event = new touchEvent({
+ touches: [touch1, touch2],
+ targetTouches: [touch1, touch2],
+ changedTouches: [touch1, touch2]
+ });
+ return event;
+}
+
+function runTests() {
+ var cwu = SpecialPowers.getDOMWindowUtils(window);
+
+ var event1 = getMultiTouchEventForTarget(d0, cwu);
+ sendTouchEvent(cwu, "touchstart", event1, 0);
+ sendTouchEvent(cwu, "touchmove", event1, 0);
+ is(evictedTouchesCount, 0, "Still no evicted touches");
+
+ var event2 = getSingleTouchEventForTarget(d0, cwu);
+ sendTouchEvent(cwu, "touchstart", event2, 0);
+
+ // By now we should get touchend event
+ ok(evictedTouchesCount > 0, "Got evicted touch");
+
+ finishTest();
+}
+
+function finishTest() {
+ // Let window.onerror have a chance to fire
+ setTimeout(function() {
+ SimpleTest.finish();
+ }, 0);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=993936">Mozilla Bug 993936</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+<div id="d0">
+ Test div
+</div>
+
+<script>
+var d0 = document.getElementById("d0");
+
+d0.addEventListener("touchend", function(ev) {
+ evictedTouchesCount++;
+});
+
+window.onload = function () {
+ setTimeout(function() {
+ runTests();
+ }, 0);
+}
+
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_emulateMedium.html b/layout/base/tests/test_emulateMedium.html
new file mode 100644
index 000000000..fc3b4a16e
--- /dev/null
+++ b/layout/base/tests/test_emulateMedium.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=819930
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 819930</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <style>
+ @media braille {
+ body {
+ background-color: rgb(255, 255, 0);
+ }
+ }
+
+ @media embossed {
+ body {
+ background-color: rgb(210, 180, 140);
+ }
+ }
+
+ @media handheld {
+ body {
+ background-color: rgb(0, 255, 0);
+ }
+ }
+
+ @media print {
+ body {
+ background-color: rgb(0, 255, 255);
+ }
+ }
+
+ @media projection {
+ body {
+ background-color: rgb(30, 144, 255);
+ }
+ }
+
+ @media screen {
+ body {
+ background-color: green;
+ }
+ }
+
+ @media speech {
+ body {
+ background-color: rgb(192, 192, 192);
+ }
+ }
+
+ @media tty {
+ body {
+ background-color: rgb(255, 192, 203);
+ }
+ }
+
+ @media tv {
+ body {
+ background-color: rgb(75, 0, 130);
+ }
+ }
+ </style>
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=819930">Mozilla Bug 819930</a>
+ <p id="display"></p>
+
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ <script type="application/javascript;version=1.7">
+ let tests = [{name: 'braille', value: 'rgb(255, 255, 0)'},
+ {name: 'embossed', value: 'rgb(210, 180, 140)'},
+ {name: 'handheld', value: 'rgb(0, 255, 0)'},
+ {name: 'print', value: 'rgb(0, 255, 255)'},
+ {name: 'projection', value: 'rgb(30, 144, 255)'},
+ {name: 'speech', value: 'rgb(192, 192, 192)'},
+ {name: 'tty', value: 'rgb(255, 192, 203)'},
+ {name: 'tv', value: 'rgb(75, 0, 130)'}];
+
+ let originalColor = 'rgb(0, 128, 0)';
+ let body = document.body;
+
+ let getColor = function() {
+ return window.getComputedStyle(body)
+ .getPropertyValue('background-color');
+ };
+
+ tests.forEach(function(test) {
+ // Emulate the given media
+ SpecialPowers.emulateMedium(window, test.name);
+ is(getColor(), test.value, 'emulating ' + test.name + ' produced ' +
+ 'correct rendering');
+
+ // Do the @media screen rules get applied after ending the emulation?
+ SpecialPowers.stopEmulatingMedium(window);
+ is(getColor(), originalColor, 'Ending ' + test.name +
+ ' emulation restores style for original medium');
+
+ // CSS media types are case-insensitive; we should be too.
+ SpecialPowers.emulateMedium(window, test.name.toUpperCase());
+ is(getColor(), test.value,
+ test.name + ' emulation is case-insensitive');
+ SpecialPowers.stopEmulatingMedium(window);
+ });
+
+ // Emulating screen should produce the same rendering as when there is
+ // no emulation in effect
+ SpecialPowers.emulateMedium(window, 'screen');
+ is(getColor(), originalColor,
+ 'Emulating screen produces original rendering');
+ SpecialPowers.stopEmulatingMedium(window);
+
+ // Screen should be case-insensitive too
+ SpecialPowers.emulateMedium(window, 'SCREEN');
+ is(getColor(), originalColor, 'screen emulation is case-insensitive');
+ SpecialPowers.stopEmulatingMedium(window);
+
+ // An invalid parameter shouldn't fail. Given the CSS rules above,
+ // an invalid parameter should result in a different rendering from any
+ // produced thus far
+ try {
+ SpecialPowers.emulateMedium(window, 'clay');
+ let invalid = getColor();
+ tests.push({name: 'screen', value: 'green'});
+ tests.forEach(function(test) {
+ isnot(invalid, test.value, 'Emulating invalid type differs from ' +
+ test.name);
+ });
+ } catch (e) {
+ ok(false, 'Supplying invalid type to emulateMedium shouldn\'t throw');
+ }
+
+ SpecialPowers.stopEmulatingMedium(window);
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/layout/base/tests/test_event_target_iframe_oop.html b/layout/base/tests/test_event_target_iframe_oop.html
new file mode 100644
index 000000000..89aa19817
--- /dev/null
+++ b/layout/base/tests/test_event_target_iframe_oop.html
@@ -0,0 +1,178 @@
+<!DOCTYPE HTML>
+<html id="html" style="height:100%">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=921928
+-->
+<head>
+ <title>Test for bug 921928</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #dialer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 50px;
+ background: green;
+ }
+
+ #apps {
+ position: absolute;
+ left: 0;
+ top: 51px;
+ width: 100%;
+ height: 100px;
+ background: blue;
+ }
+
+ .hit {
+ position: absolute;
+ width: 3px;
+ height: 3px;
+ z-index: 20;
+ background: red;
+ border: 1px solid red;
+ }
+ </style>
+</head>
+<body id="body" style="margin:0; width:100%; height:100%">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var prefs = [
+ ["ui.mouse.radius.enabled", true],
+ ["ui.mouse.radius.inputSource.touchOnly", false],
+ ["ui.mouse.radius.leftmm", 12],
+ ["ui.mouse.radius.topmm", 8],
+ ["ui.mouse.radius.rightmm", 4],
+ ["ui.mouse.radius.bottommm", 4],
+ ["ui.mouse.radius.visitedweight", 50],
+ ["dom.mozBrowserFramesEnabled", true]
+];
+
+var eventTarget;
+var debugHit = [];
+
+function endTest() {
+ SimpleTest.finish();
+ SpecialPowers.removePermission("browser", location.href);
+ for (var pref in prefs) {
+ SpecialPowers.pushPrefEnv({"clear": pref[0]}, function() {});
+ }
+}
+
+function testMouseClick(idPosition, dx, dy, idTarget, msg, options) {
+ eventTarget = null;
+ synthesizeMouse(document.getElementById(idPosition), dx, dy, options || {});
+ try {
+ is(eventTarget.id, idTarget,
+ "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]");
+ } catch (ex) {
+ ok(false, "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]; got " + eventTarget);
+ }
+}
+
+function showDebug() {
+ for (var i = 0; i < debugHit.length; i++) {
+ document.body.appendChild(debugHit[i]);
+ }
+
+ var screenshot = SpecialPowers.snapshotWindow(window, true);
+ dump('IMAGE:' + screenshot.toDataURL() + '\n');
+}
+
+/*
+ Setup the test environment: enabling event fluffing (all ui.* preferences),
+ and enabling remote process.
+*/
+function setupTest(cont) {
+ SpecialPowers.addPermission("browser", true, document);
+ SpecialPowers.pushPrefEnv({"set": prefs}, cont);
+}
+
+function execTest() {
+ /*
+ Creating two iframes that mimics the attention screen behavior on the
+ device:
+ - the 'dialer' iframe is the attention screen you have when a call is
+ in place. it is a green bar, so we copy it as green here too
+ - the 'apps' iframe mimics another application that is being run, be it
+ dialer, sms, ..., anything that the user might want to trigger during
+ a call
+
+ The bug we intent to reproduce here is that in this case, if the user taps
+ onto the top of the 'apps', the event fluffing code will in fact redirect
+ the event to the 'dialer' iframe. In practice, this is bug 921928 where
+ during a call the user wants to place a second call, and while typing the
+ phone number, wants to tap onto the 'delete' key to erase a digit, but ends
+ tapping and activating the dialer.
+ */
+ var dialer = document.createElement('iframe');
+ dialer.id = 'dialer';
+ dialer.src = '';
+ // Force OOP
+ dialer.setAttribute('mozbrowser', 'true');
+ dialer.setAttribute('remote', 'true');
+ document.body.appendChild(dialer);
+
+ var apps = document.createElement('iframe');
+ apps.id = 'apps';
+ apps.src = 'bug921928_event_target_iframe_apps_oop.html';
+ // Force OOP
+ apps.setAttribute('mozbrowser', 'true');
+ apps.setAttribute('remote', 'true');
+ document.body.appendChild(apps);
+
+ var handleEvent = function(event) {
+ eventTarget = event.target;
+
+ // We draw a small red div to show where the event has tapped
+ var hit = document.createElement('div');
+ hit.style.left = (event.clientX - 1.5) + 'px';
+ hit.style.top = (event.clientY - 1.5) + 'px';
+ hit.classList.add('hit');
+ debugHit.push(hit);
+ };
+
+ // In real life, the 'dialer' has a 'mousedown', so we mimic one too,
+ // to reproduce the same behavior
+ dialer.addEventListener('mousedown', function(e) {});
+
+ // This event listener is just here to record what iframe has been hit,
+ // and sets the 'eventTarget' to the iframe's id value so that the
+ // testMouseClick() code can correctly check. We cannot add it on the
+ // 'apps' otherwise it will alter the behavior of the test.
+ document.addEventListener('mousedown', handleEvent);
+
+ // In the following, the coordinates are relative to the iframe
+
+ // First, we check that tapping onto the 'dialer' correctly triggers the
+ // dialer.
+ testMouseClick("dialer", 20, 1, "dialer", "correct hit on dialer with mouse input");
+ testMouseClick("dialer", 20, 1, "dialer", "correct hit on dialer with touch input", {
+ inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+ });
+
+ // Now this is it: we tap inside 'apps', but very close to the border between
+ // 'apps' and 'dialer'. Without the fix from this bug, this test will fail.
+ testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for mouse input");
+ testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for touch input", {
+ inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+ });
+
+ // Show small red spots of where the click happened
+ // showDebug();
+
+ endTest();
+}
+
+function runTest() {
+ setupTest(execTest);
+}
+
+addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_event_target_radius.html b/layout/base/tests/test_event_target_radius.html
new file mode 100644
index 000000000..0657e9a69
--- /dev/null
+++ b/layout/base/tests/test_event_target_radius.html
@@ -0,0 +1,293 @@
+<!DOCTYPE HTML>
+<html id="html" style="height:100%">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=780847
+-->
+<head>
+ <title>Test radii for mouse events</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .target { position:absolute; left:100px; top:100px; width:100px; height:100px; background:blue; }
+ </style>
+</head>
+<body id="body" onload="setTimeout(startTest, 0)" style="margin:0; width:100%; height:100%; overflow:hidden">
+<p id="display"></p>
+<div id="content">
+ <div id="ruler" style="position:absolute; left:0; top:0; width:1mozmm; height:0;"></div>
+
+ <!-- the iframe holding this test is only 300px tall on B2G, so we need to
+ make the t target shorter than normal to test the bottom edge fluffing
+ -->
+ <div class="target" style="height:80px" id="t" onmousedown="x=1"></div>
+
+ <div class="target" id="t2" hidden></div>
+
+ <input class="target" id="t3_1" hidden></input>
+ <a href="#" class="target" id="t3_2" hidden></a>
+ <label class="target" id="t3_3" hidden></label>
+ <button class="target" id="t3_4" hidden></button>
+ <select class="target" id="t3_5" hidden></select>
+ <textarea class="target" id="t3_6" hidden></textarea>
+ <div role="button" class="target" id="t3_7" hidden></div>
+ <div role="key" class="target" id="t3_8" hidden></div>
+ <img class="target" id="t3_9" hidden></img>
+
+ <div class="target" style="transform:translate(-80px,0);" id="t4" onmousedown="x=1" hidden></div>
+
+ <div class="target" style="left:0; z-index:1" id="t5_left" onmousedown="x=1" hidden></div>
+ <div class="target" style="left:106px;" id="t5_right" onmousedown="x=1" hidden></div>
+ <div class="target" style="left:0; top:210px;" id="t5_below" onmousedown="x=1" hidden></div>
+
+ <div class="target" id="t6" onmousedown="x=1" style="width: 300px" hidden>
+ <div id="t6_inner" style="position:absolute; left:-40px; top:20px; width:60px; height:60px; background:yellow;"></div>
+ <div id="t6_inner_clickable" style="position:absolute; left:-40px; top: 80px; width: 60px; height: 5px; background:red" onmousedown="x=1"></div>
+ </div>
+ <div id="t6_outer" style="position:absolute; left:360px; top:120px; width:60px; height:60px; background:green;" onmousedown="x=1" hidden></div>
+
+ <div class="target" id="t7" onmousedown="x=1" hidden></div>
+ <div class="target" id="t7_over" hidden></div>
+
+ <div id="t8" contenteditable="true" class="target" hidden></div>
+
+ <div id="t9" class="target" ontouchend="x=1" hidden></div>
+
+ <div id="t10_left" class="target" style="left:-50px;" onmousedown="x=1" hidden></div>
+ <div id="t10_right" class="target" style="left:auto;right:-50px" onmousedown="x=1" hidden></div>
+ <div id="t10_top" class="target" style="top:-50px;" onmousedown="x=1" hidden></div>
+ <div id="t10_bottom" class="target" style="top:auto;bottom:-50px;" onmousedown="x=1" hidden></div>
+ <div id="t10_over" style="position:absolute; left:0; top:0; width:100%; height:100%; background:yellow;" hidden></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+function startTest() {
+ SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.enabled", true],
+ ["ui.mouse.radius.inputSource.touchOnly", false],
+ ["ui.mouse.radius.leftmm", 12],
+ ["ui.mouse.radius.topmm", 8],
+ ["ui.mouse.radius.rightmm", 4],
+ ["ui.mouse.radius.bottommm", 4],
+ ["ui.mouse.radius.visitedweight", 50]]}, runTest);
+}
+
+
+SimpleTest.waitForExplicitFinish();
+
+function endTest() {
+ SimpleTest.finish();
+}
+
+var eventTarget;
+window.onmousedown = function(event) { eventTarget = event.target; };
+
+function testMouseClick(idPosition, dx, dy, idTarget, msg, options) {
+ eventTarget = null;
+ synthesizeMouse(document.getElementById(idPosition), dx, dy, options || {});
+ try {
+ is(eventTarget.id, idTarget,
+ "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]");
+ } catch (ex) {
+ ok(false, "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]; got " + eventTarget);
+ }
+}
+
+function setShowing(id, show) {
+ var e = document.getElementById(id);
+ e.hidden = !show;
+}
+
+var mm;
+function runTest() {
+ let resolution = 1;
+ if (SpecialPowers.Services.appinfo.name == "B2G") {
+ // This test runs on B2G as well, zoomed out. Therefore we need to account
+ // for the resolution as well, because the fluff area is relative to screen
+ // pixels rather than CSS pixels.
+ let out = {};
+ SpecialPowers.getDOMWindowUtils(window.top).getResolution(out);
+ resolution = 1.0 / out.value;
+ }
+ mm = document.getElementById("ruler").getBoundingClientRect().width * resolution;
+ ok(4*mm >= 10, "WARNING: mm " + mm + " too small in this configuration. Test results will be bogus");
+
+ // Test basic functionality: clicks sufficiently close to the element
+ // should be allowed to hit the element. We test points just inside and
+ // just outside the edges we set up in the prefs.
+ testMouseClick("t", 100 + 13*mm, 10, "body", "basic functionality");
+ testMouseClick("t", 100 + 11*mm, 10, "t", "basic functionality");
+ testMouseClick("t", 10, 80 + 9*mm, "body", "basic functionality");
+ testMouseClick("t", 10, 80 + 7*mm, "t", "basic functionality");
+ testMouseClick("t", -5*mm, 10, "body", "basic functionality");
+ testMouseClick("t", -3*mm, 10, "t", "basic functionality");
+ testMouseClick("t", 10, -5*mm, "body", "basic functionality");
+ testMouseClick("t", 10, -3*mm, "t", "basic functionality");
+
+ // When inputSource.touchOnly is true, mouse input is not retargeted.
+ SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.inputSource.touchOnly", true]]}, test2);
+}
+
+function test2() {
+ testMouseClick("t", 100 + 11*mm, 10, "body", "disabled for mouse input");
+ testMouseClick("t", 100 + 11*mm, 10, "t", "enabled for touch input", {
+ inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+ });
+ testMouseClick("t", 100 + 13*mm, 10, "body", "basic functionality for touch", {
+ inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+ });
+ SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.inputSource.touchOnly", false]]}, test3);
+}
+
+function test3() {
+ setShowing("t", false);
+
+ // Now test the criteria we use to determine which elements are hittable
+ // this way.
+
+ setShowing("t2", true);
+ var t2 = document.getElementById("t2");
+ // Unadorned DIVs are not click radius targets
+ testMouseClick("t2", 100 + 11*mm, 10, "body", "unadorned DIV");
+ // DIVs with the right event handlers are click radius targets
+ t2.onmousedown = function() {};
+ testMouseClick("t2", 100 + 11*mm, 10, "t2", "DIV with onmousedown");
+ t2.onmousedown = null;
+ testMouseClick("t2", 100 + 11*mm, 10, "body", "DIV with onmousedown removed");
+ t2.onmouseup = function() {};
+ testMouseClick("t2", 100 + 11*mm, 10, "t2", "DIV with onmouseup");
+ t2.onmouseup = null;
+ t2.onclick = function() {};
+ testMouseClick("t2", 100 + 11*mm, 10, "t2", "DIV with onclick");
+ t2.onclick = null;
+ // Keypresses don't make click radius targets
+ t2.onkeypress = function() {};
+ testMouseClick("t2", 100 + 11*mm, 10, "body", "DIV with onkeypress");
+ t2.onkeypress = null;
+ setShowing("t2", false);
+
+ // Now check that certain elements are click radius targets and others are not
+ for (var i = 1; i <= 9; ++i) {
+ var id = "t3_" + i;
+ var shouldHit = i <= 8;
+ setShowing(id, true);
+ testMouseClick(id, 100 + 11*mm, 10, shouldHit ? id : "body",
+ "<" + document.getElementById(id).tagName + "> element");
+ setShowing(id, false);
+ }
+
+ // Check that our targeting computations take into account the effects of
+ // CSS transforms
+ setShowing("t4", true);
+ testMouseClick("t4", -1, 10, "t4", "translated DIV");
+ setShowing("t4", false);
+
+ // Test the prioritization of multiple targets based on distance to
+ // the target.
+ setShowing("t5_left", true);
+ setShowing("t5_right", true);
+ setShowing("t5_below", true);
+ testMouseClick("t5_left", 102, 10, "t5_left", "closest DIV is left");
+ testMouseClick("t5_left", 102.5, 10, "t5_left",
+ "closest DIV to midpoint is left because of its higher z-index");
+ testMouseClick("t5_left", 104, 10, "t5_right", "closest DIV is right");
+ testMouseClick("t5_left", 10, 104, "t5_left", "closest DIV is left");
+ testMouseClick("t5_left", 10, 105, "t5_left",
+ "closest DIV to midpoint is left because of its higher z-index");
+ testMouseClick("t5_left", 10, 106, "t5_below", "closest DIV is below");
+ setShowing("t5_left", false);
+ setShowing("t5_right", false);
+ setShowing("t5_below", false);
+
+ // Test behavior of nested elements.
+ // The following behaviors are questionable and may need to be changed.
+ setShowing("t6", true);
+ setShowing("t6_outer", true);
+ testMouseClick("t6_inner", -1, 10, "t6_inner",
+ "inner element is clickable because its parent is, even when it sticks outside parent");
+ testMouseClick("t6_inner", 39, -1, "t6_inner",
+ "when outside both inner and parent, but in range of both, the inner is selected");
+ testMouseClick("t6_inner", 45, -1, "t6_inner",
+ "clicking in clickable parent close to inner activates inner, not parent");
+ testMouseClick("t6_inner_clickable", 1, -1, "t6_inner",
+ "clicking on inner doesn't get redirected to inner_clickable because they are both clickable");
+ testMouseClick("t6_inner_clickable", 1, 1, "t6_inner_clickable",
+ "clicking on inner_clickable doesn't get redirected to inner because they are both clickable");
+ testMouseClick("t6_inner_clickable", 45, -1, "t6_inner",
+ "clicking on inner while backed by its parent still doesn't get redirected to inner_clickable");
+ testMouseClick("t6_inner_clickable", 45, 1, "t6_inner_clickable",
+ "clicking on inner_clickable while backed by its parent still doesn't get redirected to inner");
+ testMouseClick("t6_inner_clickable", 45, 6, "t6_inner_clickable",
+ "clicking on parent near inner_clickable gets redirected to inner_clickable rather than inner because it is closer");
+ // 280 is the distance from t6_inner's right edge to t6's right edge
+ // 240 is the distance from t6_inner's right edge to t6_outer's right edge.
+ // we want to click on t6, but at least 13mm away from t6_inner, so that
+ // t6_inner doesn't steal the click.
+ ok(13*mm < 280, "no point inside t6 that's not within radius of t6_inner; adjust layout of t6/inner/outer as needed");
+ testMouseClick("t6_outer", -240 + 13*mm, -1, "t6",
+ "clicking in clickable container close to outer activates parent, not outer");
+ testMouseClick("t6_outer", 1, 1, "t6_outer",
+ "clicking directly on the outer activates it");
+ setShowing("t6", false);
+ setShowing("t6_outer", false);
+
+ setShowing("t7", true);
+ setShowing("t7_over", true);
+ testMouseClick("t7", 100 + 11*mm, 10, "body", "covered div is not clickable");
+ testMouseClick("t7", 10, 10, "t7_over", "covered div is not clickable even within its bounds");
+ setShowing("t7", false);
+ setShowing("t7_over", false);
+
+ // Check that contenteditable elements are considered clickable for fluffing.
+ setShowing("t8", true);
+ var rect = document.getElementById("t8").getBoundingClientRect();
+ testMouseClick("t8", rect.left + 1, rect.top + 1, "t8", "content editable enabled for mouse input");
+ testMouseClick("t8", rect.left + 1, rect.top + 1, "t8", "content editable enabled for touch input", {
+ inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+ });
+ setShowing("t8", false);
+
+ // Check that elements are touchable
+ setShowing("t9", true);
+ var rect = document.getElementById("t9").getBoundingClientRect();
+ testMouseClick("t9", rect.left + 1, rect.top + 1, "t9", "div enabled with mouse input");
+ testMouseClick("t9", rect.left + 1, rect.top + 1, "t9", "div enabled with touch input", {
+ inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+ });
+ setShowing("t9", false);
+
+ setShowing("t10_over", true);
+ setShowing("t10_left", true);
+ setShowing("t10_right", true);
+ setShowing("t10_top", true);
+ setShowing("t10_bottom", true);
+ testMouseClick("t10_left", 51, 10, "t10_over", "element outside of visible area is not selected");
+ if (self.frameElement &&
+ (self.frameElement.offsetLeft + self.innerWidth >
+ SpecialPowers.wrap(top).innerWidth)) {
+ info("WARNING: Window is too narrow, can't test t10_right");
+ } else {
+ testMouseClick("t10_right", 49, 10, "t10_over", "element outside of visible area is not selected");
+ }
+ testMouseClick("t10_top", 10, 51, "t10_over", "element outside of visible area is not selected");
+ if (self.frameElement &&
+ (self.frameElement.offsetTop + self.innerHeight >
+ SpecialPowers.wrap(top).innerHeight)) {
+ info("WARNING: Window is too short, can't test t10_bottom");
+ } else {
+ testMouseClick("t10_bottom", 10, 49, "t10_over", "element outside of visible area is not selected");
+ }
+ setShowing("t10_over", false);
+ setShowing("t10_left", false);
+ setShowing("t10_right", false);
+ setShowing("t10_top", false);
+ setShowing("t10_bottom", false);
+
+ // Not yet tested:
+ // -- visited link weight
+ // -- "Closest" using Euclidean distance
+ endTest();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_flush_on_paint.html b/layout/base/tests/test_flush_on_paint.html
new file mode 100644
index 000000000..de088b4de
--- /dev/null
+++ b/layout/base/tests/test_flush_on_paint.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that we flush before painting</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="doIteration()">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<embed type="application/x-test" id="plugin" drawmode="solid" style="width:200px; height:200px;"></embed>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("This test deals with painting and invalidation. " +
+ "Those are tricky to detect, so we have to poll here, which means that we have to rely on flaky timeouts. " +
+ "This special case is safe because we're only polling for events.");
+
+var iterations = 0;
+var plugin = document.getElementById("plugin");
+var lastPaintCount;
+var expectedWidth;
+
+var toggle = true;
+function invalidationLoop() {
+ toggle = !toggle;
+ var color = toggle ? "8F" : "00";
+ plugin.setColor("FFFFFF" + color);
+ setTimeout(invalidationLoop, 20);
+}
+invalidationLoop();
+
+function doIteration() {
+ lastPaintCount = window.mozPaintCount;
+ ok(true, "Beginning iteration " + iterations + ", last paint count: " + lastPaintCount);
+
+ expectedWidth = 201 + iterations;
+ plugin.style.width = expectedWidth + "px";
+ checkDone();
+}
+
+function checkDone() {
+ ok(true, "Check to see if we're done: " + window.mozPaintCount);
+ if (window.mozPaintCount == lastPaintCount) {
+ setTimeout(checkDone, 30);
+ return;
+ }
+
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ is(plugin.getWidthAtLastPaint(), utils.screenPixelsPerCSSPixel*expectedWidth,
+ "Check that we set width before painting");
+
+ ++iterations;
+ if (iterations < 100) {
+ doIteration();
+ } else {
+ SimpleTest.finish();
+ }
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_frame_reconstruction_for_pseudo_elements.html b/layout/base/tests/test_frame_reconstruction_for_pseudo_elements.html
new file mode 100644
index 000000000..e6339d94b
--- /dev/null
+++ b/layout/base/tests/test_frame_reconstruction_for_pseudo_elements.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1110277
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1110277</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .testspan {
+ color: yellow;
+ }
+ .testspan[attributestate],
+ .testspan[attributestate]::before, .testspan[attributestate]::after {
+ color: blue;
+ }
+
+ #firstlinetest::first-line {
+ color: purple;
+ }
+ #firstlinetest > .testspan::before {
+ content: "[*]";
+ }
+
+ #aftertest > .testspan::after {
+ content: "[*]";
+ }
+ </style>
+ <script type="application/javascript">
+
+ /** Test for Bug 1110277 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ function run() {
+ runtest("first line test", "#firstlinetest > .testspan");
+ runtest("after test", "#aftertest > .testspan");
+ SimpleTest.finish();
+ }
+
+ function runtest(description, selector) {
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ var span = document.querySelector(selector);
+ var cs = getComputedStyle(span, "");
+
+ var startcolor = cs.color;
+ var startcount = utils.framesConstructed;
+ is(startcolor, "rgb(255, 255, 0)", description + ": initial color");
+
+ span.setAttribute("attributestate", "true");
+
+ var endcolor = cs.color;
+ var endcount = utils.framesConstructed;
+ is(endcolor, "rgb(0, 0, 255)", description + ": final color");
+ is(endcount, startcount,
+ description + ": should not do frame construction")
+ }
+
+ </script>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1110277">Mozilla Bug 1110277</a>
+<div id="firstlinetest">
+ <span class="testspan">This <span style="display:block">is a</span> test.</span>
+</div>
+<div id="aftertest">
+ <span class="testspan">This <span style="display:block">is a</span> test.</span>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_frame_reconstruction_scroll_restore.html b/layout/base/tests/test_frame_reconstruction_scroll_restore.html
new file mode 100644
index 000000000..69758b9c1
--- /dev/null
+++ b/layout/base/tests/test_frame_reconstruction_scroll_restore.html
@@ -0,0 +1,68 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1268195
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1268195</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ }
+
+ .noscroll {
+ overflow: hidden;
+ height: 100%;
+ }
+
+ /* Toggling this on and off triggers a frame reconstruction on the <body> */
+ html.reconstruct-body::before {
+ top: 0;
+ content: '';
+ display: block;
+ height: 2px;
+ position: absolute;
+ width: 100%;
+ z-index: 99;
+ }
+ </style>
+ <script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+
+ function run() {
+ // Make sure we have the right scroll element
+ SimpleTest.is(document.body.scrollTopMax > 0, true, "Body is the scrolling element");
+
+ // Scroll to the bottom
+ document.body.scrollTop = document.body.scrollTopMax;
+ SimpleTest.is(document.body.scrollTop > 0, true, "Scrolled body");
+
+ // Do a frame reconstruction on the body while also shortening the
+ // height.
+ document.body.classList.toggle('noscroll');
+ document.documentElement.classList.toggle('reconstruct-body');
+ document.getElementById('spacer').style.height = '1px';
+ SimpleTest.is(document.body.scrollTop, 0, "Scroll forced to top");
+
+ // Do another frame reconstruction while lengthening the height again.
+ document.body.classList.toggle('noscroll');
+ document.documentElement.classList.toggle('reconstruct-body');
+ document.getElementById('spacer').style.height = '5000px';
+ SimpleTest.is(document.body.scrollTop, 0, "Scroll remained at top");
+
+ SimpleTest.finish();
+ }
+ </script>
+</head>
+<body onload="setTimeout(run, 0)">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1268195">Mozilla Bug 1268195</a><br/>
+The scroll position should end the top of the page. This is the top, yay!
+<div id="spacer" style="height: 5000px"></div>
+The scroll position should end the top of the page. This is the bottom!
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html b/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html
new file mode 100644
index 000000000..7ec4f7b56
--- /dev/null
+++ b/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html
@@ -0,0 +1,713 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="startTest()">
+<p id="display"></p>
+<script>
+// Global variables we want eval() to be able to reference from anywhere
+var f1d;
+var text;
+var suppressedText;
+var suppressedText2;
+var comment;
+var fragment;
+var openedWindow;
+var zeroPoint;
+var zeroRect;
+var zeroQuad;
+var notInDocument = document.createElement('div');
+
+function isEval(expr, b) {
+ is(eval(expr), b, expr);
+}
+
+function isApprox(a, b, msg, options) {
+ if (a != b && 'tolerance' in options &&
+ Math.abs(a - b) < options.tolerance) {
+ ok(true, msg + "(" + a + " within " + options.tolerance + " of " + b + ")");
+ return;
+ }
+ is(a, b, msg);
+}
+
+function makeQuadsExpr(fromStr, options) {
+ var getBoxQuadsOptionParts = [];
+ if ('box' in options) {
+ getBoxQuadsOptionParts.push("box:'" + options.box + "'");
+ }
+ if ('toStr' in options) {
+ getBoxQuadsOptionParts.push("relativeTo:" + options.toStr);
+ }
+ return fromStr + ".getBoxQuads({" + getBoxQuadsOptionParts.join(',') + "})";
+}
+
+function makePointExpr(fromStr, options, x, y) {
+ var convertPointOptionParts = [];
+ if ('box' in options) {
+ convertPointOptionParts.push("fromBox:'" + options.box + "'");
+ }
+ if ('toBox' in options) {
+ convertPointOptionParts.push("toBox:'" + options.toBox + "'");
+ }
+ return ('toStr' in options ? options.toStr : "document") +
+ ".convertPointFromNode(new DOMPoint(" + x + "," + y + ")," + fromStr + ",{" +
+ convertPointOptionParts.join(",") + "})";
+}
+
+function checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
+ var selfQuads = eval(fromStr).getBoxQuads(
+ {box:options.box == "" ? "border" : options.box,
+ relativeTo:eval(fromStr)});
+ var boxWidth = selfQuads[0].bounds.width;
+ var boxHeight = selfQuads[0].bounds.height;
+
+ var convertTopLeftPointExpr = makePointExpr(fromStr, options, 0, 0);
+ var topLeft = eval(convertTopLeftPointExpr);
+ isApprox(topLeft.x, x1, convertTopLeftPointExpr + ".x", options);
+ isApprox(topLeft.y, y1, convertTopLeftPointExpr + ".y", options);
+
+ var convertTopRightPointExpr = makePointExpr(fromStr, options, boxWidth, 0);
+ var topRight = eval(convertTopRightPointExpr);
+ isApprox(topRight.x, x2, convertTopRightPointExpr + ".x", options);
+ isApprox(topRight.y, y2, convertTopRightPointExpr + ".y", options);
+
+ var convertBottomRightPointExpr = makePointExpr(fromStr, options, boxWidth, boxHeight);
+ var bottomRight = eval(convertBottomRightPointExpr);
+ isApprox(bottomRight.x, x3, convertBottomRightPointExpr + ".x", options);
+ isApprox(bottomRight.y, y3, convertBottomRightPointExpr + ".y", options);
+
+ var convertBottomLeftPointExpr = makePointExpr(fromStr, options, 0, boxHeight);
+ var bottomLeft = eval(convertBottomLeftPointExpr);
+ isApprox(bottomLeft.x, x4, convertBottomLeftPointExpr + ".x", options);
+ isApprox(bottomLeft.y, y4, convertBottomLeftPointExpr + ".y", options);
+}
+
+function checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
+ var selfQuads = eval(fromStr).getBoxQuads(
+ {box:options.box == "" ? "border" : options.box,
+ relativeTo:eval(fromStr)});
+ var boxWidth = selfQuads[0].bounds.width;
+ var boxHeight = selfQuads[0].bounds.height;
+
+ var convertPointOptionParts = [];
+ if ('box' in options) {
+ convertPointOptionParts.push("fromBox:'" + options.box + "'");
+ }
+ if ('toBox' in options) {
+ convertPointOptionParts.push("toBox:'" + options.toBox + "'");
+ }
+
+ var convertRectExpr = ('toStr' in options ? options.toStr : "document") +
+ ".convertRectFromNode(new DOMRect(0,0," + boxWidth + "," + boxHeight + ")," +
+ fromStr + ",{" + convertPointOptionParts.join(",") + "})";
+ var quad = eval(convertRectExpr);
+ isApprox(quad.p1.x, x1, convertRectExpr + ".p1.x", options);
+ isApprox(quad.p1.y, y1, convertRectExpr + ".p1.y", options);
+ isApprox(quad.p2.x, x2, convertRectExpr + ".p2.x", options);
+ isApprox(quad.p2.y, y2, convertRectExpr + ".p2.y", options);
+ isApprox(quad.p3.x, x3, convertRectExpr + ".p3.x", options);
+ isApprox(quad.p3.y, y3, convertRectExpr + ".p3.y", options);
+ isApprox(quad.p4.x, x4, convertRectExpr + ".p4.x", options);
+ isApprox(quad.p4.y, y4, convertRectExpr + ".p4.y", options);
+}
+
+function checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
+ var selfQuads = eval(fromStr).getBoxQuads(
+ {box:options.box == "" ? "border" : options.box,
+ relativeTo:eval(fromStr)});
+ var boxWidth = selfQuads[0].bounds.width;
+ var boxHeight = selfQuads[0].bounds.height;
+
+ var convertPointOptionParts = [];
+ if ('box' in options) {
+ convertPointOptionParts.push("fromBox:'" + options.box + "'");
+ }
+ if ('toBox' in options) {
+ convertPointOptionParts.push("toBox:'" + options.toBox + "'");
+ }
+
+ var convertQuadExpr = ('toStr' in options ? options.toStr : "document") +
+ ".convertQuadFromNode(new DOMQuad(new DOMRect(0,0," + boxWidth + "," + boxHeight + "))," +
+ fromStr + ",{" + convertPointOptionParts.join(",") + "})";
+ var quad = eval(convertQuadExpr);
+ isApprox(quad.p1.x, x1, convertQuadExpr + ".p1.x", options);
+ isApprox(quad.p1.y, y1, convertQuadExpr + ".p1.y", options);
+ isApprox(quad.p2.x, x2, convertQuadExpr + ".p2.x", options);
+ isApprox(quad.p2.y, y2, convertQuadExpr + ".p2.y", options);
+ isApprox(quad.p3.x, x3, convertQuadExpr + ".p3.x", options);
+ isApprox(quad.p3.y, y3, convertQuadExpr + ".p3.y", options);
+ isApprox(quad.p4.x, x4, convertQuadExpr + ".p4.x", options);
+ isApprox(quad.p4.y, y4, convertQuadExpr + ".p4.y", options);
+}
+
+function checkQuadIsRect(fromStr, options, x, y, w, h) {
+ var quadsExpr = makeQuadsExpr(fromStr, options);
+ var quads = eval(quadsExpr);
+ is(quads.length, 1, quadsExpr + " checking quad count");
+ var q = quads[0];
+ isApprox(q.p1.x, x, quadsExpr + " checking quad.p1.x", options);
+ isApprox(q.p1.y, y, quadsExpr + " checking quad.p1.y", options);
+ isApprox(q.p2.x, x + w, quadsExpr + " checking quad.p2.x", options);
+ isApprox(q.p2.y, y, quadsExpr + " checking quad.p2.y", options);
+ isApprox(q.p3.x, x + w, quadsExpr + " checking quad.p3.x", options);
+ isApprox(q.p3.y, y + h, quadsExpr + " checking quad.p3.y", options);
+ isApprox(q.p4.x, x, quadsExpr + " checking quad.p4.x", options);
+ isApprox(q.p4.y, y + h, quadsExpr + " checking quad.p4.y", options);
+
+ isApprox(q.bounds.left, x, quadsExpr + " checking quad.bounds.left", options);
+ isApprox(q.bounds.top, y, quadsExpr + " checking quad.bounds.top", options);
+ isApprox(q.bounds.width, w, quadsExpr + " checking quad.bounds.width", options);
+ isApprox(q.bounds.height, h, quadsExpr + " checking quad.bounds.height", options);
+
+ checkConvertPoints(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
+ checkConvertRect(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
+ checkConvertQuad(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h);
+}
+
+function checkQuadIsQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) {
+ var quadsExpr = makeQuadsExpr(fromStr, options);
+ var quads = eval(quadsExpr);
+ is(quads.length, 1, quadsExpr + " checking quad count");
+ var q = quads[0];
+ isApprox(q.p1.x, x1, quadsExpr + " checking quad.p1.x", options);
+ isApprox(q.p1.y, y1, quadsExpr + " checking quad.p1.y", options);
+ isApprox(q.p2.x, x2, quadsExpr + " checking quad.p2.x", options);
+ isApprox(q.p2.y, y2, quadsExpr + " checking quad.p2.y", options);
+ isApprox(q.p3.x, x3, quadsExpr + " checking quad.p3.x", options);
+ isApprox(q.p3.y, y3, quadsExpr + " checking quad.p3.y", options);
+ isApprox(q.p4.x, x4, quadsExpr + " checking quad.p4.x", options);
+ isApprox(q.p4.y, y4, quadsExpr + " checking quad.p4.y", options);
+
+ isApprox(q.bounds.left, Math.min(x1,x2,x3,x4), quadsExpr + " checking quad.bounds.left", options);
+ isApprox(q.bounds.top, Math.min(y1,y2,y3,y4), quadsExpr + " checking quad.bounds.top", options);
+ isApprox(q.bounds.right, Math.max(x1,x2,x3,x4), quadsExpr + " checking quad.bounds.right", options);
+ isApprox(q.bounds.bottom, Math.max(y1,y2,y3,y4), quadsExpr + " checking quad.bounds.bottom", options);
+
+ checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
+ checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
+ checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4);
+}
+
+function checkException(expr, name) {
+ try {
+ eval(expr);
+ ok(false, "Exception should have been thrown for " + expr);
+ } catch (ex) {
+ is(ex.name, name, "Checking exception type for " + expr);
+ }
+}
+
+function checkNotFound(fromStr, toStr, x1, y1, x2, y2) {
+ var convertPointExpr = toStr + ".convertPointFromNode(new DOMPoint(" + x1 +
+ "," + y1 + ")," + fromStr + ")";
+ checkException(convertPointExpr, "NotFoundError");
+
+ var convertRectExpr = toStr + ".convertRectFromNode(new DOMRect(" + x1 +
+ "," + y1 + "," + x2 + "," + y2 + ")," + fromStr + ")";
+ checkException(convertRectExpr, "NotFoundError");
+
+ var convertQuadExpr = toStr + ".convertQuadFromNode(new DOMQuad(new DOMRect(" + x1 +
+ "," + y1 + "," + x2 + "," + y2 + "))," + fromStr + ")";
+ checkException(convertQuadExpr, "NotFoundError");
+}
+</script>
+<style>
+em {
+ display:inline-block; height:10px; background:gray;
+}
+</style>
+<div id="dContainer"
+ style="padding:13px 14px 15px 16px;
+ border-width:17px 18px 19px 20px; border-style:solid; border-color:yellow;
+ margin:21px 22px 23px 24px;">
+ <div id="d"
+ style="width:120px; height:90px; padding:1px 2px 3px 4px;
+ border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
+ margin:9px 10px 11px 12px; background:blue;">
+ </div>
+</div>
+
+<div id="dUnrelated" style="width:50px; height:50px;"></div>
+
+<iframe id="f1" style="width:50px; height:50px; border:0; background:lime;"
+ src="data:text/html,<!DOCTYPE HTML><html style='padding:25px'><div id='f1d' style='position:absolute; left:14px; top:15px; width:16px; height:17px; background:pink'></div>">
+</iframe>
+<!--
+It matters that the first part of this span is on the same line as the above <iframe>!
+That ensures the first quad's X position is not equal to the anonymous block's X position.
+-->
+<span id="ibSplit"
+ ><em id="ibSplitPart1" style="width:100px;"></em
+ ><div style="width:110px; height:20px; background:black"></div
+ ><em style="width:130px;"></em></span>
+
+<table cellspacing="0" id="table" style="border:0; margin:8px; padding:0; background:orange">
+ <tbody style="padding:0; margin:0; border:0; background:blue">
+ <tr style="height:50px; padding:0; margin:0; border:0">
+ <td style="border:0; margin:0; padding:0">Cell</td>
+ </tr>
+ </tbody>
+ <caption style="height:40px; background:yellow">Caption</caption>
+</table>
+
+<div style="height:80px; -moz-column-count:2; -moz-column-fill:auto; border:2px solid black;">
+ <div style="height:20px;"></div>
+ <div id="colSplit" style="height:80px; background:blue; border:10px solid red; border-bottom-width:15px"></div>
+</div>
+
+<div style="width:200px; border:2px solid black;"
+ ><em style="width:150px;"></em
+ ><span id="inlineSplit" style="background:pink; border:10px solid red; border-right-width:15px"
+ ><em style="width:20px; background:green"></em><em style="width:60px"></em
+ ></span
+></div>
+
+<div style="width:200px; border:2px solid black;"
+ ><em style="width:150px;"></em
+ ><span id="textContainer">T
+TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText</span
+></div>
+
+<div id="suppressedTextContainer"> </div>
+<div id="suppressedTextContainer2"> </div>
+
+<div id="commentContainer"><!-- COMMENT --></div>
+
+<div id="displayNone" style="display:none"></div>
+
+<div id="overflowHidden"
+ style="overflow:hidden; width:120px; height:90px; padding:1px 2px 3px 4px;
+ border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
+ margin:9px 10px 11px 12px; background:blue;">
+ <div style="height:400px; background:lime;"></div>
+</div>
+
+<div id="overflowScroll"
+ style="overflow:scroll; width:120px; height:90px; padding:1px 2px 3px 4px;
+ border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
+ margin:9px 10px 11px 12px; background:blue; background-clip:content-box;">
+ <div id="overflowScrollChild" style="height:400px;"></div>
+</div>
+
+<div id="scaleTransformContainer" style="width:200px; height:200px;">
+ <div id="scaleTransform"
+ style="transform:scale(2); transform-origin:top left; width:70px; height:80px; background:yellow"></div>
+</div>
+
+<div id="translateTransformContainer" style="width:200px; height:200px;">
+ <div id="translateTransform"
+ style="transform:translate(30px,40px); width:70px; height:80px; background:yellow"></div>
+</div>
+
+<div id="rotateTransformContainer" style="width:200px; height:200px;">
+ <div id="rotateTransform"
+ style="transform:rotate(90deg); width:70px; height:80px; background:yellow"></div>
+</div>
+
+<div id="flipTransformContainer" style="width:200px; height:200px;">
+ <div id="flipTransform"
+ style="transform:scaleY(-1); width:70px; height:80px; background:yellow"></div>
+</div>
+
+<div id="rot45TransformContainer" style="width:200px; height:200px;">
+ <div id="rot45Transform"
+ style="transform:rotate(45deg); width:100px; height:100px; background:yellow"></div>
+</div>
+
+<div id="singularTransform" style="transform:scale(0); width:200px; height:200px;">
+ <div id="singularTransformChild1" style="height:50px;"></div>
+ <div id="singularTransformChild2" style="height:50px;"></div>
+</div>
+
+<div id="threeDTransformContainer" style="perspective:600px; width:200px; height:200px">
+ <div id="threeDTransform" style="transform:rotateY(70deg); background:yellow; height:100px; perspective:600px">
+ <div id="threeDTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div>
+ </div>
+</div>
+
+<div id="preserve3DTransformContainer" style="perspective:600px; width:200px; height:200px">
+ <div id="preserve3DTransform" style="transform:rotateY(70deg); transform-style:preserve-3d; background:yellow; height:100px;">
+ <div id="preserve3DTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div>
+ </div>
+</div>
+
+<div id="svgContainer">
+ <svg id="svg" style="width:200px; height:200px; background:lightgray; border:7px solid blue; padding:4px">
+ <circle id="circle" cx="50" cy="50" r="20" fill="red" style="margin:20px; padding:10px; border:15px solid black"></circle>
+ <g transform="scale(2)">
+ <foreignObject x="50" y="20">
+ <div id="foreign" style="width:100px; height:60px; background:purple"></div>
+ </foreignObject>
+ </g>
+ </svg>
+</div>
+
+<script>
+SimpleTest.waitForExplicitFinish();
+
+window.scrollTo(0,0);
+
+function startTest() {
+ SpecialPowers.pushPrefEnv({"set": [["layout.css.DOMPoint.enabled", true],
+ ["layout.css.DOMQuad.enabled", true],
+ ["layout.css.getBoxQuads.enabled", true],
+ ["layout.css.convertFromNode.enabled", true]]}, grabFeatures);
+}
+
+// This is a bit of a hack but it works. Our Window object was set up while
+// the prefs might have been false so it may not have the features we're
+// testing. Create an <iframe> whose Window is initialized while the prefs are
+// true, and we can steal the features from that Window.
+// When these prefs are enabled on all builds by default, we can skip this step.
+function grabFeatures() {
+ var x = document.createElement('iframe');
+ x.src = "about:blank";
+ document.body.appendChild(x);
+ function setupFeatures(w) {
+ for (var name of ["getBoxQuads", "convertQuadFromNode", "convertRectFromNode", "convertPointFromNode"]) {
+ w.Text.prototype[name] = x.contentWindow.Text.prototype[name];
+ w.Element.prototype[name] = x.contentWindow.Element.prototype[name];
+ w.Document.prototype[name] = x.contentWindow.Document.prototype[name];
+ }
+ for (var name of ["DOMPoint", "DOMQuad"]) {
+ w[name] = x.contentWindow[name];
+ }
+ }
+ x.onload = function() {
+ setupFeatures(window);
+ setupFeatures(f1.contentWindow);
+ runTest();
+ };
+}
+
+function runTest() {
+ zeroPoint = new DOMPoint(0,0);
+ zeroRect = new DOMRect(0,0,0,0);
+ zeroQuad = new DOMQuad(zeroRect);
+
+ // Setup globals
+ f1d = f1.contentWindow.f1d;
+ text = textContainer.firstChild;
+ suppressedText = suppressedTextContainer.firstChild;
+ suppressedText2 = suppressedTextContainer2.firstChild;
+ comment = commentContainer.firstChild;
+ fragment = document.createDocumentFragment();
+
+ // Test basic BoxQuadOptions.box.
+ var dX = d.getBoundingClientRect().left;
+ var dY = d.getBoundingClientRect().top;
+ var dW = d.getBoundingClientRect().width;
+ var dH = d.getBoundingClientRect().height;
+
+ checkQuadIsRect("d", {box:"content"},
+ dX + 4 + 8, dY + 1 + 5, 120, 90);
+ checkQuadIsRect("d", {box:"padding"},
+ dX + 8, dY + 5, 120 + 2 + 4, 90 + 1 + 3);
+ checkQuadIsRect("d", {box:"border"},
+ dX, dY, dW, dH);
+ checkQuadIsRect("d", {},
+ dX, dY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
+ checkQuadIsRect("d", {box:"margin"},
+ dX - 12, dY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
+
+ // Test basic BoxQuadOptions.relativeTo
+ checkQuadIsRect("d", {toStr:"dContainer"},
+ 12 + 16 + 20, 9 + 13 + 17, dW, dH);
+
+ // Test BoxQuadOptions.relativeTo relative to this document
+ checkQuadIsRect("d", {toStr:"document"},
+ dX, dY, dW, dH);
+ // Test BoxQuadOptions.relativeTo relative to a non-ancestor.
+ var dUnrelatedX = dUnrelated.getBoundingClientRect().left;
+ var dUnrelatedY = dUnrelated.getBoundingClientRect().top;
+ checkQuadIsRect("d", {toStr:"dUnrelated"},
+ dX - dUnrelatedX, dY - dUnrelatedY, dW, dH);
+ // Test BoxQuadOptions.relativeTo relative to an element in a different document (and the document)
+ var f1X = f1.getBoundingClientRect().left;
+ var f1Y = f1.getBoundingClientRect().top;
+ checkQuadIsRect("d", {toStr:"f1.contentWindow.f1d"},
+ dX - (f1X + 14), dY - (f1Y + 15), dW, dH);
+ checkQuadIsRect("d", {toStr:"f1.contentDocument"},
+ dX - f1X, dY - f1Y, dW, dH);
+ // Test one document relative to another
+ checkQuadIsRect("f1.contentDocument", {toStr:"document"},
+ f1X, f1Y, 50, 50);
+ // The box type is irrelevant for a document
+ checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"content"},
+ f1X, f1Y, 50, 50);
+ checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"margin"},
+ f1X, f1Y, 50, 50);
+ checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"padding"},
+ f1X, f1Y, 50, 50);
+
+ // Test that anonymous boxes are correctly ignored when building quads.
+ var ibSplitPart1X = ibSplitPart1.getBoundingClientRect().left;
+ var ibSplitY = ibSplit.getBoundingClientRect().top;
+ isEval("ibSplit.getBoxQuads().length", 3);
+ isEval("ibSplit.getBoxQuads()[0].bounds.left", ibSplitPart1X);
+ isEval("ibSplit.getBoxQuads()[0].bounds.width", 100);
+ isEval("ibSplit.getBoxQuads()[1].bounds.width", 110);
+ isEval("ibSplit.getBoxQuads()[2].bounds.width", 130);
+ isEval("table.getBoxQuads().length", 2);
+ isEval("table.getBoxQuads()[0].bounds.height", 50);
+ isEval("table.getBoxQuads()[1].bounds.height", 40);
+
+ // Test that we skip anonymous boxes when finding the right box to be relative to.
+ checkQuadIsRect("d", {toStr:"ibSplit"},
+ dX - ibSplitPart1X, dY - ibSplitY, dW, dH);
+ var tableX = table.getClientRects()[0].left;
+ var tableY = table.getClientRects()[0].top;
+ checkQuadIsRect("d", {toStr:"table"},
+ dX - tableX, dY - tableY, dW, dH);
+ isEval("ibSplit.convertPointFromNode(zeroPoint,d).x", dX - ibSplitPart1X);
+ isEval("table.convertPointFromNode(zeroPoint,d).x", dX - table.getClientRects()[0].left);
+
+ // Test boxes generated by block splitting. Check for borders being placed correctly.
+ var colSplitY = colSplit.getClientRects()[0].top;
+ isEval("colSplit.getBoxQuads().length", 2);
+ isEval("colSplit.getBoxQuads()[0].bounds.top", colSplitY);
+ isEval("colSplit.getBoxQuads()[0].bounds.height", 60);
+ isEval("colSplit.getBoxQuads()[1].bounds.top", colSplitY - 20);
+ isEval("colSplit.getBoxQuads()[1].bounds.height", 45);
+ isEval("colSplit.getBoxQuads({box:'content'}).length", 2);
+ // The first box for the block has the top border; the second box has the bottom border.
+ isEval("colSplit.getBoxQuads({box:'content'})[0].bounds.top", colSplitY + 10);
+ isEval("colSplit.getBoxQuads({box:'content'})[0].bounds.height", 50);
+ isEval("colSplit.getBoxQuads({box:'content'})[1].bounds.top", colSplitY - 20);
+ isEval("colSplit.getBoxQuads({box:'content'})[1].bounds.height", 30);
+
+ var inlineSplitX = inlineSplit.getClientRects()[0].left;
+ isEval("inlineSplit.getBoxQuads().length", 2);
+ isEval("inlineSplit.getBoxQuads()[0].bounds.left", inlineSplitX);
+ isEval("inlineSplit.getBoxQuads()[0].bounds.width", 30);
+ isEval("inlineSplit.getBoxQuads()[1].bounds.left", inlineSplitX - 150);
+ isEval("inlineSplit.getBoxQuads()[1].bounds.width", 75);
+ isEval("inlineSplit.getBoxQuads({box:'content'}).length", 2);
+ // The first box for the inline has the left border; the second box has the right border.
+ isEval("inlineSplit.getBoxQuads({box:'content'})[0].bounds.left", inlineSplitX + 10);
+ isEval("inlineSplit.getBoxQuads({box:'content'})[0].bounds.width", 20);
+ isEval("inlineSplit.getBoxQuads({box:'content'})[1].bounds.left", inlineSplitX - 150);
+ isEval("inlineSplit.getBoxQuads({box:'content'})[1].bounds.width", 60);
+
+ var textX = textContainer.getClientRects()[0].left;
+ isEval("text.getBoxQuads().length", 2);
+ isEval("text.getBoxQuads()[0].bounds.left", textX);
+ isEval("text.getBoxQuads()[1].bounds.left", textX - 150);
+ // Box types are irrelevant for text
+ isEval("text.getBoxQuads({box:'content'}).length", 2);
+ isEval("text.getBoxQuads({box:'content'})[0].bounds.left", textX);
+ isEval("text.getBoxQuads({box:'content'})[1].bounds.left", textX - 150);
+ isEval("text.getBoxQuads({box:'padding'}).length", 2);
+ isEval("text.getBoxQuads({box:'padding'})[0].bounds.left", textX);
+ isEval("text.getBoxQuads({box:'padding'})[1].bounds.left", textX - 150);
+ isEval("text.getBoxQuads({box:'margin'}).length", 2);
+ isEval("text.getBoxQuads({box:'margin'})[0].bounds.left", textX);
+ isEval("text.getBoxQuads({box:'margin'})[1].bounds.left", textX - 150);
+
+ // Test table margins
+ isEval("table.getBoxQuads({box:'margin'}).length", 1);
+ isEval("table.getBoxQuads({box:'margin'})[0].bounds.height", 106);
+
+ // Check that a text node whose layout might have been optimized away gives
+ // correct results.
+ var suppressedTextContainerX = suppressedTextContainer.getBoundingClientRect().left;
+ isEval("suppressedText.getBoxQuads().length", 1);
+ isEval("suppressedText.getBoxQuads()[0].bounds.left", suppressedTextContainerX);
+ isEval("suppressedText.getBoxQuads()[0].bounds.width", 0);
+
+ var suppressedTextContainer2X = suppressedTextContainer2.getBoundingClientRect().left;
+ isEval("document.convertPointFromNode(zeroPoint,suppressedText2).x",
+ suppressedTextContainer2X);
+
+ checkException("comment.getBoxQuads()", "TypeError");
+ checkException("d.getBoxQuads({relativeTo:comment})", "TypeError");
+ checkException("comment.convertPointFromNode(zeroPoint,document)", "TypeError");
+ checkException("document.convertPointFromNode(zeroPoint,comment)", "TypeError");
+ checkException("comment.convertRectFromNode(zeroRect,document)", "TypeError");
+ checkException("document.convertRectFromNode(zeroRect,comment)", "TypeError");
+ checkException("comment.convertQuadFromNode(zeroQuad,document)", "TypeError");
+ checkException("document.convertQuadFromNode(zeroQuad,comment)", "TypeError");
+
+ checkException("fragment.getBoxQuads()", "TypeError");
+ checkException("d.getBoxQuads({relativeTo:fragment})", "TypeError");
+ checkException("fragment.convertPointFromNode(zeroPoint,document)", "TypeError");
+ checkException("document.convertPointFromNode(zeroPoint,fragment)", "TypeError");
+ checkException("fragment.convertRectFromNode(zeroRect,document)", "TypeError");
+ checkException("document.convertRectFromNode(zeroRect,fragment)", "TypeError");
+ checkException("fragment.convertQuadFromNode(zeroQuad,document)", "TypeError");
+ checkException("document.convertQuadFromNode(zeroQuad,fragment)", "TypeError");
+
+ isEval("displayNone.getBoxQuads().length", 0);
+ isEval("notInDocument.getBoxQuads().length", 0);
+ checkNotFound("displayNone", "document", 1, 2, 3, 4);
+ checkNotFound("notInDocument", "document", 1, 2, 3, 4);
+ checkNotFound("document", "displayNone", 1, 2, 3, 4);
+ checkNotFound("document", "notInDocument", 1, 2, 3, 4);
+
+ // Test an overflow:hidden version of d. overflow:hidden should not affect
+ // the quads, basically.
+ var oHX = overflowHidden.getBoundingClientRect().left;
+ var oHY = overflowHidden.getBoundingClientRect().top;
+ checkQuadIsRect("overflowHidden", {box:"content"},
+ oHX + 4 + 8, oHY + 1 + 5, 120, 90);
+ checkQuadIsRect("overflowHidden", {box:"padding"},
+ oHX + 8, oHY + 5, 120 + 2 + 4, 90 + 1 + 3);
+ checkQuadIsRect("overflowHidden", {box:"border"},
+ oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
+ checkQuadIsRect("overflowHidden", {},
+ oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
+ checkQuadIsRect("overflowHidden", {box:"margin"},
+ oHX - 12, oHY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
+
+ // Test an overflow:scroll version of d. I assume that boxes aren't affected
+ // by the scrollbar although it's not clear that this is correct.
+ var oSX = overflowScroll.getBoundingClientRect().left;
+ var oSY = overflowScroll.getBoundingClientRect().top;
+ checkQuadIsRect("overflowScroll", {box:"content"},
+ oSX + 4 + 8, oSY + 1 + 5, 120, 90);
+ checkQuadIsRect("overflowScroll", {box:"padding"},
+ oSX + 8, oSY + 5, 120 + 2 + 4, 90 + 1 + 3);
+ checkQuadIsRect("overflowScroll", {box:"border"},
+ oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
+ checkQuadIsRect("overflowScroll", {},
+ oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7);
+ checkQuadIsRect("overflowScroll", {box:"margin"},
+ oSX - 12, oSY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11);
+
+ // Test simple 2D transforms.
+ var stcX = scaleTransformContainer.getBoundingClientRect().left;
+ var stcY = scaleTransformContainer.getBoundingClientRect().top;
+ checkQuadIsRect("scaleTransform", {},
+ stcX, stcY, 140, 160);
+ var ttcX = translateTransformContainer.getBoundingClientRect().left;
+ var ttcY = translateTransformContainer.getBoundingClientRect().top;
+ checkQuadIsRect("translateTransform", {},
+ ttcX + 30, ttcY + 40, 70, 80);
+ // Test mapping into a transformed element.
+ checkQuadIsRect("scaleTransform", {toStr:"translateTransform"},
+ stcX - (ttcX + 30), stcY - (ttcY + 40), 140, 160);
+ // Test 90 degree rotation.
+ var rotatetcX = rotateTransformContainer.getBoundingClientRect().left;
+ var rotatetcY = rotateTransformContainer.getBoundingClientRect().top;
+ checkQuadIsQuad("rotateTransform", {},
+ rotatetcX + 75, rotatetcY + 5,
+ rotatetcX + 75, rotatetcY + 75,
+ rotatetcX - 5, rotatetcY + 75,
+ rotatetcX - 5, rotatetcY + 5);
+ // Test vertical flip.
+ var fliptcX = flipTransformContainer.getBoundingClientRect().left;
+ var fliptcY = flipTransformContainer.getBoundingClientRect().top;
+ checkQuadIsQuad("flipTransform", {},
+ fliptcX, fliptcY + 80,
+ fliptcX + 70, fliptcY + 80,
+ fliptcX + 70, fliptcY,
+ fliptcX, fliptcY);
+ // Test non-90deg rotation.
+ var rot45tcX = rot45TransformContainer.getBoundingClientRect().left;
+ var rot45tcY = rot45TransformContainer.getBoundingClientRect().top;
+ var halfDiagonal = 100/Math.sqrt(2);
+ checkQuadIsQuad("rot45Transform", {tolerance:0.01},
+ rot45tcX + 50, rot45tcY + 50 - halfDiagonal,
+ rot45tcX + 50 + halfDiagonal, rot45tcY + 50,
+ rot45tcX + 50, rot45tcY + 50 + halfDiagonal,
+ rot45tcX + 50 - halfDiagonal, rot45tcY + 50);
+
+ // Test singular transforms.
+ var singularTransformX = singularTransform.getBoundingClientRect().left;
+ var singularTransformY = singularTransform.getBoundingClientRect().top;
+ // They map everything to a point.
+ checkQuadIsRect("singularTransform", {},
+ singularTransformX, singularTransformY, 0, 0);
+ checkQuadIsRect("singularTransformChild2", {},
+ singularTransformX, singularTransformY, 0, 0);
+ // Mapping into an element with a singular transform from outside sets
+ // everything to zero.
+ checkQuadIsRect("d", {toStr:"singularTransform"},
+ 0, 0, 0, 0);
+ // But mappings within a subtree of an element with a singular transform work.
+ checkQuadIsRect("singularTransformChild2", {toStr:"singularTransformChild1"},
+ 0, 50, 200, 50);
+
+ // Test 3D transforms.
+ var t3tcX = threeDTransformContainer.getBoundingClientRect().left;
+ var t3tcY = threeDTransformContainer.getBoundingClientRect().top;
+ checkQuadIsQuad("threeDTransform", {tolerance:0.01},
+ t3tcX + 59.446714, t3tcY - 18.569847,
+ t3tcX + 129.570778, t3tcY + 13.540874,
+ t3tcX + 129.570778, t3tcY + 100,
+ t3tcX + 59.446714, t3tcY + 100);
+ // Test nested 3D transforms (without preserve-3d).
+ checkQuadIsQuad("threeDTransformChild", {tolerance:0.01},
+ t3tcX + 89.395061, t3tcY + 2.243033,
+ t3tcX + 113.041727, t3tcY - 2.758530,
+ t3tcX + 113.041727, t3tcY + 52.985921,
+ t3tcX + 89.395061, t3tcY + 47.571899);
+ // Test preserve-3D.
+ var p3dtcX = preserve3DTransformContainer.getBoundingClientRect().left;
+ var p3dtcY = preserve3DTransformContainer.getBoundingClientRect().top;
+ checkQuadIsRect("preserve3DTransformChild", {tolerance:0.01},
+ p3dtcX, p3dtcY, 200, 50,
+ {tolerance:0.0001});
+ // Test mapping back into preserve-3D.
+ checkQuadIsRect("d", {toStr:"preserve3DTransformChild",tolerance:0.01},
+ dX - p3dtcX, dY - p3dtcY, dW, dH);
+
+ // Test SVG.
+ var svgContainerX = svgContainer.getBoundingClientRect().left;
+ var svgContainerY = svgContainer.getBoundingClientRect().top;
+ checkQuadIsRect("circle", {},
+ svgContainerX + 41, svgContainerY + 41, 40, 40);
+ // Box types are ignored for SVG elements.
+ checkQuadIsRect("circle", {box:"content"},
+ svgContainerX + 41, svgContainerY + 41, 40, 40);
+ checkQuadIsRect("circle", {box:"padding"},
+ svgContainerX + 41, svgContainerY + 41, 40, 40);
+ checkQuadIsRect("circle", {box:"margin"},
+ svgContainerX + 41, svgContainerY + 41, 40, 40);
+ checkQuadIsRect("d", {toStr:"circle"},
+ dX - (svgContainerX + 41), dY - (svgContainerY + 41), dW, dH);
+ // Test foreignObject inside an SVG transform.
+ checkQuadIsRect("foreign", {},
+ svgContainerX + 111, svgContainerY + 51, 200, 120);
+ // Outer <svg> elements support padding and content boxes
+ checkQuadIsRect("svg", {box:"border"},
+ svgContainerX, svgContainerY, 222, 222);
+ checkQuadIsRect("svg", {box:"padding"},
+ svgContainerX + 7, svgContainerY + 7, 208, 208);
+ checkQuadIsRect("svg", {box:"content"},
+ svgContainerX + 11, svgContainerY + 11, 200, 200);
+
+ // XXX Test SVG text (probably broken; unclear what the best way is to handle it)
+
+ // Test that converting between nodes in different toplevel browsing contexts
+ // throws an exception.
+ try {
+ openedWindow = window.open("data:text/html,<div id='d'>","");
+ } catch (ex) {
+ // in some cases we can't open the window.
+ openedWindow = null;
+ }
+ if (openedWindow) {
+ openedWindow.addEventListener("load", function() {
+ checkException("openedWindow.d.getBoxQuads({relativeTo:document})", "NotFoundError");
+ checkException("document.getBoxQuads({relativeTo:openedWindow.d})", "NotFoundError");
+ checkException("openedWindow.d.convertPointFromNode(zeroPoint,document)", "NotFoundError");
+ checkException("document.convertPointFromNode(zeroPoint,openedWindow.d)", "NotFoundError");
+ checkException("openedWindow.d.convertRectFromNode(zeroRect,document)", "NotFoundError");
+ checkException("document.convertRectFromNode(zeroRect,openedWindow.d)", "NotFoundError");
+ checkException("openedWindow.d.convertQuadFromNode(zeroQuad,document)", "NotFoundError");
+ checkException("document.convertQuadFromNode(zeroQuad,openedWindow.d)", "NotFoundError");
+ openedWindow.close();
+ SimpleTest.finish();
+ });
+ } else {
+ SimpleTest.finish();
+ }
+}
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_getClientRects_emptytext.html b/layout/base/tests/test_getClientRects_emptytext.html
new file mode 100644
index 000000000..c009a190e
--- /dev/null
+++ b/layout/base/tests/test_getClientRects_emptytext.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<div id="testDiv"> </div>
+<script>
+var textNode = testDiv.firstChild;
+var range = new Range();
+range.selectNodeContents(textNode);
+is(range.getClientRects().length, 1, "Text node should have a rectangle");
+var rect = range.getClientRects()[0];
+ok(rect.left > 0, "Rectangle x should be greater than zero");
+ok(rect.top > 0, "Rectangle y should be greater than zero");
+is(rect.width, 0, "Rectangle should be zero width");
+is(rect.height, 0, "Rectangle should be zero height");
+</script>
+</body>
+</html>
diff --git a/layout/base/tests/test_mozPaintCount.html b/layout/base/tests/test_mozPaintCount.html
new file mode 100644
index 000000000..4a6c3f714
--- /dev/null
+++ b/layout/base/tests/test_mozPaintCount.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Tests for mozPaintCount</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <script type="application/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="doBackgroundFlicker()">
+<p id="display">
+<embed type="application/x-test" width="100" height="100" id="p"
+ drawmode="solid" color="FF00FF00"></embed>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var startPaintCount = window.mozPaintCount;
+ok(true, "Got to initial paint count: " + startPaintCount);
+var color = 0;
+
+function doPluginFlicker() {
+ ok(true, "Plugin color iteration " + color + ", paint count: " + window.mozPaintCount);
+ if (window.mozPaintCount - startPaintCount > 20) {
+ ok(true, "Got enough paints from plugin color changes");
+ SimpleTest.finish();
+ return;
+ }
+
+ color = (color + 1) % 256;
+ var str = color.toString(16);
+ if (str.length < 2) {
+ str = "0" + str;
+ }
+ str = "FF" + str + str + str;
+ document.getElementById("p").setColor(str);
+ setTimeout(doPluginFlicker, 0);
+}
+
+function doBackgroundFlicker() {
+ ok(true, "Background color iteration " + color + ", paint count: " + window.mozPaintCount);
+ if (window.mozPaintCount - startPaintCount > 20) {
+ ok(true, "Got enough paints from background color changes");
+ startPaintCount = window.mozPaintCount;
+ doPluginFlicker();
+ return;
+ }
+
+ color = (color + 1) % 256;
+ document.body.style.backgroundColor = "rgb(" + color + "," + color + "," + color + ")";
+ setTimeout(doBackgroundFlicker, 0);
+}
+
+</script>
+</pre>
+
+<div style="height:4000px"></div>
+<a id="first" href="http://www.mozilla.org/">first<br>link</a>
+<a id="second" href="http://www.mozilla.org/">second link</a>
+<a id="third" href="http://www.mozilla.org/">third<br>link</a>
+<div style="height:4000px"></div>
+
+</body>
+</html>
+
diff --git a/layout/base/tests/test_preserve3d_sorting_hit_testing.html b/layout/base/tests/test_preserve3d_sorting_hit_testing.html
new file mode 100644
index 000000000..15417713c
--- /dev/null
+++ b/layout/base/tests/test_preserve3d_sorting_hit_testing.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=684759
+-->
+<head>
+ <title>Test for Bug 684759</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=684759">Mozilla Bug 684759</a>
+<iframe src="preserve3d_sorting_hit_testing_iframe.html" id="iframe" height="1000" width="1000" style="border:none"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 684759 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run() {
+
+ var iframe = document.getElementById("iframe");
+
+ var doc = iframe.contentDocument;
+
+ var big= doc.getElementById("big");
+ var small = doc.getElementById("small");
+
+ function check(x, y, expected_element, description)
+ {
+ is(doc.elementFromPoint(x, y).id, expected_element.id,
+ "point (" + x + ", " + y + "): " + description);
+ }
+
+ check(650, 250, small, "Small object should be infront of big");
+ check(650, 308, big, "Check bounds of small object");
+ check(650, 207, big, "Check bounds of small object");
+ check(607, 250, big, "Check bounds of small object");
+ check(708, 250, big, "Check bounds of small object");
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_preserve3d_sorting_hit_testing2.html b/layout/base/tests/test_preserve3d_sorting_hit_testing2.html
new file mode 100644
index 000000000..991b94640
--- /dev/null
+++ b/layout/base/tests/test_preserve3d_sorting_hit_testing2.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1241394
+-->
+<head>
+ <title>Test for Bug 1241394</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1241394">Mozilla Bug 1241394</a>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1241394 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run() {
+ var win;
+
+ window.child_opened = function(doc) {
+ var container= doc.getElementById("container");
+
+ isnot(doc.elementFromPoint(60, 50).id, container.id,
+ "point (50, 50): should not hit background");
+
+ win.close();
+ SimpleTest.finish();
+ }
+
+ win = window.open("preserve3d_sorting_hit_testing2_iframe.html");
+}
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_reftests_with_caret.html b/layout/base/tests/test_reftests_with_caret.html
new file mode 100644
index 000000000..d9b5d4a6c
--- /dev/null
+++ b/layout/base/tests/test_reftests_with_caret.html
@@ -0,0 +1,341 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Reftests with caret drawing</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <style>
+ iframe {
+ border: none;
+ width: 600px;
+ height: 400px;
+ }
+ </style>
+<script type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestLongerTimeout(2);
+
+var iframes = [];
+function callbackTestIframe(iframe)
+{
+ iframes.push(iframe);
+
+ if (iframes.length != 2)
+ return;
+
+ var result = iframes[0];
+ var reference = iframes[1];
+
+ // Using assertSnapshots is important to get the data-URIs of failing tests
+ // dumped into the log in a format that reftest-analyzer.xhtml can process.
+ var passed = assertSnapshots(result.snapshot, reference.snapshot, true,
+ null /*no fuzz*/, result.src, reference.src);
+
+ // Remove the iframes if the test was successful
+ if (passed) {
+ result.parentNode.removeChild(result);
+ reference.parentNode.removeChild(reference);
+ }
+
+ iframes = [];
+ SimpleTest.waitForFocus(nextTest);
+}
+
+function doSnapShot(iframe) {
+ iframe.snapshot = snapshotWindow(iframe.contentWindow, true);
+ callbackTestIframe(iframe);
+};
+
+function remotePageLoaded(callback) {
+ var iframe = this;
+ setTimeout(function(){
+ doSnapShot(iframe);
+ callback();
+ }, 0);
+};
+
+const MAX_ITERATIONS = 1000;
+
+function createIframe(url,next) {
+ var iframe = document.createElement("iframe");
+ iframe.src = url;
+ iframe.remotePageLoaded = remotePageLoaded;
+ var me = this;
+ var currentIteration = 0;
+ function iframeLoadCompleted() {
+ var docEl = iframe.contentDocument.documentElement;
+ if (docEl.className.indexOf("reftest-wait") >= 0) {
+ if (currentIteration++ > MAX_ITERATIONS) {
+ ok(false, "iframe load for " + url + " timed out");
+ endTest();
+ } else {
+ setTimeout(iframeLoadCompleted, 0);
+ }
+ return;
+ }
+ iframe.remotePageLoaded(function() {
+ if (next) {
+ setTimeout(function(){createIframe(next,null);}, 0)
+ }
+ });
+ }
+ iframe.addEventListener("load", iframeLoadCompleted, false);
+ window.document.body.appendChild(iframe);
+ iframe.focus();
+};
+
+function refTest(test,ref) {
+ createIframe(test,ref);
+};
+
+var caretBlinkTime = null;
+function endTest() {
+ var parentDoc = window.parent.document;
+ parentDoc.styleSheets[parentDoc.styleSheets.length-1].deleteRule(0);
+ // finish(), yet let the test actually end first, to be safe.
+ SimpleTest.executeSoon(SimpleTest.finish);
+}
+
+var tests = [
+ [ 'bug106855-1.html' , 'bug106855-1-ref.html' ] ,
+ [ 'bug106855-2.html' , 'bug106855-1-ref.html' ] ,
+ [ 'bug389321-2.html' , 'bug389321-2-ref.html' ] ,
+ [ 'bug613807-1.html' , 'bug613807-1-ref.html' ] ,
+ [ 'bug1082486-1.html', 'bug1082486-1-ref.html'] ,
+ [ 'bug1082486-2.html', 'bug1082486-2-ref.html'] ,
+ // The following test cases are all involving with one sending
+ // synthesizeKey(), the other without. They fail when accessiblecaret
+ // is enabled. Test them with the preference off.
+ function() {SpecialPowers.pushPrefEnv({'set': [['layout.accessiblecaret.enabled', false]]}, nextTest);} ,
+ [ 'bug240933-1.html' , 'bug240933-1-ref.html' ] ,
+ [ 'bug240933-2.html' , 'bug240933-1-ref.html' ] ,
+ [ 'bug389321-1.html' , 'bug389321-1-ref.html' ] ,
+ [ 'bug389321-3.html' , 'bug389321-3-ref.html' ] ,
+ [ 'bug482484.html' , 'bug482484-ref.html' ] ,
+ [ 'bug503399.html' , 'bug503399-ref.html' ] ,
+ [ 'bug585922.html' , 'bug585922-ref.html' ] ,
+ [ 'bug597519-1.html' , 'bug597519-1-ref.html' ] ,
+ [ 'bug602141-1.html' , 'bug602141-1-ref.html' ] ,
+ [ 'bug602141-2.html' , 'bug602141-2-ref.html' ] ,
+ [ 'bug602141-3.html' , 'bug602141-3-ref.html' ] ,
+ [ 'bug602141-4.html' , 'bug602141-4-ref.html' ] ,
+ [ 'bug612271-1.html' , 'bug612271-ref.html' ] ,
+ [ 'bug612271-2.html' , 'bug612271-ref.html' ] ,
+ [ 'bug612271-3.html' , 'bug612271-ref.html' ] ,
+ [ 'bug613433-1.html' , 'bug613433-ref.html' ] ,
+ [ 'bug613433-2.html' , 'bug613433-ref.html' ] ,
+ [ 'bug613433-3.html' , 'bug613433-ref.html' ] ,
+ [ 'bug632215-1.html' , 'bug632215-ref.html' ] ,
+ [ 'bug632215-2.html' , 'bug632215-ref.html' ] ,
+ [ 'bug633044-1.html' , 'bug633044-1-ref.html' ] ,
+ [ 'bug634406-1.html' , 'bug634406-1-ref.html' ] ,
+ [ 'bug644428-1.html' , 'bug644428-1-ref.html' ] ,
+ [ 'input-maxlength-valid-before-change.html', 'input-valid-ref.html'] ,
+ [ 'input-maxlength-valid-change.html', 'input-valid-ref.html'] ,
+ [ 'input-maxlength-invalid-change.html', 'input-invalid-ref.html'] ,
+ [ 'input-minlength-valid-before-change.html', 'input-valid-ref.html'] ,
+ [ 'input-minlength-valid-change.html', 'input-valid-ref.html'] ,
+ [ 'input-minlength-invalid-change.html', 'input-invalid-ref.html'] ,
+ [ 'input-maxlength-ui-valid-change.html', 'input-valid-ref.html'] ,
+ [ 'input-maxlength-ui-invalid-change.html', 'input-invalid-ref.html'] ,
+ [ 'input-minlength-ui-valid-change.html', 'input-valid-ref.html'] ,
+ [ 'input-minlength-ui-invalid-change.html', 'input-invalid-ref.html'] ,
+ [ 'textarea-maxlength-valid-before-change.html', 'textarea-valid-ref.html'] ,
+ [ 'textarea-maxlength-valid-change.html', 'textarea-valid-ref.html'] ,
+ [ 'textarea-maxlength-invalid-change.html', 'textarea-invalid-ref.html'] ,
+ [ 'textarea-minlength-valid-before-change.html', 'textarea-valid-ref.html'] ,
+ [ 'textarea-minlength-valid-change.html', 'textarea-valid-ref.html'] ,
+ [ 'textarea-minlength-invalid-change.html', 'textarea-invalid-ref.html'] ,
+ [ 'textarea-maxlength-ui-valid-change.html', 'textarea-valid-ref.html'] ,
+ [ 'textarea-maxlength-ui-invalid-change.html', 'textarea-invalid-ref.html'] ,
+ [ 'textarea-minlength-ui-valid-change.html', 'textarea-valid-ref.html'] ,
+ [ 'textarea-minlength-ui-invalid-change.html', 'textarea-invalid-ref.html'] ,
+ function() {SpecialPowers.pushPrefEnv({'set': [['bidi.browser.ui', true]]}, nextTest);} ,
+ [ 'bug646382-1.html' , 'bug646382-1-ref.html' ] ,
+ [ 'bug646382-2.html' , 'bug646382-2-ref.html' ] ,
+ [ 'bug664087-1.html' , 'bug664087-1-ref.html' ] ,
+ [ 'bug664087-2.html' , 'bug664087-2-ref.html' ] ,
+ [ 'bug682712-1.html' , 'bug682712-1-ref.html' ] ,
+ function() {SpecialPowers.pushPrefEnv({'clear': [['bidi.browser.ui']]}, nextTest);} ,
+ [ 'bug746993-1.html' , 'bug746993-1-ref.html' ] ,
+ [ 'bug956530-1.html' , 'bug956530-1-ref.html' ] ,
+ [ 'bug989012-1.html' , 'bug989012-1-ref.html' ] ,
+ [ 'bug989012-2.html' , 'bug989012-2-ref.html' ] ,
+ [ 'bug989012-3.html' , 'bug989012-3-ref.html' ] ,
+ [ 'bug1007065-1.html' , 'bug1007065-1-ref.html' ] ,
+ [ 'bug1007067-1.html' , 'bug1007067-1-ref.html' ] ,
+ [ 'bug1061468.html' , 'bug1061468-ref.html' ] ,
+ [ 'bug1097242-1.html', 'bug1097242-1-ref.html'] ,
+ [ 'bug1109968-1.html', 'bug1109968-1-ref.html'] ,
+ [ 'bug1109968-2.html', 'bug1109968-2-ref.html'] ,
+ // [ 'bug1123067-1.html' , 'bug1123067-ref.html' ] , TODO: bug 1129205
+ [ 'bug1123067-2.html' , 'bug1123067-ref.html' ] ,
+ [ 'bug1123067-3.html' , 'bug1123067-ref.html' ] ,
+ [ 'bug1132768-1.html' , 'bug1132768-1-ref.html'] ,
+ [ 'bug1237236-1.html' , 'bug1237236-1-ref.html' ] ,
+ [ 'bug1237236-2.html' , 'bug1237236-2-ref.html' ] ,
+ [ 'bug1258308-2.html' , 'bug1258308-2-ref.html' ] ,
+ [ 'bug1259949-1.html' , 'bug1259949-1-ref.html'] ,
+ [ 'bug1259949-2.html' , 'bug1259949-2-ref.html'] ,
+ [ 'bug1263288.html' , 'bug1263288-ref.html'] ,
+ [ 'bug1263357-1.html' , 'bug1263357-1-ref.html'] ,
+ [ 'bug1263357-2.html' , 'bug1263357-2-ref.html'] ,
+ [ 'bug1263357-3.html' , 'bug1263357-3-ref.html'] ,
+ [ 'bug1263357-4.html' , 'bug1263357-4-ref.html'] ,
+ [ 'bug1263357-5.html' , 'bug1263357-5-ref.html'] ,
+ function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled']]}, nextTest);} ,
+];
+
+if (navigator.appVersion.indexOf("Android") == -1 &&
+ SpecialPowers.Services.appinfo.name != "B2G") {
+ tests.push([ 'bug512295-1.html' , 'bug512295-1-ref.html' ]);
+ tests.push([ 'bug512295-2.html' , 'bug512295-2-ref.html' ]);
+ tests.push([ 'bug923376.html' , 'bug923376-ref.html' ]);
+ tests.push(function() {SpecialPowers.pushPrefEnv({'set': [['layout.css.overflow-clip-box.enabled', true]]}, nextTest);});
+ tests.push([ 'bug966992-1.html' , 'bug966992-1-ref.html' ]);
+ tests.push([ 'bug966992-2.html' , 'bug966992-2-ref.html' ]);
+ tests.push([ 'bug966992-3.html' , 'bug966992-3-ref.html' ]);
+ tests.push(function() {SpecialPowers.pushPrefEnv({'clear': [['layout.css.overflow-clip-box.enabled']]}, nextTest);});
+ tests.push([ 'bug1258308-1.html' , 'bug1258308-1-ref.html' ]); // maybe VK_END doesn't work on Android?
+} else {
+ is(SpecialPowers.getIntPref("layout.spellcheckDefault"), 0, "Spellcheck should be turned off for this platform or this if..else check removed");
+}
+
+if (navigator.platform.indexOf("Linux") >= 0 &&
+ SpecialPowers.Services.appinfo.name != "B2G") {
+ tests = tests.concat([
+ // eDirPrevious, Shift+click
+ [ 'multi-range-user-select.html#prev1S_' , 'multi-range-user-select-ref.html#prev1S_' ] ,
+ [ 'multi-range-user-select.html#prev2S_' , 'multi-range-user-select-ref.html#prev2S_' ] ,
+ [ 'multi-range-user-select.html#prev3S_' , 'multi-range-user-select-ref.html#prev3S_' ] ,
+ [ 'multi-range-user-select.html#prev4S_' , 'multi-range-user-select-ref.html#prev4S_' ] ,
+ [ 'multi-range-user-select.html#prev5S_' , 'multi-range-user-select-ref.html#prev5S_' ] ,
+ [ 'multi-range-user-select.html#prev6S_' , 'multi-range-user-select-ref.html#prev6S_' ] ,
+ [ 'multi-range-user-select.html#prev7S_' , 'multi-range-user-select-ref.html#prev7S_' ] ,
+ // eDirPrevious, Shift+Accel+click
+ [ 'multi-range-user-select.html#prev1SA' , 'multi-range-user-select-ref.html#prev1SA' ] ,
+ [ 'multi-range-user-select.html#prev2SA' , 'multi-range-user-select-ref.html#prev2SA' ] ,
+ [ 'multi-range-user-select.html#prev3SA' , 'multi-range-user-select-ref.html#prev3SA' ] ,
+ [ 'multi-range-user-select.html#prev4SA' , 'multi-range-user-select-ref.html#prev4SA' ] ,
+ [ 'multi-range-user-select.html#prev5SA' , 'multi-range-user-select-ref.html#prev5SA' ] ,
+ [ 'multi-range-user-select.html#prev6SA' , 'multi-range-user-select-ref.html#prev6SA' ] ,
+ [ 'multi-range-user-select.html#prev7SA' , 'multi-range-user-select-ref.html#prev7SA' ] ,
+ // eDirPrevious, Accel+drag-select (adding an additional range)
+ [ 'multi-range-user-select.html#prev1AD' , 'multi-range-user-select-ref.html#prev1AD' ] ,
+ [ 'multi-range-user-select.html#prev7AD' , 'multi-range-user-select-ref.html#prev7AD' ] ,
+ // eDirPrevious, Accel+drag-select (bug 1128722)
+ [ 'multi-range-user-select.html#prev8AD' , 'multi-range-user-select-ref.html#prev8AD' ] ,
+ // eDirPrevious, VK_RIGHT / LEFT
+ [ 'multi-range-user-select.html#prev1SR' , 'multi-range-user-select-ref.html#prev1SR' ] ,
+ [ 'multi-range-user-select.html#prev1SL' , 'multi-range-user-select-ref.html#prev1SL' ] ,
+ // eDirNext, Shift+click
+ [ 'multi-range-user-select.html#next1S_' , 'multi-range-user-select-ref.html#next1S_' ] ,
+ [ 'multi-range-user-select.html#next2S_' , 'multi-range-user-select-ref.html#next2S_' ] ,
+ [ 'multi-range-user-select.html#next3S_' , 'multi-range-user-select-ref.html#next3S_' ] ,
+ [ 'multi-range-user-select.html#next4S_' , 'multi-range-user-select-ref.html#next4S_' ] ,
+ [ 'multi-range-user-select.html#next5S_' , 'multi-range-user-select-ref.html#next5S_' ] ,
+ [ 'multi-range-user-select.html#next6S_' , 'multi-range-user-select-ref.html#next6S_' ] ,
+ [ 'multi-range-user-select.html#next7S_' , 'multi-range-user-select-ref.html#next7S_' ] ,
+ // eDirNext, Shift+Accel+click
+ [ 'multi-range-user-select.html#next1SA' , 'multi-range-user-select-ref.html#next1SA' ] ,
+ [ 'multi-range-user-select.html#next2SA' , 'multi-range-user-select-ref.html#next2SA' ] ,
+ [ 'multi-range-user-select.html#next3SA' , 'multi-range-user-select-ref.html#next3SA' ] ,
+ [ 'multi-range-user-select.html#next4SA' , 'multi-range-user-select-ref.html#next4SA' ] ,
+ [ 'multi-range-user-select.html#next5SA' , 'multi-range-user-select-ref.html#next5SA' ] ,
+ [ 'multi-range-user-select.html#next6SA' , 'multi-range-user-select-ref.html#next6SA' ] ,
+ [ 'multi-range-user-select.html#next7SA' , 'multi-range-user-select-ref.html#next7SA' ] ,
+ // eDirNext, Accel+drag-select (adding an additional range)
+ [ 'multi-range-user-select.html#next1AD' , 'multi-range-user-select-ref.html#next1AD' ] ,
+ [ 'multi-range-user-select.html#next7AD' , 'multi-range-user-select-ref.html#next7AD' ] ,
+ // eDirNext, Accel+drag-select (bug 1128722)
+ [ 'multi-range-user-select.html#next8AD' , 'multi-range-user-select-ref.html#next8AD' ] ,
+ // eDirNext, VK_RIGHT / LEFT
+ [ 'multi-range-user-select.html#next1SR' , 'multi-range-user-select-ref.html#next1SR' ] ,
+ [ 'multi-range-user-select.html#next1SL' , 'multi-range-user-select-ref.html#next1SL' ] ,
+ // eDirPrevious, Shift+click
+ [ 'multi-range-script-select.html#prev1S_' , 'multi-range-script-select-ref.html#prev1S_' ] ,
+ [ 'multi-range-script-select.html#prev2S_' , 'multi-range-script-select-ref.html#prev2S_' ] ,
+ [ 'multi-range-script-select.html#prev3S_' , 'multi-range-script-select-ref.html#prev3S_' ] ,
+ [ 'multi-range-script-select.html#prev4S_' , 'multi-range-script-select-ref.html#prev4S_' ] ,
+ [ 'multi-range-script-select.html#prev5S_' , 'multi-range-script-select-ref.html#prev5S_' ] ,
+ [ 'multi-range-script-select.html#prev6S_' , 'multi-range-script-select-ref.html#prev6S_' ] ,
+ [ 'multi-range-script-select.html#prev7S_' , 'multi-range-script-select-ref.html#prev7S_' ] ,
+ // eDirPrevious, Shift+Accel+click
+ [ 'multi-range-script-select.html#prev1SA' , 'multi-range-script-select-ref.html#prev1SA' ] ,
+ [ 'multi-range-script-select.html#prev2SA' , 'multi-range-script-select-ref.html#prev2SA' ] ,
+ [ 'multi-range-script-select.html#prev3SA' , 'multi-range-script-select-ref.html#prev3SA' ] ,
+ [ 'multi-range-script-select.html#prev4SA' , 'multi-range-script-select-ref.html#prev4SA' ] ,
+ [ 'multi-range-script-select.html#prev5SA' , 'multi-range-script-select-ref.html#prev5SA' ] ,
+ [ 'multi-range-script-select.html#prev6SA' , 'multi-range-script-select-ref.html#prev6SA' ] ,
+ [ 'multi-range-script-select.html#prev7SA' , 'multi-range-script-select-ref.html#prev7SA' ] ,
+ // eDirPrevious, Accel+drag-select (adding an additional range)
+ [ 'multi-range-script-select.html#prev1AD' , 'multi-range-script-select-ref.html#prev1AD' ] ,
+ [ 'multi-range-script-select.html#prev7AD' , 'multi-range-script-select-ref.html#prev7AD' ] ,
+ // eDirPrevious, VK_RIGHT / LEFT
+ [ 'multi-range-script-select.html#prev1SR' , 'multi-range-script-select-ref.html#prev1SR' ] ,
+ [ 'multi-range-script-select.html#prev1SL' , 'multi-range-script-select-ref.html#prev1SL' ] ,
+ // eDirNext, Shift+click
+ [ 'multi-range-script-select.html#next1S_' , 'multi-range-script-select-ref.html#next1S_' ] ,
+ [ 'multi-range-script-select.html#next2S_' , 'multi-range-script-select-ref.html#next2S_' ] ,
+ [ 'multi-range-script-select.html#next3S_' , 'multi-range-script-select-ref.html#next3S_' ] ,
+ [ 'multi-range-script-select.html#next4S_' , 'multi-range-script-select-ref.html#next4S_' ] ,
+ [ 'multi-range-script-select.html#next5S_' , 'multi-range-script-select-ref.html#next5S_' ] ,
+ [ 'multi-range-script-select.html#next6S_' , 'multi-range-script-select-ref.html#next6S_' ] ,
+ [ 'multi-range-script-select.html#next7S_' , 'multi-range-script-select-ref.html#next7S_' ] ,
+ // eDirNext, Shift+Accel+click
+ [ 'multi-range-script-select.html#next1SA' , 'multi-range-script-select-ref.html#next1SA' ] ,
+ [ 'multi-range-script-select.html#next2SA' , 'multi-range-script-select-ref.html#next2SA' ] ,
+ [ 'multi-range-script-select.html#next3SA' , 'multi-range-script-select-ref.html#next3SA' ] ,
+ [ 'multi-range-script-select.html#next4SA' , 'multi-range-script-select-ref.html#next4SA' ] ,
+ [ 'multi-range-script-select.html#next5SA' , 'multi-range-script-select-ref.html#next5SA' ] ,
+ [ 'multi-range-script-select.html#next6SA' , 'multi-range-script-select-ref.html#next6SA' ] ,
+ [ 'multi-range-script-select.html#next7SA' , 'multi-range-script-select-ref.html#next7SA' ] ,
+ // eDirNext, Accel+drag-select (adding an additional range)
+ [ 'multi-range-script-select.html#next1AD' , 'multi-range-script-select-ref.html#next1AD' ] ,
+ [ 'multi-range-script-select.html#next7AD' , 'multi-range-script-select-ref.html#next7AD' ] ,
+ // eDirNext, VK_RIGHT / LEFT
+ [ 'multi-range-script-select.html#next1SR' , 'multi-range-script-select-ref.html#next1SR' ] ,
+ [ 'multi-range-script-select.html#next1SL' , 'multi-range-script-select-ref.html#next1SL' ] ,
+ ]);
+}
+
+var testIndex = 0;
+
+function nextTest() {
+ if (testIndex < tests.length) {
+ if (typeof(tests[testIndex]) == 'function') {
+ tests[testIndex]();
+ } else {
+ refTest(tests[testIndex][0],tests[testIndex][1]);
+ }
+ ++testIndex;
+ } else {
+ endTest();
+ }
+}
+function runTests() {
+ try {
+ if (window.parent) {
+ var parentDoc = window.parent.document;
+ extraCSSRule = parentDoc.styleSheets[parentDoc.styleSheets.length-1]
+ .insertRule("iframe#testframe{width:600px;height:400px}",0);
+ }
+ try {
+ caretBlinkTime = SpecialPowers.getIntPref("ui.caretBlinkTime");
+ } catch (e) {}
+ SpecialPowers.pushPrefEnv({'set': [['ui.caretBlinkTime', -1]]}, nextTest);
+ } catch(e) {
+ endTest();
+ }
+}
+
+SimpleTest.waitForFocus(runTests);
+
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/base/tests/test_remote_frame.html b/layout/base/tests/test_remote_frame.html
new file mode 100644
index 000000000..765d526ae
--- /dev/null
+++ b/layout/base/tests/test_remote_frame.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ div, iframe {
+ position:absolute;
+ left:0; top:50px;
+ width:400px; height:400px;
+ transform: translateY(50px);
+ border:5px solid black;
+ }
+ </style>
+</head>
+ <body>
+ <div id="d" style="background:blue"></div>
+
+ <script type="application/javascript;version=1.7">
+ "use strict";
+
+ var referenceSnapshot;
+ var iterations = 0;
+
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+
+ function pollForTestPass() {
+ var snapshot = snapshotWindow(window);
+ if (compareSnapshots(referenceSnapshot, snapshot, true)[0]) {
+ ok(true, "Test passed after " + iterations + " iterations");
+ SimpleTest.finish();
+ return;
+ }
+
+ ++iterations;
+ if (iterations == 20) {
+ todo(false, "We couldn't draw the frame, but at least we didn't crash");
+ SimpleTest.finish();
+ return;
+ }
+ setTimeout(pollForTestPass, 10);
+ }
+ function addRemoteFrame() {
+ let iframe = document.createElement("iframe");
+ SpecialPowers.wrap(iframe).mozbrowser = true;
+ iframe.src = "data:text/html,<html style='background:blue;'>";
+
+ document.body.appendChild(iframe);
+
+ pollForTestPass();
+ }
+ addEventListener("load", function() {
+ referenceSnapshot = snapshotWindow(window);
+ document.getElementById("d").style.display = 'none';
+ SpecialPowers.addPermission("browser", true, document);
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.ipc.browser_frames.oop_by_default", true],
+ ["dom.mozBrowserFramesEnabled", true]
+ ]
+ }, addRemoteFrame);
+ });
+ </script>
+</body>
diff --git a/layout/base/tests/test_resize_flush.html b/layout/base/tests/test_resize_flush.html
new file mode 100644
index 000000000..471560747
--- /dev/null
+++ b/layout/base/tests/test_resize_flush.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1279202
+-->
+<head>
+ <title>Test for Bug 1279202</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1279202">Mozilla Bug 1279202</a>
+<iframe src="resize_flush_iframe.html" id="iframe" height="200" width="200" style="border:none"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1279202 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run() {
+
+ var iframe = document.getElementById("iframe");
+ var doc = iframe.contentDocument.documentElement;
+ var win = iframe.contentWindow;
+ var body = iframe.contentDocument.body;
+
+ // Flush any pending layout changes before we start.
+ var width = doc.clientWidth;
+
+ // Resize the iframe
+ iframe.width = '300px';
+
+ // Flush pending style changes, but not layout ones. We do this twice because the first flush
+ // does a partial flush of the resize (setting the size on the pres context) which sets the
+ // need style flush flag again. The second call makes sure mNeedStyleFlush is false.
+ var color = win.getComputedStyle(body).getPropertyValue("background-color");
+ color = win.getComputedStyle(body).getPropertyValue("background-color");
+ is(color, "rgb(0, 128, 0)", "Style flush not completed when resizing an iframe!");
+
+ // Query the size of the inner document and make sure it has had a layout flush.
+ width = doc.clientWidth;
+
+ is(width, 300, "Layout flush not completed when resizing an iframe!");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_scroll_event_ordering.html b/layout/base/tests/test_scroll_event_ordering.html
new file mode 100644
index 000000000..be1764a7a
--- /dev/null
+++ b/layout/base/tests/test_scroll_event_ordering.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785588
+-->
+<head>
+ <title>Test for Bug 785588 --- ordering of scroll-related events</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785588">Mozilla Bug 785588</a>
+<div id="content">
+ <div id="d" style="border:2px solid black; width:100px; height:100px; overflow:auto">
+ <div id="inner" style="height:200px;">Hello</div>
+ </div>
+</div>
+<pre id="test">
+<script>
+SimpleTest.waitForExplicitFinish();
+
+var smoothScrollPref = "general.smoothScroll";
+
+var d = document.getElementById("d");
+d.scrollTop = 0;
+var inner = document.getElementById("inner");
+
+var state = "initial";
+
+function onFrame() {
+ is(state, "initial", "Must be in initial state");
+ ok(d.scrollTop > 0, "Must have scrolled by some amount (got " + d.scrollTop + ")");
+ state = "didOnFrame";
+}
+
+function onScroll() {
+ is(state, "didOnFrame", "Must have got requestAnimationFrame callback already");
+ ok(d.scrollTop > 0, "Must have scrolled by some amount (got " + d.scrollTop + ")");
+ SimpleTest.finish();
+}
+
+function doTest() {
+ window.getSelection().collapse(inner.firstChild, 0);
+ window.requestAnimationFrame(onFrame);
+ d.onscroll = onScroll;
+ sendKey("DOWN");
+}
+
+function prepareTest() {
+ // Start the test after we've gotten at least one rAF callback, to make sure
+ // that rAF is no longer throttled. (See bug 1145439.)
+ window.requestAnimationFrame(function() {
+ SpecialPowers.pushPrefEnv({"set":[[smoothScrollPref, false]]}, doTest);
+ });
+}
+
+SimpleTest.waitForFocus(prepareTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_scroll_selection_into_view.html b/layout/base/tests/test_scroll_selection_into_view.html
new file mode 100644
index 000000000..aea94b899
--- /dev/null
+++ b/layout/base/tests/test_scroll_selection_into_view.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for scrolling selection into view</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var ANCHOR = 0;
+var FOCUS = 1;
+var win;
+
+function testCollapsed(id, vPercent, startAt, expected) {
+ var selection = SpecialPowers.wrap(win.getSelection())
+ .QueryInterface(SpecialPowers.Ci.nsISelectionPrivate);
+
+ var c = win.document.getElementById("c" + id);
+ var target = win.document.getElementById("target" + id);
+ if (target.contentDocument) {
+ selection = SpecialPowers.wrap(target.contentWindow.getSelection())
+ .QueryInterface(SpecialPowers.Ci.nsISelectionPrivate);
+ target = target.contentDocument.getElementById("target" + id);
+ }
+ selection.collapse(target.parentNode, 0);
+ c.scrollTop = startAt;
+ selection.scrollIntoView(FOCUS, true, vPercent, 0);
+ is(c.scrollTop, expected, "Scrolling " + target.id +
+ " into view with vPercent " + vPercent + ", starting at " + startAt);
+}
+
+function doTest() {
+ // Test scrolling an element smaller than the scrollport
+ testCollapsed("1", 0, 0, 400);
+ testCollapsed("1", 100, 0, 220);
+ testCollapsed("1", -1, 0, 220);
+ testCollapsed("1", 0, 500, 400);
+ testCollapsed("1", 100, 500, 220);
+ testCollapsed("1", -1, 500, 400);
+
+ // overflow:hidden elements should not be scrolled by selection
+ // scrolling-into-view
+ testCollapsed("2", 0, 0, 0);
+ testCollapsed("2", 100, 0, 0);
+ testCollapsed("2", -1, 0, 0);
+ testCollapsed("2", 0, 500, 500);
+ testCollapsed("2", 100, 500, 500);
+ testCollapsed("2", -1, 500, 500);
+
+ // Test scrolling an element larger than the scrollport
+ testCollapsed("3", 0, 0, 400);
+ testCollapsed("3", 100, 0, 500);
+ testCollapsed("3", -1, 0, 400);
+ testCollapsed("3", 0, 1000, 400);
+ testCollapsed("3", 100, 1000, 500);
+ // If the element can't be completely visible, we make the top edge
+ // visible.
+ testCollapsed("3", -1, 1000, 400);
+
+ // Test scrolling an element larger than the scrollport
+ testCollapsed("4", 0, 0, 400);
+ testCollapsed("4", 100, 0, 500);
+ testCollapsed("4", -1, 0, 400);
+ testCollapsed("4", 0, 1000, 400);
+ testCollapsed("4", 100, 1000, 500);
+ // If the element can't be completely visible, we make the top edge
+ // visible.
+ testCollapsed("4", -1, 1000, 400);
+
+ // Test that scrolling a translated element into view takes
+ // account of the transform.
+ testCollapsed("5", 0, 0, 400);
+
+ // Test that scrolling a scaled element into view takes
+ // account of the transform.
+ testCollapsed("6", 0, 0, 150);
+
+ // Test that scrolling an element with a translated, scrolling container
+ // into view takes account of the transform.
+ testCollapsed("7", 0, 0, 400);
+
+ win.close();
+ SimpleTest.finish();
+}
+
+function openWindow() {
+ win = open("scroll_selection_into_view_window.html", "_blank", "width=500,height=350");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(openWindow);
+</script>
+</pre>
+</body>
+
+</html>
diff --git a/layout/base/tests/test_scroll_snapping.html b/layout/base/tests/test_scroll_snapping.html
new file mode 100644
index 000000000..1ba862ee1
--- /dev/null
+++ b/layout/base/tests/test_scroll_snapping.html
@@ -0,0 +1,806 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for scroll snapping</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<p id="display"></p>
+<div id="sc" style="margin: 0px; padding: 0px; overflow: scroll; width: 500px; height: 250px;">
+ <div id="sd" style="margin: 0px; padding: 0px; width: 1500px; height: 1250px;"></div>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var testCases = [
+ {
+ "description" : "Proximity + Within proximity => Snaps to point (Right)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "525px 500px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_RIGHT",
+ "expectedX" : 525,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Proximity + Within proximity => Snaps to point (Left)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "475px 500px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_LEFT",
+ "expectedX" : 475,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Proximity + Within proximity => Snaps to point (Up)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 475px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_UP",
+ "expectedX" : 500,
+ "expectedY" : 475,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Proximity + Within proximity => Snaps to point (Down)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 525px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_DOWN",
+ "expectedX" : 500,
+ "expectedY" : 525,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Proximity + Beyond proximity => Does not snap to point (Right)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "700px 500px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_RIGHT",
+ "expectedX" : 700,
+ "expectedY" : 500,
+ "notExpected" : true
+ },
+
+ {
+ "description" : "Proximity + Beyond proximity => Does not snap to point (Left)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "300px 500px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_LEFT",
+ "expectedX" : 300,
+ "expectedY" : 500,
+ "notExpected" : true
+ },
+
+ {
+ "description" : "Proximity + Beyond proximity => Does not snap to point (Up)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 300px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_UP",
+ "expectedX" : 500,
+ "expectedY" : 300,
+ "notExpected" : true
+ },
+
+ {
+ "description" : "Proximity + Beyond proximity => Does not snap to point (Down)",
+ "scrollSnapType" : "proximity",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 700px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_DOWN",
+ "expectedX" : 500,
+ "expectedY" : 700,
+ "notExpected" : true
+ },
+
+ {
+ "description" : "Mandatory + Beyond proximity => Snaps to point (Right)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "700px 500px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_RIGHT",
+ "expectedX" : 700,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + Beyond proximity => Snaps to point (Left)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "300px 500px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_LEFT",
+ "expectedX" : 300,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + Beyond proximity => Snaps to point (Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 300px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_UP",
+ "expectedX" : 500,
+ "expectedY" : 300,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + Beyond proximity => Snaps to point (Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 700px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_DOWN",
+ "expectedX" : 500,
+ "expectedY" : 700,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + No snap points => Does not snap or scroll (Left)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_LEFT",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + No snap points => Does not snap or scroll (Right)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_RIGHT",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + No snap points => Does not snap or scroll (Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_UP",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + No snap points => Does not snap or scroll (Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_DOWN",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y + scroll-snap-destination + Start of page + No snap point at start of page => Does not snap to top of page (Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(500px)",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 0,
+ "initialY" : 200,
+ "key" : "VK_UP",
+ "expectedX" : 0,
+ "expectedY" : 200,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y + scroll-snap-destination + Start of page + No snap point at start of page => Does not snap to top of page (Page Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(500px)",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 0,
+ "initialY" : 200,
+ "key" : "VK_PAGE_UP",
+ "expectedX" : 0,
+ "expectedY" : 200,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y + scroll-snap-destination + Start of page + No snap point at start of page => Snaps to highest snap point (Home)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(500px)",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 0,
+ "initialY" : 200,
+ "key" : "VK_HOME",
+ "expectedX" : 0,
+ "expectedY" : 475,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-x + scroll-snap-destination + Start of page + No snap point at start of page => Does not snap to left of page (Left)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "repeat(500px)",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 200,
+ "initialY" : 0,
+ "key" : "VK_LEFT",
+ "expectedX" : 200,
+ "expectedY" : 0,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y + negative scroll-snap-destination + End of page + No snap point at end of page => Does not snap to end of page (Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(500px)",
+ "scrollSnapDestination" : "-25px -25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 0,
+ "initialY" : 800,
+ "key" : "VK_DOWN",
+ "expectedX" : 0,
+ "expectedY" : 800,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y + negative scroll-snap-destination + End of page + No snap point at end of page => Does not snap to end of page (Page Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(500px)",
+ "scrollSnapDestination" : "-25px -25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 0,
+ "initialY" : 800,
+ "key" : "VK_PAGE_DOWN",
+ "expectedX" : 0,
+ "expectedY" : 800,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y + negative scroll-snap-destination + End of page + No snap point at end of page => Snaps to lowest snap point (End)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(500px)",
+ "scrollSnapDestination" : "-25px -25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 0,
+ "initialY" : 800,
+ "key" : "VK_END",
+ "expectedX" : 0,
+ "expectedY" : 525,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-coordinate + No snap point at start of page => Does not snap to top of page (Home)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 100px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_HOME",
+ "expectedX" : 500,
+ "expectedY" : 100,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-coordinate + No snap point at end of page => Does not snap to end of page (End)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "500px 900px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_END",
+ "expectedX" : 500,
+ "expectedY" : 900,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y greater than scrolling rect + positive non-zero scroll-snap-destination => No snap points, does not scroll or snap (Left)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(1500px)",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_LEFT",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y greater than scrolling rect + positive non-zero scroll-snap-destination => No snap points, does not scroll or snap (Right)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(1500px)",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_RIGHT",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y greater than scrolling rect + positive non-zero scroll-snap-destination => No snap points, does not scroll or snap (Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(1500px)",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_UP",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-y greater than scrolling rect + positive non-zero scroll-snap-destination => No snap points, does not scroll or snap (Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "repeat(1500px)",
+ "scrollSnapDestination" : "25px 25px",
+ "scrollSnapCoordinate" : "none",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_DOWN",
+ "expectedX" : 500,
+ "expectedY" : 500,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-{x|y} + scroll-snap-coordinate with two points => Interval and element snapping points are combined. Test 1 snap point generated by scroll-snap-points-{x|y} and two generated by scroll-snap-coordinate, ensure that they are evaluated as snap points. (Right #1)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "repeat(200px)",
+ "scrollSnapPointsY" : "repeat(200px)",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "120px 120px, 220px 220px",
+ "initialX" : 0,
+ "initialY" : 0,
+ "key" : "VK_RIGHT",
+ "expectedX" : 120,
+ "expectedY" : 0,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-{x|y} + scroll-snap-coordinate with two points => Interval and element snapping points are combined. Test 1 snap point generated by scroll-snap-points-{x|y} and two generated by scroll-snap-coordinate, ensure that they are evaluated as snap points. (Right #2)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "repeat(200px)",
+ "scrollSnapPointsY" : "repeat(200px)",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "120px 120px, 220px 220px",
+ "initialX" : 120,
+ "initialY" : 0,
+ "key" : "VK_RIGHT",
+ "expectedX" : 200,
+ "expectedY" : 0,
+ "notExpected" : false
+ },
+
+
+ {
+ "description" : "Mandatory + scroll-snap-points-{x|y} + scroll-snap-coordinate with two points => Interval and element snapping points are combined. Test 1 snap point generated by scroll-snap-points-{x|y} and two generated by scroll-snap-coordinate, ensure that they are evaluated as snap points. (Right #3)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "repeat(200px)",
+ "scrollSnapPointsY" : "repeat(200px)",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "120px 120px, 220px 220px",
+ "initialX" : 200,
+ "initialY" : 0,
+ "key" : "VK_RIGHT",
+ "expectedX" : 220,
+ "expectedY" : 0,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-{x|y} + scroll-snap-coordinate with two points => Interval and element snapping points are combined. Test 1 snap point generated by scroll-snap-points-{x|y} and two generated by scroll-snap-coordinate, ensure that they are evaluated as snap points. (Up #1)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "repeat(200px)",
+ "scrollSnapPointsY" : "repeat(200px)",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "120px 120px, 220px 220px",
+ "initialX" : 0,
+ "initialY" : 300,
+ "key" : "VK_UP",
+ "expectedX" : 0,
+ "expectedY" : 220,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-{x|y} + scroll-snap-coordinate with two points => Interval and element snapping points are combined. Test 1 snap point generated by scroll-snap-points-{x|y} and two generated by scroll-snap-coordinate, ensure that they are evaluated as snap points. (Up #2)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "repeat(200px)",
+ "scrollSnapPointsY" : "repeat(200px)",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "120px 120px, 220px 220px",
+ "initialX" : 0,
+ "initialY" : 220,
+ "key" : "VK_UP",
+ "expectedX" : 0,
+ "expectedY" : 200,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Mandatory + scroll-snap-points-{x|y} + scroll-snap-coordinate with two points => Interval and element snapping points are combined. Test 1 snap point generated by scroll-snap-points-{x|y} and two generated by scroll-snap-coordinate, ensure that they are evaluated as snap points. (Up #3)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "repeat(200px)",
+ "scrollSnapPointsY" : "repeat(200px)",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "120px 120px, 220px 220px",
+ "initialX" : 0,
+ "initialY" : 200,
+ "key" : "VK_UP",
+ "expectedX" : 0,
+ "expectedY" : 120,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when paging down/up that the next snap point in the direction of the scroll is selected rather than a closer point in the opposite direction (page Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "600px 600px, 475px 475px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_PAGE_DOWN",
+ "expectedX" : 500,
+ "expectedY" : 600,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when paging down/up that the next snap point in the direction of the scroll is selected rather than a closer point in the opposite direction (Page Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "400px 400px, 525px 525px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_PAGE_UP",
+ "expectedX" : 500,
+ "expectedY" : 400,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when paging down/up that the farthest snap point before the destination is selected and prioritized over a snap point that is past the destination, even if the snap point past the destination is closer to the destination. Setup - two snap points between current position and destination and one snap point past the destination which is closer than any of the other points. Scrollable rect size is 500px. (Page Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "525px 525px, 550px 550px, 800px 800px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_PAGE_DOWN",
+ "expectedX" : 500,
+ "expectedY" : 550,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when paging down/up that the farthest snap point before the destination is selected and prioritized over a snap point that is past the destination, even if the snap point past the destination is closer to the destination. Setup - two snap points between current position and destination and one snap point past the destination which is closer than any of the other points. Scrollable rect size is 500px. (Page Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "475px 475px, 450px 450px, 200px 200px",
+ "initialX" : 500,
+ "initialY" : 500,
+ "key" : "VK_PAGE_UP",
+ "expectedX" : 500,
+ "expectedY" : 450,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when paging down/up that the closest snap point past the destination is selected when no snap points exist between the starting position and the destination. Additionally, a snap point closer to the destination than the one past the snap point, but not in the scrolling direction, must not be selected. Setup - Two snap points beyond the destination and one snap point in the opposite direction of scrolling which is closest to the destination. Scrollable rect size is 500px. (Page Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "50px 50px, 800px 800px, 900px 900px",
+ "initialX" : 100,
+ "initialY" : 100,
+ "key" : "VK_PAGE_DOWN",
+ "expectedX" : 100,
+ "expectedY" : 800,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when paging down/up that the closest snap point past the destination is selected when no snap points exist between the starting position and the destination. Additionally, a snap point closer to the destination than the one past the snap point, but not in the scrolling direction, must not be selected. Setup - Two snap points beyond the destination and one snap point in the opposite direction of scrolling which is closest to the destination. Scrollable rect size is 500px. (Page Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "950px 950px, 200px 200px, 100px 100px",
+ "initialX" : 900,
+ "initialY" : 900,
+ "key" : "VK_PAGE_UP",
+ "expectedX" : 900,
+ "expectedY" : 200,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when scrolling by lines up,down,left,or right, that the closest snap point to the destination in the direction of travel is selected. Setup - Two snap points in the direction of travel and one in the opposite direction. Snap point in opposite direction is closest to the destination but must not be selected. (Down)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "50px 50px, 800px 800px, 900px 900px",
+ "initialX" : 100,
+ "initialY" : 100,
+ "key" : "VK_PAGE_DOWN",
+ "expectedX" : 100,
+ "expectedY" : 800,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when scrolling by lines up,down,left,or right, that the closest snap point to the destination in the direction of travel is selected. Setup - Two snap points in the direction of travel and one in the opposite direction. Snap point in opposite direction is closest to the destination but must not be selected. (Up)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "950px 950px, 200px 200px, 100px 100px",
+ "initialX" : 900,
+ "initialY" : 900,
+ "key" : "VK_PAGE_UP",
+ "expectedX" : 900,
+ "expectedY" : 200,
+ "notExpected" : false
+ },
+
+ {
+ "description" : "Ensure that when scrolling by lines up,down,left,or right, that the closest snap point to the destination in the direction of travel is selected. Setup - Two snap points in the direction of travel and one in the opposite direction. Snap point in opposite direction is closest to the destination but must not be selected. (Left)",
+ "scrollSnapType" : "mandatory",
+ "scrollSnapPointsX" : "none",
+ "scrollSnapPointsY" : "none",
+ "scrollSnapDestination" : "0px 0px",
+ "scrollSnapCoordinate" : "950px 950px, 200px 200px, 100px 100px",
+ "initialX" : 900,
+ "initialY" : 900,
+ "key" : "VK_LEFT",
+ "expectedX" : 200,
+ "expectedY" : 900,
+ "notExpected" : false
+ }
+];
+
+var step = 0;
+var sc; // Scroll Container
+var sd; // Scrolled Div
+
+var lastScrollTop;
+var lastScrollLeft;
+var stopFrameCount;
+
+// The tests should work the same way when all the values for the scroll
+// container are provided in percentages. To assert that, we just duplicate all
+// the test cases and replace the pixel values related to the scroll container
+// with percentage values, based on its clientWidth/Height sespectively.
+function addPercentageTests() {
+ var width = sc.clientWidth;
+ var height = sc.clientHeight;
+ var pxRegexp = /(\d+)px/;
+ var rewriteW = (_, w) => (parseInt(w, 10) / width * 100) + "%";
+ var rewriteH = (_, h) => (parseInt(h, 10) / height * 100) + "%";
+ testCases = testCases.concat(testCases.map(testCase => Object.assign({}, testCase, {
+ description: "With Percentages: " + testCase.description,
+ scrollSnapPointsX: testCase.scrollSnapPointsX.replace(pxRegexp, rewriteW),
+ scrollSnapPointsY: testCase.scrollSnapPointsY.replace(pxRegexp, rewriteH),
+ scrollSnapDestination: testCase.scrollSnapDestination
+ .replace(pxRegexp, rewriteW).replace(pxRegexp, rewriteH),
+ })));
+}
+
+function initTest() {
+ var testCase = testCases[step];
+ sc.style.scrollSnapType = testCase.scrollSnapType;
+ sc.style.scrollSnapPointsX = testCase.scrollSnapPointsX;
+ sc.style.scrollSnapPointsY = testCase.scrollSnapPointsY;
+ sc.style.scrollSnapDestination = testCase.scrollSnapDestination;
+ sd.style.scrollSnapCoordinate = testCase.scrollSnapCoordinate;
+ sc.scrollTo(testCase.initialX, testCase.initialY);
+ sc.focus();
+ synthesizeKey(testCase.key, {});
+
+ stopFrameCount = 0;
+ lastScrollTop = sc.scrollTop;
+ lastScrollLeft = sc.scrollLeft;
+
+ window.requestAnimationFrame(waitForScrollStop);
+}
+
+function waitForScrollStop() {
+ if (stopFrameCount > 30) {
+ // We have the same position for 30 consecutive frames -- we are stopped
+ testScrolling();
+ } else {
+ // Still moving
+ if (lastScrollTop == sc.scrollTop && lastScrollLeft == sc.scrollLeft) {
+ stopFrameCount++;
+ } else {
+ stopFrameCount = 0;
+ lastScrollTop = sc.scrollTop;
+ lastScrollLeft = sc.scrollLeft;
+ }
+ window.requestAnimationFrame(waitForScrollStop);
+ }
+}
+
+function testScrollSnapping() {
+ sc = document.getElementById("sc");
+ sd = document.getElementById("sd");
+
+ addPercentageTests();
+
+ initTest();
+}
+
+function testScrolling() {
+ var testCase = testCases[step];
+ if (document.getElementById('display').style.direction == "rtl") {
+ if (testCase.notExpected) {
+ isnot("(" + -sc.scrollLeft + "," + sc.scrollTop + ")",
+ "(" + -testCase.expectedX + "," + testCase.expectedY + ")",
+ "rtl: " + testCase.description);
+ } else {
+ is("(" + -sc.scrollLeft + "," + sc.scrollTop + ")",
+ "(" + -testCase.expectedX + "," + testCase.expectedY + ")",
+ "rtl: " + testCase.description);
+ }
+ } else {
+ // ltr direction
+ if (testCase.notExpected) {
+ isnot("(" + sc.scrollLeft + "," + sc.scrollTop + ")",
+ "(" + testCase.expectedX + "," + testCase.expectedY + ")",
+ "ltr: " + testCase.description);
+ } else {
+ is("(" + sc.scrollLeft + "," + sc.scrollTop + ")",
+ "(" + testCase.expectedX + "," + testCase.expectedY + ")",
+ "ltr: " + testCase.description);
+ }
+ }
+
+ step++;
+ if (step < Object.keys(testCases).length) {
+ initTest();
+ } else {
+ if (document.getElementById('display').style.direction == "rtl") {
+ SimpleTest.finish();
+ } else {
+ // Do everything again, but with rtl
+ document.getElementById('display').style.direction = "rtl";
+ step = 0;
+ initTest();
+ }
+ }
+}
+
+function doTest() {
+ SpecialPowers.pushPrefEnv({
+ "set": [["layout.css.scroll-snap.enabled", true],
+ ["layout.css.scroll-snap.proximity-threshold", 100]]},
+ testScrollSnapping);
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+</script>
+</pre>
+</body>
+
+</html>
diff --git a/layout/base/tests/test_scroll_snapping_scrollbars.html b/layout/base/tests/test_scroll_snapping_scrollbars.html
new file mode 100644
index 000000000..7caf62a59
--- /dev/null
+++ b/layout/base/tests/test_scroll_snapping_scrollbars.html
@@ -0,0 +1,349 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for scroll snapping</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<p id="display"></p>
+<div id="sc" style="margin: 0px; padding: 0px; overflow: scroll; width:250px; height: 250px;">
+ <div id="sd" style="margin: 0px; padding: 0px; width: 1250px; height: 1250px;"></div>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var runtime = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"]
+ .getService(SpecialPowers.Ci.nsIXULRuntime);
+var isMac = navigator.platform.indexOf("Mac") != -1;
+var isGtk = runtime.widgetToolkit.indexOf("gtk") != -1;
+var isWin = navigator.platform.indexOf("Win") != -1;
+var isSN = /mac os x 10\.6/.test(navigator.userAgent.toLowerCase());
+
+// Half of the scrollbar control width, in CSS pixels
+var scrollbarOffset = isWin ? 8 : 5;
+
+// OSX 10.6 scroll bar thumbs are off-center due to the bundling of buttons on one end
+// of the scroll bar frame.
+var scrollbarCenter = isSN ? 100 : 125;
+
+var testCases = [
+ {
+ "description" : "Drag scrollbar left, expect scroll snapping.",
+ "snapCoord" : "500px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : scrollbarCenter, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : -10, "y" : 0 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Drag scrollbar right, expect scroll snapping.",
+ "snapCoord" : "500px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : scrollbarCenter, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : 10, "y" : 0 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Drag scrollbar up, expect scroll snapping.",
+ "snapCoord" : "500px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : scrollbarCenter },
+ "mouseOffset" : { "x" : 0, "y" : -10 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Drag scrollbar down, expect scroll snapping.",
+ "snapCoord" : "500px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : scrollbarCenter },
+ "mouseOffset" : { "x" : 0, "y" : 10 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Page scrollbar left, expect scroll snapping.",
+ "snapCoord" : "500px 500px, 1000px 500px",
+ "startScroll" : { "x" : 1000, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : 50, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Page scrollbar right, expect scroll snapping.",
+ "snapCoord" : "500px 500px, 0px 500px",
+ "startScroll" : { "x" : 0, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : 200, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Page scrollbar up, expect scroll snapping.",
+ "snapCoord" : "500px 500px, 500px 1000px",
+ "startScroll" : { "x" : 500, "y" : 1000 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : 50 },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Page scrollbar down, expect scroll snapping.",
+ "snapCoord" : "500px 500px, 500px 0px",
+ "startScroll" : { "x" : 500, "y" : 0 },
+ "endScroll" : { "x" : 500, "y" : 500 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : 200 },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : true,
+ "runGtk" : true,
+ "runWin" : true
+ },
+ {
+ "description" : "Click scrollbar left button, expect scroll snapping.",
+ "snapCoord" : "50px 500px, 250px 500px, 500px 500px, 750px 500px, 950px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 250, "y" : 500 },
+ "mousePosition" : { "x" : scrollbarOffset, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+ {
+ "description" : "Hold scrollbar left button until repeating, expect scroll snapping.",
+ "snapCoord" : "50px 500px, 500px 500px, 950px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 50, "y" : 500 },
+ "mousePosition" : { "x" : scrollbarOffset, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "500",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+ {
+ "description" : "Click scrollbar right button, expect scroll snapping.",
+ "snapCoord" : "50px 500px, 250px 500px, 500px 500px, 750px 500px, 950px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 750, "y" : 500 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset * 3, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+ {
+ "description" : "Hold scrollbar right button until repeating, expect scroll snapping.",
+ "snapCoord" : "50px 500px, 500px 500px, 950px 500px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 950, "y" : 500 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset * 3, "y" : 250 - scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "500",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+ {
+ "description" : "Click scrollbar up button, expect scroll snapping.",
+ "snapCoord" : "500px 50px, 500px 250px, 500px 500px, 500px 750px, 500px 950px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 250 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+ {
+ "description" : "Hold scrollbar up button until repeating, expect scroll snapping.",
+ "snapCoord" : "500px 50px, 500px 500px, 500px 950px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 50 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : scrollbarOffset },
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "500",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+ {
+ "description" : "Click scrollbar down button, expect scroll snapping.",
+ "snapCoord" : "500px 50px, 500px 250px, 500px 500px, 500px 750px, 500px 950px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 750 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : 250 - scrollbarOffset * 3},
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "0",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+ {
+ "description" : "Hold scrollbar down button until repeating, expect scroll snapping.",
+ "snapCoord" : "500px 50px, 500px 500px, 500px 950px",
+ "startScroll" : { "x" : 500, "y" : 500 },
+ "endScroll" : { "x" : 500, "y" : 950 },
+ "mousePosition" : { "x" : 250 - scrollbarOffset, "y" : 250 - scrollbarOffset * 3},
+ "mouseOffset" : { "x" : 0, "y" : 0 },
+ "duration" : "500",
+ "runMac" : false, // OSX does not have have line-scroll buttons
+ "runGtk" : false, // Some GTK themes may not have scroll buttons
+ "runWin" : true
+ },
+
+];
+
+var step = 0;
+var sc; // Scroll Container
+var sd; // Scrolled Div
+
+var lastScrollTop;
+var lastScrollLeft;
+var stopFrameCount;
+var winUtils = SpecialPowers.DOMWindowUtils;
+
+function doTest() {
+ var testCase = testCases[step];
+
+ stopFrameCount = 0;
+ lastScrollTop = sc.scrollTop;
+ lastScrollLeft = sc.scrollLeft;
+
+ sc.scrollTo(testCase.startScroll.x, testCase.startScroll.y);
+ sc.style.scrollSnapType = "mandatory";
+ sd.style.scrollSnapCoordinate = testCase.snapCoord;
+
+ synthesizeMouse(sc,
+ testCase.mousePosition.x,
+ testCase.mousePosition.y,
+ { type: "mousedown" });
+
+ synthesizeMouse(sc,
+ testCase.mousePosition.x + testCase.mouseOffset.x,
+ testCase.mousePosition.y + testCase.mouseOffset.y,
+ { type: "mousemove" });
+
+ stopFrameCount = 0;
+ waitForScrollStart();
+}
+
+function waitForScrollStart() {
+ // Wait for up to 30 frames for scrolling to start
+ var testCase = testCases[step];
+ if (testCase.startScroll.y != sc.scrollTop
+ || testCase.startScroll.x != sc.scrollLeft
+ || ++stopFrameCount < 30) {
+ window.requestAnimationFrame(doMouseUp);
+ } else {
+ window.requestAnimationFrame(waitForScrollStart);
+ }
+}
+
+function doMouseUp() {
+ var testCase = testCases[step];
+ isnot("(" + sc.scrollLeft + "," + sc.scrollTop + ")",
+ "(" + testCase.startScroll.x +"," + testCase.startScroll.y + ")",
+ "Step " + step + ": Synthesized mouse events move scroll position. ("
+ + testCase.description + ")");
+
+ window.setTimeout(function() {
+ synthesizeMouse(sc,
+ testCase.mousePosition.x + testCase.mouseOffset.x,
+ testCase.mousePosition.y + testCase.mouseOffset.y,
+ { type: "mouseup" });
+
+ stopFrameCount = 0;
+ window.requestAnimationFrame(waitForScrollStop);
+ }, testCase.duration);
+}
+
+function waitForScrollStop() {
+ if (stopFrameCount > 30) {
+ // We have the same position for 30 consecutive frames -- we are stopped
+ verifyTest();
+ } else {
+ // Still moving
+ if (lastScrollTop == sc.scrollTop && lastScrollLeft == sc.scrollLeft) {
+ stopFrameCount++;
+ } else {
+ stopFrameCount = 0;
+ lastScrollTop = sc.scrollTop;
+ lastScrollLeft = sc.scrollLeft;
+ }
+ window.requestAnimationFrame(waitForScrollStop);
+ }
+}
+
+function verifyTest() {
+ // Test ended, check if scroll position matches expected position
+ var testCase = testCases[step];
+ is("(" + sc.scrollLeft + "," + sc.scrollTop + ")",
+ "(" + testCase.endScroll.x +"," + testCase.endScroll.y + ")",
+ "Step " + step + ": " + testCase.description);
+
+ // Find next test to run
+ while (true) {
+ if (++step == testCases.length) {
+ SimpleTest.finish();
+ break;
+ } else {
+ testCase = testCases[step];
+ if ((testCase.runGtk && isGtk)
+ || (testCase.runMac && isMac)
+ || (testCase.runWin && isWin)) {
+ doTest();
+ break;
+ }
+ }
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("Delays added to allow synthesized mouse " +
+ "events to trigger scrollbar repeating scrolls.");
+addLoadEvent(function() {
+ sc = document.getElementById("sc");
+ sd = document.getElementById("sd");
+ SpecialPowers.pushPrefEnv({
+ "set": [["layout.css.scroll-snap.enabled", true],
+ ["layout.css.scroll-snap.proximity-threshold", 100]]},
+ doTest);
+});
+</script>
+</pre>
+</body>
+
+</html>
diff --git a/layout/base/tests/test_transformed_scrolling_repaints.html b/layout/base/tests/test_transformed_scrolling_repaints.html
new file mode 100644
index 000000000..00e6cbfd5
--- /dev/null
+++ b/layout/base/tests/test_transformed_scrolling_repaints.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that scaled elements with scrolled contents don't repaint unnecessarily when we scroll inside them</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="setPrefAndStartTest()">
+<div id="t" style="-moz-transform: scale(1.2, 1.2); -moz-transform-origin:top left; width:200px; height:500px; background:yellow; overflow:auto">
+ <div style="height:40px;">Hello</div>
+ <div id="e" style="height:30px; background:lime">Kitty</div>
+ <div style="height:800px; background:yellow">Kitty</div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var t = document.getElementById("t");
+var e = document.getElementById("e");
+var utils = SpecialPowers.getDOMWindowUtils(window);
+
+function startTest() {
+ // Do a couple of scrolls to ensure we've triggered activity heuristics.
+ waitForAllPaintsFlushed(function () {
+ t.scrollTop = 5;
+ waitForAllPaintsFlushed(function () {
+ t.scrollTop = 10;
+ waitForAllPaintsFlushed(function () {
+ // Clear paint state now and scroll again.
+ utils.checkAndClearPaintedState(e);
+ t.scrollTop = 15;
+ waitForAllPaintsFlushed(function () {
+ var painted = utils.checkAndClearPaintedState(e);
+ is(painted, false, "Fully-visible scrolled element should not have been painted");
+ SimpleTest.finish();
+ });
+ });
+ });
+ });
+}
+function setPrefAndStartTest() {
+ SpecialPowers.pushPrefEnv(
+ {"set": [["layers.single-tile.enabled", false]]},
+ // Need a timeout here to allow paint unsuppression before we start the test
+ function() {
+ setTimeout(startTest, 0);
+ }
+ );
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_transformed_scrolling_repaints_2.html b/layout/base/tests/test_transformed_scrolling_repaints_2.html
new file mode 100644
index 000000000..84de2dd4d
--- /dev/null
+++ b/layout/base/tests/test_transformed_scrolling_repaints_2.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that scaled elements with scrolled contents don't repaint unnecessarily when we scroll inside them (1.1 scale)</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="setPrefAndStartTest()">
+<div id="t" style="-moz-transform: scale(1.1, 1.1); -moz-transform-origin:top left; width:200px; height:100px; background:yellow; overflow:hidden">
+ <div style="height:40px;"></div>
+ <div id="e" style="height:30px; background:lime"></div>
+ <div style="height:300px; background:yellow"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var t = document.getElementById("t");
+var e = document.getElementById("e");
+var utils = SpecialPowers.getDOMWindowUtils(window);
+
+function startTest() {
+ // Do a couple of scrolls to ensure we've triggered activity heuristics
+ waitForAllPaintsFlushed(function () {
+ t.scrollTop = 5;
+ waitForAllPaintsFlushed(function () {
+ t.scrollTop = 10;
+ waitForAllPaintsFlushed(function () {
+ // Clear paint state now and scroll again.
+ utils.checkAndClearPaintedState(e);
+ t.scrollTop = 20;
+ waitForAllPaintsFlushed(function () {
+ var painted = utils.checkAndClearPaintedState(e);
+ is(painted, false, "Fully-visible scrolled element should not have been painted");
+ SimpleTest.finish();
+ });
+ });
+ });
+ });
+}
+function setPrefAndStartTest() {
+ SpecialPowers.pushPrefEnv(
+ {"set": [["layers.single-tile.enabled", false]]},
+ // Need a timeout here to allow paint unsuppression before we start the test
+ function() {
+ setTimeout(startTest, 0);
+ }
+ );
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/test_transformed_scrolling_repaints_3.html b/layout/base/tests/test_transformed_scrolling_repaints_3.html
new file mode 100644
index 000000000..d8cbd0891
--- /dev/null
+++ b/layout/base/tests/test_transformed_scrolling_repaints_3.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that scaled elements with scrolled contents don't repaint unnecessarily when we scroll inside them</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<!-- Need a timeout here to allow paint unsuppression before we start the test -->
+<body>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv(
+ {"set": [["layers.single-tile.enabled", false]]},
+ function() {
+ window.open("transformed_scrolling_repaints_3_window.html", "transformed_scrolling_repaints_3",
+ "chrome,width=300,height=400,scrollbars=no");
+ }
+);
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/base/tests/textarea-invalid-ref.html b/layout/base/tests/textarea-invalid-ref.html
new file mode 100644
index 000000000..c5607603d
--- /dev/null
+++ b/layout/base/tests/textarea-invalid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <textarea style="background-color:red">foo</textarea>
+ </body>
+</html>
+
diff --git a/layout/base/tests/textarea-maxlength-invalid-change.html b/layout/base/tests/textarea-maxlength-invalid-change.html
new file mode 100644
index 000000000..8c1691b91
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with maxlength is invalid if the user edits and it's too long -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" maxlength="2">fooo</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-maxlength-ui-invalid-change.html b/layout/base/tests/textarea-maxlength-ui-invalid-change.html
new file mode 100644
index 000000000..eed6de90f
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with maxlength is -moz-ui-invalid if the user edits and it's too long -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" maxlength="2">fooo</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-maxlength-ui-valid-change.html b/layout/base/tests/textarea-maxlength-ui-valid-change.html
new file mode 100644
index 000000000..b7385ee6d
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with maxlength is -moz-ui-valid if the user edits and it's not too long -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+ textarea.blur();
+ textarea.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" maxlength="3">foooo</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-maxlength-valid-before-change.html b/layout/base/tests/textarea-maxlength-valid-before-change.html
new file mode 100644
index 000000000..3466d310a
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with maxlength is valid until the user edits it, even if it's too long -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ </head>
+ <body onload="document.documentElement.className=''">
+ <textarea id="textarea" maxlength="2">foo</textarea>
+ </body>
+</html>
+
diff --git a/layout/base/tests/textarea-maxlength-valid-change.html b/layout/base/tests/textarea-maxlength-valid-change.html
new file mode 100644
index 000000000..c845111ac
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with maxlength is valid if the user edits and it's not too long -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+ textarea.blur();
+ textarea.focus();
+ synthesizeKey('VK_BACK_SPACE', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" maxlength="3">foooo</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-minlength-invalid-change.html b/layout/base/tests/textarea-minlength-invalid-change.html
new file mode 100644
index 000000000..3e26feada
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with minlength is invalid if the user edits and it's too short -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('o', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" minlength="4">fo</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-minlength-ui-invalid-change.html b/layout/base/tests/textarea-minlength-ui-invalid-change.html
new file mode 100644
index 000000000..99ce7721e
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with minlength is -moz-ui-invalid if the user edits and it's too short -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { box-shadow:none; background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('o', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" minlength="4">fo</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-minlength-ui-valid-change.html b/layout/base/tests/textarea-minlength-ui-valid-change.html
new file mode 100644
index 000000000..1449b5fa2
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with minlength is -moz-ui-valid if the user edits and it's not too short -->
+ <head>
+ <style>
+ :-moz-ui-valid { background-color:green; }
+ :-moz-ui-invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('o', {}); // so that it becomes invalid first
+ textarea.blur();
+ textarea.focus();
+ synthesizeKey('o', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" minlength="3">f</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-minlength-valid-before-change.html b/layout/base/tests/textarea-minlength-valid-before-change.html
new file mode 100644
index 000000000..6fd7ad979
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with minlength is valid until the user edits it, even if it's too short -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ </head>
+ <body onload="document.documentElement.className=''">
+ <textarea id="textarea" minlength="5">foo</textarea>
+ </body>
+</html>
+
diff --git a/layout/base/tests/textarea-minlength-valid-change.html b/layout/base/tests/textarea-minlength-valid-change.html
new file mode 100644
index 000000000..081d5d21a
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <!-- Test: textarea with minlength is valid if the user edits and it's not too short -->
+ <head>
+ <style>
+ :valid { background-color:green; }
+ :invalid { background-color:red; }
+ * { background-color:white; }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script>
+ function runTest() {
+ var textarea = document.getElementById('textarea');
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length)
+ textarea.focus();
+ synthesizeKey('o', {}); // so that it becomes invalid first
+ textarea.blur();
+ textarea.focus();
+ synthesizeKey('o', {});
+ textarea.blur(); // to hide the caret
+ document.documentElement.className='';
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <textarea id="textarea" minlength="3">f</textarea>
+ </body>
+</html>
diff --git a/layout/base/tests/textarea-valid-ref.html b/layout/base/tests/textarea-valid-ref.html
new file mode 100644
index 000000000..547b4fb7c
--- /dev/null
+++ b/layout/base/tests/textarea-valid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <textarea style="background-color:green">foo</textarea>
+ </body>
+</html>
+
diff --git a/layout/base/tests/transformed_scrolling_repaints_3_window.html b/layout/base/tests/transformed_scrolling_repaints_3_window.html
new file mode 100644
index 000000000..26ea43eec
--- /dev/null
+++ b/layout/base/tests/transformed_scrolling_repaints_3_window.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that scaled elements with scrolled contents don't repaint unnecessarily when we scroll inside them</title>
+ <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+</head>
+<!-- Need a timeout here to allow paint unsuppression before we start the test -->
+<body onload="setTimeout(startTest,0)" style="background:white;">
+<iframe id="t" style="-moz-transform: scale(0.48979); -moz-transform-origin:top left; width:500px; height:600px;"
+ src="data:text/html,
+<body style='background:yellow;'>
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p id='e'>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that
+there are some real dicks out there, and some of them happen to be
+scientists.
+</body>"></iframe>
+<pre id="test">
+<script type="application/javascript">
+var SimpleTest = window.opener.SimpleTest;
+var SpecialPowers = window.opener.SpecialPowers;
+var is = window.opener.is;
+var t, e, utils, iterations;
+var smoothScrollPref = "general.smoothScroll";
+
+function startTest() {
+ SpecialPowers.pushPrefEnv({"set":[[smoothScrollPref, false]]}, runTest);
+}
+function runTest() {
+ t = document.getElementById("t");
+ e = t.contentDocument.getElementById("e");
+ t.contentWindow.scrollTo(0,0);
+ utils = SpecialPowers.getDOMWindowUtils(window);
+ iterations = 0;
+
+ // Do a couple of scrolls to ensure we've triggered activity heuristics.
+ waitForAllPaintsFlushed(function () {
+ t.contentWindow.scrollByLines(1);
+ waitForAllPaintsFlushed(function () {
+ t.contentWindow.scrollByLines(1);
+ waitForAllPaintsFlushed(function () {
+ // Clear paint state now and scroll again.
+ utils.checkAndClearPaintedState(e);
+ t.contentWindow.scrollByLines(1);
+ waitForAllPaintsFlushed(nextIteration);
+ });
+ });
+ });
+}
+function nextIteration() {
+ var painted = utils.checkAndClearPaintedState(e);
+ is(painted, false, "Fully-visible scrolled element should not have been painted");
+ if (++iterations == 10) {
+ SimpleTest.finish();
+ window.close();
+ } else {
+ t.contentWindow.scrollByLines(1);
+ waitForAllPaintsFlushed(nextIteration);
+ }
+}
+</script>
+</pre>
+</body>
+</html>