summaryrefslogtreecommitdiff
path: root/docshell/test
diff options
context:
space:
mode:
Diffstat (limited to 'docshell/test')
-rw-r--r--docshell/test/browser/browser.ini93
-rw-r--r--docshell/test/browser/browser_bug1206879.js31
-rw-r--r--docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js35
-rw-r--r--docshell/test/browser/browser_bug134911.js41
-rw-r--r--docshell/test/browser/browser_bug234628-1.js18
-rw-r--r--docshell/test/browser/browser_bug234628-10.js18
-rw-r--r--docshell/test/browser/browser_bug234628-11.js18
-rw-r--r--docshell/test/browser/browser_bug234628-2.js18
-rw-r--r--docshell/test/browser/browser_bug234628-3.js18
-rw-r--r--docshell/test/browser/browser_bug234628-4.js18
-rw-r--r--docshell/test/browser/browser_bug234628-5.js18
-rw-r--r--docshell/test/browser/browser_bug234628-6.js18
-rw-r--r--docshell/test/browser/browser_bug234628-7.js18
-rw-r--r--docshell/test/browser/browser_bug234628-8.js11
-rw-r--r--docshell/test/browser/browser_bug234628-9.js11
-rw-r--r--docshell/test/browser/browser_bug349769.js47
-rw-r--r--docshell/test/browser/browser_bug388121-1.js15
-rw-r--r--docshell/test/browser/browser_bug388121-2.js58
-rw-r--r--docshell/test/browser/browser_bug420605.js122
-rw-r--r--docshell/test/browser/browser_bug422543.js116
-rw-r--r--docshell/test/browser/browser_bug441169.js37
-rw-r--r--docshell/test/browser/browser_bug503832.js87
-rw-r--r--docshell/test/browser/browser_bug554155.js26
-rw-r--r--docshell/test/browser/browser_bug655270.js60
-rw-r--r--docshell/test/browser/browser_bug655273.js30
-rw-r--r--docshell/test/browser/browser_bug670318.js70
-rw-r--r--docshell/test/browser/browser_bug673467.js51
-rw-r--r--docshell/test/browser/browser_bug852909.js23
-rw-r--r--docshell/test/browser/browser_bug92473.js54
-rw-r--r--docshell/test/browser/browser_loadDisallowInherit.js65
-rw-r--r--docshell/test/browser/browser_loadURI.js34
-rw-r--r--docshell/test/browser/browser_multiple_pushState.js15
-rw-r--r--docshell/test/browser/browser_onbeforeunload_navigation.js176
-rw-r--r--docshell/test/browser/browser_search_notification.js51
-rw-r--r--docshell/test/browser/browser_tab_touch_events.js49
-rw-r--r--docshell/test/browser/browser_timelineMarkers-01.js32
-rw-r--r--docshell/test/browser/browser_timelineMarkers-02.js15
-rw-r--r--docshell/test/browser/browser_timelineMarkers-03.js8
-rw-r--r--docshell/test/browser/browser_timelineMarkers-04.js8
-rw-r--r--docshell/test/browser/browser_timelineMarkers-05.js15
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-02.js133
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-03.js91
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-04.js88
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-05.js117
-rw-r--r--docshell/test/browser/browser_ua_emulation.js36
-rw-r--r--docshell/test/browser/browser_uriFixupAlternateRedirects.js24
-rw-r--r--docshell/test/browser/browser_uriFixupIntegration.js51
-rw-r--r--docshell/test/browser/favicon_bug655270.icobin0 -> 1406 bytes
-rw-r--r--docshell/test/browser/file_bug1046022.html50
-rw-r--r--docshell/test/browser/file_bug1206879.html9
-rw-r--r--docshell/test/browser/file_bug234628-1-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-1.html17
-rw-r--r--docshell/test/browser/file_bug234628-10-child.xhtml4
-rw-r--r--docshell/test/browser/file_bug234628-10.html17
-rw-r--r--docshell/test/browser/file_bug234628-11-child.xhtml4
-rw-r--r--docshell/test/browser/file_bug234628-11-child.xhtml^headers^1
-rw-r--r--docshell/test/browser/file_bug234628-11.html17
-rw-r--r--docshell/test/browser/file_bug234628-2-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-2.html17
-rw-r--r--docshell/test/browser/file_bug234628-3-child.html13
-rw-r--r--docshell/test/browser/file_bug234628-3.html18
-rw-r--r--docshell/test/browser/file_bug234628-4-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-4.html18
-rw-r--r--docshell/test/browser/file_bug234628-5-child.htmlbin0 -> 498 bytes
-rw-r--r--docshell/test/browser/file_bug234628-5.html18
-rw-r--r--docshell/test/browser/file_bug234628-6-child.htmlbin0 -> 540 bytes
-rw-r--r--docshell/test/browser/file_bug234628-6-child.html^headers^1
-rw-r--r--docshell/test/browser/file_bug234628-6.html18
-rw-r--r--docshell/test/browser/file_bug234628-7-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-7-child.html^headers^1
-rw-r--r--docshell/test/browser/file_bug234628-7.html18
-rw-r--r--docshell/test/browser/file_bug234628-8-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-8.html17
-rw-r--r--docshell/test/browser/file_bug234628-9-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-9.htmlbin0 -> 740 bytes
-rw-r--r--docshell/test/browser/file_bug420605.html31
-rw-r--r--docshell/test/browser/file_bug422543_script.js98
-rw-r--r--docshell/test/browser/file_bug503832.html35
-rw-r--r--docshell/test/browser/file_bug655270.html11
-rw-r--r--docshell/test/browser/file_bug670318.html23
-rw-r--r--docshell/test/browser/file_bug852909.pdfbin0 -> 1568 bytes
-rw-r--r--docshell/test/browser/file_bug852909.pngbin0 -> 94 bytes
-rw-r--r--docshell/test/browser/file_multiple_pushState.html14
-rw-r--r--docshell/test/browser/frame-head.js113
-rw-r--r--docshell/test/browser/head.js99
-rw-r--r--docshell/test/browser/print_postdata.sjs22
-rw-r--r--docshell/test/browser/redirect_to_example.sjs4
-rw-r--r--docshell/test/browser/test-form_sjis.html24
-rw-r--r--docshell/test/browser/timelineMarkers-04.html55
-rw-r--r--docshell/test/bug123696-subframe.html16
-rw-r--r--docshell/test/bug369814.jarbin0 -> 1311 bytes
-rw-r--r--docshell/test/bug369814.zipbin0 -> 1000 bytes
-rw-r--r--docshell/test/bug404548-subframe.html7
-rw-r--r--docshell/test/bug413310-post.sjs7
-rw-r--r--docshell/test/bug413310-subframe.html7
-rw-r--r--docshell/test/bug529119-window.html7
-rw-r--r--docshell/test/bug530396-noref.sjs20
-rw-r--r--docshell/test/bug530396-subframe.html7
-rw-r--r--docshell/test/bug570341_recordevents.html21
-rw-r--r--docshell/test/bug668513_redirect.html1
-rw-r--r--docshell/test/bug668513_redirect.html^headers^2
-rw-r--r--docshell/test/bug691547_frame.html12
-rw-r--r--docshell/test/chrome/112564_nocache.html10
-rw-r--r--docshell/test/chrome/112564_nocache.html^headers^1
-rw-r--r--docshell/test/chrome/215405_nocache.html14
-rw-r--r--docshell/test/chrome/215405_nocache.html^headers^1
-rw-r--r--docshell/test/chrome/215405_nostore.html14
-rw-r--r--docshell/test/chrome/215405_nostore.html^headers^1
-rw-r--r--docshell/test/chrome/582176_dummy.html1
-rw-r--r--docshell/test/chrome/582176_xml.xml2
-rw-r--r--docshell/test/chrome/582176_xslt.xsl8
-rw-r--r--docshell/test/chrome/662200a.html8
-rw-r--r--docshell/test/chrome/662200b.html8
-rw-r--r--docshell/test/chrome/662200c.html7
-rw-r--r--docshell/test/chrome/89419.html7
-rw-r--r--docshell/test/chrome/92598_nostore.html10
-rw-r--r--docshell/test/chrome/92598_nostore.html^headers^1
-rw-r--r--docshell/test/chrome/allowContentRetargeting.sjs7
-rw-r--r--docshell/test/chrome/blue.pngbin0 -> 2745 bytes
-rw-r--r--docshell/test/chrome/bug112564_window.xul117
-rw-r--r--docshell/test/chrome/bug113934_window.xul161
-rw-r--r--docshell/test/chrome/bug215405_window.xul167
-rw-r--r--docshell/test/chrome/bug293235.html13
-rw-r--r--docshell/test/chrome/bug293235_p2.html8
-rw-r--r--docshell/test/chrome/bug293235_window.xul162
-rw-r--r--docshell/test/chrome/bug294258_testcase.html43
-rw-r--r--docshell/test/chrome/bug294258_window.xul76
-rwxr-xr-xdocshell/test/chrome/bug298622_window.xul148
-rw-r--r--docshell/test/chrome/bug301397_1.html9
-rw-r--r--docshell/test/chrome/bug301397_2.html10
-rw-r--r--docshell/test/chrome/bug301397_3.html10
-rw-r--r--docshell/test/chrome/bug301397_4.html9
-rw-r--r--docshell/test/chrome/bug301397_window.xul250
-rw-r--r--docshell/test/chrome/bug303267.html25
-rwxr-xr-xdocshell/test/chrome/bug303267_window.xul101
-rw-r--r--docshell/test/chrome/bug311007_window.xul199
-rwxr-xr-xdocshell/test/chrome/bug321671_window.xul133
-rw-r--r--docshell/test/chrome/bug360511_case1.html15
-rw-r--r--docshell/test/chrome/bug360511_case2.html15
-rwxr-xr-xdocshell/test/chrome/bug360511_window.xul134
-rw-r--r--docshell/test/chrome/bug364461_window.xul277
-rw-r--r--docshell/test/chrome/bug396519_window.xul169
-rwxr-xr-xdocshell/test/chrome/bug396649_window.xul122
-rw-r--r--docshell/test/chrome/bug449778_window.xul106
-rw-r--r--docshell/test/chrome/bug449780_window.xul77
-rw-r--r--docshell/test/chrome/bug454235-subframe.xul7
-rw-r--r--docshell/test/chrome/bug582176_window.xul88
-rw-r--r--docshell/test/chrome/bug608669.xul6
-rw-r--r--docshell/test/chrome/bug662200_window.xul129
-rw-r--r--docshell/test/chrome/bug690056_window.xul176
-rw-r--r--docshell/test/chrome/bug846906.html10
-rw-r--r--docshell/test/chrome/bug89419.sjs13
-rw-r--r--docshell/test/chrome/bug89419_window.xul82
-rw-r--r--docshell/test/chrome/bug909218.html11
-rw-r--r--docshell/test/chrome/bug909218.js2
-rw-r--r--docshell/test/chrome/bug92598_window.xul118
-rw-r--r--docshell/test/chrome/chrome.ini88
-rwxr-xr-xdocshell/test/chrome/docshell_helpers.js496
-rw-r--r--docshell/test/chrome/file_viewsource_forbidden_in_iframe.html11
-rw-r--r--docshell/test/chrome/gen_template.pl39
-rw-r--r--docshell/test/chrome/generic.html12
-rw-r--r--docshell/test/chrome/mozFrameType_window.xul57
-rw-r--r--docshell/test/chrome/red.pngbin0 -> 82 bytes
-rw-r--r--docshell/test/chrome/test.template.txt41
-rw-r--r--docshell/test/chrome/test_allowContentRetargeting.html94
-rw-r--r--docshell/test/chrome/test_bug112564.xul38
-rw-r--r--docshell/test/chrome/test_bug113934.xul31
-rw-r--r--docshell/test/chrome/test_bug215405.xul38
-rw-r--r--docshell/test/chrome/test_bug293235.xul39
-rw-r--r--docshell/test/chrome/test_bug294258.xul39
-rw-r--r--docshell/test/chrome/test_bug298622.xul39
-rw-r--r--docshell/test/chrome/test_bug301397.xul39
-rw-r--r--docshell/test/chrome/test_bug303267.xul40
-rw-r--r--docshell/test/chrome/test_bug311007.xul45
-rw-r--r--docshell/test/chrome/test_bug321671.xul39
-rw-r--r--docshell/test/chrome/test_bug360511.xul40
-rw-r--r--docshell/test/chrome/test_bug364461.xul38
-rw-r--r--docshell/test/chrome/test_bug396519.xul29
-rw-r--r--docshell/test/chrome/test_bug396649.xul41
-rw-r--r--docshell/test/chrome/test_bug428288.html37
-rw-r--r--docshell/test/chrome/test_bug449778.xul31
-rw-r--r--docshell/test/chrome/test_bug449780.xul31
-rw-r--r--docshell/test/chrome/test_bug453650.xul115
-rw-r--r--docshell/test/chrome/test_bug454235.xul56
-rw-r--r--docshell/test/chrome/test_bug456980.xul31
-rw-r--r--docshell/test/chrome/test_bug565388.xul83
-rw-r--r--docshell/test/chrome/test_bug582176.xul39
-rw-r--r--docshell/test/chrome/test_bug608669.xul117
-rw-r--r--docshell/test/chrome/test_bug662200.xul39
-rw-r--r--docshell/test/chrome/test_bug690056.xul26
-rw-r--r--docshell/test/chrome/test_bug789773.xul71
-rw-r--r--docshell/test/chrome/test_bug846906.xul96
-rw-r--r--docshell/test/chrome/test_bug89419.xul39
-rw-r--r--docshell/test/chrome/test_bug909218.html127
-rw-r--r--docshell/test/chrome/test_bug92598.xul38
-rw-r--r--docshell/test/chrome/test_mozFrameType.xul43
-rw-r--r--docshell/test/chrome/test_principalInherit.xul108
-rw-r--r--docshell/test/chrome/test_private_hidden_window.html56
-rw-r--r--docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul180
-rw-r--r--docshell/test/chrome/window.template.txt44
-rw-r--r--docshell/test/file_anchor_scroll_after_document_open.html15
-rw-r--r--docshell/test/file_bug385434_1.html29
-rw-r--r--docshell/test/file_bug385434_2.html26
-rw-r--r--docshell/test/file_bug385434_3.html22
-rw-r--r--docshell/test/file_bug475636.sjs90
-rw-r--r--docshell/test/file_bug509055.html9
-rw-r--r--docshell/test/file_bug511449.html6
-rw-r--r--docshell/test/file_bug540462.html16
-rw-r--r--docshell/test/file_bug580069_1.html8
-rw-r--r--docshell/test/file_bug580069_2.sjs5
-rw-r--r--docshell/test/file_bug590573_1.html8
-rw-r--r--docshell/test/file_bug590573_2.html8
-rw-r--r--docshell/test/file_bug634834.html5
-rw-r--r--docshell/test/file_bug640387.html26
-rw-r--r--docshell/test/file_bug653741.html13
-rw-r--r--docshell/test/file_bug6604045
-rw-r--r--docshell/test/file_bug660404^headers^1
-rw-r--r--docshell/test/file_bug662170.html13
-rw-r--r--docshell/test/file_bug668513.html107
-rw-r--r--docshell/test/file_bug669671.sjs14
-rw-r--r--docshell/test/file_bug680257.html16
-rw-r--r--docshell/test/file_bug703855.html2
-rw-r--r--docshell/test/file_bug728939.html3
-rw-r--r--docshell/test/file_framedhistoryframes.html16
-rw-r--r--docshell/test/file_pushState_after_document_open.html11
-rw-r--r--docshell/test/historyframes.html150
-rw-r--r--docshell/test/iframesandbox/file_marquee_event_handlers.html17
-rw-r--r--docshell/test/iframesandbox/file_other_auxiliary_navigation_by_location.html15
-rw-r--r--docshell/test/iframesandbox/file_our_auxiliary_navigation_by_location.html15
-rw-r--r--docshell/test/iframesandbox/file_parent_navigation_by_location.html18
-rw-r--r--docshell/test/iframesandbox/file_sibling_navigation_by_location.html15
-rw-r--r--docshell/test/iframesandbox/file_top_navigation_by_location.html20
-rw-r--r--docshell/test/iframesandbox/file_top_navigation_by_location_exotic.html26
-rw-r--r--docshell/test/iframesandbox/mochitest.ini24
-rw-r--r--docshell/test/iframesandbox/test_child_navigation_by_location.html92
-rw-r--r--docshell/test/iframesandbox/test_marquee_event_handlers.html95
-rw-r--r--docshell/test/iframesandbox/test_other_auxiliary_navigation_by_location.html80
-rw-r--r--docshell/test/iframesandbox/test_our_auxiliary_navigation_by_location.html84
-rw-r--r--docshell/test/iframesandbox/test_parent_navigation_by_location.html75
-rw-r--r--docshell/test/iframesandbox/test_sibling_navigation_by_location.html78
-rw-r--r--docshell/test/iframesandbox/test_top_navigation_by_location.html167
-rw-r--r--docshell/test/iframesandbox/test_top_navigation_by_location_exotic.html204
-rw-r--r--docshell/test/mochitest.ini94
-rw-r--r--docshell/test/navigation/NavigationUtils.js213
-rw-r--r--docshell/test/navigation/blank.html1
-rw-r--r--docshell/test/navigation/browser.ini12
-rw-r--r--docshell/test/navigation/browser_bug343515.js262
-rw-r--r--docshell/test/navigation/browser_test-content-chromeflags.js45
-rw-r--r--docshell/test/navigation/bug343515_pg1.html5
-rw-r--r--docshell/test/navigation/bug343515_pg2.html7
-rw-r--r--docshell/test/navigation/bug343515_pg3.html7
-rw-r--r--docshell/test/navigation/bug343515_pg3_1.html6
-rw-r--r--docshell/test/navigation/bug343515_pg3_1_1.html1
-rw-r--r--docshell/test/navigation/bug343515_pg3_2.html1
-rw-r--r--docshell/test/navigation/file_bug1300461.html63
-rw-r--r--docshell/test/navigation/file_bug1300461_back.html31
-rw-r--r--docshell/test/navigation/file_bug1300461_redirect.html10
-rw-r--r--docshell/test/navigation/file_bug1300461_redirect.html^headers^2
-rw-r--r--docshell/test/navigation/file_bug462076_1.html55
-rw-r--r--docshell/test/navigation/file_bug462076_2.html52
-rw-r--r--docshell/test/navigation/file_bug462076_3.html52
-rw-r--r--docshell/test/navigation/file_bug508537_1.html34
-rw-r--r--docshell/test/navigation/file_bug534178.html31
-rw-r--r--docshell/test/navigation/file_document_write_1.html30
-rw-r--r--docshell/test/navigation/file_fragment_handling_during_load.html24
-rw-r--r--docshell/test/navigation/file_nested_frames.html28
-rw-r--r--docshell/test/navigation/file_scrollRestoration.html137
-rw-r--r--docshell/test/navigation/file_shiftReload_and_pushState.html29
-rw-r--r--docshell/test/navigation/file_static_and_dynamic_1.html32
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_frame_1.html27
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_frame_2.html8
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a.html6
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html6
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_b.html15
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_base.html6
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_nav.html6
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_subframe.html15
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_subframe_nav.html21
-rw-r--r--docshell/test/navigation/file_triggeringprincipal_window_open.html6
-rw-r--r--docshell/test/navigation/frame0.html3
-rw-r--r--docshell/test/navigation/frame1.html3
-rw-r--r--docshell/test/navigation/frame2.html3
-rw-r--r--docshell/test/navigation/frame3.html3
-rw-r--r--docshell/test/navigation/goback.html5
-rw-r--r--docshell/test/navigation/iframe.html8
-rw-r--r--docshell/test/navigation/mochitest.ini64
-rw-r--r--docshell/test/navigation/navigate.html36
-rw-r--r--docshell/test/navigation/open.html9
-rw-r--r--docshell/test/navigation/parent.html14
-rw-r--r--docshell/test/navigation/test_bug13871.html81
-rw-r--r--docshell/test/navigation/test_bug270414.html93
-rw-r--r--docshell/test/navigation/test_bug278916.html37
-rw-r--r--docshell/test/navigation/test_bug279495.html48
-rw-r--r--docshell/test/navigation/test_bug344861.html35
-rw-r--r--docshell/test/navigation/test_bug386782.html137
-rw-r--r--docshell/test/navigation/test_bug430624.html56
-rw-r--r--docshell/test/navigation/test_bug430723.html138
-rw-r--r--docshell/test/navigation/test_child.html48
-rw-r--r--docshell/test/navigation/test_grandchild.html48
-rw-r--r--docshell/test/navigation/test_not-opener.html51
-rw-r--r--docshell/test/navigation/test_opener.html52
-rw-r--r--docshell/test/navigation/test_popup-navigates-children.html62
-rw-r--r--docshell/test/navigation/test_reserved.html100
-rw-r--r--docshell/test/navigation/test_sessionhistory.html68
-rw-r--r--docshell/test/navigation/test_sibling-matching-parent.html46
-rw-r--r--docshell/test/navigation/test_sibling-off-domain.html46
-rw-r--r--docshell/test/navigation/test_triggeringprincipal_frame_nav.html69
-rw-r--r--docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html87
-rw-r--r--docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html70
-rw-r--r--docshell/test/navigation/test_triggeringprincipal_window_open.html101
-rw-r--r--docshell/test/test_anchor_scroll_after_document_open.html55
-rw-r--r--docshell/test/test_bfcache_plus_hash.html120
-rw-r--r--docshell/test/test_bug1045096.html29
-rw-r--r--docshell/test/test_bug1121701.html71
-rw-r--r--docshell/test/test_bug1186774.html51
-rw-r--r--docshell/test/test_bug123696.html46
-rw-r--r--docshell/test/test_bug369814.html211
-rw-r--r--docshell/test/test_bug384014.html41
-rw-r--r--docshell/test/test_bug385434.html209
-rw-r--r--docshell/test/test_bug387979.html54
-rw-r--r--docshell/test/test_bug402210.html50
-rw-r--r--docshell/test/test_bug404548.html39
-rw-r--r--docshell/test/test_bug413310.html106
-rw-r--r--docshell/test/test_bug475636.html52
-rw-r--r--docshell/test/test_bug509055.html98
-rw-r--r--docshell/test/test_bug511449.html56
-rw-r--r--docshell/test/test_bug529119-1.html95
-rw-r--r--docshell/test/test_bug529119-2.html90
-rw-r--r--docshell/test/test_bug530396.html57
-rw-r--r--docshell/test/test_bug540462.html44
-rw-r--r--docshell/test/test_bug551225.html32
-rw-r--r--docshell/test/test_bug570341.html142
-rw-r--r--docshell/test/test_bug580069.html61
-rw-r--r--docshell/test/test_bug590573.html232
-rw-r--r--docshell/test/test_bug598895.html53
-rw-r--r--docshell/test/test_bug634834.html53
-rw-r--r--docshell/test/test_bug637644.html53
-rw-r--r--docshell/test/test_bug640387_1.html109
-rw-r--r--docshell/test/test_bug640387_2.html90
-rw-r--r--docshell/test/test_bug653741.html49
-rw-r--r--docshell/test/test_bug660404.html48
-rw-r--r--docshell/test/test_bug662170.html51
-rw-r--r--docshell/test/test_bug668513.html28
-rw-r--r--docshell/test/test_bug669671.html146
-rw-r--r--docshell/test/test_bug675587.html34
-rw-r--r--docshell/test/test_bug680257.html59
-rw-r--r--docshell/test/test_bug691547.html60
-rw-r--r--docshell/test/test_bug694612.html27
-rw-r--r--docshell/test/test_bug703855.html79
-rw-r--r--docshell/test/test_bug713825.html42
-rw-r--r--docshell/test/test_bug728939.html37
-rw-r--r--docshell/test/test_bug797909.html66
-rw-r--r--docshell/test/test_forceinheritprincipal_overrule_owner.html51
-rw-r--r--docshell/test/test_framedhistoryframes.html32
-rw-r--r--docshell/test/test_pushState_after_document_open.html37
-rw-r--r--docshell/test/test_windowedhistoryframes.html32
-rw-r--r--docshell/test/unit/head_docshell.js11
-rw-r--r--docshell/test/unit/test_bug414201_jfif.js27
-rw-r--r--docshell/test/unit/test_bug442584.js30
-rw-r--r--docshell/test/unit/test_nsDefaultURIFixup.js93
-rw-r--r--docshell/test/unit/test_nsDefaultURIFixup_info.js620
-rw-r--r--docshell/test/unit/test_nsDefaultURIFixup_search.js117
-rw-r--r--docshell/test/unit/test_nsIDownloadHistory.js68
-rw-r--r--docshell/test/unit/test_pb_notification.js23
-rw-r--r--docshell/test/unit/test_privacy_transition.js23
-rw-r--r--docshell/test/unit/test_setUsePrivateBrowsing.js65
-rw-r--r--docshell/test/unit/xpcshell.ini17
-rw-r--r--docshell/test/unit_ipc/test_pb_notification_ipc.js20
-rw-r--r--docshell/test/unit_ipc/xpcshell.ini8
369 files changed, 18281 insertions, 0 deletions
diff --git a/docshell/test/browser/browser.ini b/docshell/test/browser/browser.ini
new file mode 100644
index 0000000000..9211092a49
--- /dev/null
+++ b/docshell/test/browser/browser.ini
@@ -0,0 +1,93 @@
+[DEFAULT]
+support-files =
+ favicon_bug655270.ico
+ file_bug234628-1-child.html
+ file_bug234628-1.html
+ file_bug234628-10-child.xhtml
+ file_bug234628-10.html
+ file_bug234628-11-child.xhtml
+ file_bug234628-11-child.xhtml^headers^
+ file_bug234628-11.html
+ file_bug234628-2-child.html
+ file_bug234628-2.html
+ file_bug234628-3-child.html
+ file_bug234628-3.html
+ file_bug234628-4-child.html
+ file_bug234628-4.html
+ file_bug234628-5-child.html
+ file_bug234628-5.html
+ file_bug234628-6-child.html
+ file_bug234628-6-child.html^headers^
+ file_bug234628-6.html
+ file_bug234628-7-child.html
+ file_bug234628-7-child.html^headers^
+ file_bug234628-7.html
+ file_bug234628-8-child.html
+ file_bug234628-8.html
+ file_bug234628-9-child.html
+ file_bug234628-9.html
+ file_bug420605.html
+ file_bug422543_script.js
+ file_bug503832.html
+ file_bug655270.html
+ file_bug670318.html
+ file_bug852909.pdf
+ file_bug852909.png
+ file_bug1046022.html
+ file_bug1206879.html
+ file_multiple_pushState.html
+ print_postdata.sjs
+ test-form_sjis.html
+ timelineMarkers-04.html
+ browser_timelineMarkers-frame-02.js
+ browser_timelineMarkers-frame-03.js
+ browser_timelineMarkers-frame-04.js
+ browser_timelineMarkers-frame-05.js
+ head.js
+ frame-head.js
+
+[browser_bug1206879.js]
+[browser_bug1309900_crossProcessHistoryNavigation.js]
+[browser_bug134911.js]
+[browser_bug234628-1.js]
+[browser_bug234628-10.js]
+[browser_bug234628-11.js]
+[browser_bug234628-2.js]
+[browser_bug234628-3.js]
+[browser_bug234628-4.js]
+[browser_bug234628-5.js]
+[browser_bug234628-6.js]
+[browser_bug234628-7.js]
+[browser_bug234628-8.js]
+[browser_bug234628-9.js]
+[browser_bug349769.js]
+[browser_bug388121-1.js]
+[browser_bug388121-2.js]
+[browser_bug420605.js]
+[browser_bug422543.js]
+[browser_bug441169.js]
+[browser_bug503832.js]
+[browser_bug554155.js]
+[browser_bug655270.js]
+[browser_bug655273.js]
+[browser_bug670318.js]
+[browser_bug673467.js]
+[browser_bug852909.js]
+[browser_bug92473.js]
+[browser_uriFixupIntegration.js]
+[browser_uriFixupAlternateRedirects.js]
+support-files =
+ redirect_to_example.sjs
+[browser_loadDisallowInherit.js]
+[browser_loadURI.js]
+[browser_multiple_pushState.js]
+[browser_onbeforeunload_navigation.js]
+[browser_search_notification.js]
+[browser_tab_touch_events.js]
+[browser_timelineMarkers-01.js]
+[browser_timelineMarkers-02.js]
+skip-if = true # Bug 1220415
+[browser_timelineMarkers-03.js]
+[browser_timelineMarkers-04.js]
+[browser_timelineMarkers-05.js]
+[browser_ua_emulation.js]
diff --git a/docshell/test/browser/browser_bug1206879.js b/docshell/test/browser/browser_bug1206879.js
new file mode 100644
index 0000000000..1276f64280
--- /dev/null
+++ b/docshell/test/browser/browser_bug1206879.js
@@ -0,0 +1,31 @@
+add_task(function*() {
+ let url = getRootDirectory(gTestPath) + "file_bug1206879.html";
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, true);
+
+ let numLocationChanges = 0;
+
+ let listener = {
+ onLocationChange: function(browser, wp, request, uri, flags) {
+ if (browser != tab.linkedBrowser) {
+ return;
+ }
+ info("onLocationChange: " + uri.spec);
+ numLocationChanges++;
+ this.resolve();
+ }
+ };
+ let locationPromise = new Promise((resolve, reject) => {
+ listener.resolve = resolve;
+ gBrowser.addTabsProgressListener(listener);
+ });
+ yield ContentTask.spawn(tab.linkedBrowser, {}, function() {
+ content.frames[0].history.pushState(null, null, "foo");
+ });
+
+ yield locationPromise;
+
+ gBrowser.removeTab(tab);
+ gBrowser.removeTabsProgressListener(listener);
+ is(numLocationChanges, 1,
+ "pushState with a different URI should cause a LocationChange event.");
+});
diff --git a/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js b/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js
new file mode 100644
index 0000000000..a4b4645e84
--- /dev/null
+++ b/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+add_task(function* runTests() {
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:about");
+
+ registerCleanupFunction(function* () {
+ gBrowser.removeTab(tab);
+ });
+
+ let browser = tab.linkedBrowser;
+
+ browser.loadURI("about:accounts");
+ let href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "about:accounts", "Check about:accounts loaded");
+
+ // Using a dummy onunload listener to disable the bfcache as that can prevent
+ // the test browser load detection mechanism from working.
+ browser.loadURI("data:text/html,<body%20onunload=''><iframe></iframe></body>");
+ href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
+ "Check data URL loaded");
+
+ browser.goBack();
+ href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "about:accounts", "Check we've gone back to about:accounts");
+
+ browser.goForward();
+ href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
+ "Check we've gone forward to data URL");
+});
diff --git a/docshell/test/browser/browser_bug134911.js b/docshell/test/browser/browser_bug134911.js
new file mode 100644
index 0000000000..aa54cfd1a2
--- /dev/null
+++ b/docshell/test/browser/browser_bug134911.js
@@ -0,0 +1,41 @@
+const TEXT = {
+ /* The test text decoded correctly as Shift_JIS */
+ rightText: "\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059",
+
+ enteredText1: "The quick brown fox jumps over the lazy dog",
+ enteredText2: "\u03BE\u03B5\u03C3\u03BA\u03B5\u03C0\u03AC\u03B6\u03C9\u0020\u03C4\u1F74\u03BD\u0020\u03C8\u03C5\u03C7\u03BF\u03C6\u03B8\u03CC\u03C1\u03B1\u0020\u03B2\u03B4\u03B5\u03BB\u03C5\u03B3\u03BC\u03AF\u03B1",
+};
+
+function test() {
+ waitForExplicitFinish();
+
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "test-form_sjis.html");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpen);
+}
+
+function afterOpen() {
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
+
+ ContentTask.spawn(gBrowser.selectedBrowser, TEXT, function(TEXT) {
+ content.document.getElementById("testtextarea").value = TEXT.enteredText1;
+ content.document.getElementById("testinput").value = TEXT.enteredText2;
+ }).then(() => {
+ /* Force the page encoding to Shift_JIS */
+ BrowserSetForcedCharacterSet("Shift_JIS");
+ });
+}
+
+function afterChangeCharset() {
+ ContentTask.spawn(gBrowser.selectedBrowser, TEXT, function(TEXT) {
+ is(content.document.getElementById("testpar").innerHTML, TEXT.rightText,
+ "encoding successfully changed");
+ is(content.document.getElementById("testtextarea").value, TEXT.enteredText1,
+ "text preserved in <textarea>");
+ is(content.document.getElementById("testinput").value, TEXT.enteredText2,
+ "text preserved in <input>");
+ }).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+}
diff --git a/docshell/test/browser/browser_bug234628-1.js b/docshell/test/browser/browser_bug234628-1.js
new file mode 100644
index 0000000000..bfb4d3708f
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-1.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-1.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 129, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 85, "Child doc should be windows-1252 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 129, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0402'), 85, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-10.js b/docshell/test/browser/browser_bug234628-10.js
new file mode 100644
index 0000000000..7dbe805c4f
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-10.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-10.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 151, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 71, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 151, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 71, "Child doc should decode as utf-8 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-11.js b/docshell/test/browser/browser_bug234628-11.js
new file mode 100644
index 0000000000..fc597f5c09
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-11.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-11.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 193, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 193, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should decode as utf-8 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-2.js b/docshell/test/browser/browser_bug234628-2.js
new file mode 100644
index 0000000000..638e223c09
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-2.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-2.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 129, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u00E2\u201A\u00AC'), 78, "Child doc should be windows-1252 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 129, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 78, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-3.js b/docshell/test/browser/browser_bug234628-3.js
new file mode 100644
index 0000000000..51aca7ec83
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-3.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-3.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 118, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 73, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 118, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 73, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-4.js b/docshell/test/browser/browser_bug234628-4.js
new file mode 100644
index 0000000000..fe7f1545fe
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-4.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-4.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 132, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 79, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 132, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 79, "Child doc should decode as utf-8 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-5.js b/docshell/test/browser/browser_bug234628-5.js
new file mode 100644
index 0000000000..a37f14b8d6
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-5.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-5.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 146, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 87, "Child doc should be utf-16 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 146, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 87, "Child doc should decode as utf-16 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-16LE", "Child doc should report UTF-16LE subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-6.js b/docshell/test/browser/browser_bug234628-6.js
new file mode 100644
index 0000000000..7d2d925315
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-6.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-6.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 190, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 109, "Child doc should be utf-16 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 190, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 109, "Child doc should decode as utf-16 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-16BE", "Child doc should report UTF-16 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-7.js b/docshell/test/browser/browser_bug234628-7.js
new file mode 100644
index 0000000000..0bafd67e78
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-7.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-7.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 188, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 188, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 107, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-8.js b/docshell/test/browser/browser_bug234628-8.js
new file mode 100644
index 0000000000..40a0c69469
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-8.js
@@ -0,0 +1,11 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-8.html", afterOpen);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 156, "Parent doc should be windows-1251");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0402'), 99, "Child doc should be windows-1251");
+}
+
diff --git a/docshell/test/browser/browser_bug234628-9.js b/docshell/test/browser/browser_bug234628-9.js
new file mode 100644
index 0000000000..72da65e80b
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-9.js
@@ -0,0 +1,11 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-9.html", afterOpen);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 145, "Parent doc should be UTF-16");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 96, "Child doc should be windows-1252");
+}
+
diff --git a/docshell/test/browser/browser_bug349769.js b/docshell/test/browser/browser_bug349769.js
new file mode 100644
index 0000000000..76d4e0f28d
--- /dev/null
+++ b/docshell/test/browser/browser_bug349769.js
@@ -0,0 +1,47 @@
+add_task(function* test() {
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
+ const uris = [undefined, "about:blank"];
+
+ function checkContentProcess(uri) {
+ yield ContentTask.spawn(newBrowser, uri, function* (uri) {
+ var prin = content.document.nodePrincipal;
+ Assert.notEqual(prin, null, "Loaded principal must not be null when adding " + uri);
+ Assert.notEqual(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
+
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+ .getService(Ci.nsIScriptSecurityManager);
+ Assert.equal(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system when loading " + uri);
+ });
+ }
+
+ for (var uri of uris) {
+ yield BrowserTestUtils.withNewTab({ gBrowser }, function* (newBrowser) {
+ yield BrowserTestUtils.loadURI(newBrowser, uri);
+
+ var prin = newBrowser.contentPrincipal;
+ isnot(prin, null, "Forced principal must not be null when loading " + uri);
+ isnot(prin, undefined,
+ "Forced principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Forced principal must not be system when loading " + uri);
+
+ // Belt-and-suspenders e10s check: make sure that the same checks hold
+ // true in the content process.
+ checkContentProcess(uri);
+
+ yield BrowserTestUtils.browserLoaded(newBrowser);
+
+ prin = newBrowser.contentPrincipal;
+ isnot(prin, null, "Loaded principal must not be null when adding " + uri);
+ isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system when loading " + uri);
+
+ // Belt-and-suspenders e10s check: make sure that the same checks hold
+ // true in the content process.
+ checkContentProcess(uri);
+ });
+ }
+});
+
diff --git a/docshell/test/browser/browser_bug388121-1.js b/docshell/test/browser/browser_bug388121-1.js
new file mode 100644
index 0000000000..7da617594a
--- /dev/null
+++ b/docshell/test/browser/browser_bug388121-1.js
@@ -0,0 +1,15 @@
+add_task(function* test() {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (newBrowser) {
+ yield ContentTask.spawn(newBrowser, null, function* () {
+ var prin = content.document.nodePrincipal;
+ Assert.notEqual(prin, null, "Loaded principal must not be null");
+ Assert.notEqual(prin, undefined, "Loaded principal must not be undefined");
+
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+ .getService(Ci.nsIScriptSecurityManager);
+ Assert.equal(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system");
+ });
+ });
+});
+
diff --git a/docshell/test/browser/browser_bug388121-2.js b/docshell/test/browser/browser_bug388121-2.js
new file mode 100644
index 0000000000..6c050d971a
--- /dev/null
+++ b/docshell/test/browser/browser_bug388121-2.js
@@ -0,0 +1,58 @@
+function test() {
+ waitForExplicitFinish();
+
+ var w;
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
+ var iteration = 1;
+ const uris = ["", "about:blank"];
+ var uri;
+ var origDoc;
+
+ function testLoad() {
+ if (w.document == origDoc) {
+ // Go back to polling
+ setTimeout(testLoad, 10);
+ return;
+ }
+ var prin = w.document.nodePrincipal;
+ isnot(prin, null, "Loaded principal must not be null when adding " + uri);
+ isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system when loading " + uri);
+ w.close();
+
+ if (iteration == uris.length) {
+ finish();
+ } else {
+ ++iteration;
+ doTest();
+ }
+ }
+
+ function doTest() {
+ uri = uris[iteration - 1];
+ w = window.open(uri, "_blank", "width=10,height=10");
+ var prin = w.document.nodePrincipal;
+ if (!uri) {
+ uri = undefined;
+ }
+ isnot(prin, null, "Forced principal must not be null when loading " + uri);
+ isnot(prin, undefined,
+ "Forced principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Forced principal must not be system when loading " + uri);
+ if (uri == undefined) {
+ // No actual load here, so just move along.
+ w.close();
+ ++iteration;
+ doTest();
+ } else {
+ origDoc = w.document;
+ // Need to poll, because load listeners on the content window won't
+ // survive the load.
+ setTimeout(testLoad, 10);
+ }
+ }
+
+ doTest();
+}
diff --git a/docshell/test/browser/browser_bug420605.js b/docshell/test/browser/browser_bug420605.js
new file mode 100644
index 0000000000..f07d45e932
--- /dev/null
+++ b/docshell/test/browser/browser_bug420605.js
@@ -0,0 +1,122 @@
+/* Test for Bug 420605
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=420605
+ */
+
+function test() {
+ waitForExplicitFinish();
+
+ var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html";
+ var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html#firefox";
+
+ var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
+ .getService(Ci.nsINavHistoryService);
+
+ /* Queries nsINavHistoryService and returns a single history entry
+ * for a given URI */
+ function getNavHistoryEntry(aURI) {
+ var options = historyService.getNewQueryOptions();
+ options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
+ options.maxResults = 1;
+
+ var query = historyService.getNewQuery();
+ query.uri = aURI;
+
+ var result = historyService.executeQuery(query, options);
+ result.root.containerOpen = true;
+
+ if (!result.root.childCount) {
+ return null;
+ }
+ return result.root.getChild(0);
+ }
+
+ // We'll save the favicon URL of the orignal page here and check that the
+ // page with a hash has the same favicon.
+ var originalFavicon;
+
+ // Control flow in this test is a bit complicated.
+ //
+ // When the page loads, onPageLoad (the DOMContentLoaded handler) and
+ // historyObserver::onPageChanged are both called, in some order. Once
+ // they've both run, we click a fragment link in the content page
+ // (clickLinkIfReady), which should trigger another onPageChanged event,
+ // this time for the fragment's URL.
+
+ var _clickLinkTimes = 0;
+ function clickLinkIfReady() {
+ _clickLinkTimes++;
+ if (_clickLinkTimes == 2) {
+ BrowserTestUtils.synthesizeMouseAtCenter('#firefox-link', {},
+ gBrowser.selectedBrowser);
+ }
+ }
+
+ /* Global history observer that triggers for the two test URLs above. */
+ var historyObserver = {
+ onBeginUpdateBatch: function() {},
+ onEndUpdateBatch: function() {},
+ onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
+ aTransitionType, _added) {},
+ onTitleChanged: function(aURI, aPageTitle) {},
+ onDeleteURI: function(aURI) {},
+ onClearHistory: function() {},
+ onPageChanged: function(aURI, aWhat, aValue) {
+ if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
+ return;
+ }
+ aURI = aURI.spec;
+ switch (aURI) {
+ case pageurl:
+ ok(aValue, "Favicon value is not null for page without fragment.");
+ originalFavicon = aValue;
+
+ // Now that the favicon has loaded, click on fragment link.
+ // This should trigger the |case fragmenturl| below.
+ clickLinkIfReady();
+
+ return;
+ case fragmenturl:
+ // If the fragment URL's favicon isn't set, this branch won't
+ // be called and the test will time out.
+
+ is(aValue, originalFavicon, "New favicon should be same as original favicon.");
+
+ // Let's explicitly check that we can get the favicon
+ // from nsINavHistoryService now.
+ let info = getNavHistoryEntry(makeURI(aURI));
+ ok(info, "There must be a history entry for the fragment.");
+ ok(info.icon, "The history entry must have an associated favicon.");
+ historyService.removeObserver(historyObserver, false);
+ gBrowser.removeCurrentTab();
+ finish();
+ }
+ },
+ onPageExpired: function(aURI, aVisitTime, aWholeEntry) {},
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsINavHistoryObserver) ||
+ iid.equals(Ci.nsISupports)) {
+ return this;
+ }
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ };
+ historyService.addObserver(historyObserver, false);
+
+ function onPageLoad() {
+ gBrowser.selectedBrowser
+ .removeEventListener("DOMContentLoaded", arguments.callee, true);
+ clickLinkIfReady();
+ }
+
+ // Make sure neither of the test pages haven't been loaded before.
+ var info = getNavHistoryEntry(makeURI(pageurl));
+ ok(!info, "The test page must not have been visited already.");
+ info = getNavHistoryEntry(makeURI(fragmenturl));
+ ok(!info, "The fragment test page must not have been visited already.");
+
+ // Now open the test page in a new tab.
+ gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.selectedBrowser.addEventListener(
+ "DOMContentLoaded", onPageLoad, true);
+ content.location = pageurl;
+}
diff --git a/docshell/test/browser/browser_bug422543.js b/docshell/test/browser/browser_bug422543.js
new file mode 100644
index 0000000000..0655a17b7a
--- /dev/null
+++ b/docshell/test/browser/browser_bug422543.js
@@ -0,0 +1,116 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(function* runTests() {
+ yield setup();
+ let browser = gBrowser.selectedBrowser;
+ // Now that we're set up, initialize our frame script.
+ yield checkListeners("initial", "listeners initialized");
+
+ // Check if all history listeners are always notified.
+ info("# part 1");
+ yield whenPageShown(browser, () => browser.loadURI("http://www.example.com/"));
+ yield checkListeners("newentry", "shistory has a new entry");
+ ok(browser.canGoBack, "we can go back");
+
+ yield whenPageShown(browser, () => browser.goBack());
+ yield checkListeners("goback", "back to the first shentry");
+ ok(browser.canGoForward, "we can go forward");
+
+ yield whenPageShown(browser, () => browser.goForward());
+ yield checkListeners("goforward", "forward to the second shentry");
+
+ yield whenPageShown(browser, () => browser.reload());
+ yield checkListeners("reload", "current shentry reloaded");
+
+ yield whenPageShown(browser, () => browser.gotoIndex(0));
+ yield checkListeners("gotoindex", "back to the first index");
+
+ // Check nsISHistoryInternal.notifyOnHistoryReload
+ info("# part 2");
+ ok((yield notifyReload()), "reloading has not been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+
+ // Let the first listener cancel the reload action.
+ info("# part 3");
+ yield resetListeners();
+ yield setListenerRetval(0, false);
+ ok(!(yield notifyReload()), "reloading has been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+
+ // Let both listeners cancel the reload action.
+ info("# part 4");
+ yield resetListeners();
+ yield setListenerRetval(1, false);
+ ok(!(yield notifyReload()), "reloading has been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+
+ // Let the second listener cancel the reload action.
+ info("# part 5");
+ yield resetListeners();
+ yield setListenerRetval(0, true);
+ ok(!(yield notifyReload()), "reloading has been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+});
+
+function listenOnce(message, arg = {}) {
+ return new Promise(resolve => {
+ let mm = gBrowser.selectedBrowser.messageManager;
+ mm.addMessageListener(message + ":return", function listener(msg) {
+ mm.removeMessageListener(message + ":return", listener);
+ resolve(msg.data);
+ });
+
+ mm.sendAsyncMessage(message, arg);
+ });
+}
+
+function checkListeners(aLast, aMessage) {
+ return listenOnce("bug422543:getListenerStatus").then((listenerStatuses) => {
+ is(listenerStatuses[0], aLast, aMessage);
+ is(listenerStatuses[1], aLast, aMessage);
+ });
+}
+
+function resetListeners() {
+ return listenOnce("bug422543:resetListeners");
+}
+
+function notifyReload() {
+ return listenOnce("bug422543:notifyReload").then(({ rval }) => {
+ return rval;
+ });
+}
+
+function setListenerRetval(num, val) {
+ return listenOnce("bug422543:setRetval", { num, val });
+}
+
+function setup() {
+ return BrowserTestUtils.openNewForegroundTab(gBrowser,
+ "http://mochi.test:8888")
+ .then(function (tab) {
+ let browser = tab.linkedBrowser;
+ registerCleanupFunction(function* () {
+ yield listenOnce("bug422543:cleanup");
+ gBrowser.removeTab(tab);
+ });
+
+ browser.messageManager
+ .loadFrameScript(getRootDirectory(gTestPath) + "file_bug422543_script.js", false);
+ });
+}
+
+function whenPageShown(aBrowser, aNavigation) {
+ let listener = ContentTask.spawn(aBrowser, null, function () {
+ return new Promise(resolve => {
+ addEventListener("pageshow", function onLoad() {
+ removeEventListener("pageshow", onLoad, true);
+ resolve();
+ }, true);
+ });
+ });
+
+ aNavigation();
+ return listener;
+}
diff --git a/docshell/test/browser/browser_bug441169.js b/docshell/test/browser/browser_bug441169.js
new file mode 100644
index 0000000000..0151157933
--- /dev/null
+++ b/docshell/test/browser/browser_bug441169.js
@@ -0,0 +1,37 @@
+/* Make sure that netError won't allow HTML injection through badcert parameters. See bug 441169. */
+var newBrowser
+
+function task() {
+ let resolve;
+ let promise = new Promise(r => { resolve = r; });
+
+ addEventListener("DOMContentLoaded", checkPage, false);
+
+ function checkPage(event) {
+ if (event.target != content.document) {
+ return;
+ }
+ removeEventListener("DOMContentLoaded", checkPage, false);
+
+ is(content.document.getElementById("test_span"), null, "Error message should not be parsed as HTML, and hence shouldn't include the 'test_span' element.");
+ resolve();
+ }
+
+ var chromeURL = "about:neterror?e=nssBadCert&u=https%3A//test.kuix.de/&c=UTF-8&d=This%20sentence%20should%20not%20be%20parsed%20to%20include%20a%20%3Cspan%20id=%22test_span%22%3Enamed%3C/span%3E%20span%20tag.%0A%0AThe%20certificate%20is%20only%20valid%20for%20%3Ca%20id=%22cert_domain_link%22%20title=%22kuix.de%22%3Ekuix.de%3C/a%3E%0A%0A(Error%20code%3A%20ssl_error_bad_cert_domain)";
+ content.location = chromeURL;
+
+ return promise;
+}
+
+function test() {
+ waitForExplicitFinish();
+
+ var newTab = gBrowser.addTab();
+ gBrowser.selectedTab = newTab;
+ newBrowser = gBrowser.getBrowserForTab(newTab);
+
+ ContentTask.spawn(newBrowser, null, task).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+}
diff --git a/docshell/test/browser/browser_bug503832.js b/docshell/test/browser/browser_bug503832.js
new file mode 100644
index 0000000000..66904cbae8
--- /dev/null
+++ b/docshell/test/browser/browser_bug503832.js
@@ -0,0 +1,87 @@
+/* Test for Bug 503832
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=503832
+ */
+
+add_task(function* () {
+ var pagetitle = "Page Title for Bug 503832";
+ var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug503832.html";
+ var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug503832.html#firefox";
+
+ var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
+ .getService(Ci.nsINavHistoryService);
+
+ let fragmentPromise = new Promise(resolve => {
+ /* Global history observer that triggers for the two test URLs above. */
+ var historyObserver = {
+ onBeginUpdateBatch: function() {},
+ onEndUpdateBatch: function() {},
+ onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
+ aTransitionType, _added) {},
+ onTitleChanged: function(aURI, aPageTitle) {
+ aURI = aURI.spec;
+ switch (aURI) {
+ case pageurl:
+ is(aPageTitle, pagetitle, "Correct page title for " + aURI);
+ return;
+ case fragmenturl:
+ is(aPageTitle, pagetitle, "Correct page title for " + aURI);
+ // If titles for fragment URLs aren't set, this code
+ // branch won't be called and the test will timeout,
+ // resulting in a failure
+ historyService.removeObserver(historyObserver, false);
+ resolve();
+ }
+ },
+ onDeleteURI: function(aURI) {},
+ onClearHistory: function() {},
+ onPageChanged: function(aURI, aWhat, aValue) {},
+ onDeleteVisits: function () {},
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsINavHistoryObserver) ||
+ iid.equals(Ci.nsISupports)) {
+ return this;
+ }
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ };
+
+ historyService.addObserver(historyObserver, false);
+ });
+
+ /* Queries nsINavHistoryService and returns a single history entry
+ * for a given URI */
+ function getNavHistoryEntry(aURI) {
+ var options = historyService.getNewQueryOptions();
+ options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
+ options.maxResults = 1;
+
+ var query = historyService.getNewQuery();
+ query.uri = aURI;
+
+ var result = historyService.executeQuery(query, options);
+ result.root.containerOpen = true;
+
+ if (!result.root.childCount) {
+ return null;
+ }
+ var node = result.root.getChild(0);
+ result.root.containerOpen = false;
+ return node;
+ }
+
+ // Make sure neither of the test pages haven't been loaded before.
+ var info = getNavHistoryEntry(makeURI(pageurl));
+ ok(!info, "The test page must not have been visited already.");
+ info = getNavHistoryEntry(makeURI(fragmenturl));
+ ok(!info, "The fragment test page must not have been visited already.");
+
+ // Now open the test page in a new tab
+ yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageurl);
+
+ // Now that the page is loaded, click on fragment link
+ yield BrowserTestUtils.synthesizeMouseAtCenter("#firefox-link", {},
+ gBrowser.selectedBrowser);
+ yield fragmentPromise;
+
+ gBrowser.removeCurrentTab();
+});
diff --git a/docshell/test/browser/browser_bug554155.js b/docshell/test/browser/browser_bug554155.js
new file mode 100644
index 0000000000..efc74a1c16
--- /dev/null
+++ b/docshell/test/browser/browser_bug554155.js
@@ -0,0 +1,26 @@
+add_task(function* test() {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" }, function* (browser) {
+ let numLocationChanges = 0;
+
+ let listener = {
+ onLocationChange: function(browser, webProgress, request, uri, flags) {
+ info("location change: " + (uri && uri.spec));
+ numLocationChanges++;
+ }
+ };
+
+ gBrowser.addTabsProgressListener(listener);
+
+ yield ContentTask.spawn(browser, null, function() {
+ // pushState to a new URL (http://example.com/foo"). This should trigger
+ // exactly one LocationChange event.
+ content.history.pushState(null, null, "foo");
+ });
+
+ yield Promise.resolve();
+
+ gBrowser.removeTabsProgressListener(listener);
+ is(numLocationChanges, 1,
+ "pushState should cause exactly one LocationChange event.");
+ });
+});
diff --git a/docshell/test/browser/browser_bug655270.js b/docshell/test/browser/browser_bug655270.js
new file mode 100644
index 0000000000..275245df82
--- /dev/null
+++ b/docshell/test/browser/browser_bug655270.js
@@ -0,0 +1,60 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test for Bug 655273
+ *
+ * Call pushState and then make sure that the favicon service associates our
+ * old favicon with the new URI.
+ */
+
+function test() {
+ const testDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ const origURL = testDir + "file_bug655270.html";
+ const newURL = origURL + '?new_page';
+
+ const faviconURL = testDir + "favicon_bug655270.ico";
+
+ waitForExplicitFinish();
+
+ let tab = gBrowser.addTab(origURL);
+
+ // The page at origURL has a <link rel='icon'>, so we should get a call into
+ // our observer below when it loads. Once we verify that we have the right
+ // favicon URI, we call pushState, which should trigger another onPageChange
+ // event, this time for the URI after pushState.
+
+ let observer = {
+ onPageChanged: function(aURI, aWhat, aValue) {
+ if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON)
+ return;
+
+ if (aURI.spec == origURL) {
+ is(aValue, faviconURL, 'FaviconURL for original URI');
+ // Ignore the promise returned here and wait for the next
+ // onPageChanged notification.
+ ContentTask.spawn(tab.linkedBrowser, null, function() {
+ content.history.pushState('', '', '?new_page');
+ });
+ }
+
+ if (aURI.spec == newURL) {
+ is(aValue, faviconURL, 'FaviconURL for new URI');
+ gBrowser.removeTab(tab);
+ PlacesUtils.history.removeObserver(this);
+ finish();
+ }
+ },
+
+ onBeginUpdateBatch: function() { },
+ onEndUpdateBatch: function() { },
+ onVisit: function() { },
+ onTitleChanged: function() { },
+ onDeleteURI: function() { },
+ onClearHistory: function() { },
+ onDeleteVisits: function() { },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
+ };
+
+ PlacesUtils.history.addObserver(observer, false);
+}
diff --git a/docshell/test/browser/browser_bug655273.js b/docshell/test/browser/browser_bug655273.js
new file mode 100644
index 0000000000..3acb6ddd55
--- /dev/null
+++ b/docshell/test/browser/browser_bug655273.js
@@ -0,0 +1,30 @@
+/* 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/. */
+
+/**
+ * Test for Bug 655273. Make sure that after changing the URI via
+ * history.pushState, the resulting SHEntry has the same title as our old
+ * SHEntry.
+ **/
+
+add_task(function* test() {
+ waitForExplicitFinish();
+
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
+ function* (browser) {
+ yield ContentTask.spawn(browser, null, function* () {
+ let cw = content;
+ let oldTitle = cw.document.title;
+ ok(oldTitle, 'Content window should initially have a title.');
+ cw.history.pushState('', '', 'new_page');
+
+ let shistory = cw.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .sessionHistory;
+
+ is(shistory.getEntryAtIndex(shistory.index, false).title,
+ oldTitle, 'SHEntry title after pushstate.');
+ });
+ });
+});
diff --git a/docshell/test/browser/browser_bug670318.js b/docshell/test/browser/browser_bug670318.js
new file mode 100644
index 0000000000..a73639cab2
--- /dev/null
+++ b/docshell/test/browser/browser_bug670318.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test for Bug 670318
+ *
+ * When LoadEntry() is called on a browser that has multiple duplicate history
+ * entries, history.index can end up out of range (>= history.count).
+ */
+
+const URL = "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html";
+
+add_task(function* test() {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
+ function* (browser) {
+ yield ContentTask.spawn(browser, URL, function* (URL) {
+ let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
+ let count = 0;
+
+ let testDone = {};
+ testDone.promise = new Promise(resolve => { testDone.resolve = resolve; });
+
+ let listener = {
+ OnHistoryNewEntry: function (aNewURI) {
+ if (aNewURI.spec == URL && 5 == ++count) {
+ addEventListener("load", function onLoad() {
+ removeEventListener("load", onLoad, true);
+
+ Assert.ok(history.index < history.count, "history.index is valid");
+ testDone.resolve();
+ }, true);
+
+ history.removeSHistoryListener(listener);
+ delete content._testListener;
+ content.setTimeout(() => { content.location.reload(); }, 0);
+ }
+
+ return true;
+ },
+
+ OnHistoryReload: () => true,
+ OnHistoryGoBack: () => true,
+ OnHistoryGoForward: () => true,
+ OnHistoryGotoIndex: () => true,
+ OnHistoryPurge: () => true,
+ OnHistoryReplaceEntry: () => {
+ // The initial load of about:blank causes a transient entry to be
+ // created, so our first navigation to a real page is a replace
+ // instead of a new entry.
+ ++count;
+ return true;
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
+ Ci.nsISupportsWeakReference])
+ };
+
+ history.addSHistoryListener(listener);
+ // Since listener implements nsISupportsWeakReference, we are
+ // responsible for keeping it alive so that the GC doesn't clear
+ // it before the test completes. We do this by anchoring the listener
+ // to the content global window, and clearing it just before the test
+ // completes.
+ content._testListener = listener;
+ content.location = URL;
+
+ yield testDone.promise;
+ });
+ });
+});
diff --git a/docshell/test/browser/browser_bug673467.js b/docshell/test/browser/browser_bug673467.js
new file mode 100644
index 0000000000..10139a48cc
--- /dev/null
+++ b/docshell/test/browser/browser_bug673467.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test for bug 673467. In a new tab, load a page which inserts a new iframe
+// before the load and then sets its location during the load. This should
+// create just one SHEntry.
+
+var doc = "data:text/html,<html><body onload='load()'>" +
+ "<script>" +
+ " var iframe = document.createElement('iframe');" +
+ " iframe.id = 'iframe';" +
+ " document.documentElement.appendChild(iframe);" +
+ " function load() {" +
+ " iframe.src = 'data:text/html,Hello!';" +
+ " }" +
+ "</script>" +
+ "</body></html>"
+
+function test() {
+ waitForExplicitFinish();
+
+ let tab = gBrowser.addTab(doc);
+ let tabBrowser = tab.linkedBrowser;
+
+ BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
+ return ContentTask.spawn(tab.linkedBrowser, null, () => {
+ return new Promise(resolve => {
+ // The main page has loaded. Now wait for the iframe to load.
+ let iframe = content.document.getElementById('iframe');
+ iframe.addEventListener('load', function listener(aEvent) {
+
+ // Wait for the iframe to load the new document, not about:blank.
+ if (!iframe.src)
+ return;
+
+ iframe.removeEventListener('load', listener, true);
+ let shistory = content
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .sessionHistory;
+
+ Assert.equal(shistory.count, 1, "shistory count should be 1.");
+ resolve();
+ }, true);
+ });
+ });
+ }).then(() => {
+ gBrowser.removeTab(tab);
+ finish();
+ });
+}
diff --git a/docshell/test/browser/browser_bug852909.js b/docshell/test/browser/browser_bug852909.js
new file mode 100644
index 0000000000..5e2374c436
--- /dev/null
+++ b/docshell/test/browser/browser_bug852909.js
@@ -0,0 +1,23 @@
+var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+
+function test() {
+ waitForExplicitFinish();
+
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug852909.png");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(image);
+}
+
+function image(event) {
+ ok(!gBrowser.selectedTab.mayEnableCharacterEncodingMenu, "Docshell should say the menu should be disabled for images.");
+
+ gBrowser.removeCurrentTab();
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug852909.pdf");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(pdf);
+}
+
+function pdf(event) {
+ ok(!gBrowser.selectedTab.mayEnableCharacterEncodingMenu, "Docshell should say the menu should be disabled for PDF.js.");
+
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/docshell/test/browser/browser_bug92473.js b/docshell/test/browser/browser_bug92473.js
new file mode 100644
index 0000000000..d1c4aebdb1
--- /dev/null
+++ b/docshell/test/browser/browser_bug92473.js
@@ -0,0 +1,54 @@
+/* The test text as octets for reference
+ * %83%86%83%6a%83%52%81%5b%83%68%82%cd%81%41%82%b7%82%d7%82%c4%82%cc%95%b6%8e%9a%82%c9%8c%c5%97%4c%82%cc%94%d4%8d%86%82%f0%95%74%97%5e%82%b5%82%dc%82%b7
+ */
+
+function testContent(text) {
+ return ContentTask.spawn(gBrowser.selectedBrowser, text, text => {
+ Assert.equal(content.document.getElementById("testpar").innerHTML, text,
+ "<p> contains expected text");
+ Assert.equal(content.document.getElementById("testtextarea").innerHTML, text,
+ "<textarea> contains expected text");
+ Assert.equal(content.document.getElementById("testinput").value, text,
+ "<input> contains expected text");
+ });
+}
+
+function afterOpen() {
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
+
+ /* The test text decoded incorrectly as Windows-1251. This is the "right" wrong
+ text; anything else is unexpected. */
+ const wrongText="\u0453\u2020\u0453\u006A\u0453\u0052\u0403\u005B\u0453\u0068\u201A\u041D\u0403\u0041\u201A\u00B7\u201A\u0427\u201A\u0414\u201A\u041C\u2022\u00B6\u040B\u0459\u201A\u0419\u040A\u0415\u2014\u004C\u201A\u041C\u201D\u0424\u040C\u2020\u201A\u0440\u2022\u0074\u2014\u005E\u201A\u00B5\u201A\u042C\u201A\u00B7";
+
+ /* Test that the content on load is the expected wrong decoding */
+ testContent(wrongText).then(() => {
+ BrowserSetForcedCharacterSet("Shift_JIS");
+ });
+}
+
+function afterChangeCharset() {
+ /* The test text decoded correctly as Shift_JIS */
+ const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059";
+
+ /* test that the content is decoded correctly */
+ testContent(rightText).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+}
+
+function test() {
+ waitForExplicitFinish();
+
+ // Get the local directory. This needs to be a file: URI because chrome: URIs
+ // are always UTF-8 (bug 617339) and we are testing decoding from other
+ // charsets.
+ var jar = getJar(getRootDirectory(gTestPath));
+ var dir = jar ?
+ extractJarToTmp(jar) :
+ getChromeDir(getResolvedURI(gTestPath));
+ var rootDir = Services.io.newFileURI(dir).spec;
+
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "test-form_sjis.html");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpen);
+}
diff --git a/docshell/test/browser/browser_loadDisallowInherit.js b/docshell/test/browser/browser_loadDisallowInherit.js
new file mode 100644
index 0000000000..71789890fc
--- /dev/null
+++ b/docshell/test/browser/browser_loadDisallowInherit.js
@@ -0,0 +1,65 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+ waitForExplicitFinish();
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab();
+ registerCleanupFunction(function () {
+ gBrowser.removeTab(tab);
+ });
+
+ let browser = gBrowser.getBrowserForTab(tab);
+
+ function loadURL(url, flags, func) {
+ browser.addEventListener("load", function loadListener(e) {
+ if (browser.currentURI.spec != url)
+ return;
+ browser.removeEventListener(e.type, loadListener, true);
+ func();
+ }, true);
+ browser.loadURIWithFlags(url, flags, null, null, null);
+ }
+
+ // Load a normal http URL
+ function testURL(url, func) {
+ loadURL("http://example.com/", 0, function () {
+ let pagePrincipal = browser.contentPrincipal;
+ ok(pagePrincipal, "got principal for http:// page");
+
+ // Now load the URL normally
+ loadURL(url, 0, function () {
+ ok(browser.contentPrincipal.equals(pagePrincipal), url + " should inherit principal");
+
+ // Now load the URL and disallow inheriting the principal
+ let webNav = Components.interfaces.nsIWebNavigation;
+ loadURL(url, webNav.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, function () {
+ let newPrincipal = browser.contentPrincipal;
+ ok(newPrincipal, "got inner principal");
+ ok(!newPrincipal.equals(pagePrincipal),
+ url + " should not inherit principal when loaded with DISALLOW_INHERIT_OWNER");
+
+ func();
+ });
+ });
+ });
+ }
+
+ let urls = [
+ "data:text/html,<body>hi",
+ // We used to test javascript: here as well, but now that we no longer run
+ // javascript: in a sandbox, we end up not running it at all in the
+ // DISALLOW_INHERIT_OWNER case, so never actually do a load for it at all.
+ ];
+
+ function nextTest() {
+ let url = urls.shift();
+ if (url)
+ testURL(url, nextTest);
+ else
+ finish();
+ }
+
+ nextTest();
+}
+
diff --git a/docshell/test/browser/browser_loadURI.js b/docshell/test/browser/browser_loadURI.js
new file mode 100644
index 0000000000..a68e1c2de6
--- /dev/null
+++ b/docshell/test/browser/browser_loadURI.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+
+const gPostData = "postdata=true";
+
+function test() {
+ waitForExplicitFinish();
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab();
+ registerCleanupFunction(function () {
+ gBrowser.removeTab(tab);
+ });
+
+ var dataStream = Cc["@mozilla.org/io/string-input-stream;1"].
+ createInstance(Ci.nsIStringInputStream);
+ dataStream.data = gPostData;
+
+ var postStream = Cc["@mozilla.org/network/mime-input-stream;1"].
+ createInstance(Ci.nsIMIMEInputStream);
+ postStream.addHeader("Content-Type", "application/x-www-form-urlencoded");
+ postStream.addContentLength = true;
+ postStream.setData(dataStream);
+
+ tab.linkedBrowser.loadURIWithFlags("http://mochi.test:8888/browser/docshell/test/browser/print_postdata.sjs", 0, null, null, postStream);
+ BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
+ ContentTask.spawn(tab.linkedBrowser, gPostData, function(postData) {
+ var bodyText = content.document.body.textContent;
+ is(bodyText, postData, "post data was submitted correctly");
+ }).then(() => { finish(); });
+ });
+}
diff --git a/docshell/test/browser/browser_multiple_pushState.js b/docshell/test/browser/browser_multiple_pushState.js
new file mode 100644
index 0000000000..5c2f5aef4f
--- /dev/null
+++ b/docshell/test/browser/browser_multiple_pushState.js
@@ -0,0 +1,15 @@
+add_task(function* test_multiple_pushState() {
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: "http://example.org/browser/docshell/test/browser/file_multiple_pushState.html",
+ }, function* (browser) {
+ const kExpected = "http://example.org/bar/ABC/DEF?key=baz";
+
+ let contentLocation = yield ContentTask.spawn(browser, null, function* () {
+ return content.document.location.href;
+ });
+
+ is(contentLocation, kExpected);
+ is(browser.documentURI.spec, kExpected);
+ });
+});
diff --git a/docshell/test/browser/browser_onbeforeunload_navigation.js b/docshell/test/browser/browser_onbeforeunload_navigation.js
new file mode 100644
index 0000000000..d2feb69d4a
--- /dev/null
+++ b/docshell/test/browser/browser_onbeforeunload_navigation.js
@@ -0,0 +1,176 @@
+var contentWindow;
+var originalLocation;
+var currentTest = -1;
+var stayingOnPage = true;
+
+var TEST_PAGE = "http://mochi.test:8888/browser/docshell/test/browser/file_bug1046022.html";
+var TARGETED_PAGE = "data:text/html," + encodeURIComponent("<body>Shouldn't be seeing this</body>");
+
+SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
+
+var loadExpected = TEST_PAGE;
+var testTab;
+var testsLength;
+
+var loadStarted = false;
+var tabStateListener = {
+ onStateChange: function(webprogress, request, stateFlags, status) {
+ let startDocumentFlags = Ci.nsIWebProgressListener.STATE_START |
+ Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
+ if ((stateFlags & startDocumentFlags) == startDocumentFlags) {
+ loadStarted = true;
+ }
+ },
+ onStatusChange: () => {},
+ onLocationChange: () => {},
+ onSecurityChange: () => {},
+ onProgressChange: () => {},
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener])
+};
+
+function onTabLoaded(event) {
+ info("A document loaded in a tab!");
+ let loadedPage = event.target.location.href;
+ if (loadedPage == "about:blank" ||
+ event.originalTarget != testTab.linkedBrowser.contentDocument) {
+ return;
+ }
+
+ if (!loadExpected) {
+ ok(false, "Expected no page loads, but loaded " + loadedPage + " instead!");
+ return;
+ }
+
+ if (!testsLength) {
+ testsLength = testTab.linkedBrowser.contentWindow.wrappedJSObject.testFns.length;
+ }
+
+ is(loadedPage, loadExpected, "Loaded the expected page");
+ if (contentWindow) {
+ is(contentWindow.document, event.target, "Same doc");
+ }
+ if (onAfterPageLoad) {
+ onAfterPageLoad();
+ }
+}
+
+function onAfterTargetedPageLoad() {
+ ok(!stayingOnPage, "We should only fire if we're expecting to let the onbeforeunload dialog proceed to the new location");
+ is(testTab.linkedBrowser.currentURI.spec, TARGETED_PAGE, "Should have loaded the expected new page");
+
+ runNextTest();
+}
+
+function onTabModalDialogLoaded(node) {
+ let content = testTab.linkedBrowser.contentWindow;
+ ok(!loadStarted, "No load should be started.");
+ info(content.location.href);
+ is(content, contentWindow, "Window should be the same still.");
+ is(content.location.href, originalLocation, "Page should not have changed.");
+ is(content.mySuperSpecialMark, 42, "Page should not have refreshed.");
+
+ ok(!content.dialogWasInvoked, "Dialog should only be invoked once per test.");
+ content.dialogWasInvoked = true;
+
+
+ // Now listen for the dialog going away again...
+ let observer = new MutationObserver(function(muts) {
+ if (!node.parentNode) {
+ info("Dialog is gone");
+ observer.disconnect();
+ observer = null;
+ // If we're staying on the page, run the next test from here
+ if (stayingOnPage) {
+ // Evil, but necessary: without this delay, we manage to still break our
+ // own onbeforeunload code, because we'll basically cause a new load to be
+ // started while processing the destruction of the dialog for the old one.
+ executeSoon(runNextTest);
+ }
+ // if we accepted a page load in the dialog, the next test will get started
+ // by the load handler for that page loading
+ }
+ });
+ observer.observe(node.parentNode, {childList: true});
+
+ // If we're going to let the page load, set us up to listen for that happening:
+ if (!stayingOnPage) {
+ loadExpected = TARGETED_PAGE;
+ onAfterPageLoad = onAfterTargetedPageLoad;
+ }
+
+ let button = stayingOnPage ? node.ui.button1 : node.ui.button0;
+ // ... and then actually make the dialog go away
+ info("Clicking button: " + button.label);
+ EventUtils.synthesizeMouseAtCenter(button, {});
+}
+
+// Listen for the dialog being created
+Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
+
+function runNextTest() {
+ currentTest++;
+ if (currentTest >= testsLength) {
+ if (!stayingOnPage) {
+ finish();
+ return;
+ }
+ // Run the same tests again, but this time let the navigation happen:
+ stayingOnPage = false;
+ // Remove onbeforeunload handler, or this load will trigger the dialog...
+ contentWindow.onbeforeunload = null;
+ currentTest = 0;
+ }
+
+
+ if (!stayingOnPage) {
+ // Right now we're on the data: page. Null contentWindow out to
+ // avoid CPOW errors when contentWindow is no longer the correct
+ // outer window proxy object.
+ contentWindow = null;
+
+ onAfterPageLoad = runCurrentTest;
+ loadExpected = TEST_PAGE;
+ testTab.linkedBrowser.loadURI(TEST_PAGE);
+ } else {
+ runCurrentTest();
+ }
+}
+
+function runCurrentTest() {
+ // Reset things so we're sure the previous tests failings don't influence this one:
+ contentWindow = testTab.linkedBrowser.contentWindow;
+ contentWindow.mySuperSpecialMark = 42;
+ contentWindow.dialogWasInvoked = false;
+ originalLocation = contentWindow.location.href;
+ // And run this test:
+ info("Running test with onbeforeunload " + contentWindow.wrappedJSObject.testFns[currentTest].toSource());
+ contentWindow.onbeforeunload = contentWindow.wrappedJSObject.testFns[currentTest];
+ loadStarted = false;
+ testTab.linkedBrowser.loadURI(TARGETED_PAGE);
+}
+
+var onAfterPageLoad = runNextTest;
+
+function test() {
+ waitForExplicitFinish();
+ gBrowser.addProgressListener(tabStateListener);
+
+ testTab = gBrowser.selectedTab = gBrowser.addTab();
+ testTab.linkedBrowser.addEventListener("load", onTabLoaded, true);
+ testTab.linkedBrowser.loadURI(TEST_PAGE);
+}
+
+registerCleanupFunction(function() {
+ // Remove the handler, or closing this tab will prove tricky:
+ if (contentWindow) {
+ try {
+ contentWindow.onbeforeunload = null;
+ } catch (ex) {}
+ }
+ contentWindow = null;
+ testTab.linkedBrowser.removeEventListener("load", onTabLoaded, true);
+ Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
+ gBrowser.removeProgressListener(tabStateListener);
+ gBrowser.removeTab(testTab);
+});
+
diff --git a/docshell/test/browser/browser_search_notification.js b/docshell/test/browser/browser_search_notification.js
new file mode 100644
index 0000000000..b0a4571e58
--- /dev/null
+++ b/docshell/test/browser/browser_search_notification.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+ waitForExplicitFinish();
+
+ const kSearchEngineID = "test_urifixup_search_engine";
+ const kSearchEngineURL = "http://localhost/?search={searchTerms}";
+ Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
+ kSearchEngineURL);
+
+ let oldDefaultEngine = Services.search.defaultEngine;
+ Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+
+ let selectedName = Services.search.defaultEngine.name;
+ is(selectedName, kSearchEngineID, "Check fake search engine is selected");
+
+ registerCleanupFunction(function() {
+ if (oldDefaultEngine) {
+ Services.search.defaultEngine = oldDefaultEngine;
+ }
+ let engine = Services.search.getEngineByName(kSearchEngineID);
+ if (engine) {
+ Services.search.removeEngine(engine);
+ }
+ });
+
+ let tab = gBrowser.addTab();
+ gBrowser.selectedTab = tab;
+
+ function observer(subject, topic, data) {
+ Services.obs.removeObserver(observer, "keyword-search");
+ is(topic, "keyword-search", "Got keyword-search notification");
+
+ let engine = Services.search.defaultEngine;
+ ok(engine, "Have default search engine.");
+ is(engine, subject, "Notification subject is engine.");
+ is("firefox health report", data, "Notification data is search term.");
+
+ executeSoon(function cleanup() {
+ gBrowser.removeTab(tab);
+ finish();
+ });
+ }
+
+ Services.obs.addObserver(observer, "keyword-search", false);
+
+ gURLBar.value = "firefox health report";
+ gURLBar.handleCommand();
+}
+
diff --git a/docshell/test/browser/browser_tab_touch_events.js b/docshell/test/browser/browser_tab_touch_events.js
new file mode 100644
index 0000000000..615983f616
--- /dev/null
+++ b/docshell/test/browser/browser_tab_touch_events.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(function*() {
+ const URI = "data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>";
+
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: URI }, function* (browser) {
+ yield ContentTask.spawn(browser, null, test_body);
+ });
+});
+
+function* test_body() {
+ let docshell = docShell;
+
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_NONE,
+ "touchEventsOverride flag should be initially set to NONE");
+
+ docshell.touchEventsOverride = Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED;
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "touchEventsOverride flag should be changed to DISABLED");
+
+ let frameWin = content.document.querySelector("#test-iframe").contentWindow;
+ docshell = frameWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "touchEventsOverride flag should be passed on to frames.");
+
+ let newFrame = content.document.createElement("iframe");
+ content.document.body.appendChild(newFrame);
+
+ let newFrameWin = newFrame.contentWindow;
+ docshell = newFrameWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "Newly created frames should use the new touchEventsOverride flag");
+
+ newFrameWin.location.reload();
+ yield ContentTaskUtils.waitForEvent(newFrameWin, "load");
+
+ docshell = newFrameWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "New touchEventsOverride flag should persist across reloads");
+}
diff --git a/docshell/test/browser/browser_timelineMarkers-01.js b/docshell/test/browser/browser_timelineMarkers-01.js
new file mode 100644
index 0000000000..59eeb57dbd
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-01.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell has the right profile timeline API
+
+const URL = "data:text/html;charset=utf-8,Test page";
+
+add_task(function* () {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: URL },
+ function* (browser) {
+ yield ContentTask.spawn(browser, null, function() {
+ ok("recordProfileTimelineMarkers" in docShell,
+ "The recordProfileTimelineMarkers attribute exists");
+ ok("popProfileTimelineMarkers" in docShell,
+ "The popProfileTimelineMarkers function exists");
+ ok(docShell.recordProfileTimelineMarkers === false,
+ "recordProfileTimelineMarkers is false by default");
+ ok(docShell.popProfileTimelineMarkers().length === 0,
+ "There are no markers by default");
+
+ docShell.recordProfileTimelineMarkers = true;
+ ok(docShell.recordProfileTimelineMarkers === true,
+ "recordProfileTimelineMarkers can be set to true");
+
+ docShell.recordProfileTimelineMarkers = false;
+ ok(docShell.recordProfileTimelineMarkers === false,
+ "recordProfileTimelineMarkers can be set to false");
+ });
+ });
+});
diff --git a/docshell/test/browser/browser_timelineMarkers-02.js b/docshell/test/browser/browser_timelineMarkers-02.js
new file mode 100644
index 0000000000..34142760ed
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-02.js
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var URL = '<!DOCTYPE html><style>' +
+ 'body {margin:0; padding: 0;} ' +
+ 'div {width:100px;height:100px;background:red;} ' +
+ '.resize-change-color {width:50px;height:50px;background:blue;} ' +
+ '.change-color {width:50px;height:50px;background:yellow;} ' +
+ '.add-class {}' +
+ '</style><div></div>';
+URL = "data:text/html;charset=utf8," + encodeURIComponent(URL);
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-02.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-03.js b/docshell/test/browser/browser_timelineMarkers-03.js
new file mode 100644
index 0000000000..b104367c10
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-03.js
@@ -0,0 +1,8 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var URL = "data:text/html;charset=utf-8,<p>Test page</p>";
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-03.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-04.js b/docshell/test/browser/browser_timelineMarkers-04.js
new file mode 100644
index 0000000000..fdee867e7b
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-04.js
@@ -0,0 +1,8 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const URL = "http://mochi.test:8888/browser/docshell/test/browser/timelineMarkers-04.html";
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-04.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-05.js b/docshell/test/browser/browser_timelineMarkers-05.js
new file mode 100644
index 0000000000..0130c58d97
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-05.js
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var URL = '<!DOCTYPE html><style>' +
+ 'body {margin:0; padding: 0;} ' +
+ 'div {width:100px;height:100px;background:red;} ' +
+ '.resize-change-color {width:50px;height:50px;background:blue;} ' +
+ '.change-color {width:50px;height:50px;background:yellow;} ' +
+ '.add-class {}' +
+ '</style><div></div>';
+URL = "data:text/html;charset=utf8," + encodeURIComponent(URL);
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-05.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-02.js b/docshell/test/browser/browser_timelineMarkers-frame-02.js
new file mode 100644
index 0000000000..83750395d8
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-02.js
@@ -0,0 +1,133 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell profile timeline API returns the right markers when
+// restyles, reflows and paints occur
+
+function rectangleContains(rect, x, y, width, height) {
+ return rect.x <= x && rect.y <= y && rect.width >= width &&
+ rect.height >= height;
+}
+
+function sanitizeMarkers(list) {
+ // These markers are currently gathered from all docshells, which may
+ // interfere with this test.
+ return list.filter(e => e.name != "Worker" && e.name != "MinorGC");
+}
+
+var TESTS = [{
+ desc: "Changing the width of the test element",
+ searchFor: "Paint",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ div.setAttribute("class", "resize-change-color");
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ ok(markers.length > 0, "markers were returned");
+ console.log(markers);
+ info(JSON.stringify(markers.filter(m => m.name == "Paint")));
+ ok(markers.some(m => m.name == "Reflow"), "markers includes Reflow");
+ ok(markers.some(m => m.name == "Paint"), "markers includes Paint");
+ for (let marker of markers.filter(m => m.name == "Paint")) {
+ // This change should generate at least one rectangle.
+ ok(marker.rectangles.length >= 1, "marker has one rectangle");
+ // One of the rectangles should contain the div.
+ ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 100, 100)));
+ }
+ ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
+ }
+}, {
+ desc: "Changing the test element's background color",
+ searchFor: "Paint",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ div.setAttribute("class", "change-color");
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ ok(markers.length > 0, "markers were returned");
+ ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow");
+ ok(markers.some(m => m.name == "Paint"), "markers includes Paint");
+ for (let marker of markers.filter(m => m.name == "Paint")) {
+ // This change should generate at least one rectangle.
+ ok(marker.rectangles.length >= 1, "marker has one rectangle");
+ // One of the rectangles should contain the div.
+ ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 50, 50)));
+ }
+ ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
+ }
+}, {
+ desc: "Changing the test element's classname",
+ searchFor: "Paint",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ div.setAttribute("class", "change-color add-class");
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ ok(markers.length > 0, "markers were returned");
+ ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow");
+ ok(!markers.some(m => m.name == "Paint"), "markers doesn't include Paint");
+ ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
+ }
+}, {
+ desc: "sync console.time/timeEnd",
+ searchFor: "ConsoleTime",
+ setup: function(docShell) {
+ content.console.time("FOOBAR");
+ content.console.timeEnd("FOOBAR");
+ let markers = docShell.popProfileTimelineMarkers();
+ is(markers.length, 1, "Got one marker");
+ is(markers[0].name, "ConsoleTime", "Got ConsoleTime marker");
+ is(markers[0].causeName, "FOOBAR", "Got ConsoleTime FOOBAR detail");
+ content.console.time("FOO");
+ content.setTimeout(() => {
+ content.console.time("BAR");
+ content.setTimeout(() => {
+ content.console.timeEnd("FOO");
+ content.console.timeEnd("BAR");
+ }, 100);
+ }, 100);
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ is(markers.length, 2, "Got 2 markers");
+ is(markers[0].name, "ConsoleTime", "Got first ConsoleTime marker");
+ is(markers[0].causeName, "FOO", "Got ConsoleTime FOO detail");
+ is(markers[1].name, "ConsoleTime", "Got second ConsoleTime marker");
+ is(markers[1].causeName, "BAR", "Got ConsoleTime BAR detail");
+ }
+}, {
+ desc: "Timestamps created by console.timeStamp()",
+ searchFor: "Timestamp",
+ setup: function(docshell) {
+ content.console.timeStamp("rock");
+ let markers = docShell.popProfileTimelineMarkers();
+ is(markers.length, 1, "Got one marker");
+ is(markers[0].name, "TimeStamp", "Got Timestamp marker");
+ is(markers[0].causeName, "rock", "Got Timestamp label value");
+ content.console.timeStamp("paper");
+ content.console.timeStamp("scissors");
+ content.console.timeStamp();
+ content.console.timeStamp(undefined);
+ },
+ check: function (markers) {
+ markers = sanitizeMarkers(markers);
+ is(markers.length, 4, "Got 4 markers");
+ is(markers[0].name, "TimeStamp", "Got Timestamp marker");
+ is(markers[0].causeName, "paper", "Got Timestamp label value");
+ is(markers[1].name, "TimeStamp", "Got Timestamp marker");
+ is(markers[1].causeName, "scissors", "Got Timestamp label value");
+ is(markers[2].name, "TimeStamp", "Got empty Timestamp marker when no argument given");
+ is(markers[2].causeName, void 0, "Got empty Timestamp label value");
+ is(markers[3].name, "TimeStamp", "Got empty Timestamp marker when argument is undefined");
+ is(markers[3].causeName, void 0, "Got empty Timestamp label value");
+ markers.forEach(m => is(m.end, m.start,
+ "All Timestamp markers should have identical start/end times"));
+ }
+}];
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-03.js b/docshell/test/browser/browser_timelineMarkers-frame-03.js
new file mode 100644
index 0000000000..cf5f150ad8
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-03.js
@@ -0,0 +1,91 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell profile timeline API returns the right
+// markers for DOM events.
+
+var TESTS = [{
+ desc: "Event dispatch with single handler",
+ searchFor: 'DOMEvent',
+ setup: function(docShell) {
+ content.document.body.addEventListener("dog",
+ function(e) { console.log("hi"); },
+ true);
+ content.document.body.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 1, "Got 1 marker");
+ is(markers[0].type, "dog", "Got dog event name");
+ is(markers[0].eventPhase, 2, "Got phase 2");
+ }
+}, {
+ desc: "Event dispatch with a second handler",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ content.document.body.addEventListener("dog",
+ function(e) { console.log("hi"); },
+ false);
+ content.document.body.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 2, "Got 2 markers");
+ }
+}, {
+ desc: "Event targeted at child",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ let child = content.document.body.firstElementChild;
+ child.addEventListener("dog", function(e) { });
+ child.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 2, "Got 2 markers");
+ is(markers[0].eventPhase, 1, "Got phase 1 marker");
+ is(markers[1].eventPhase, 2, "Got phase 2 marker");
+ }
+}, {
+ desc: "Event dispatch on a new document",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ let doc = content.document.implementation.createHTMLDocument("doc");
+ let p = doc.createElement("p");
+ p.innerHTML = "inside";
+ doc.body.appendChild(p);
+
+ p.addEventListener("zebra", function(e) {console.log("hi");});
+ p.dispatchEvent(new content.Event("zebra"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 1, "Got 1 marker");
+ }
+}, {
+ desc: "Event dispatch on window",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ let doc = content.window.addEventListener("aardvark", function(e) {
+ console.log("I like ants!");
+ });
+
+ content.window.dispatchEvent(new content.Event("aardvark"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 1, "Got 1 marker");
+ }
+}];
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-04.js b/docshell/test/browser/browser_timelineMarkers-frame-04.js
new file mode 100644
index 0000000000..427312993f
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-04.js
@@ -0,0 +1,88 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell profile timeline API returns the right
+// markers for XMLHttpRequest events.
+
+var TESTS = [{
+ desc: "Event dispatch from XMLHttpRequest",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == "DOMEvent").length >= 5;
+ },
+ setup: function(docShell) {
+ content.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ let domMarkers = markers.filter(m => m.name == "DOMEvent");
+ // One subtlety here is that we have five events: the event we
+ // inject in "setup", plus the four state transition events. The
+ // first state transition is reported synchronously and so should
+ // show up as a nested marker.
+ is(domMarkers.length, 5, "Got 5 markers");
+
+ // We should see some Javascript markers, and they should have a
+ // cause.
+ let jsMarkers = markers.filter(m => m.name == "Javascript" && m.causeName);
+ ok(jsMarkers.length > 0, "Got some Javascript markers");
+ is(jsMarkers[0].stack.functionDisplayName, "do_xhr",
+ "Javascript marker has entry point name");
+ }
+}];
+
+if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
+ TESTS.push({
+ desc: "Async stack trace on Javascript marker",
+ searchFor: (markers) => {
+ return markers.some(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ },
+ setup: function(docShell) {
+ content.dispatchEvent(new content.Event("promisetest"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ ok(markers.length > 0, "Found a Javascript marker");
+
+ let frame = markers[0].stack;
+ ok(frame.asyncParent !== null, "Parent frame has async parent");
+ is(frame.asyncParent.asyncCause, "promise callback",
+ "Async parent has correct cause");
+ let asyncFrame = frame.asyncParent;
+ // Skip over self-hosted parts of our Promise implementation.
+ while (asyncFrame.source === 'self-hosted')
+ asyncFrame = asyncFrame.parent;
+ is(asyncFrame.functionDisplayName, "do_promise",
+ "Async parent has correct function name");
+ }
+ }, {
+ desc: "Async stack trace on Javascript marker with script",
+ searchFor: (markers) => {
+ return markers.some(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ },
+ setup: function(docShell) {
+ content.dispatchEvent(new content.Event("promisescript"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ ok(markers.length > 0, "Found a Javascript marker");
+
+ let frame = markers[0].stack;
+ ok(frame.asyncParent !== null, "Parent frame has async parent");
+ is(frame.asyncParent.asyncCause, "promise callback",
+ "Async parent has correct cause");
+ let asyncFrame = frame.asyncParent;
+ // Skip over self-hosted parts of our Promise implementation.
+ while (asyncFrame.source === 'self-hosted')
+ asyncFrame = asyncFrame.parent;
+ is(asyncFrame.functionDisplayName, "do_promise_script",
+ "Async parent has correct function name");
+ }
+ });
+}
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-05.js b/docshell/test/browser/browser_timelineMarkers-frame-05.js
new file mode 100644
index 0000000000..713f0e5604
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-05.js
@@ -0,0 +1,117 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function forceSyncReflow(div) {
+ div.setAttribute('class', 'resize-change-color');
+ // Force a reflow.
+ return div.offsetWidth;
+}
+
+function testSendingEvent() {
+ content.document.body.dispatchEvent(new content.Event("dog"));
+}
+
+function testConsoleTime() {
+ content.console.time("cats");
+}
+
+function testConsoleTimeEnd() {
+ content.console.timeEnd("cats");
+}
+
+function makePromise() {
+ let resolver;
+ new Promise(function(resolve, reject) {
+ testConsoleTime();
+ resolver = resolve;
+ }).then(function(val) {
+ testConsoleTimeEnd();
+ });
+ return resolver;
+}
+
+function resolvePromise(resolver) {
+ resolver(23);
+}
+
+var TESTS = [{
+ desc: "Stack trace on sync reflow",
+ searchFor: "Reflow",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ forceSyncReflow(div);
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "Reflow");
+ ok(markers.length > 0, "Reflow marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "forceSyncReflow");
+ }
+}, {
+ desc: "Stack trace on DOM event",
+ searchFor: "DOMEvent",
+ setup: function(docShell) {
+ content.document.body.addEventListener("dog",
+ function(e) { console.log("hi"); },
+ true);
+ testSendingEvent();
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "DOMEvent");
+ ok(markers.length > 0, "DOMEvent marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "testSendingEvent",
+ "testSendingEvent is on the stack");
+ }
+}, {
+ desc: "Stack trace on console event",
+ searchFor: "ConsoleTime",
+ setup: function(docShell) {
+ testConsoleTime();
+ testConsoleTimeEnd();
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "ConsoleTime");
+ ok(markers.length > 0, "ConsoleTime marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "testConsoleTime",
+ "testConsoleTime is on the stack");
+ ok(markers[0].endStack.functionDisplayName == "testConsoleTimeEnd",
+ "testConsoleTimeEnd is on the stack");
+ }
+}];
+
+if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
+ TESTS.push({
+ desc: "Async stack trace on Promise",
+ searchFor: "ConsoleTime",
+ setup: function(docShell) {
+ let resolver = makePromise();
+ resolvePromise(resolver);
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "ConsoleTime");
+ ok(markers.length > 0, "Promise marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "testConsoleTime",
+ "testConsoleTime is on the stack");
+ let frame = markers[0].endStack;
+ ok(frame.functionDisplayName == "testConsoleTimeEnd",
+ "testConsoleTimeEnd is on the stack");
+
+ frame = frame.parent;
+ ok(frame.functionDisplayName == "makePromise/<",
+ "makePromise/< is on the stack");
+ let asyncFrame = frame.asyncParent;
+ ok(asyncFrame !== null, "Frame has async parent");
+ is(asyncFrame.asyncCause, "promise callback",
+ "Async parent has correct cause");
+ // Skip over self-hosted parts of our Promise implementation.
+ while (asyncFrame.source === 'self-hosted') {
+ asyncFrame = asyncFrame.parent;
+ }
+ is(asyncFrame.functionDisplayName, "makePromise",
+ "Async parent has correct function name");
+ }
+ });
+}
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_ua_emulation.js b/docshell/test/browser/browser_ua_emulation.js
new file mode 100644
index 0000000000..94a602d4b2
--- /dev/null
+++ b/docshell/test/browser/browser_ua_emulation.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const URL = "data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>";
+
+// Test that the docShell UA emulation works
+function* contentTask() {
+ let docshell = docShell;
+ is(docshell.customUserAgent, "", "There should initially be no customUserAgent");
+
+ docshell.customUserAgent = "foo";
+ is(content.navigator.userAgent, "foo", "The user agent should be changed to foo");
+
+ let frameWin = content.document.querySelector("#test-iframe").contentWindow;
+ is(frameWin.navigator.userAgent, "foo", "The UA should be passed on to frames.");
+
+ let newFrame = content.document.createElement("iframe");
+ content.document.body.appendChild(newFrame);
+
+ let newFrameWin = newFrame.contentWindow;
+ is(newFrameWin.navigator.userAgent, "foo", "Newly created frames should use the new UA");
+
+ newFrameWin.location.reload();
+ yield ContentTaskUtils.waitForEvent(newFrameWin, "load");
+
+ is(newFrameWin.navigator.userAgent, "foo", "New UA should persist across reloads");
+}
+
+add_task(function* () {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: URL },
+ function* (browser) {
+ yield ContentTask.spawn(browser, null, contentTask);
+ });
+});
diff --git a/docshell/test/browser/browser_uriFixupAlternateRedirects.js b/docshell/test/browser/browser_uriFixupAlternateRedirects.js
new file mode 100644
index 0000000000..f5a00a2df3
--- /dev/null
+++ b/docshell/test/browser/browser_uriFixupAlternateRedirects.js
@@ -0,0 +1,24 @@
+"use strict";
+
+const REDIRECTURL = "http://www.example.com/browser/docshell/test/browser/redirect_to_example.sjs"
+
+add_task(function* () {
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+ gURLBar.value = REDIRECTURL;
+ gURLBar.select();
+ let errorPageLoaded = BrowserTestUtils.waitForErrorPage(tab.linkedBrowser);
+ EventUtils.sendKey("return");
+ yield errorPageLoaded;
+ let [contentURL, originalURL] = yield ContentTask.spawn(tab.linkedBrowser, null, () => {
+ return [
+ content.document.documentURI,
+ content.document.mozDocumentURIIfNotForErrorPages.spec,
+ ];
+ });
+ info("Page that loaded: " + contentURL);
+ ok(contentURL.startsWith("about:neterror?"), "Should be on an error page");
+ originalURL = new URL(originalURL);
+ is(originalURL.host, "example", "Should be an error for http://example, not http://www.example.com/");
+
+ yield BrowserTestUtils.removeTab(tab);
+});
diff --git a/docshell/test/browser/browser_uriFixupIntegration.js b/docshell/test/browser/browser_uriFixupIntegration.js
new file mode 100644
index 0000000000..e041e1f67a
--- /dev/null
+++ b/docshell/test/browser/browser_uriFixupIntegration.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const kSearchEngineID = "browser_urifixup_search_engine";
+const kSearchEngineURL = "http://example.com/?search={searchTerms}";
+
+add_task(function* setup() {
+ // Add a new fake search engine.
+ Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
+ kSearchEngineURL);
+
+ let oldDefaultEngine = Services.search.defaultEngine;
+ Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+
+ // Remove the fake engine when done.
+ registerCleanupFunction(() => {
+ if (oldDefaultEngine) {
+ Services.search.defaultEngine = oldDefaultEngine;
+ }
+
+ let engine = Services.search.getEngineByName(kSearchEngineID);
+ if (engine) {
+ Services.search.removeEngine(engine);
+ }
+ });
+});
+
+add_task(function* test() {
+ for (let searchParams of ["foo bar", "brokenprotocol:somethingelse"]) {
+ // Add a new blank tab.
+ gBrowser.selectedTab = gBrowser.addTab("about:blank");
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+
+ // Enter search terms and start a search.
+ gURLBar.value = searchParams;
+ gURLBar.focus();
+ EventUtils.synthesizeKey("VK_RETURN", {});
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+
+ // Check that we arrived at the correct URL.
+ let escapedParams = encodeURIComponent(searchParams).replace("%20", "+");
+ let expectedURL = kSearchEngineURL.replace("{searchTerms}", escapedParams);
+ is(gBrowser.selectedBrowser.currentURI.spec, expectedURL,
+ "New tab should have loaded with expected url.");
+
+ // Cleanup.
+ gBrowser.removeCurrentTab();
+ }
+});
diff --git a/docshell/test/browser/favicon_bug655270.ico b/docshell/test/browser/favicon_bug655270.ico
new file mode 100644
index 0000000000..d44438903b
--- /dev/null
+++ b/docshell/test/browser/favicon_bug655270.ico
Binary files differ
diff --git a/docshell/test/browser/file_bug1046022.html b/docshell/test/browser/file_bug1046022.html
new file mode 100644
index 0000000000..2de68cb43a
--- /dev/null
+++ b/docshell/test/browser/file_bug1046022.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Bug 1046022 - test navigating inside onbeforeunload</title>
+ </head>
+ <body>
+ Waiting for onbeforeunload to hit...
+ </body>
+
+ <script>
+var testFns = [
+ function(e) {
+ e.target.location.href = 'otherpage-href-set.html';
+ return "stop";
+ },
+ function(e) {
+ e.target.location.reload();
+ return "stop";
+ },
+ function(e) {
+ e.target.location.replace('otherpage-location-replaced.html');
+ return "stop";
+ },
+ function(e) {
+ var link = e.target.createElement('a');
+ link.href = "otherpage.html";
+ e.target.body.appendChild(link);
+ link.click();
+ return "stop";
+ },
+ function(e) {
+ var link = e.target.createElement('a');
+ link.href = "otherpage.html";
+ link.setAttribute("target", "_blank");
+ e.target.body.appendChild(link);
+ link.click();
+ return "stop";
+ },
+ function(e) {
+ var link = e.target.createElement('a');
+ link.href = e.target.location.href;
+ e.target.body.appendChild(link);
+ link.setAttribute("target", "somearbitrarywindow");
+ link.click();
+ return "stop";
+ },
+];
+ </script>
+</html>
diff --git a/docshell/test/browser/file_bug1206879.html b/docshell/test/browser/file_bug1206879.html
new file mode 100644
index 0000000000..5313902a9b
--- /dev/null
+++ b/docshell/test/browser/file_bug1206879.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test page for bug 1206879</title>
+ </head>
+ <body>
+ <iframe src="http://example.com/"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/browser/file_bug234628-1-child.html b/docshell/test/browser/file_bug234628-1-child.html
new file mode 100644
index 0000000000..c36197ac4f
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-1-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-1.html b/docshell/test/browser/file_bug234628-1.html
new file mode 100644
index 0000000000..11c523ccd9
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-1.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<h1>No encoding declaration in parent or child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-1-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-10-child.xhtml b/docshell/test/browser/file_bug234628-10-child.xhtml
new file mode 100644
index 0000000000..cccf6f2bc0
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-10-child.xhtml
@@ -0,0 +1,4 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title>XML child with no encoding declaration</title></head>
+<body><p>Euro sign if decoded as UTF-8: €</p></body>
+</html>
diff --git a/docshell/test/browser/file_bug234628-10.html b/docshell/test/browser/file_bug234628-10.html
new file mode 100644
index 0000000000..78b8f0035d
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-10.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in HTML parent or XHTML child</title>
+</head>
+<body>
+<h1>No encoding declaration in HTML parent or XHTML child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-10-child.xhtml"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-11-child.xhtml b/docshell/test/browser/file_bug234628-11-child.xhtml
new file mode 100644
index 0000000000..11ef668b0c
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-11-child.xhtml
@@ -0,0 +1,4 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title>No encoding declaration in HTML parent and HTTP declaration in XHTML child</title></head>
+<body><p>Euro sign if decoded as UTF-8: €</p></body>
+</html>
diff --git a/docshell/test/browser/file_bug234628-11-child.xhtml^headers^ b/docshell/test/browser/file_bug234628-11-child.xhtml^headers^
new file mode 100644
index 0000000000..30fb304056
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-11-child.xhtml^headers^
@@ -0,0 +1 @@
+Content-Type: application/xhtml+xml; charset=utf-8
diff --git a/docshell/test/browser/file_bug234628-11.html b/docshell/test/browser/file_bug234628-11.html
new file mode 100644
index 0000000000..21c5b733e0
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-11.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in HTML parent and HTTP declaration in XHTML child</title>
+</head>
+<body>
+<h1>No encoding declaration in HTML parent and HTTP declaration in XHTML child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-11-child.xhtml"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-2-child.html b/docshell/test/browser/file_bug234628-2-child.html
new file mode 100644
index 0000000000..0acd2e0b27
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-2-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-2.html b/docshell/test/browser/file_bug234628-2.html
new file mode 100644
index 0000000000..a87d29e126
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-2.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<h1>No encoding declaration in parent or child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-2-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-3-child.html b/docshell/test/browser/file_bug234628-3-child.html
new file mode 100644
index 0000000000..a6ad832310
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-3-child.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-3.html b/docshell/test/browser/file_bug234628-3.html
new file mode 100644
index 0000000000..8caab60402
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-3.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and child</title>
+</head>
+<body>
+<h1>meta declaration in parent and child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-3-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-4-child.html b/docshell/test/browser/file_bug234628-4-child.html
new file mode 100644
index 0000000000..f0e7c2c058
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-4-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOM in child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-4.html b/docshell/test/browser/file_bug234628-4.html
new file mode 100644
index 0000000000..0137579010
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-4.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOM in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and BOM in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-4-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-5-child.html b/docshell/test/browser/file_bug234628-5-child.html
new file mode 100644
index 0000000000..a650552f63
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-5-child.html
Binary files differ
diff --git a/docshell/test/browser/file_bug234628-5.html b/docshell/test/browser/file_bug234628-5.html
new file mode 100644
index 0000000000..987e6420be
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-5.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and UTF-16 BOM in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and UTF-16 BOM in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-5-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-6-child.html b/docshell/test/browser/file_bug234628-6-child.html
new file mode 100644
index 0000000000..52c37f2596
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-6-child.html
Binary files differ
diff --git a/docshell/test/browser/file_bug234628-6-child.html^headers^ b/docshell/test/browser/file_bug234628-6-child.html^headers^
new file mode 100644
index 0000000000..bfdcf487fb
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-6-child.html^headers^
@@ -0,0 +1 @@
+Content-Type: text/html; charset=utf-16be
diff --git a/docshell/test/browser/file_bug234628-6.html b/docshell/test/browser/file_bug234628-6.html
new file mode 100644
index 0000000000..9d7fc580c3
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-6.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOMless UTF-16 with HTTP charset in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and BOMless UTF-16 with HTTP charset in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-6-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-7-child.html b/docshell/test/browser/file_bug234628-7-child.html
new file mode 100644
index 0000000000..c761ace101
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-7-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-7-child.html^headers^ b/docshell/test/browser/file_bug234628-7-child.html^headers^
new file mode 100644
index 0000000000..2d1c08b9e8
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-7-child.html^headers^
@@ -0,0 +1 @@
+Content-Type: text/html; charset=utf-8
diff --git a/docshell/test/browser/file_bug234628-7.html b/docshell/test/browser/file_bug234628-7.html
new file mode 100644
index 0000000000..7cb506096d
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-7.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-7-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-8-child.html b/docshell/test/browser/file_bug234628-8-child.html
new file mode 100644
index 0000000000..254e0fb2b3
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-8-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and no declaration in child</title>
+</head>
+<body>
+<p>Capital dje if decoded as Windows-1251: </p>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-8.html b/docshell/test/browser/file_bug234628-8.html
new file mode 100644
index 0000000000..b44e91801c
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-8.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1251">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and no declaration in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and no declaration in child</h1>
+
+<p>Capital dje if decoded as Windows-1251: </p>
+
+<iframe src="file_bug234628-8-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-9-child.html b/docshell/test/browser/file_bug234628-9-child.html
new file mode 100644
index 0000000000..a86b14d7ee
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-9-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>UTF-16 with BOM in parent and no declaration in child</title>
+</head>
+<body>
+<p>Euro sign if decoded as Windows-1251: </p>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-9.html b/docshell/test/browser/file_bug234628-9.html
new file mode 100644
index 0000000000..8a469da3aa
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-9.html
Binary files differ
diff --git a/docshell/test/browser/file_bug420605.html b/docshell/test/browser/file_bug420605.html
new file mode 100644
index 0000000000..8424b92f8f
--- /dev/null
+++ b/docshell/test/browser/file_bug420605.html
@@ -0,0 +1,31 @@
+<head>
+<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="/>
+ <title>Page Title for Bug 420605</title>
+</head>
+<body>
+ <h1>Fragment links</h1>
+
+ <p>This page has a bunch of fragment links to sections below:</p>
+
+ <ul>
+ <li><a id="firefox-link" href="#firefox">Firefox</a></li>
+ <li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
+ <li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
+ </ul>
+
+ <p>And here are the sections:</p>
+
+ <h2 id="firefox">Firefox</h2>
+
+ <p>Firefox is a browser.</p>
+
+ <h2 id="thunderbird">Thunderbird</h2>
+
+ <p>Thunderbird is an email client</p>
+
+ <h2 id="seamonkey">Seamonkey</h2>
+
+ <p>Seamonkey is the all-in-one application.</p>
+
+</body>
+</html>
diff --git a/docshell/test/browser/file_bug422543_script.js b/docshell/test/browser/file_bug422543_script.js
new file mode 100644
index 0000000000..cd69df1ec4
--- /dev/null
+++ b/docshell/test/browser/file_bug422543_script.js
@@ -0,0 +1,98 @@
+const { utils: Cu, interfaces: Ci } = Components;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function SHistoryListener() {
+}
+
+SHistoryListener.prototype = {
+ retval: true,
+ last: "initial",
+
+ OnHistoryNewEntry: function (aNewURI) {
+ this.last = "newentry";
+ },
+
+ OnHistoryGoBack: function (aBackURI) {
+ this.last = "goback";
+ return this.retval;
+ },
+
+ OnHistoryGoForward: function (aForwardURI) {
+ this.last = "goforward";
+ return this.retval;
+ },
+
+ OnHistoryGotoIndex: function (aIndex, aGotoURI) {
+ this.last = "gotoindex";
+ return this.retval;
+ },
+
+ OnHistoryPurge: function (aNumEntries) {
+ this.last = "purge";
+ return this.retval;
+ },
+
+ OnHistoryReload: function (aReloadURI, aReloadFlags) {
+ this.last = "reload";
+ return this.retval;
+ },
+
+ OnHistoryReplaceEntry: function (aIndex) {},
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
+ Ci.nsISupportsWeakReference])
+};
+
+let testAPI = {
+ shistory: null,
+ listeners: [ new SHistoryListener(),
+ new SHistoryListener() ],
+
+ init() {
+ this.shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
+ for (let listener of this.listeners) {
+ this.shistory.addSHistoryListener(listener);
+ }
+ },
+
+ cleanup() {
+ for (let listener of this.listeners) {
+ this.shistory.removeSHistoryListener(listener);
+ }
+ this.shistory = null;
+ sendAsyncMessage("bug422543:cleanup:return", {});
+ },
+
+ getListenerStatus() {
+ sendAsyncMessage("bug422543:getListenerStatus:return",
+ this.listeners.map(l => l.last));
+ },
+
+ resetListeners() {
+ for (let listener of this.listeners) {
+ listener.last = "initial";
+ }
+
+ sendAsyncMessage("bug422543:resetListeners:return", {});
+ },
+
+ notifyReload() {
+ let internal = this.shistory.QueryInterface(Ci.nsISHistoryInternal);
+ let rval =
+ internal.notifyOnHistoryReload(content.document.documentURIObject, 0);
+ sendAsyncMessage("bug422543:notifyReload:return", { rval });
+ },
+
+ setRetval({ num, val }) {
+ this.listeners[num].retval = val;
+ sendAsyncMessage("bug422543:setRetval:return", {});
+ },
+};
+
+addMessageListener("bug422543:cleanup", () => { testAPI.cleanup(); });
+addMessageListener("bug422543:getListenerStatus", () => { testAPI.getListenerStatus(); });
+addMessageListener("bug422543:notifyReload", () => { testAPI.notifyReload(); });
+addMessageListener("bug422543:resetListeners", () => { testAPI.resetListeners(); });
+addMessageListener("bug422543:setRetval", (msg) => { testAPI.setRetval(msg.data); });
+
+testAPI.init();
diff --git a/docshell/test/browser/file_bug503832.html b/docshell/test/browser/file_bug503832.html
new file mode 100644
index 0000000000..338631c8a0
--- /dev/null
+++ b/docshell/test/browser/file_bug503832.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test page for https://bugzilla.mozilla.org/show_bug.cgi?id=503832
+-->
+<head>
+ <title>Page Title for Bug 503832</title>
+</head>
+<body>
+ <h1>Fragment links</h1>
+
+ <p>This page has a bunch of fragment links to sections below:</p>
+
+ <ul>
+ <li><a id="firefox-link" href="#firefox">Firefox</a></li>
+ <li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
+ <li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
+ </ul>
+
+ <p>And here are the sections:</p>
+
+ <h2 id="firefox">Firefox</h2>
+
+ <p>Firefox is a browser.</p>
+
+ <h2 id="thunderbird">Thunderbird</h2>
+
+ <p>Thunderbird is an email client</p>
+
+ <h2 id="seamonkey">Seamonkey</h2>
+
+ <p>Seamonkey is the all-in-one application.</p>
+
+</body>
+</html>
diff --git a/docshell/test/browser/file_bug655270.html b/docshell/test/browser/file_bug655270.html
new file mode 100644
index 0000000000..0c08d982b1
--- /dev/null
+++ b/docshell/test/browser/file_bug655270.html
@@ -0,0 +1,11 @@
+<html>
+
+<head>
+ <link rel='icon' href='favicon_bug655270.ico'>
+</head>
+
+<body>
+Nothing to see here...
+</body>
+
+</html>
diff --git a/docshell/test/browser/file_bug670318.html b/docshell/test/browser/file_bug670318.html
new file mode 100644
index 0000000000..4cd9b454a2
--- /dev/null
+++ b/docshell/test/browser/file_bug670318.html
@@ -0,0 +1,23 @@
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<script>
+function load() {
+ function next() {
+ if (count < 5)
+ iframe.src = 'data:text/html;charset=utf-8,iframe ' + (++count);
+ }
+
+ var count = 0;
+ var iframe = document.createElement('iframe');
+ iframe.onload = function () { setTimeout(next, 0) };
+ document.body.appendChild(iframe);
+
+ setTimeout(next, 0);
+}
+</script>
+</head>
+
+<body onload="load()">
+Testcase
+</body>
+</html>
diff --git a/docshell/test/browser/file_bug852909.pdf b/docshell/test/browser/file_bug852909.pdf
new file mode 100644
index 0000000000..89066463f1
--- /dev/null
+++ b/docshell/test/browser/file_bug852909.pdf
Binary files differ
diff --git a/docshell/test/browser/file_bug852909.png b/docshell/test/browser/file_bug852909.png
new file mode 100644
index 0000000000..c7510d388f
--- /dev/null
+++ b/docshell/test/browser/file_bug852909.png
Binary files differ
diff --git a/docshell/test/browser/file_multiple_pushState.html b/docshell/test/browser/file_multiple_pushState.html
new file mode 100644
index 0000000000..c58a1a71b9
--- /dev/null
+++ b/docshell/test/browser/file_multiple_pushState.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test multiple calls to history.pushState</title>
+ </head>
+ <body>
+ <h1>Ohai</h1>
+ </body>
+ <script type="text/javascript">
+ window.history.pushState({}, "", "/bar/ABC?key=baz");
+ window.history.pushState({}, "", "/bar/ABC/DEF?key=baz");
+ </script>
+</html>
diff --git a/docshell/test/browser/frame-head.js b/docshell/test/browser/frame-head.js
new file mode 100644
index 0000000000..5cb3b15133
--- /dev/null
+++ b/docshell/test/browser/frame-head.js
@@ -0,0 +1,113 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Functions that are automatically loaded as frame scripts for
+// timeline tests.
+
+var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+var { Promise } = Cu.import('resource://gre/modules/Promise.jsm', {});
+
+Cu.import("resource://gre/modules/Timer.jsm");
+
+// Functions that look like mochitest functions but forward to the
+// browser process.
+
+this.ok = function(value, message) {
+ sendAsyncMessage("browser:test:ok", {
+ value: !!value,
+ message: message});
+}
+
+this.is = function(v1, v2, message) {
+ ok(v1 == v2, message);
+}
+
+this.info = function(message) {
+ sendAsyncMessage("browser:test:info", {message: message});
+}
+
+this.finish = function() {
+ sendAsyncMessage("browser:test:finish");
+}
+
+/* Start a task that runs some timeline tests in the ordinary way.
+ *
+ * @param array tests
+ * The tests to run. This is an array where each element
+ * is of the form { desc, searchFor, setup, check }.
+ *
+ * desc is the test description, a string.
+ * searchFor is a string or a function
+ * If a string, then when a marker with this name is
+ * found, marker-reading is stopped.
+ * If a function, then the accumulated marker array is
+ * passed to it, and marker reading stops when it returns
+ * true.
+ * setup is a function that takes the docshell as an argument.
+ * It should start the test.
+ * check is a function that takes an array of markers
+ * as an argument and checks the results of the test.
+ */
+this.timelineContentTest = function(tests) {
+ Task.spawn(function*() {
+ let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+
+ info("Start recording");
+ docShell.recordProfileTimelineMarkers = true;
+
+ for (let {desc, searchFor, setup, check} of tests) {
+
+ info("Running test: " + desc);
+
+ info("Flushing the previous markers if any");
+ docShell.popProfileTimelineMarkers();
+
+ info("Running the test setup function");
+ let onMarkers = timelineWaitForMarkers(docShell, searchFor);
+ setup(docShell);
+ info("Waiting for new markers on the docShell");
+ let markers = yield onMarkers;
+
+ // Cycle collection markers are non-deterministic, and none of these tests
+ // expect them to show up.
+ markers = markers.filter(m => m.name.indexOf("nsCycleCollector") === -1);
+
+ info("Running the test check function");
+ check(markers);
+ }
+
+ info("Stop recording");
+ docShell.recordProfileTimelineMarkers = false;
+ finish();
+ });
+}
+
+function timelineWaitForMarkers(docshell, searchFor) {
+ if (typeof(searchFor) == "string") {
+ let searchForString = searchFor;
+ let f = function (markers) {
+ return markers.some(m => m.name == searchForString);
+ };
+ searchFor = f;
+ }
+
+ return new Promise(function(resolve, reject) {
+ let waitIterationCount = 0;
+ let maxWaitIterationCount = 10; // Wait for 2sec maximum
+ let markers = [];
+
+ setTimeout(function timeoutHandler() {
+ let newMarkers = docshell.popProfileTimelineMarkers();
+ markers = [...markers, ...newMarkers];
+ if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) {
+ resolve(markers);
+ } else {
+ setTimeout(timeoutHandler, 200);
+ waitIterationCount++;
+ }
+ }, 200);
+ });
+}
diff --git a/docshell/test/browser/head.js b/docshell/test/browser/head.js
new file mode 100644
index 0000000000..24ca8f45b3
--- /dev/null
+++ b/docshell/test/browser/head.js
@@ -0,0 +1,99 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* Helper function for timeline tests. Returns an async task that is
+ * suitable for use as a particular timeline test.
+ * @param string frameScriptName
+ * Base name of the frame script file.
+ * @param string url
+ * URL to load.
+ */
+function makeTimelineTest(frameScriptName, url) {
+ info("in timelineTest");
+ return Task.async(function*() {
+ info("in in timelineTest");
+ waitForExplicitFinish();
+
+ yield timelineTestOpenUrl(url);
+
+ const here = "chrome://mochitests/content/browser/docshell/test/browser/";
+
+ let mm = gBrowser.selectedBrowser.messageManager;
+ mm.loadFrameScript(here + "frame-head.js", false);
+ mm.loadFrameScript(here + frameScriptName, false);
+
+ // Set up some listeners so that timeline tests running in the
+ // content process can forward their results to the main process.
+ mm.addMessageListener("browser:test:ok", function(message) {
+ ok(message.data.value, message.data.message);
+ });
+ mm.addMessageListener("browser:test:info", function(message) {
+ info(message.data.message);
+ });
+ mm.addMessageListener("browser:test:finish", function(ignore) {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+ });
+}
+
+/* Open a URL for a timeline test. */
+function timelineTestOpenUrl(url) {
+ window.focus();
+
+ let tabSwitchPromise = new Promise((resolve, reject) => {
+ window.gBrowser.addEventListener("TabSwitchDone", function listener() {
+ window.gBrowser.removeEventListener("TabSwitchDone", listener);
+ resolve();
+ });
+ });
+
+ let loadPromise = new Promise(function(resolve, reject) {
+ let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
+ let linkedBrowser = tab.linkedBrowser;
+
+ linkedBrowser.addEventListener("load", function onload() {
+ linkedBrowser.removeEventListener("load", onload, true);
+ resolve(tab);
+ }, true);
+ });
+
+ return Promise.all([tabSwitchPromise, loadPromise]).then(([_, tab]) => tab);
+}
+
+/**
+ * Helper function for charset tests. It loads |url| in a new tab,
+ * runs |check1| in a ContentTask when the page is ready, switches the
+ * charset to |charset|, and then runs |check2| in a ContentTask when
+ * the page has finished reloading.
+ *
+ * |charset| and |check2| can be omitted, in which case the test
+ * finishes when |check1| completes.
+ */
+function runCharsetTest(url, check1, charset, check2) {
+ waitForExplicitFinish();
+
+ BrowserTestUtils.openNewForegroundTab(gBrowser, url, true).then(afterOpen);
+
+ function afterOpen() {
+ if (charset) {
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
+
+ ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
+ BrowserSetForcedCharacterSet(charset);
+ });
+ } else {
+ ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+ }
+ }
+
+ function afterChangeCharset() {
+ ContentTask.spawn(gBrowser.selectedBrowser, null, check2).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+ }
+}
diff --git a/docshell/test/browser/print_postdata.sjs b/docshell/test/browser/print_postdata.sjs
new file mode 100644
index 0000000000..4175a24805
--- /dev/null
+++ b/docshell/test/browser/print_postdata.sjs
@@ -0,0 +1,22 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/plain", false);
+ if (request.method == "GET") {
+ response.write(request.queryString);
+ } else {
+ var body = new BinaryInputStream(request.bodyInputStream);
+
+ var avail;
+ var bytes = [];
+
+ while ((avail = body.available()) > 0)
+ Array.prototype.push.apply(bytes, body.readByteArray(avail));
+
+ var data = String.fromCharCode.apply(null, bytes);
+ response.bodyOutputStream.write(data, data.length);
+ }
+}
diff --git a/docshell/test/browser/redirect_to_example.sjs b/docshell/test/browser/redirect_to_example.sjs
new file mode 100644
index 0000000000..eef5e49f43
--- /dev/null
+++ b/docshell/test/browser/redirect_to_example.sjs
@@ -0,0 +1,4 @@
+function handleRequest(request, response) {
+ response.setStatusLine(request.httpVersion, 302, "Moved Permanently");
+ response.setHeader("Location", "http://example");
+}
diff --git a/docshell/test/browser/test-form_sjis.html b/docshell/test/browser/test-form_sjis.html
new file mode 100644
index 0000000000..91c375deef
--- /dev/null
+++ b/docshell/test/browser/test-form_sjis.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/REC-html401-19991224/strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+ <title>Shift_JIS in body and text area</title>
+ </head>
+ <body>
+ <h1>Incorrect meta charset</h1>
+ <h2>This page is encoded in Shift_JIS, but has an incorrect meta charset
+ claiming that it is windows-1251</h2>
+ <p id="testpar">jR[h́AׂĂ̕ɌŗL̔ԍt^܂</p>
+ <form>
+ <p>
+ <textarea id="testtextarea" rows=6 cols=60>jR[h́AׂĂ̕ɌŗL̔ԍt^܂</textarea>
+ <input id="testinput" type="text" size=60 value="jR[h́AׂĂ̕ɌŗL̔ԍt^܂">
+ </p>
+ </form>
+ <h2>Expected text on load:</h2>
+ <p>&#x453;&#x2020;&#x453;&#x6A;&#x453;&#x52;&#x403;&#x5B;&#x453;&#x68;&#x201A;&#x41D;&#x403;&#x41;&#x201A;&#xB7;&#x201A;&#x427;&#x201A;&#x414;&#x201A;&#x41C;&#x2022;&#xB6;&#x40B;&#x459;&#x201A;&#x419;&#x40A;&#x415;&#x2014;&#x4C;&#x201A;&#x41C;&#x201D;&#x424;&#x40C;&#x2020;&#x201A;&#x440;&#x2022;&#x74;&#x2014;&#x5E;&#x201A;&#xB5;&#x201A;&#x42C;&#x201A;&#xB7;</p>
+ <h2>Expected text on resetting the encoding to Shift_JIS:</h2>
+ <p>&#x30E6;&#x30CB;&#x30B3;&#x30FC;&#x30C9;&#x306F;&#x3001;&#x3059;&#x3079;&#x3066;&#x306E;&#x6587;&#x5B57;&#x306B;&#x56FA;&#x6709;&#x306E;&#x756A;&#x53F7;&#x3092;&#x4ED8;&#x4E0E;&#x3057;&#x307E;&#x3059;</p>
+ </body>
+</html>
diff --git a/docshell/test/browser/timelineMarkers-04.html b/docshell/test/browser/timelineMarkers-04.html
new file mode 100644
index 0000000000..8299983874
--- /dev/null
+++ b/docshell/test/browser/timelineMarkers-04.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8"></meta>
+ <title>markers test</title>
+</head>
+<body>
+
+ <p>Test page</p>
+
+ <script>
+ function do_xhr() {
+ const theURL = "timelineMarkers-04.html";
+
+ xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ dump("ReadyState = " + xhr.readyState + "\n");
+ };
+ xhr.open("get", theURL, true);
+ xhr.send();
+ }
+
+ window.addEventListener("dog", do_xhr, true);
+
+ function do_promise() {
+ new Promise(function(resolve, reject) {
+ console.time("Bob");
+ window.setTimeout(function() {
+ resolve(23);
+ }, 10);
+ }).then(function (val) {
+ console.timeEnd("Bob");
+ });
+ }
+
+ window.addEventListener("promisetest", do_promise, true);
+
+ var globalResolver;
+ function do_promise_script() {
+ new Promise(function(resolve, reject) {
+ console.time("Bob");
+ globalResolver = resolve;
+ window.setTimeout("globalResolver(23);", 10);
+ }).then(function (val) {
+ console.timeEnd("Bob");
+ });
+ }
+
+ window.addEventListener("promisescript", do_promise_script, true);
+
+ </script>
+
+</body>
+</html>
+
diff --git a/docshell/test/bug123696-subframe.html b/docshell/test/bug123696-subframe.html
new file mode 100644
index 0000000000..136d0a184c
--- /dev/null
+++ b/docshell/test/bug123696-subframe.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script>
+ function change() {
+ return "<html><body>change</body></html>";
+ }
+ function change2() {
+ return "<html><body>change2</body></html>";
+ }
+ </script>
+ </head>
+ <body>
+ <iframe src="javascript:parent.change()"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/bug369814.jar b/docshell/test/bug369814.jar
new file mode 100644
index 0000000000..86b9c8c096
--- /dev/null
+++ b/docshell/test/bug369814.jar
Binary files differ
diff --git a/docshell/test/bug369814.zip b/docshell/test/bug369814.zip
new file mode 100644
index 0000000000..ed8234dbc4
--- /dev/null
+++ b/docshell/test/bug369814.zip
Binary files differ
diff --git a/docshell/test/bug404548-subframe.html b/docshell/test/bug404548-subframe.html
new file mode 100644
index 0000000000..0afd17544d
--- /dev/null
+++ b/docshell/test/bug404548-subframe.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body onload="setTimeout(function() { window.location = &quot;data:text/html,<body onload='window.opener.finishTest()'>&quot; }, 10)">
+<iframe src="data:text/html,<body onpagehide='var p = window.parent.opener; var e = window.frameElement; e.parentNode.removeChild(e); if (e.parentNode == null && e.contentWindow == null) { p.firstRemoved = true; }'>">
+</iframe>
+<iframe src="data:text/html,<body onpagehide='window.parent.opener.secondHidden = true;'>">
+</iframe>
diff --git a/docshell/test/bug413310-post.sjs b/docshell/test/bug413310-post.sjs
new file mode 100644
index 0000000000..b8d85dd3cf
--- /dev/null
+++ b/docshell/test/bug413310-post.sjs
@@ -0,0 +1,7 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/html");
+ response.write("<body onload='window.parent.onloadCount++'>" +
+ request.method + " " +
+ Date.now() +
+ "</body>");
+}
diff --git a/docshell/test/bug413310-subframe.html b/docshell/test/bug413310-subframe.html
new file mode 100644
index 0000000000..bcff1886fd
--- /dev/null
+++ b/docshell/test/bug413310-subframe.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body onload="window.parent.onloadCount++">
+ <form action="bug413310-post.sjs" method="POST">
+ </form>
+ </body>
+</html>
diff --git a/docshell/test/bug529119-window.html b/docshell/test/bug529119-window.html
new file mode 100644
index 0000000000..f1908835a7
--- /dev/null
+++ b/docshell/test/bug529119-window.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119, sub-window</title>
+<body onload="window.opener.windowLoaded();">
+</body>
+</html>
diff --git a/docshell/test/bug530396-noref.sjs b/docshell/test/bug530396-noref.sjs
new file mode 100644
index 0000000000..1ed5f7aa21
--- /dev/null
+++ b/docshell/test/bug530396-noref.sjs
@@ -0,0 +1,20 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/html");
+ response.setHeader("Cache-Control", "no-cache");
+ response.write("<body onload='");
+
+ if (!request.hasHeader('Referer')) {
+ response.write("window.parent.onloadCount++;");
+ }
+
+ if (request.queryString == "newwindow") {
+ response.write("if (window.opener) { window.opener.parent.onloadCount++; window.opener.parent.doNextStep(); }");
+ response.write("if (!window.opener) window.close();");
+ response.write("'>");
+ } else {
+ response.write("window.parent.doNextStep();'>");
+ }
+
+ response.write(request.method + " " + Date.now());
+ response.write("</body>");
+}
diff --git a/docshell/test/bug530396-subframe.html b/docshell/test/bug530396-subframe.html
new file mode 100644
index 0000000000..be81b9f144
--- /dev/null
+++ b/docshell/test/bug530396-subframe.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body onload="window.parent.onloadCount++">
+ <a href="bug530396-noref.sjs" rel="noreferrer foo" id="target1">bug530396-noref.sjs</a>
+ <a href="bug530396-noref.sjs?newwindow" rel="nofollow noreferrer" id="target2" target="newwindow">bug530396-noref.sjs with new window</a>
+ </body>
+</html>
diff --git a/docshell/test/bug570341_recordevents.html b/docshell/test/bug570341_recordevents.html
new file mode 100644
index 0000000000..51fc1cd762
--- /dev/null
+++ b/docshell/test/bug570341_recordevents.html
@@ -0,0 +1,21 @@
+<html>
+<head>
+<script>
+ var start = Date.now();
+ window._testing_js_start = Date.now();
+ window['_testing_js_after_' + document.readyState] = start;
+ document.addEventListener('DOMContentLoaded',
+ function () {
+ window._testing_evt_DOMContentLoaded = Date.now();
+ }, true);
+ document.addEventListener('readystatechange', function(){
+ window['_testing_evt_DOM_' + document.readyState] = Date.now();
+ }, true);
+ function recordLoad() {
+ window._testing_evt_load = Date.now();
+ }
+</script>
+</head>
+<body onload="recordLoad()">This document collects time
+for events related to the page load progress.</body>
+</html>
diff --git a/docshell/test/bug668513_redirect.html b/docshell/test/bug668513_redirect.html
new file mode 100644
index 0000000000..1b8f66c631
--- /dev/null
+++ b/docshell/test/bug668513_redirect.html
@@ -0,0 +1 @@
+<html><body>This document is redirected to a blank document.</body></html>
diff --git a/docshell/test/bug668513_redirect.html^headers^ b/docshell/test/bug668513_redirect.html^headers^
new file mode 100644
index 0000000000..0e785833c6
--- /dev/null
+++ b/docshell/test/bug668513_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 302 Moved Temporarily
+Location: navigation/blank.html
diff --git a/docshell/test/bug691547_frame.html b/docshell/test/bug691547_frame.html
new file mode 100644
index 0000000000..00172f7119
--- /dev/null
+++ b/docshell/test/bug691547_frame.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=691547
+-->
+<head>
+ <title>Test for Bug 691547</title>
+</head>
+<body>
+<iframe style="width:95%"></iframe>
+</body>
+</html>
diff --git a/docshell/test/chrome/112564_nocache.html b/docshell/test/chrome/112564_nocache.html
new file mode 100644
index 0000000000..29fb990b86
--- /dev/null
+++ b/docshell/test/chrome/112564_nocache.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>test1</title>
+</head>
+<body>
+<p>
+This document will be sent with a no-cache cache-control header. When sent over a secure connection, it should not be stored in bfcache.
+</p>
+</body>
+</html>
diff --git a/docshell/test/chrome/112564_nocache.html^headers^ b/docshell/test/chrome/112564_nocache.html^headers^
new file mode 100644
index 0000000000..c829a41ae9
--- /dev/null
+++ b/docshell/test/chrome/112564_nocache.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-cache
diff --git a/docshell/test/chrome/215405_nocache.html b/docshell/test/chrome/215405_nocache.html
new file mode 100644
index 0000000000..c7d48c4eba
--- /dev/null
+++ b/docshell/test/chrome/215405_nocache.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>test1</title>
+</head>
+<body style="height: 100%">
+ <input type="text" id="inp" value="">
+ </input>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%; width: 300%">Some more text</div>
+</body>
+</html>
diff --git a/docshell/test/chrome/215405_nocache.html^headers^ b/docshell/test/chrome/215405_nocache.html^headers^
new file mode 100644
index 0000000000..c829a41ae9
--- /dev/null
+++ b/docshell/test/chrome/215405_nocache.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-cache
diff --git a/docshell/test/chrome/215405_nostore.html b/docshell/test/chrome/215405_nostore.html
new file mode 100644
index 0000000000..4f5bd0f4f0
--- /dev/null
+++ b/docshell/test/chrome/215405_nostore.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>test1</title>
+</head>
+<body style="height: 100%">
+ <input type="text" id="inp" value="">
+ </input>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%; width: 350%">Some more text</div>
+</body>
+</html>
diff --git a/docshell/test/chrome/215405_nostore.html^headers^ b/docshell/test/chrome/215405_nostore.html^headers^
new file mode 100644
index 0000000000..59ba296103
--- /dev/null
+++ b/docshell/test/chrome/215405_nostore.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-store
diff --git a/docshell/test/chrome/582176_dummy.html b/docshell/test/chrome/582176_dummy.html
new file mode 100644
index 0000000000..3b18e512db
--- /dev/null
+++ b/docshell/test/chrome/582176_dummy.html
@@ -0,0 +1 @@
+hello world
diff --git a/docshell/test/chrome/582176_xml.xml b/docshell/test/chrome/582176_xml.xml
new file mode 100644
index 0000000000..d3dd576dfe
--- /dev/null
+++ b/docshell/test/chrome/582176_xml.xml
@@ -0,0 +1,2 @@
+<?xml-stylesheet type="text/xsl" href="582176_xslt.xsl"?>
+<out/>
diff --git a/docshell/test/chrome/582176_xslt.xsl b/docshell/test/chrome/582176_xslt.xsl
new file mode 100644
index 0000000000..5957416899
--- /dev/null
+++ b/docshell/test/chrome/582176_xslt.xsl
@@ -0,0 +1,8 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match="out">
+ <html>
+ <head><title>XSLT result doc</title></head>
+ <body><p>xslt result</p></body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/docshell/test/chrome/662200a.html b/docshell/test/chrome/662200a.html
new file mode 100644
index 0000000000..0b9ead6f3e
--- /dev/null
+++ b/docshell/test/chrome/662200a.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>A</title>
+ </head>
+ <body>
+ <a id="link" href="662200b.html">Next</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/662200b.html b/docshell/test/chrome/662200b.html
new file mode 100644
index 0000000000..91e6b971d6
--- /dev/null
+++ b/docshell/test/chrome/662200b.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>B</title>
+ </head>
+ <body>
+ <a id="link" href="662200c.html">Next</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/662200c.html b/docshell/test/chrome/662200c.html
new file mode 100644
index 0000000000..bc00e6b14b
--- /dev/null
+++ b/docshell/test/chrome/662200c.html
@@ -0,0 +1,7 @@
+<html>
+ <head>
+ <title>C</title>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/docshell/test/chrome/89419.html b/docshell/test/chrome/89419.html
new file mode 100644
index 0000000000..b36b8d788c
--- /dev/null
+++ b/docshell/test/chrome/89419.html
@@ -0,0 +1,7 @@
+<html>
+<head>
+<title>Bug 89419</title>
+</head>
+<body>
+<img src="http://mochi.test:8888/tests/docshell/test/chrome/bug89419.sjs">
+</body>
diff --git a/docshell/test/chrome/92598_nostore.html b/docshell/test/chrome/92598_nostore.html
new file mode 100644
index 0000000000..47bb90441e
--- /dev/null
+++ b/docshell/test/chrome/92598_nostore.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>test1</title>
+</head>
+<body>
+<p>
+This document will be sent with a no-store cache-control header. It should not be stored in bfcache.
+</p>
+</body>
+</html>
diff --git a/docshell/test/chrome/92598_nostore.html^headers^ b/docshell/test/chrome/92598_nostore.html^headers^
new file mode 100644
index 0000000000..59ba296103
--- /dev/null
+++ b/docshell/test/chrome/92598_nostore.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-store
diff --git a/docshell/test/chrome/allowContentRetargeting.sjs b/docshell/test/chrome/allowContentRetargeting.sjs
new file mode 100644
index 0000000000..96e467ef68
--- /dev/null
+++ b/docshell/test/chrome/allowContentRetargeting.sjs
@@ -0,0 +1,7 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function handleRequest(req, resp) {
+ resp.setHeader("Content-Type", "application/octet-stream", false);
+ resp.write("hi");
+}
diff --git a/docshell/test/chrome/blue.png b/docshell/test/chrome/blue.png
new file mode 100644
index 0000000000..8df58f3a5f
--- /dev/null
+++ b/docshell/test/chrome/blue.png
Binary files differ
diff --git a/docshell/test/chrome/bug112564_window.xul b/docshell/test/chrome/bug112564_window.xul
new file mode 100644
index 0000000000..e9c05ca9f8
--- /dev/null
+++ b/docshell/test/chrome/bug112564_window.xul
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="112564Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="112564 test">
+
+ <script type="application/javascript"><![CDATA[
+ const LISTEN_EVENTS = ["load", "unload", "pageshow", "pagehide"];
+
+ var gBrowser;
+ var gTestsIterator;
+ var gExpected = [];
+
+ function ok(condition, message) {
+ window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
+ }
+
+ function is(a, b, message) {
+ window.opener.wrappedJSObject.SimpleTest.is(a, b, message);
+ }
+
+ function finish() {
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.removeEventListener(eventType, eventListener, true);
+ }
+
+ // Work around bug 467960
+ var history = gBrowser.webNavigation.sessionHistory;
+ history.PurgeHistory(history.count);
+
+ window.close();
+ window.opener.wrappedJSObject.SimpleTest.finish();
+ }
+
+ function onLoad() {
+ gBrowser = document.getElementById("content");
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.addEventListener(eventType, eventListener, true);
+ }
+
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function eventListener(event) {
+ ok(gExpected.length >= 1, "Unexpected event " + event.type);
+ if (gExpected.length == 0) {
+ // in case of unexpected event, try to continue anyway
+ setTimeout(nextTest, 0);
+ return;
+ }
+
+ var exp = gExpected.shift();
+ is(event.type, exp.type, "Invalid event received");
+ if (typeof(exp.persisted) != "undefined") {
+ is(event.persisted, exp.persisted, "Invalid persisted state");
+ }
+ if (exp.title) {
+ ok(event.originalTarget instanceof HTMLDocument,
+ "originalTarget not a HTMLDocument");
+ is(event.originalTarget.title, exp.title, "titles don't match");
+ }
+
+ if (gExpected.length == 0) {
+ setTimeout(nextTest, 0);
+ }
+ }
+
+ function nextTest() {
+ try {
+ gTestsIterator.next();
+ } catch (err if err instanceof StopIteration) {
+ finish();
+ }
+ }
+
+ function testsIterator() {
+ // Load a secure page with a no-cache header, followed by a simple page.
+ // no-cache should not interfere with the bfcache in the way no-store
+ // does.
+ var test1DocURI = "https://example.com:443/tests/docshell/test/chrome/112564_nocache.html";
+
+ gExpected = [{type: "pagehide", persisted: true},
+ {type: "load", title: "test1"},
+ {type: "pageshow", title: "test1", persisted: false}];
+ gBrowser.loadURI(test1DocURI);
+ yield undefined;
+
+ var test2Doc = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test1", persisted: true},
+ {type: "load", title: "test2"},
+ {type: "pageshow", title: "test2", persisted: false}];
+ gBrowser.loadURI(test2Doc);
+ yield undefined;
+
+ // Now go back in history. First page has been cached.
+ // Check persisted property to confirm
+ gExpected = [{type: "pagehide", title: "test2", persisted: true},
+ {type: "pageshow", title: "test1", persisted: true}];
+ gBrowser.goBack();
+ yield undefined;
+ }
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug113934_window.xul b/docshell/test/chrome/bug113934_window.xul
new file mode 100644
index 0000000000..9dbfc3b8f4
--- /dev/null
+++ b/docshell/test/chrome/bug113934_window.xul
@@ -0,0 +1,161 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 113934" onload="doTheTest()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <vbox id="box1">
+ </vbox>
+ <vbox id="box2">
+ </vbox>
+ <spacer flex="1"/>
+ </hbox>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ var imports = [ "SimpleTest", "is", "isnot", "ok", "snapshotWindow",
+ "compareSnapshots", "onerror" ];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ function $(id) {
+ return document.getElementById(id);
+ }
+
+ function addBrowser(parent, id, width, height) {
+ var b =
+ document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
+ var type = window.location.search.slice(1);
+ is(type == "chrome" || type == "content", true, "Unexpected type");
+ b.setAttribute("type", type);
+ b.setAttribute("id", id);
+ b.setAttribute("width", width);
+ b.setAttribute("height", height);
+ $(parent).appendChild(b);
+ }
+ addBrowser("box1", "f1", 300, 200);
+ addBrowser("box1", "f2", 300, 200);
+ addBrowser("box2", "f3", 30, 200);
+
+ /** Test for Bug 113934 **/
+ var doc1 =
+ "data:text/html,<html><body onbeforeunload='document.documentElement.textContent = \"\"' onunload='document.documentElement.textContent = \"\"' onpagehide='document.documentElement.textContent = \"\"'>This is a test</body></html>";
+ var doc2 = "data:text/html,<html><head></head><body>This is a second test</body></html>";
+
+
+ $("f1").setAttribute("src", doc1);
+ $("f2").setAttribute("src", doc2);
+ $("f3").setAttribute("src", doc2);
+
+ function doTheTest() {
+ var s1 = snapshotWindow($("f1").contentWindow);
+ var s2 = snapshotWindow($("f2").contentWindow);
+ var s3 = snapshotWindow($("f3").contentWindow);
+
+ // This test is broken - see bug 1090274
+ //ok(!compareSnapshots(s2, s3, true)[0],
+ // "Should look different due to different sizing");
+
+ function getDOM(id) {
+ return $(id).contentDocument.documentElement.innerHTML;
+ }
+
+ var dom1 = getDOM("f1");
+
+ var dom2 = getDOM("f2");
+ $("f2").contentDocument.body.textContent = "Modified the text";
+ var dom2star = getDOM("f2");
+ isnot(dom2, dom2star, "We changed the DOM!");
+
+ $("f1").swapDocShells($("f2"));
+ // now we have doms 2*, 1, 2 in the frames
+
+ is(getDOM("f1"), dom2star, "Shouldn't have changed the DOM on swap");
+ is(getDOM("f2"), dom1, "Shouldn't have fired event handlers");
+
+ // Test for bug 480149
+ // The DOMLink* events are dispatched asynchronously, thus I cannot
+ // just include the <link> element in the initial DOM and swap the
+ // docshells. Instead, the link element is added now. Then, when the
+ // first DOMLinkAdded event (which is a result of the actual addition)
+ // is dispatched, the docshells are swapped and the pageshow and pagehide
+ // events are tested. Only then, we wait for the DOMLink* events,
+ // which are a result of swapping the docshells.
+ var DOMLinkListener = {
+ _afterFirst: false,
+ _removedDispatched: false,
+ _addedDispatched: false,
+ handleEvent: function(aEvent) {
+ if (!this._afterFirst) {
+ is(aEvent.type, "DOMLinkAdded");
+
+ var strs = { "f1": "", "f3" : "" };
+ function attachListener(node, type) {
+ var listener = function(e) {
+ if (strs[node.id]) strs[node.id] += " ";
+ strs[node.id] += node.id + ".page" + type;
+ }
+ node.addEventListener("page" + type, listener, false);
+
+ listener.detach = function() {
+ node.removeEventListener("page" + type, listener, false);
+ }
+ return listener;
+ }
+
+ var l1 = attachListener($("f1"), "show");
+ var l2 = attachListener($("f1"), "hide");
+ var l3 = attachListener($("f3"), "show");
+ var l4 = attachListener($("f3"), "hide");
+
+ $("f1").swapDocShells($("f3"));
+ // now we have DOMs 2, 1, 2* in the frames
+
+ l1.detach();
+ l2.detach();
+ l3.detach();
+ l4.detach();
+
+ var s1_new = snapshotWindow($("f1").contentWindow);
+ var [same, first, second] = compareSnapshots(s1_new, s2, true);
+ ok(same, "Should reflow on swap", "Expected " + second + " but got " + first);
+
+ is(strs["f1"], "f1.pagehide f1.pageshow");
+ is(strs["f3"], "f3.pagehide f3.pageshow");
+ this._afterFirst = true;
+ return;
+ }
+ if (aEvent.type == "DOMLinkAdded") {
+ is(this._addedDispatched, false);
+ this._addedDispatched = true;
+ }
+ else {
+ is(this._removedDispatched, false);
+ this._removedDispatched = true;
+ }
+
+ if (this._addedDispatched && this._removedDispatched) {
+ $("f1").removeEventListener("DOMLinkAdded", this, false);
+ $("f1").removeEventListener("DOMLinkRemoved", this, false);
+ $("f3").removeEventListener("DOMLinkAdded", this, false);
+ $("f3").removeEventListener("DOMLinkRemoved", this, false);
+ window.close();
+ SimpleTest.finish();
+ }
+ }
+ };
+
+ $("f1").addEventListener("DOMLinkAdded", DOMLinkListener, false);
+ $("f1").addEventListener("DOMLinkRemoved", DOMLinkListener, false);
+ $("f3").addEventListener("DOMLinkAdded", DOMLinkListener, false);
+ $("f3").addEventListener("DOMLinkRemoved", DOMLinkListener, false);
+
+ var linkElement = $("f1").contentDocument.createElement("link");
+ linkElement.setAttribute("rel", "alternate");
+ linkElement.setAttribute("href", "about:blank");
+ $("f1").contentDocument.documentElement.firstChild.appendChild(linkElement);
+ }
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/bug215405_window.xul b/docshell/test/chrome/bug215405_window.xul
new file mode 100644
index 0000000000..1935eddee1
--- /dev/null
+++ b/docshell/test/chrome/bug215405_window.xul
@@ -0,0 +1,167 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="215405Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="215405 test">
+
+ <script type="application/javascript"><![CDATA[
+ var imports = [ "SimpleTest", "is", "isnot", "ok"];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ const text="MOZILLA";
+ const nostoreURI = "http://mochi.test:8888/tests/docshell/test/chrome/" +
+ "215405_nostore.html";
+ const nocacheURI = "https://example.com:443/tests/docshell/test/chrome/" +
+ "215405_nocache.html";
+
+ var gBrowser;
+ var gTestsIterator;
+ var scrollX = 0;
+ var scrollY = 0;
+
+ function finish() {
+ gBrowser.removeEventListener("pageshow", eventListener, true);
+ // Work around bug 467960
+ var history = gBrowser.webNavigation.sessionHistory;
+ history.PurgeHistory(history.count);
+
+ window.close();
+ window.opener.wrappedJSObject.SimpleTest.finish();
+ }
+
+ function onLoad(e) {
+ gBrowser = document.getElementById("content");
+ gBrowser.addEventListener("pageshow", eventListener, true);
+
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function eventListener(event) {
+ setTimeout(nextTest, 0);
+ }
+
+ function nextTest() {
+ try {
+ gTestsIterator.next();
+ } catch (err if err instanceof StopIteration) {
+ finish();
+ }
+ }
+
+ function testsIterator() {
+ // No-store tests
+ var testName = "[nostore]";
+
+ // Load a page with a no-store header
+ gBrowser.loadURI(nostoreURI);
+ yield undefined;
+
+
+ // Now that the page has loaded, amend the form contents
+ var form = gBrowser.contentDocument.getElementById("inp");
+ form.value = text;
+
+ // Attempt to scroll the page
+ var originalXPosition = gBrowser.contentWindow.scrollX;
+ var originalYPosition = gBrowser.contentWindow.scrollY;
+ var scrollToX = gBrowser.contentWindow.scrollMaxX;
+ var scrollToY = gBrowser.contentWindow.scrollMaxY;
+ gBrowser.contentWindow.scrollBy(scrollToX, scrollToY);
+
+ // Save the scroll position for future comparison
+ scrollX = gBrowser.contentWindow.scrollX;
+ scrollY = gBrowser.contentWindow.scrollY;
+ isnot(scrollX, originalXPosition,
+ testName + " failed to scroll window horizontally");
+ isnot(scrollY, originalYPosition,
+ testName + " failed to scroll window vertically");
+
+ // Load a new document into the browser
+ var simple = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+ gBrowser.loadURI(simple);
+ yield undefined;
+
+
+ // Now go back in history. First page should not have been cached.
+ gBrowser.goBack();
+ yield undefined;
+
+
+ // First uncacheable page will now be reloaded. Check scroll position
+ // restored, and form contents not
+ is(gBrowser.contentWindow.scrollX, scrollX, testName +
+ " horizontal axis scroll position not correctly restored");
+ is(gBrowser.contentWindow.scrollY, scrollY, testName +
+ " vertical axis scroll position not correctly restored");
+ var formValue = gBrowser.contentDocument.getElementById("inp").value;
+ isnot(formValue, text, testName + " form value incorrectly restored");
+
+
+ // https no-cache
+ testName = "[nocache]";
+
+ // Load a page with a no-cache header. This should not be
+ // restricted like no-store (bug 567365)
+ gBrowser.loadURI(nocacheURI);
+ yield undefined;
+
+
+ // Now that the page has loaded, amend the form contents
+ form = gBrowser.contentDocument.getElementById("inp");
+ form.value = text;
+
+ // Attempt to scroll the page
+ originalXPosition = gBrowser.contentWindow.scrollX;
+ originalYPosition = gBrowser.contentWindow.scrollY;
+ scrollToX = gBrowser.contentWindow.scrollMaxX;
+ scrollToY = gBrowser.contentWindow.scrollMaxY;
+ gBrowser.contentWindow.scrollBy(scrollToX, scrollToY);
+
+ // Save the scroll position for future comparison
+ scrollX = gBrowser.contentWindow.scrollX;
+ scrollY = gBrowser.contentWindow.scrollY;
+ isnot(scrollX, originalXPosition,
+ testName + " failed to scroll window horizontally");
+ isnot(scrollY, originalYPosition,
+ testName + " failed to scroll window vertically");
+
+ gBrowser.loadURI(simple);
+ yield undefined;
+
+
+ // Now go back in history to the cached page.
+ gBrowser.goBack();
+ yield undefined;
+
+
+ // First page will now be reloaded. Check scroll position
+ // and form contents are restored
+ is(gBrowser.contentWindow.scrollX, scrollX, testName +
+ " horizontal axis scroll position not correctly restored");
+ is(gBrowser.contentWindow.scrollY, scrollY, testName +
+ " vertical axis scroll position not correctly restored");
+ var formValue = gBrowser.contentDocument.getElementById("inp").value;
+ is(formValue, text, testName + " form value not correctly restored");
+
+ // nextTest has to be called from here, as no events are fired in this
+ // step
+ setTimeout(nextTest, 0);
+ yield undefined;
+ }
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug293235.html b/docshell/test/chrome/bug293235.html
new file mode 100644
index 0000000000..458f88431c
--- /dev/null
+++ b/docshell/test/chrome/bug293235.html
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <title>Bug 293235 page1</title>
+ <style type="text/css">
+ a:visited, a.forcevisited.forcevisited { color: rgb(128, 0, 128); }
+ a:link, a.forcelink.forcelink { color: rgb(0, 0, 128); }
+ a:focus { color: rgb(128, 0, 0); }
+ </style>
+ </head>
+ <body>
+ <a id="link1" href="bug293235_p2.html">This is a test link.</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug293235_p2.html b/docshell/test/chrome/bug293235_p2.html
new file mode 100644
index 0000000000..2de067b80e
--- /dev/null
+++ b/docshell/test/chrome/bug293235_p2.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>Bug 293235 page2</title>
+ </head>
+ <body>
+ Nothing to see here, move along.
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug293235_window.xul b/docshell/test/chrome/bug293235_window.xul
new file mode 100644
index 0000000000..b5b359d48c
--- /dev/null
+++ b/docshell/test/chrome/bug293235_window.xul
@@ -0,0 +1,162 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="293235Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 293235 test">
+
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/specialpowersAPI.js"/>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js"/>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/>
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <script type="application/javascript"><![CDATA[
+ var Ci = Components.interfaces;
+ var Cc = Components.classes;
+ Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ // Return the Element object for the specified element id
+ function $(id) { return TestWindow.getDocument().getElementById(id); }
+
+ ////
+ // Generator function for test steps for bug 293235:
+ // A visited link should have the :visited style applied
+ // to it when displayed on a page which was fetched from
+ // the bfcache.
+ //
+ function testIterator()
+ {
+ // Register our observer to know when the link lookup is complete.
+ let testURI = NetUtil.newURI(getHttpUrl("bug293235_p2.html"));
+ let os = Cc["@mozilla.org/observer-service;1"].
+ getService(Ci.nsIObserverService);
+ const URI_VISITED_RESOLUTION_TOPIC = "visited-status-resolution";
+ let observer = {
+ notified: false,
+ observe: function(aSubject, aTopic, aData)
+ {
+ if (!testURI.equals(aSubject.QueryInterface(Ci.nsIURI))) {
+ return;
+ }
+ is(aTopic, URI_VISITED_RESOLUTION_TOPIC, "Unexpected topic");
+ this.notified = true;
+
+ // Cleanup after ourselves...
+ os.removeObserver(this, URI_VISITED_RESOLUTION_TOPIC);
+ },
+ };
+ os.addObserver(observer, URI_VISITED_RESOLUTION_TOPIC, false);
+ function notified() {
+ return observer.notified;
+ }
+
+ // Load a test page containing a link that should be initially
+ // blue, per the :link style.
+ doPageNavigation({
+ uri: getHttpUrl("bug293235.html"),
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Before we go any further, make sure our link has been notified.
+ waitForTrue(notified, nextTest);
+ yield undefined;
+
+ // Now that we've been notified, we can check our link color.
+ // Since we can't use getComputedStyle() for this because
+ // getComputedStyle lies about styles that result from :visited,
+ // we have to take snapshots.
+ // First, take two reference snapshots.
+ var link1 = $("link1");
+ link1.className = "forcelink";
+ var refLink = snapshotWindow(TestWindow.getWindow());
+ link1.className = "forcevisited";
+ var refVisited = snapshotWindow(TestWindow.getWindow());
+ link1.className = "";
+ function snapshotsEqual(snap1, snap2) {
+ return compareSnapshots(snap1, snap2, true)[0];
+ }
+ ok(!snapshotsEqual(refLink, refVisited), "references should not match");
+ ok(snapshotsEqual(refLink, snapshotWindow(TestWindow.getWindow())),
+ "link should initially be blue");
+
+ let observedVisit = false, observedPageShow = false;
+ function maybeRunNextTest() {
+ ok(true, "maybe run next test? visited: " + observedVisit + " pageShow: " + observedPageShow);
+ if (observedVisit && observedPageShow)
+ nextTest();
+ }
+
+ // Because adding visits is async, we will not be notified imemdiately.
+ let visitObserver = {
+ observe: function(aSubject, aTopic, aData)
+ {
+ if (!testURI.equals(aSubject.QueryInterface(Ci.nsIURI))) {
+ return;
+ }
+ os.removeObserver(this, aTopic);
+ observedVisit = true;
+ maybeRunNextTest();
+ },
+ };
+ os.addObserver(visitObserver, "uri-visit-saved", false);
+ // Load the page that the link on the previous page points to.
+ doPageNavigation({
+ uri: getHttpUrl("bug293235_p2.html"),
+ onNavComplete: function() {
+ observedPageShow = true;
+ maybeRunNextTest();
+ }
+ });
+ yield undefined;
+
+ // And the nodes get notified after the "link-visited" topic, so
+ // we need to execute soon...
+ SimpleTest.executeSoon(nextTest);
+ yield undefined;
+
+ // Go back, verify the original page was loaded from the bfcache,
+ // and verify that the link is now purple, per the
+ // :visited style.
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ { type: "pageshow",
+ persisted: true,
+ title: "Bug 293235 page1" } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Now we can test the link color.
+ ok(snapshotsEqual(refVisited, snapshotWindow(TestWindow.getWindow())),
+ "visited link should be purple");
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug294258_testcase.html b/docshell/test/chrome/bug294258_testcase.html
new file mode 100644
index 0000000000..cd80fefd06
--- /dev/null
+++ b/docshell/test/chrome/bug294258_testcase.html
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Bug 294258 Testcase</title>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml"/>
+ <style type="text/css">
+ * {
+ font-family: monospace;
+ }
+ </style>
+ </head>
+ <body>
+ <div>
+ <p>
+ input type="text": <input id="text" type="text"/>
+ </p>
+ <p>
+ input type="checkbox": <input id="checkbox" type="checkbox"/>
+ </p>
+ <p>
+ input type="file": <input id="file" type="file"/>
+ </p>
+ <p>
+ input type="radio":
+ <input type="radio" id="radio1" name="radio" value="radio1"/>
+ <input id="radio2" type="radio" name="radio" value="radio2"/>
+ </p>
+ <p>
+ textarea: <textarea id="textarea" rows="4" cols="80"></textarea>
+ </p>
+ <p>
+ select -> option: <select id="select">
+ <option>1</option>
+ <option>2</option>
+ <option>3</option>
+ <option>4</option>
+ </select>
+ </p>
+ </div>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug294258_window.xul b/docshell/test/chrome/bug294258_window.xul
new file mode 100644
index 0000000000..f25097eab9
--- /dev/null
+++ b/docshell/test/chrome/bug294258_window.xul
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="294258Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 294258 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ function $(id) { return TestWindow.getDocument().getElementById(id); }
+
+ ////
+ // Generator function for test steps for bug 294258:
+ // Form values should be preserved on reload.
+ //
+ function testIterator()
+ {
+ // Load a page containing a form.
+ doPageNavigation( {
+ uri: getHttpUrl("bug294258_testcase.html"),
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ // Change the data for each of the form fields, and reload.
+ $("text").value = "text value";
+ $("checkbox").checked = true;
+ var file = Components.classes["@mozilla.org/file/directory_service;1"]
+ .getService(Components.interfaces.nsIProperties)
+ .get("TmpD", Components.interfaces.nsILocalFile);
+ file.append("294258_test.file");
+ file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
+ filePath = file.path;
+ $("file").value = filePath;
+ $("textarea").value = "textarea value";
+ $("radio1").checked = true;
+ $("select").selectedIndex = 2;
+ doPageNavigation( {
+ reload: true,
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ // Verify that none of the form data has changed.
+ is($("text").value, "text value", "Text value changed");
+ is($("checkbox").checked, true, "Checkbox value changed");
+ is($("file").value, filePath, "File value changed");
+ is($("textarea").value, "textarea value", "Textarea value changed");
+ is($("radio1").checked, true, "Radio value changed");
+ is($("select").selectedIndex, 2, "Select value changed");
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug298622_window.xul b/docshell/test/chrome/bug298622_window.xul
new file mode 100755
index 0000000000..2773f34202
--- /dev/null
+++ b/docshell/test/chrome/bug298622_window.xul
@@ -0,0 +1,148 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="298622Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 298622 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src= "docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ // Global variable that holds a reference to the find bar.
+ var gFindBar;
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 298622:
+ // Find should work correctly on a page loaded from the
+ // bfcache.
+ //
+ function testIterator()
+ {
+ // Make sure bfcache is on.
+ enableBFCache(true);
+
+ // Load a test page which contains some text to be found.
+ doPageNavigation({
+ uri: "data:text/html,<html><head><title>test1</title></head>" +
+ "<body>find this!</body></html>",
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Load a second, dummy page, verifying that the original
+ // page gets stored in the bfcache.
+ doPageNavigation({
+ uri: getHttpUrl("generic.html"),
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "test1",
+ persisted: true },
+ { type: "pageshow",
+ title: "generic page" } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Make sure we unsuppress painting before continuing
+ SimpleTest.executeSoon(nextTest);
+ yield undefined;
+
+ // Search for some text that's on the second page (but not on
+ // the first page), and verify that it can be found.
+ gFindBar = document.getElementById("FindToolbar");
+ document.getElementById("cmd_find").doCommand();
+ ok(!gFindBar.hidden, "failed to open findbar");
+ gFindBar._findField.value = "A generic page";
+ gFindBar._find();
+ SimpleTest.executeSoon(nextTest);
+ yield undefined;
+
+ // Make sure Find bar's internal status is not 'notfound'
+ isnot(gFindBar._findField.getAttribute("status"), "notfound",
+ "Findfield status attribute should not have been 'notfound'" +
+ " after Find");
+
+ // Make sure the key events above have time to be processed
+ // before continuing
+ waitForTrue(function() {
+ return (
+ TestWindow.getWindow().getSelection().toString().toLowerCase() ==
+ "a generic page");
+ }, nextTest, 20);
+ yield undefined;
+
+ is(gFindBar._findField.inputField.value, "A generic page",
+ "expected text not present in find input field");
+ is(TestWindow.getWindow().getSelection().toString().toLowerCase(),
+ "a generic page",
+ "find failed on second page loaded");
+
+ // Go back to the original page and verify it's loaded from the
+ // bfcache.
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ { type: "pageshow",
+ title: "test1",
+ persisted: true } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Search for some text that's on the original page (but not
+ // the dummy page loaded above), and verify that it can
+ // be found.
+ gFindBar = document.getElementById("FindToolbar");
+ document.getElementById("cmd_find").doCommand();
+ ok(!gFindBar.hidden, "failed to open findbar");
+ gFindBar._findField.value = "find this";
+ gFindBar._find();
+ SimpleTest.executeSoon(nextTest);
+ yield undefined;
+
+ // Make sure Find bar's internal status is not 'notfound'
+ isnot(gFindBar._findField.getAttribute("status"), "notfound",
+ "Findfield status attribute should not have been 'notfound'" +
+ " after Find");
+
+ // Make sure the key events above have time to be processed
+ // before continuing
+ waitForTrue(function() {
+ return (
+ TestWindow.getWindow().getSelection().toString().toLowerCase() ==
+ "find this");
+ }, nextTest, 20);
+ yield undefined;
+
+ is(TestWindow.getWindow().getSelection().toString().toLowerCase(),
+ "find this",
+ "find failed on page loaded from bfcache");
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <commandset>
+ <command id="cmd_find"
+ oncommand="document.getElementById('FindToolbar').onFindCommand();"/>
+ </commandset>
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+ <findbar id="FindToolbar" browserid="content"/>
+</window>
diff --git a/docshell/test/chrome/bug301397_1.html b/docshell/test/chrome/bug301397_1.html
new file mode 100644
index 0000000000..9943c2efe6
--- /dev/null
+++ b/docshell/test/chrome/bug301397_1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>iframe parent</title>
+ </head>
+<body>
+ <iframe id="iframe" src="bug301397_2.html"/>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_2.html b/docshell/test/chrome/bug301397_2.html
new file mode 100644
index 0000000000..4237107060
--- /dev/null
+++ b/docshell/test/chrome/bug301397_2.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>iframe content #1</title>
+ </head>
+<body>
+ iframe page 1<br/>
+ <a id="link" href="bug301397_3.html">go to next page</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_3.html b/docshell/test/chrome/bug301397_3.html
new file mode 100644
index 0000000000..8d36e92461
--- /dev/null
+++ b/docshell/test/chrome/bug301397_3.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>iframe content #2</title>
+ </head>
+<body>
+ iframe page 2<br/>
+ You made it!
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_4.html b/docshell/test/chrome/bug301397_4.html
new file mode 100644
index 0000000000..5584a4554a
--- /dev/null
+++ b/docshell/test/chrome/bug301397_4.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>dummy page, no iframe</title>
+ </head>
+<body>
+ Just a boring test page, nothing special.
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_window.xul b/docshell/test/chrome/bug301397_window.xul
new file mode 100644
index 0000000000..5df33c5c95
--- /dev/null
+++ b/docshell/test/chrome/bug301397_window.xul
@@ -0,0 +1,250 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="301397Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 301397 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Return the document element with the specified id.
+ //
+ function $(id) { return TestWindow.getDocument().getElementById(id); }
+
+ ////
+ // Verifies that the given string exists in the innerHTML of the iframe
+ // content.
+ //
+ function verifyIframeInnerHtml(string) {
+ var iframeInnerHtml = $("iframe").contentDocument.body.innerHTML;
+ ok(iframeInnerHtml.indexOf(string) != -1,
+ "iframe contains wrong document: " + iframeInnerHtml);
+ }
+
+ ////
+ // Generator function for test steps for bug 301397:
+ // The correct page should be displayed in an iframe when
+ // navigating back and forwards, when the parent page
+ // occupies multiple spots in the session history.
+ //
+ function testIterator()
+ {
+ // Make sure the bfcache is enabled.
+ enableBFCache(8);
+
+ // Load a dummy page.
+ doPageNavigation({
+ uri: getHttpUrl("generic.html"),
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Load a page containing an iframe.
+ doPageNavigation({
+ uri: getHttpUrl("bug301397_1.html"),
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "generic page",
+ persisted: true },
+ { type: "pageshow",
+ title: "iframe content #1",
+ persisted: false }, // false on initial load
+ { type: "pageshow",
+ title: "iframe parent",
+ persisted: false } ], // false on initial load
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Click a link in the iframe to cause the iframe to navigate
+ // to a new page, and wait until the related pagehide/pageshow
+ // events have occurred.
+ waitForPageEvents({
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe content #1",
+ persisted: false }, // false, subframe nav
+ { type: "pageshow",
+ title: "iframe content #2",
+ persisted: false } ], // false on initial load
+ onNavComplete: nextTest
+ });
+ var link = $("iframe").contentDocument.getElementById("link");
+ var event = $("iframe").contentDocument.createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, $("iframe").contentWindow,
+ 0, 0, 0, 0, 0,
+ false, false, false, false,
+ 0, null);
+ link.dispatchEvent(event);
+ yield undefined;
+
+ // Load another dummy page. Verify that both the outgoing parent and
+ // iframe pages are stored in the bfcache.
+ doPageNavigation({
+ uri: getHttpUrl("bug301397_4.html"),
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe parent",
+ persisted: true },
+ { type: "pagehide",
+ title: "iframe content #2",
+ persisted: true },
+ { type: "pageshow",
+ title: "dummy page, no iframe",
+ persisted: false } ], // false on initial load
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Go back. The iframe should show the second page loaded in it.
+ // Both the parent and the iframe pages should be loaded from
+ // the bfcache.
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "dummy page, no iframe",
+ persisted: true },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe content #2" },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe parent" } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ verifyIframeInnerHtml("You made it");
+
+ // Go gack again. The iframe should show the first page loaded in it.
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe content #2",
+ persisted: false }, // false, subframe nav
+ { type: "pageshow",
+ title: "iframe content #1",
+ // false since this page was never stored
+ // in the bfcache in the first place
+ persisted: false } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ verifyIframeInnerHtml("go to next page");
+
+ // Go back to the generic page. Now go forward to the last page,
+ // again verifying that the iframe shows the first and second
+ // pages in order.
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe parent",
+ persisted: true },
+ { type: "pagehide",
+ title: "iframe content #1",
+ persisted: true },
+ { type: "pageshow",
+ title: "generic page",
+ persisted: true } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ doPageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow",
+ title: "iframe content #1",
+ persisted: true},
+ {type: "pageshow",
+ title: "iframe parent",
+ persisted: true} ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ verifyIframeInnerHtml("go to next page");
+
+ doPageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe content #1",
+ persisted: false }, // false, subframe nav
+ { type: "pageshow",
+ title: "iframe content #2",
+ // false because the page wasn't stored in
+ // bfcache last time it was unloaded
+ persisted: false } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ verifyIframeInnerHtml("You made it");
+
+ doPageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe parent",
+ persisted: true },
+ { type: "pagehide",
+ title: "iframe content #2",
+ persisted: true },
+ { type: "pageshow",
+ title: "dummy page, no iframe",
+ persisted: true } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Go back once more, and again verify that the iframe shows the
+ // second page loaded in it.
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "dummy page, no iframe",
+ persisted: true },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe content #2" },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe parent" } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ verifyIframeInnerHtml("You made it");
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug303267.html b/docshell/test/chrome/bug303267.html
new file mode 100644
index 0000000000..32b575eee8
--- /dev/null
+++ b/docshell/test/chrome/bug303267.html
@@ -0,0 +1,25 @@
+<html>
+<head>
+ <title>
+ bug303267.html
+ </title>
+ </head>
+<body onpageshow="showpageshowcount()">
+<script>
+var pageshowcount = 0;
+function showpageshowcount()
+{
+ pageshowcount++;
+ var div1 = document.getElementById("div1");
+ while (div1.firstChild)
+ {
+ div1.removeChild(div1.firstChild);
+ }
+ div1.appendChild(document.createTextNode(
+ "pageshowcount: " + pageshowcount));
+}
+</script>
+<div id="div1">
+ </div>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug303267_window.xul b/docshell/test/chrome/bug303267_window.xul
new file mode 100755
index 0000000000..46a1937128
--- /dev/null
+++ b/docshell/test/chrome/bug303267_window.xul
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="303267Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 303267 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 303267: When a page is
+ // displayed from the bfcache, the script globals should
+ // remain intact from the page's initial load.
+ //
+ function testIterator()
+ {
+ // Load an initial test page which should be saved in the bfcache.
+ var navData = {
+ uri: getHttpUrl("bug303267.html"),
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow", title: "bug303267.html"} ],
+ onNavComplete: nextTest
+ };
+ doPageNavigation(navData);
+ yield undefined;
+
+ // Save the HTML of the test page for later comparison.
+ var originalHTML = getInnerHTMLById("div1");
+
+ // Load a second test page. The first test page's pagehide event should
+ // have the .persisted property set to true, indicating that it was
+ // stored in the bfcache.
+ navData = {
+ uri: "data:text/html,<html><head><title>page2</title></head>" +
+ "<body>bug303267, page2</body></html>",
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "bug303267.html",
+ persisted: true},
+ {type: "pageshow",
+ title: "page2"} ],
+ onNavComplete: nextTest
+ };
+ doPageNavigation(navData);
+ yield undefined;
+
+ // Go back. Verify that the pageshow event for the original test page
+ // had a .persisted property of true, indicating that it came from the
+ // bfcache.
+ navData = {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "page2"},
+ {type: "pageshow",
+ title: "bug303267.html",
+ persisted: true} ],
+ onNavComplete: nextTest
+ };
+ doPageNavigation(navData);
+ yield undefined;
+
+ // After going back, if showpagecount() could access a global variable
+ // and change the test div's innerHTML, then we pass. Otherwise, it
+ // threw an exception and the following test will fail.
+ var newHTML = getInnerHTMLById("div1");
+ isnot(originalHTML,
+ newHTML, "HTML not updated on pageshow; javascript broken?");
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ////
+ // Return the innerHTML of a particular element in the content document.
+ //
+ function getInnerHTMLById(id) {
+ return TestWindow.getDocument().getElementById(id).innerHTML;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug311007_window.xul b/docshell/test/chrome/bug311007_window.xul
new file mode 100644
index 0000000000..730580cc2b
--- /dev/null
+++ b/docshell/test/chrome/bug311007_window.xul
@@ -0,0 +1,199 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="311007Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="startup();"
+ title="bug 311007 test">
+
+ <script type="application/javascript" src="docshell_helpers.js"></script>
+ <script type="application/javascript"><![CDATA[
+/*
+ Regression test for bug 283733 and bug 307027.
+
+ Bug 283733
+ "accessing a relative anchor in a secure page removes the
+ locked icon and yellow background UI"
+
+ Bug 307027
+ "Going back from secure page to error page does not clear yellow bar"
+
+ And enhancements:
+
+ Bug 478927
+ onLocationChange should notify whether or not loading an error page.
+
+ */
+
+const kDNSErrorURI = "https://example/err.html";
+const kSecureURI =
+ "https://example.com/tests/docshell/test/navigation/blank.html";
+
+/*
+ Step 1: load a network error page. <err.html> Not Secure
+ Step 2: load a secure page. <blank.html> Secure
+ Step 3: a secure page + hashchange. <blank.html#foo> Secure (bug 283733)
+ Step 4: go back to the error page. <err.html> Not Secure (bug 307027)
+ */
+
+var gListener = null;
+
+function WebProgressListener() {
+ this._callback = null;
+}
+
+WebProgressListener.prototype = {
+ QueryInterface: function(aIID) {
+ if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
+ aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
+ aIID.equals(Components.interfaces.nsISupports))
+ return this;
+ throw Components.results.NS_NOINTERFACE;
+ },
+
+ onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
+ setTimeout(this._callback, 0, aWebProgress, aRequest, aLocation, aFlags);
+ },
+
+ set callback(aVal) {
+ this._callback = aVal;
+ }
+};
+
+function startup() {
+ gListener = new WebProgressListener();
+
+ document.getElementById("content")
+ .webProgress
+ .addProgressListener(gListener,
+ Components.interfaces.nsIWebProgress
+ .NOTIFY_LOCATION);
+
+ setTimeout(step1A, 0);
+}
+
+/******************************************************************************
+ * Step 1: Load an error page, and confirm UA knows it's insecure.
+ ******************************************************************************/
+
+function step1A() {
+ gListener.callback = step1B;
+ content.location = kDNSErrorURI;
+}
+
+function step1B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kDNSErrorURI, "Error page's URI (1)");
+
+ ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "DocShell loaded a document (1)");
+
+ ok((aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is an error page.");
+
+ ok(!(aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+ .securityUI.state &
+ Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is not a secure page (1)");
+
+ /* Go to step 2. */
+ setTimeout(step2A, 0);
+}
+
+/******************************************************************************
+ * Step 2: Load a HTTPS page, and confirm it's secure.
+ ******************************************************************************/
+
+function step2A() {
+ gListener.callback = step2B;
+ content.location = kSecureURI;
+}
+
+function step2B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kSecureURI, "A URI on HTTPS (2)");
+
+ ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "DocShell loaded a document (2)");
+
+ ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is not an error page.");
+
+ ok((aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+ .securityUI.state &
+ Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is a secure page (2)");
+
+ /* Go to step 3. */
+ setTimeout(step3A, 0);
+}
+
+/*****************************************************************************
+ * Step 3: Trigger hashchange within a secure page, and confirm UA knows
+ * it's secure. (Bug 283733)
+ *****************************************************************************/
+
+function step3A() {
+ gListener.callback = step3B;
+ content.location += "#foo";
+}
+
+function step3B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kSecureURI + "#foo", "hashchange on HTTPS (3)");
+
+ ok((aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "We are in the same document as before (3)");
+
+ ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is not an error page.");
+
+ ok((aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+ .securityUI.state &
+ Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is a secure page (3)");
+
+ /* Go to step 4. */
+ setTimeout(step4A, 0);
+}
+
+/*****************************************************************************
+ * Step 4: Go back from a secure page to an error page, and confirm UA knows
+ * it's not secure. (Bug 307027)
+ *****************************************************************************/
+
+function step4A() {
+ gListener.callback = step4B;
+ content.history.go(-2);
+}
+
+function step4B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kDNSErrorURI, "Go back to the error URI (4)");
+
+ ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "DocShell loaded a document (4)");
+
+ ok((aFlags & Components.interfaces.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is an error page.");
+
+ ok(!(aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+ .securityUI.state &
+ Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is not a secure page (4)");
+
+ /* End. */
+ aWebProgress.removeProgressListener(gListener);
+ delete(gListener);
+ finish();
+}
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug321671_window.xul b/docshell/test/chrome/bug321671_window.xul
new file mode 100755
index 0000000000..addd045709
--- /dev/null
+++ b/docshell/test/chrome/bug321671_window.xul
@@ -0,0 +1,133 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="321671Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 321671 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ // Maximum number of entries in the bfcache for this session history.
+ // This number is hardcoded in docshell code. In the test, we'll
+ // navigate through enough pages so that we hit one that's been
+ // evicted from the bfcache because it's farther from the current
+ // page than this number.
+ const MAX_BFCACHE_PAGES = 3;
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 321671: Scroll position
+ // should be retained when moving backwards and forwards through pages
+ // when bfcache is enabled.
+ //
+ function testIterator()
+ {
+ // Variable to hold the scroll positions of the test pages.
+ var scrollPositions = [];
+
+ // Make sure bfcache is on.
+ enableBFCache(true);
+
+ // Load enough test pages that so the first one is evicted from the
+ // bfcache, scroll down on each page, and save the
+ // current scroll position before continuing. Verify that each
+ // page we're navigating away from is initially put into the bfcache.
+ for (var i = 0; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ doPageNavigation( {
+ uri: "data:text/html,<html><head><title>bug321671 page" + (i + 1) +
+ "</title></head>" +
+ "<body><table border='1' width='300' height='1000'>" +
+ "<tbody><tr><td>" +
+ " page " + (i + 1) + ": foobar foobar foobar foobar " +
+ "</td></tr></tbody></table> " +
+ "</body></html>",
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ persisted: true,
+ title: i == 0 ?
+ undefined : "bug321671 page" + i },
+ { type: "pageshow",
+ title: "bug321671 page" + (i + 1) } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ is(TestWindow.getWindow().scrollY, 0,
+ "Page initially has non-zero scrollY position");
+ TestWindow.getWindow().scrollByLines(10 + (2*i));
+ ok(TestWindow.getWindow().scrollY > 0,
+ "Page has zero scrollY position after scrolling");
+ scrollPositions[i] = TestWindow.getWindow().scrollY;
+ }
+
+ // Go back to the first page, one page at a time. For each 'back'
+ // action, verify that its vertical scroll position is restored
+ // correctly. Verify that the last page in the sequence
+ // does not come from the bfcache. Again verify that all pages
+ // that we navigate away from are initially
+ // stored in the bfcache.
+ for (i = MAX_BFCACHE_PAGES + 1; i > 0; i--) {
+ doPageNavigation( {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "bug321671 page" + (i+1),
+ persisted: true },
+ { type: "pageshow",
+ title: "bug321671 page" + i,
+ persisted: i > 1 } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ is(TestWindow.getWindow().scrollY, scrollPositions[i-1],
+ "Scroll position not restored while going back!");
+ }
+
+ // Traverse history forward now, and verify scroll position is still
+ // restored. Similar to the backward traversal, verify that all
+ // but the last page in the sequence comes from the bfcache. Also
+ // verify that all of the pages get stored in the bfcache when we
+ // navigate away from them.
+ for (i = 1; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ doPageNavigation( {
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ persisted: true,
+ title: "bug321671 page" + i },
+ { type: "pageshow",
+ persisted: i < MAX_BFCACHE_PAGES + 1,
+ title: "bug321671 page" + (i + 1) } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ is(TestWindow.getWindow().scrollY, scrollPositions[i],
+ "Scroll position not restored while going forward!");
+ }
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug360511_case1.html b/docshell/test/chrome/bug360511_case1.html
new file mode 100644
index 0000000000..cca043bb66
--- /dev/null
+++ b/docshell/test/chrome/bug360511_case1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>
+ bug360511 case 1
+ </title>
+ </head>
+<body style="height: 100%">
+<a id="link1" href="#bottom">jump to bottom</a>
+<div id="div1" style="height: 200%; border: thin solid black;">
+ hello large div
+ </div>
+ <a name="bottom">here's the bottom of the page</a>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug360511_case2.html b/docshell/test/chrome/bug360511_case2.html
new file mode 100644
index 0000000000..217f47724e
--- /dev/null
+++ b/docshell/test/chrome/bug360511_case2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>
+ bug360511 case 2
+ </title>
+ </head>
+<body style="height: 100%">
+<a id="link1" href="#bottom">jump to bottom</a>
+<div id="div1" style="height: 200%; border: thin solid black;">
+ hello large div
+ </div>
+ <a name="bottom">here's the bottom of the page</a>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug360511_window.xul b/docshell/test/chrome/bug360511_window.xul
new file mode 100755
index 0000000000..9d0cde7f1f
--- /dev/null
+++ b/docshell/test/chrome/bug360511_window.xul
@@ -0,0 +1,134 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="360511Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 360511 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 360511:
+ // Fragment uri's in session history should be restored correctly
+ // upon back navigation.
+ //
+ function testIterator()
+ {
+ // Case 1: load a page containing a fragment link; the page should be
+ // stored in the bfcache.
+ // Case 2: load a page containing a fragment link; the page should NOT
+ // be stored in the bfcache.
+ for (var i = 1; i < 3; i++)
+ {
+ var url = "bug360511_case" + i + ".html";
+ doPageNavigation( {
+ uri: getHttpUrl(url),
+ onNavComplete: nextTest,
+ preventBFCache: i != 1
+ } );
+ yield undefined;
+
+ // Store the original url for later comparison.
+ var originalUrl = TestWindow.getBrowser().currentURI.spec;
+ var originalDocLocation = TestWindow.getDocument().location.href;
+
+ // Verify we're at the top of the page.
+ is(TestWindow.getWindow().scrollY, 0,
+ "Page initially has a non-zero scrollY property");
+
+ // Click the on the fragment link in the browser, and use setTimeout
+ // to give the event a chance to be processed.
+ var event = TestWindow.getDocument().createEvent('MouseEvent');
+ event.initMouseEvent("click", true, true, TestWindow.getWindow(), 0,
+ 0, 0, 0, 0,
+ false, false, false, false, 0, null);
+ TestWindow.getDocument().getElementById("link1").dispatchEvent(event);
+ setTimeout(nextTest, 0);
+ yield undefined;
+
+ // Store the fragment url for later comparison.
+ var fragmentUrl = TestWindow.getBrowser().currentURI.spec;
+ var fragDocLocation = TestWindow.getDocument().location.href;
+
+ // Verify we're no longer at the top of the page.
+ ok(TestWindow.getWindow().scrollY > 0,
+ "We're at the top of the page but we should be at the bottom");
+
+ // Now navigate to any other page
+ var expectedPageTitle = "bug360511 case " + i;
+ doPageNavigation( {
+ uri: getHttpUrl("generic.html"),
+ eventsToListenFor: ["pagehide", "pageshow"],
+ expectedEvents: [ {type: "pagehide", title: expectedPageTitle,
+ persisted: i == 1},
+ {type: "pageshow"} ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ // Go back
+ doPageNavigation( {
+ back: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow", title: expectedPageTitle,
+ persisted: i == 1} ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ // Verify the current url is the fragment url
+ is(TestWindow.getBrowser().currentURI.spec, fragmentUrl,
+ "current url is not the previous fragment url");
+ is(TestWindow.getDocument().location.href, fragDocLocation,
+ "document.location is not the previous fragment url");
+
+ // Go back again. Since we're just going from a fragment url to
+ // parent url, no pageshow event is fired, so don't wait for any
+ // events. Rather, just wait for the page's scrollY property to
+ // change.
+ var originalScrollY = TestWindow.getWindow().scrollY;
+ doPageNavigation( {
+ back: true,
+ eventsToListenFor: []
+ } );
+ waitForTrue(
+ function() {
+ return (TestWindow.getWindow().scrollY != originalScrollY);
+ },
+ function() {
+ setTimeout(nextTest, 0);
+ }, 20);
+ yield undefined;
+
+ // Verify the current url is the original url without fragment
+ is(TestWindow.getBrowser().currentURI.spec, originalUrl,
+ "current url is not the original url");
+ is(TestWindow.getDocument().location.href, originalDocLocation,
+ "document.location is not the original url");
+ }
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug364461_window.xul b/docshell/test/chrome/bug364461_window.xul
new file mode 100644
index 0000000000..a05a33b3f6
--- /dev/null
+++ b/docshell/test/chrome/bug364461_window.xul
@@ -0,0 +1,277 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="364461Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="364461 test">
+
+ <script type="application/javascript"><![CDATA[
+
+ const LISTEN_EVENTS = ["load", "unload", "pageshow", "pagehide"];
+
+ var gBrowser;
+ var gTestsIterator;
+ var gExpected = [];
+
+ function ok(condition, message) {
+ window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
+ }
+ function is(a, b, message) {
+ window.opener.wrappedJSObject.SimpleTest.is(a, b, message);
+ }
+ function finish() {
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.removeEventListener(eventType, eventListener, true);
+ }
+
+ window.close();
+ window.opener.wrappedJSObject.SimpleTest.finish();
+ }
+
+ function onLoad() {
+ gBrowser = document.getElementById("content");
+
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.addEventListener(eventType, eventListener, true);
+ }
+
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function eventListener(event) {
+ ok(gExpected.length >= 1, "Unexpected event " + event.type);
+ if (gExpected.length == 0) {
+ // in case of unexpected event, try to continue anyway
+ setTimeout(nextTest, 0);
+ return;
+ }
+
+ var exp = gExpected.shift();
+ is(event.type, exp.type, "Invalid event received");
+ if (typeof(exp.persisted) != "undefined") {
+ is(event.persisted, exp.persisted, "Invalid persisted state");
+ }
+ if (exp.title) {
+ ok(event.originalTarget instanceof HTMLDocument,
+ "originalTarget not a HTMLDocument");
+ is(event.originalTarget.title, exp.title, "titles don't match");
+ }
+
+ if (gExpected.length == 0) {
+ setTimeout(nextTest, 0);
+ }
+ }
+
+ function nextTest() {
+ try {
+ gTestsIterator.next();
+ } catch (err if err instanceof StopIteration) {
+ finish();
+ }
+ }
+
+ function testsIterator() {
+
+ // Tests 1 + 2:
+ // Back/forward between two simple documents. Bfcache will be used.
+
+ var test1Doc = "data:text/html,<html><head><title>test1</title></head>" +
+ "<body>test1</body></html>";
+
+ gExpected = [{type: "pagehide", persisted: true},
+
+ {type: "load", title: "test1"},
+ {type: "pageshow", title: "test1", persisted: false}];
+ gBrowser.loadURI(test1Doc);
+ yield undefined;
+
+ var test2Doc = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test1", persisted: true},
+ {type: "load", title: "test2"},
+ {type: "pageshow", title: "test2", persisted: false}];
+ gBrowser.loadURI(test2Doc);
+ yield undefined;
+
+ gExpected = [{type: "pagehide", title: "test2", persisted: true},
+ {type: "pageshow", title: "test1", persisted: true}];
+ gBrowser.goBack();
+ yield undefined;
+
+ gExpected = [{type: "pagehide", title: "test1", persisted: true},
+ {type: "pageshow", title: "test2", persisted: true}];
+ gBrowser.goForward();
+ yield undefined;
+
+ // Tests 3 + 4:
+ // Back/forward between a two-level deep iframed document and a simple
+ // document. Bfcache will be used and events should be dispatched to
+ // all frames.
+
+ var test3Doc = "data:text/html,<html><head><title>test3</title>" +
+ "</head><body>" +
+ "<iframe src='data:text/html," +
+ "<html><head><title>test3-nested1</title></head>" +
+ "<body>test3-nested1" +
+ "<iframe src=\"data:text/html," +
+ "<html><head><title>test3-nested2</title></head>" +
+ "<body>test3-nested2</body></html>\">" +
+ "</iframe>" +
+ "</body></html>'>" +
+ "</iframe>" +
+ "</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test2", persisted: true},
+ {type: "load", title: "test3-nested2"},
+ {type: "pageshow", title: "test3-nested2", persisted: false},
+ {type: "load", title: "test3-nested1"},
+ {type: "pageshow", title: "test3-nested1", persisted: false},
+ {type: "load", title: "test3"},
+ {type: "pageshow", title: "test3", persisted: false}];
+ gBrowser.loadURI(test3Doc);
+ yield undefined;
+
+ var test4Doc = "data:text/html,<html><head><title>test4</title></head>" +
+ "<body>test4</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test3", persisted: true},
+ {type: "pagehide", title: "test3-nested1", persisted: true},
+ {type: "pagehide", title: "test3-nested2", persisted: true},
+ {type: "load", title: "test4"},
+ {type: "pageshow", title: "test4", persisted: false}];
+ gBrowser.loadURI(test4Doc);
+ yield undefined;
+
+ gExpected = [{type: "pagehide", title: "test4", persisted: true},
+ {type: "pageshow", title: "test3-nested2", persisted: true},
+ {type: "pageshow", title: "test3-nested1", persisted: true},
+ {type: "pageshow", title: "test3", persisted: true}];
+ gBrowser.goBack();
+ yield undefined;
+
+ // This is where the two nested pagehide are not dispatched in bug 364461
+ gExpected = [{type: "pagehide", title: "test3", persisted: true},
+ {type: "pagehide", title: "test3-nested1", persisted: true},
+ {type: "pagehide", title: "test3-nested2", persisted: true},
+ {type: "pageshow", title: "test4", persisted: true}];
+ gBrowser.goForward();
+ yield undefined;
+
+ // Tests 5 + 6:
+ // Back/forward between a document containing an unload handler and a
+ // a simple document. Bfcache won't be used for the first one (see
+ // http://developer.mozilla.org/en/docs/Using_Firefox_1.5_caching).
+
+ var test5Doc = "data:text/html,<html><head><title>test5</title></head>" +
+ "<body onunload='while(false) { /* nop */ }'>" +
+ "test5</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test4", persisted: true},
+ {type: "load", title: "test5"},
+ {type: "pageshow", title: "test5", persisted: false}];
+ gBrowser.loadURI(test5Doc);
+ yield undefined;
+
+ var test6Doc = "data:text/html,<html><head><title>test6</title></head>" +
+ "<body>test6</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test5", persisted: false},
+ {type: "unload", title: "test5"},
+ {type: "load", title: "test6"},
+ {type: "pageshow", title: "test6", persisted: false}];
+ gBrowser.loadURI(test6Doc);
+ yield undefined;
+
+ gExpected = [{type: "pagehide", title: "test6", persisted: true},
+ {type: "load", title: "test5"},
+ {type: "pageshow", title: "test5", persisted: false}];
+ gBrowser.goBack();
+ yield undefined;
+
+ gExpected = [{type: "pagehide", title: "test5", persisted: false},
+ {type: "unload", title: "test5"},
+ {type: "pageshow", title: "test6", persisted: true}];
+ gBrowser.goForward();
+ yield undefined;
+
+ // Test 7:
+ // Testcase from https://bugzilla.mozilla.org/show_bug.cgi?id=384977#c10
+ // Check that navigation is not blocked after a document is restored
+ // from bfcache
+
+ var test7Doc = "data:text/html,<html><head><title>test7</title>" +
+ "</head><body>" +
+ "<iframe src='data:text/html," +
+ "<html><head><title>test7-nested1</title></head>" +
+ "<body>test7-nested1<br/>" +
+ "<a href=\"data:text/plain,aaa\" target=\"_top\">" +
+ "Click me, hit back, click me again</a>" +
+ "</body></html>'>" +
+ "</iframe>" +
+ "</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test6", persisted: true},
+ {type: "load", title: "test7-nested1"},
+ {type: "pageshow", title: "test7-nested1", persisted: false},
+ {type: "load", title: "test7"},
+ {type: "pageshow", title: "test7", persisted: false}];
+ gBrowser.loadURI(test7Doc);
+ yield undefined;
+
+ // Simulates a click on the link inside the iframe
+ function clickIframeLink() {
+ var iframe = gBrowser.contentDocument.getElementsByTagName("iframe")[0];
+ var w = iframe.contentWindow;
+ var d = iframe.contentDocument;
+
+ var evt = d.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, w,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ d.getElementsByTagName("a")[0].dispatchEvent(evt);
+ }
+
+ gExpected = [{type: "pagehide", title: "test7", persisted: true},
+ {type: "pagehide", title: "test7-nested1", persisted: true},
+ {type: "load"},
+ {type: "pageshow", persisted: false}];
+ clickIframeLink();
+ yield undefined;
+
+ is(gBrowser.currentURI.spec, "data:text/plain,aaa",
+ "Navigation is blocked when clicking link");
+
+ gExpected = [{type: "pagehide", persisted: true},
+ {type: "pageshow", title: "test7-nested1", persisted: true},
+ {type: "pageshow", title: "test7", persisted: true}];
+ gBrowser.goBack();
+ yield undefined;
+
+ gExpected = [{type: "pagehide", title: "test7", persisted: true},
+ {type: "pagehide", title: "test7-nested1", persisted: true},
+ {type: "load"},
+ {type: "pageshow", persisted: false}];
+ clickIframeLink();
+ yield undefined;
+
+ is(gBrowser.currentURI.spec, "data:text/plain,aaa",
+ "Navigation is blocked when clicking link");
+
+ // nextTest has to be called from here, as no events are fired in this
+ // step
+ setTimeout(nextTest, 0);
+ yield undefined;
+ }
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug396519_window.xul b/docshell/test/chrome/bug396519_window.xul
new file mode 100644
index 0000000000..32497b1639
--- /dev/null
+++ b/docshell/test/chrome/bug396519_window.xul
@@ -0,0 +1,169 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="396519Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="396519 test">
+
+ <script type="application/javascript"><![CDATA[
+
+ const LISTEN_EVENTS = ["pageshow"];
+
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+
+ var gBrowser;
+ var gTestCount = 0;
+ var gTestsIterator;
+ var gExpected = [];
+
+ function ok(condition, message) {
+ window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
+ }
+ function is(a, b, message) {
+ window.opener.wrappedJSObject.SimpleTest.is(a, b, message);
+ }
+ function finish() {
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.removeEventListener(eventType, eventListener, true);
+ }
+
+ window.close();
+ window.opener.wrappedJSObject.SimpleTest.finish();
+ }
+
+ function onLoad() {
+ gBrowser = document.getElementById("content");
+
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.addEventListener(eventType, eventListener, true);
+ }
+
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function eventListener(event) {
+ // we're in pageshow, but we need to let that finish
+ // content eviction and saving happen during pageshow, so when doTest
+ // runs, we should should be in a testable state
+ setTimeout(doTest, 0);
+ }
+
+ function doTest() {
+ var history = gBrowser.webNavigation.sessionHistory;
+ if (history.count == gExpected.length) {
+ for (var i=0; i<history.count; i++) {
+ var shEntry = history.getEntryAtIndex(i,false).
+ QueryInterface(Components.interfaces.nsISHEntry);
+ is(!!shEntry.contentViewer, gExpected[i], "content viewer "+i+", test "+gTestCount);
+ }
+
+ // Make sure none of the SHEntries share bfcache entries with one
+ // another.
+ for (var i = 0; i < history.count; i++) {
+ for (var j = 0; j < history.count; j++) {
+ if (j == i)
+ continue;
+
+ let shentry1 = history.getEntryAtIndex(i, false)
+ .QueryInterface(Ci.nsISHEntry);
+ let shentry2 = history.getEntryAtIndex(j, false)
+ .QueryInterface(Ci.nsISHEntry);
+ ok(!shentry1.sharesDocumentWith(shentry2),
+ 'Test ' + gTestCount + ': shentry[' + i + "] shouldn't " +
+ "share document with shentry[" + j + ']');
+ }
+ }
+ }
+ else {
+ is(history.count, gExpected.length, "Wrong history length in test "+gTestCount);
+ }
+
+ setTimeout(nextTest, 0);
+ }
+
+ function nextTest() {
+ try {
+ gTestsIterator.next();
+ } catch (err if err instanceof StopIteration) {
+ finish();
+ }
+ }
+
+ function testsIterator() {
+
+ // Tests 1 + 2:
+ // Back/forward between two simple documents. Bfcache will be used.
+
+ var test1Doc = "data:text/html,<html><head><title>test1</title></head>" +
+ "<body>test1</body></html>";
+
+ gTestCount++;
+ gExpected = [false];
+ gBrowser.loadURI(test1Doc);
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [true, false];
+ var test2Doc = test1Doc.replace(/1/,"2");
+ gBrowser.loadURI(test2Doc);
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [true, true, false];
+ gBrowser.loadURI(test1Doc);
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [true, true, true, false];
+ gBrowser.loadURI(test2Doc);
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [false, true, true, true, false];
+ gBrowser.loadURI(test1Doc);
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [false, false, true, true, true, false];
+ gBrowser.loadURI(test2Doc);
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [false, false, true, true, false, true];
+ gBrowser.goBack();
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [false, false, true, true, true, false];
+ gBrowser.goForward();
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [false, false, true, true, true, false];
+ gBrowser.gotoIndex(1);
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [false, true, true, true, false, false];
+ gBrowser.goBack();
+ yield undefined;
+
+ gTestCount++;
+ gExpected = [false, false, true, true, false, false];
+ gBrowser.gotoIndex(5);
+ yield undefined;
+ }
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug396649_window.xul b/docshell/test/chrome/bug396649_window.xul
new file mode 100755
index 0000000000..c94d8b78e9
--- /dev/null
+++ b/docshell/test/chrome/bug396649_window.xul
@@ -0,0 +1,122 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="396649Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 396649 test">
+
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/specialpowersAPI.js"/>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js"/>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/>
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ // Maximum number of entries in the bfcache for this session history.
+ // This number is hardcoded in docshell code. In the test, we'll
+ // navigate through enough pages so that we hit one that's been
+ // evicted from the bfcache because it's farther from the current
+ // page than this number.
+ const MAX_BFCACHE_PAGES = 3;
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 396649: Content
+ // viewers should be evicted from bfcache when going back if more
+ // than MAX_BFCACHE_PAGES from the current index.
+ //
+ function testIterator()
+ {
+ // Make sure bfcache is on.
+ enableBFCache(true);
+
+ // Load enough pages so that the first loaded is eviced from
+ // the bfcache, since it is greater the MAX_BFCACHE_PAGES from
+ // the current position in the session history. Verify all
+ // of the pages are initially stored in the bfcache when
+ // they're unloaded.
+ for (var i = 0; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ doPageNavigation( {
+ uri: "data:text/html,<!DOCTYPE html><html>" +
+ "<head><title>bug396649 page" + i +
+ "</title></head>" +
+ "<body>" +
+ "test page " + i +
+ "</body></html>",
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: i == 0 ?
+ undefined : "bug396649 page" + (i-1),
+ persisted: true },
+ { type: "pageshow",
+ title: "bug396649 page" + i } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+ }
+
+ // Go back to the first page, one page at a time. The first
+ // MAX_BFCACHE_PAGES pages loaded via back should come from the bfcache,
+ // the last should not, since it should have been evicted during the
+ // previous navigation sequence. Verify all pages are initially stored
+ // in the bfcache when they're unloaded.
+ for (i = MAX_BFCACHE_PAGES + 1; i > 0; i--) {
+ doPageNavigation( {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "bug396649 page" + i,
+ persisted: true },
+ { type: "pageshow",
+ title: "bug396649 page" + (i - 1),
+ persisted: i > 1 } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+ }
+
+ // Traverse history forward now. Again, the first MAX_BFCACHE_PAGES
+ // pages should come from the bfcache, the last should not,
+ // since it should have been evicted during the backwards
+ // traversal above. Verify all pages are initially stored
+ // in the bfcache when they're unloaded.
+ for (i = 1; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ doPageNavigation( {
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "bug396649 page" + (i-1),
+ persisted: true },
+ { type: "pageshow",
+ title: "bug396649 page" + i,
+ persisted: i < MAX_BFCACHE_PAGES + 1 } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+ }
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug449778_window.xul b/docshell/test/chrome/bug449778_window.xul
new file mode 100644
index 0000000000..b4fc5e2ba2
--- /dev/null
+++ b/docshell/test/chrome/bug449778_window.xul
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 449778" onload="doTheTest()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox id="parent">
+ </hbox>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror" ];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ function $(id) {
+ return document.getElementById(id);
+ }
+
+ function addBrowser(parent, id, width, height) {
+ var b =
+ document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
+ b.setAttribute("type", "content");
+ b.setAttribute("id", id);
+ b.setAttribute("width", width);
+ b.setAttribute("height", height);
+ $(parent).appendChild(b);
+ }
+ addBrowser("parent", "f1", 300, 200);
+ addBrowser("parent", "f2", 300, 200);
+
+ /** Test for Bug 449778 **/
+ var doc1 = "data:text/html,<html><body>This is a test</body></html>";
+ var doc2 = "data:text/html,<html><body>This is a second test</body></html>";
+ var doc3 = "data:text/html,<html><body>This is a <script>var evt = document.createEvent('Events'); evt.initEvent('testEvt', true, true); document.dispatchEvent(evt);</script>third test</body></html>";
+
+
+ $("f1").setAttribute("src", doc1);
+ $("f2").setAttribute("src", doc2);
+
+ function doTheTest() {
+ var strs = { "f1": "", "f2" : "" };
+ function attachListener(node, type) {
+ var listener = function(e) {
+ if (strs[node.id]) strs[node.id] += " ";
+ strs[node.id] += node.id + ".page" + type;
+ }
+ node.addEventListener("page" + type, listener, false);
+
+ listener.detach = function() {
+ node.removeEventListener("page" + type, listener, false);
+ }
+ return listener;
+ }
+
+ var l1 = attachListener($("f1"), "show");
+ var l2 = attachListener($("f1"), "hide");
+ var l3 = attachListener($("f2"), "show");
+ var l4 = attachListener($("f2"), "hide");
+
+ $("f1").swapDocShells($("f2"));
+
+ is(strs["f1"], "f1.pagehide f1.pageshow",
+ "Expected hide then show on first loaded page");
+ is(strs["f2"], "f2.pagehide f2.pageshow",
+ "Expected hide then show on second loaded page");
+
+ function listener2() {
+ $("f2").removeEventListener("testEvt", listener2, false);
+
+ strs = { "f1": "", "f2" : "" };
+
+ $("f1").swapDocShells($("f2"));
+ is(strs["f1"], "f1.pagehide",
+ "Expected hide on already-loaded page, then nothing");
+ is(strs["f2"], "f2.pageshow f2.pagehide f2.pageshow",
+ "Expected show on still-loading page, then hide on it, then show " +
+ "on already-loaded page");
+
+ strs = { "f1": "", "f2" : "" };
+
+ $("f1").addEventListener("pageshow", listener3, false);
+ }
+
+ function listener3() {
+ $("f1").removeEventListener("pageshow", listener3, false);
+
+ is(strs["f1"], "f1.pageshow",
+ "Expected show as our page finishes loading");
+ is(strs["f2"], "", "Expected no more events here.");
+
+ l1.detach();
+ l2.detach();
+ l3.detach();
+ l4.detach();
+
+ window.close();
+ SimpleTest.finish();
+ }
+
+ $("f2").addEventListener("testEvt", listener2, false, true);
+ $("f2").setAttribute("src", doc3);
+ }
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/bug449780_window.xul b/docshell/test/chrome/bug449780_window.xul
new file mode 100644
index 0000000000..38633c00f5
--- /dev/null
+++ b/docshell/test/chrome/bug449780_window.xul
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 449780" onload="doTheTest()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox id="parent">
+ </hbox>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror" ];
+ for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+ }
+
+ function $(id) {
+ return document.getElementById(id);
+ }
+
+ function addBrowser(parent, id, width, height) {
+ var b =
+ document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
+ b.setAttribute("type", "content");
+ b.setAttribute("id", id);
+ b.setAttribute("width", width);
+ b.setAttribute("height", height);
+ $(parent).appendChild(b);
+ }
+ addBrowser("parent", "f1", 300, 200);
+ addBrowser("parent", "f2", 300, 200);
+
+ /** Test for Bug 449780 **/
+ var doc1 = "data:text/html,<html><body>This is a test</body></html>";
+ var doc2 = "data:text/html,<html><body>This is a second test</body></html>";
+
+ function getDOM(id) {
+ return $(id).contentDocument.documentElement.innerHTML;
+ }
+
+ var tester = (function() {
+ var origDOM = getDOM("f1");
+ $("f1").contentDocument.body.textContent = "Modified";
+ var modifiedDOM = getDOM("f1");
+ isnot(origDOM, modifiedDOM, "DOM should be different");
+ $("f1").contentWindow.location.href = doc2;
+ yield undefined;
+
+ $("f1").goBack();
+ yield undefined;
+
+ is(getDOM("f1"), modifiedDOM, "Should have been bfcached");
+ $("f1").goForward();
+ yield undefined;
+
+ // Ignore the notifications during swap
+ $("f1").removeEventListener("pageshow", testDriver, false);
+ $("f1").swapDocShells($("f2"));
+ $("f2").addEventListener("pageshow", testDriver, false);
+ $("f2").goBack();
+ yield undefined;
+
+ is(getDOM("f2"), origDOM, "Should have not have been bfcached");
+ window.close();
+ SimpleTest.finish();
+ yield undefined;
+ })();
+
+ function testDriver() {
+ setTimeout(function() { tester.next() }, 0);
+ }
+
+ function doTheTest() {
+ $("f1").addEventListener("pageshow", testDriver, false);
+ $("f1").setAttribute("src", doc1);
+ }
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/bug454235-subframe.xul b/docshell/test/chrome/bug454235-subframe.xul
new file mode 100644
index 0000000000..a8b6178e65
--- /dev/null
+++ b/docshell/test/chrome/bug454235-subframe.xul
@@ -0,0 +1,7 @@
+<window title="Mozilla Bug 454235 SubFrame"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <deck flex="1">
+ <browser id="topBrowser" src="about:mozilla"/>
+ <browser id="burriedBrowser" src="about:mozilla"/>
+ </deck>
+</window>
diff --git a/docshell/test/chrome/bug582176_window.xul b/docshell/test/chrome/bug582176_window.xul
new file mode 100644
index 0000000000..ad594ee0cf
--- /dev/null
+++ b/docshell/test/chrome/bug582176_window.xul
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="303267Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="nextTestAsync();"
+ title="bug 582176 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTestAsync() {
+ SimpleTest.executeSoon(tests.next.bind(tests));
+ }
+
+ ////
+ // Generator function for test steps for bug 582176:
+ // Description goes here.
+ //
+ function testIterator()
+ {
+ var browser = document.getElementById('content');
+ browser.addEventListener("pageshow", nextTestAsync, true);
+
+ enableBFCache(true);
+
+ var notificationCount = 0;
+ var observer = {
+ observe: function(aSubject, aTopic, aData) {
+ is(aSubject, browser.contentWindow,
+ "correct subject");
+ is(aTopic, "content-document-global-created",
+ "correct topic");
+ is(aData, "http://mochi.test:8888",
+ "correct data");
+ notificationCount++;
+ }
+ };
+
+ os = Components.classes["@mozilla.org/observer-service;1"].
+ getService(Components.interfaces.nsIObserverService);
+ os.addObserver(observer, "content-document-global-created", false);
+
+ browser.loadURI("http://mochi.test:8888/tests/docshell/test/chrome/582176_dummy.html");
+ yield undefined;
+ is(browser.contentWindow.testVar, undefined,
+ "variable unexpectedly there already");
+ browser.contentWindow.wrappedJSObject.testVar = 1;
+ is(notificationCount, 1, "Should notify on first navigation");
+
+ browser.loadURI("http://mochi.test:8888/tests/docshell/test/chrome/582176_dummy.html?2");
+ yield undefined;
+ is(browser.contentWindow.wrappedJSObject.testVar, undefined,
+ "variable should no longer be there");
+ is(notificationCount, 2, "Should notify on second navigation");
+
+ browser.goBack();
+ yield undefined;
+ is(browser.contentWindow.wrappedJSObject.testVar, 1,
+ "variable should still be there");
+ is(notificationCount, 2, "Should not notify on back navigation");
+
+ browser.loadURI("http://mochi.test:8888/tests/docshell/test/chrome/582176_xml.xml");
+ yield undefined;
+ is(browser.contentDocument.body.textContent, "xslt result",
+ "Transform performed successfully");
+ is(notificationCount, 3, "Should notify only once on XSLT navigation");
+
+ os.removeObserver(observer, "content-document-global-created")
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug608669.xul b/docshell/test/chrome/bug608669.xul
new file mode 100644
index 0000000000..1ab012c14e
--- /dev/null
+++ b/docshell/test/chrome/bug608669.xul
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 608669 - Blank page"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <description flex="1" value="This window is intentionally left blank"/>
+</window>
diff --git a/docshell/test/chrome/bug662200_window.xul b/docshell/test/chrome/bug662200_window.xul
new file mode 100644
index 0000000000..a73e2d2963
--- /dev/null
+++ b/docshell/test/chrome/bug662200_window.xul
@@ -0,0 +1,129 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="303267Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 662200 test">
+
+ <script type="application/javascript"
+ src="docshell_helpers.js">
+ </script>
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 662200:
+ // Description goes here.
+ //
+ function testIterator()
+ {
+ // Load the first test page
+ var navData = {
+ uri: getHttpUrl("662200a.html"),
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow", title: "A"} ],
+ onNavComplete: nextTest
+ };
+ doPageNavigation(navData);
+ yield undefined;
+
+ // Load the second test page.
+ navData = {
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "A"},
+ {type: "pageshow",
+ title: "B"} ],
+ onNavComplete: nextTest
+ }
+ waitForPageEvents(navData);
+ var link = TestWindow.getDocument().getElementById("link");
+ var event = TestWindow.getDocument().createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, TestWindow.getWindow(),
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ link.dispatchEvent(event);
+ yield undefined;
+
+ // Load the third test page.
+ navData = {
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "B"},
+ {type: "pageshow",
+ title: "C"} ],
+ onNavComplete: nextTest
+ };
+ waitForPageEvents(navData);
+ var link = TestWindow.getDocument().getElementById("link");
+ var event = TestWindow.getDocument().createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, TestWindow.getWindow(),
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ link.dispatchEvent(event);
+ yield undefined;
+
+ // Go back.
+ navData = {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "C"},
+ {type: "pageshow",
+ title: "B"} ],
+ onNavComplete: nextTest
+ };
+ doPageNavigation(navData);
+ yield undefined;
+
+ var Ci = Components.interfaces;
+ var docshell = TestWindow.getWindow()
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ var shistory = docshell.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsISHistory)
+ .QueryInterface(Ci.nsIWebNavigation);
+
+ // Reload.
+ navData = {
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "B"},
+ {type: "pageshow",
+ title: "B"} ],
+ onNavComplete: nextTest
+ };
+ // Asking the docshell harness to reload for us will call reload on
+ // nsDocShell which has different behavior than the reload on nsSHistory
+ // so we call reload explicitly here
+ waitForPageEvents(navData);
+ shistory.reload(0);
+ yield undefined;
+
+ // After this sequence of events, we should be able to go back and forward
+ is(TestWindow.getBrowser().canGoBack, true, "Should be able to go back!");
+ is(TestWindow.getBrowser().canGoForward, true, "Should be able to go forward!");
+ is(shistory.requestedIndex, -1, "Requested index should be cleared!");
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug690056_window.xul b/docshell/test/chrome/bug690056_window.xul
new file mode 100644
index 0000000000..ce5700e39d
--- /dev/null
+++ b/docshell/test/chrome/bug690056_window.xul
@@ -0,0 +1,176 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="690056Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 6500056 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ var tests = testIterator();
+
+ function nextTest() {
+ tests.next();
+ }
+
+ // Makes sure that we fire the visibilitychange events
+ function testIterator() {
+ // Enable bfcache
+ enableBFCache(8);
+
+ // Load something for a start
+ doPageNavigation({
+ uri: 'data:text/html,<title>initial load</title>',
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Now load a new page
+ doPageNavigation({
+ uri: 'data:text/html,<title>new load</title>',
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "initial load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "hidden",
+ hidden: true },
+ // No visibilitychange events fired for initial pageload
+ { type: "pageshow",
+ title: "new load",
+ persisted: false }, // false on initial load
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Now go back
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "new load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "new load",
+ visibilityState: "hidden",
+ hidden: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "visible",
+ hidden: false },
+ { type: "pageshow",
+ title: "initial load",
+ persisted: true },
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // And forward
+ doPageNavigation({
+ forward: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "initial load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "hidden",
+ hidden: true },
+ { type: "visibilitychange",
+ title: "new load",
+ visibilityState: "visible",
+ hidden: false },
+ { type: "pageshow",
+ title: "new load",
+ persisted: true },
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ function generateDetector(state, hidden, title, name) {
+ var detector = function (event) {
+ is(event.target.hidden, hidden,
+ name + " hidden value does not match");
+ is(event.target.visibilityState, state,
+ name + " state value does not match");
+ is(event.target.title, title,
+ name + " title value does not match");
+ document.getElementById("content")
+ .removeEventListener("visibilitychange",
+ detector,
+ true);
+ nextTest();
+ }
+
+ document.getElementById("content")
+ .addEventListener("visibilitychange", detector, true);
+ }
+
+ generateDetector("hidden", true, "new load", "Going hidden");
+
+ // Now flip our docshell to not active
+ document.getElementById("content").docShellIsActive = false;
+ yield undefined;
+
+ // And navigate back; there should be no visibility state transitions
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "new load",
+ persisted: true },
+ { type: "pageshow",
+ title: "initial load",
+ persisted: true },
+ ],
+ unexpectedEvents: [ "visibilitychange" ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ generateDetector("visible", false, "initial load", "Going visible");
+
+ // Now set the docshell active again
+ document.getElementById("content").docShellIsActive = true;
+ yield undefined;
+
+ // And forward
+ doPageNavigation({
+ forward: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "initial load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "hidden",
+ hidden: true },
+ { type: "visibilitychange",
+ title: "new load",
+ visibilityState: "visible",
+ hidden: false },
+ { type: "pageshow",
+ title: "new load",
+ persisted: true },
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug846906.html b/docshell/test/chrome/bug846906.html
new file mode 100644
index 0000000000..a289417ea8
--- /dev/null
+++ b/docshell/test/chrome/bug846906.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <title>
+ </title>
+ </head>
+ <body>
+ <div id="div1" style="width:1024px; height:768px; border:none;">
+ </div>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug89419.sjs b/docshell/test/chrome/bug89419.sjs
new file mode 100644
index 0000000000..c075b1e504
--- /dev/null
+++ b/docshell/test/chrome/bug89419.sjs
@@ -0,0 +1,13 @@
+function handleRequest(request, response)
+{
+ var redirectstate = "/docshell/test/chrome/bug89419.sjs";
+ response.setStatusLine("1.1", 302, "Found");
+ if (getState(redirectstate) == "") {
+ response.setHeader("Location", "red.png", false);
+ setState(redirectstate, "red");
+ } else {
+ response.setHeader("Location", "blue.png", false);
+ setState(redirectstate, "");
+ }
+ response.setHeader("Cache-Control", "no-cache", false);
+}
diff --git a/docshell/test/chrome/bug89419_window.xul b/docshell/test/chrome/bug89419_window.xul
new file mode 100644
index 0000000000..923378ea04
--- /dev/null
+++ b/docshell/test/chrome/bug89419_window.xul
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="89419Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug 89419 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/specialpowersAPI.js"/>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js"/>
+ <script type="text/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/specialpowers.js"/>
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <script type="application/javascript"><![CDATA[
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 89419:
+ // A visited link should have the :visited style applied
+ // to it when displayed on a page which was fetched from
+ // the bfcache.
+ //
+ function testIterator()
+ {
+ // Load a test page containing an image referring to the sjs that returns
+ // a different redirect every time it's loaded.
+ doPageNavigation({
+ uri: getHttpUrl("89419.html"),
+ onNavComplete: nextTest,
+ preventBFCache: true
+ });
+ yield undefined;
+
+ var first = snapshotWindow(TestWindow.getWindow());
+
+ doPageNavigation({
+ uri: "about:blank",
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ var second = snapshotWindow(TestWindow.getWindow());
+ function snapshotsEqual(snap1, snap2) {
+ return compareSnapshots(snap1, snap2, true)[0];
+ }
+ ok(!snapshotsEqual(first, second), "about:blank should not be the same as the image web page");
+
+ doPageNavigation({
+ back: true,
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ var third = snapshotWindow(TestWindow.getWindow());
+ ok(!snapshotsEqual(third, second), "going back should not be the same as about:blank");
+ ok(snapshotsEqual(first, third), "going back should be the same as the initial load");
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug909218.html b/docshell/test/chrome/bug909218.html
new file mode 100644
index 0000000000..a11fa6000d
--- /dev/null
+++ b/docshell/test/chrome/bug909218.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+ <link rel="stylesheet" type="text/css" href="http://mochi.test:8888/tests/SimpleTest/test.css">
+ <script src="bug909218.js"></script>
+</head>
+<body>
+ <img src="http://mochi.test:8888/tests/docshell/test/chrome/red.png">
+ <!-- an iframe so we can check these too get the correct flags -->
+ <iframe src="generic.html"/>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug909218.js b/docshell/test/chrome/bug909218.js
new file mode 100644
index 0000000000..c360616f99
--- /dev/null
+++ b/docshell/test/chrome/bug909218.js
@@ -0,0 +1,2 @@
+// This file exists just to ensure that we load it with the correct flags.
+dump("bug909218.js loaded\n");
diff --git a/docshell/test/chrome/bug92598_window.xul b/docshell/test/chrome/bug92598_window.xul
new file mode 100644
index 0000000000..ed877b3839
--- /dev/null
+++ b/docshell/test/chrome/bug92598_window.xul
@@ -0,0 +1,118 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="92598Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="92598 test">
+
+ <script type="application/javascript"><![CDATA[
+ const LISTEN_EVENTS = ["load", "unload", "pageshow", "pagehide"];
+
+ var gBrowser;
+ var gTestsIterator;
+ var gExpected = [];
+
+ function ok(condition, message) {
+ window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
+ }
+
+ function is(a, b, message) {
+ window.opener.wrappedJSObject.SimpleTest.is(a, b, message);
+ }
+
+ function finish() {
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.removeEventListener(eventType, eventListener, true);
+ }
+
+ // Work around bug 467960
+ var history = gBrowser.webNavigation.sessionHistory;
+ history.PurgeHistory(history.count);
+
+ window.close();
+ window.opener.wrappedJSObject.SimpleTest.finish();
+ }
+
+ function onLoad() {
+ gBrowser = document.getElementById("content");
+ for (let eventType of LISTEN_EVENTS) {
+ gBrowser.addEventListener(eventType, eventListener, true);
+ }
+
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function eventListener(event) {
+ ok(gExpected.length >= 1, "Unexpected event " + event.type);
+ if (gExpected.length == 0) {
+ // in case of unexpected event, try to continue anyway
+ setTimeout(nextTest, 0);
+ return;
+ }
+
+ var exp = gExpected.shift();
+ is(event.type, exp.type, "Invalid event received");
+ if (typeof(exp.persisted) != "undefined") {
+ is(event.persisted, exp.persisted, "Invalid persisted state");
+ }
+ if (exp.title) {
+ ok(event.originalTarget instanceof HTMLDocument,
+ "originalTarget not a HTMLDocument");
+ is(event.originalTarget.title, exp.title, "titles don't match");
+ }
+
+ if (gExpected.length == 0) {
+ setTimeout(nextTest, 0);
+ }
+ }
+
+ function nextTest() {
+ try {
+ gTestsIterator.next();
+ } catch (err if err instanceof StopIteration) {
+ finish();
+ }
+ }
+
+ function testsIterator() {
+ // Load a page with a no-cache header, followed by a simple page
+ // On pagehide, first page should report it is not being persisted
+ var test1DocURI = "http://mochi.test:8888/tests/docshell/test/chrome/92598_nostore.html";
+
+ gExpected = [{type: "pagehide", persisted: true},
+ {type: "load", title: "test1"},
+ {type: "pageshow", title: "test1", persisted: false}];
+ gBrowser.loadURI(test1DocURI);
+ yield undefined;
+
+ var test2Doc = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+
+ gExpected = [{type: "pagehide", title: "test1", persisted: false},
+ {type: "unload", title: "test1"},
+ {type: "load", title: "test2"},
+ {type: "pageshow", title: "test2", persisted: false}];
+ gBrowser.loadURI(test2Doc);
+ yield undefined;
+
+ // Now go back in history. First page should not have been cached.
+ // Check persisted property to confirm
+ gExpected = [{type: "pagehide", title: "test2", persisted: true},
+ {type: "load", title: "test1"},
+ {type: "pageshow", title: "test1", persisted: false}];
+ gBrowser.goBack();
+ yield undefined;
+ }
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/chrome.ini b/docshell/test/chrome/chrome.ini
new file mode 100644
index 0000000000..c3c5b9f800
--- /dev/null
+++ b/docshell/test/chrome/chrome.ini
@@ -0,0 +1,88 @@
+[DEFAULT]
+skip-if = os == 'android'
+support-files =
+ 662200a.html
+ 662200b.html
+ 662200c.html
+ 89419.html
+ 92598_nostore.html
+ bug112564_window.xul
+ bug113934_window.xul
+ bug215405_window.xul
+ bug293235.html
+ bug293235_p2.html
+ bug293235_window.xul
+ bug294258_testcase.html
+ bug294258_window.xul
+ bug298622_window.xul
+ bug301397_1.html
+ bug301397_2.html
+ bug301397_3.html
+ bug301397_4.html
+ bug301397_window.xul
+ bug303267.html
+ bug303267_window.xul
+ bug311007_window.xul
+ bug321671_window.xul
+ bug360511_case1.html
+ bug360511_case2.html
+ bug360511_window.xul
+ bug364461_window.xul
+ bug396519_window.xul
+ bug396649_window.xul
+ bug449778_window.xul
+ bug449780_window.xul
+ bug454235-subframe.xul
+ bug582176_window.xul
+ bug608669.xul
+ bug662200_window.xul
+ bug690056_window.xul
+ bug846906.html
+ bug89419_window.xul
+ bug909218.html
+ bug909218.js
+ bug92598_window.xul
+ docshell_helpers.js
+ file_viewsource_forbidden_in_iframe.html
+ generic.html
+ mozFrameType_window.xul
+
+[test_allowContentRetargeting.html]
+[test_bug112564.xul]
+[test_bug113934.xul]
+[test_bug215405.xul]
+[test_bug293235.xul]
+[test_bug294258.xul]
+[test_bug298622.xul]
+[test_bug301397.xul]
+[test_bug303267.xul]
+[test_bug311007.xul]
+[test_bug321671.xul]
+[test_bug360511.xul]
+[test_bug364461.xul]
+[test_bug396519.xul]
+[test_bug396649.xul]
+[test_bug428288.html]
+[test_bug449778.xul]
+[test_bug449780.xul]
+[test_bug453650.xul]
+[test_bug454235.xul]
+# bug 684176
+skip-if = toolkit == "gtk2"
+[test_bug456980.xul]
+[test_bug565388.xul]
+skip-if = os == 'linux' || os == 'mac' # Bug 1026815
+[test_bug582176.xul]
+[test_bug608669.xul]
+[test_bug662200.xul]
+[test_bug690056.xul]
+[test_bug789773.xul]
+[test_bug846906.xul]
+[test_bug89419.xul]
+[test_bug909218.html]
+[test_bug92598.xul]
+[test_mozFrameType.xul]
+[test_principalInherit.xul]
+[test_private_hidden_window.html]
+[test_viewsource_forbidden_in_iframe.xul]
+skip-if = true # bug 1019315
diff --git a/docshell/test/chrome/docshell_helpers.js b/docshell/test/chrome/docshell_helpers.js
new file mode 100755
index 0000000000..2d55e5a6e0
--- /dev/null
+++ b/docshell/test/chrome/docshell_helpers.js
@@ -0,0 +1,496 @@
+/**
+ * Import common SimpleTest methods so that they're usable in this window.
+ */
+var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror", "todo",
+ "todo_is", "todo_isnot" ];
+for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+}
+
+/**
+ * Define global constants and variables.
+ */
+const NAV_NONE = 0;
+const NAV_BACK = 1;
+const NAV_FORWARD = 2;
+const NAV_URI = 3;
+const NAV_RELOAD = 4;
+
+var gExpectedEvents; // an array of events which are expected to
+ // be triggered by this navigation
+var gUnexpectedEvents; // an array of event names which are NOT expected
+ // to be triggered by this navigation
+var gFinalEvent; // true if the last expected event has fired
+var gUrisNotInBFCache = []; // an array of uri's which shouldn't be stored
+ // in the bfcache
+var gNavType = NAV_NONE; // defines the most recent navigation type
+ // executed by doPageNavigation
+var gOrigMaxTotalViewers = // original value of max_total_viewers,
+ undefined; // to be restored at end of test
+
+var gExtractedPath = null; //used to cache file path for extracting files from a .jar file
+
+/**
+ * The doPageNavigation() function performs page navigations asynchronously,
+ * listens for specified events, and compares actual events with a list of
+ * expected events. When all expected events have occurred, an optional
+ * callback can be notified. The parameter passed to this function is an
+ * object with the following properties:
+ *
+ * uri: if !undefined, the browser will navigate to this uri
+ *
+ * back: if true, the browser will execute goBack()
+ *
+ * forward: if true, the browser will execute goForward()
+ *
+ * reload: if true, the browser will execute reload()
+ *
+ * eventsToListenFor: an array containing one or more of the following event
+ * types to listen for: "pageshow", "pagehide", "onload",
+ * "onunload". If this property is undefined, only a
+ * single "pageshow" events will be listened for. If this
+ * property is explicitly empty, [], then no events will
+ * be listened for.
+ *
+ * expectedEvents: an array of one or more expectedEvent objects,
+ * corresponding to the events which are expected to be
+ * fired for this navigation. Each object has the
+ * following properties:
+ *
+ * type: one of the event type strings
+ * title (optional): the title of the window the
+ * event belongs to
+ * persisted (optional): the event's expected
+ * .persisted attribute
+ *
+ * This function will verify that events with the
+ * specified properties are fired in the same order as
+ * specified in the array. If .title or .persisted
+ * properties for an expectedEvent are undefined, those
+ * properties will not be verified for that particular
+ * event.
+ *
+ * This property is ignored if eventsToListenFor is
+ * undefined or [].
+ *
+ * preventBFCache: if true, an unload handler will be added to the loaded
+ * page to prevent it from being bfcached. This property
+ * has no effect when eventsToListenFor is [].
+ *
+ * onNavComplete: a callback which is notified after all expected events
+ * have occurred, or after a timeout has elapsed. This
+ * callback is not notified if eventsToListenFor is [].
+ *
+ * There must be an expectedEvent object for each event of the types in
+ * eventsToListenFor which is triggered by this navigation. For example, if
+ * eventsToListenFor = [ "pagehide", "pageshow" ], then expectedEvents
+ * must contain an object for each pagehide and pageshow event which occurs as
+ * a result of this navigation.
+ */
+function doPageNavigation(params) {
+ // Parse the parameters.
+ let back = params.back ? params.back : false;
+ let forward = params.forward ? params.forward : false;
+ let reload = params.reload ? params.reload : false;
+ let uri = params.uri ? params.uri : false;
+ let eventsToListenFor = typeof(params.eventsToListenFor) != "undefined" ?
+ params.eventsToListenFor : ["pageshow"];
+ gExpectedEvents = typeof(params.eventsToListenFor) == "undefined" ||
+ eventsToListenFor.length == 0 ? undefined : params.expectedEvents;
+ gUnexpectedEvents = typeof(params.eventsToListenFor) == "undefined" ||
+ eventsToListenFor.length == 0 ? undefined : params.unexpectedEvents;
+ let preventBFCache = (typeof[params.preventBFCache] == "undefined") ?
+ false : params.preventBFCache;
+ let waitOnly = (typeof(params.waitForEventsOnly) == "boolean"
+ && params.waitForEventsOnly);
+
+ // Do some sanity checking on arguments.
+ if (back && forward)
+ throw "Can't specify both back and forward";
+ if (back && uri)
+ throw "Can't specify both back and a uri";
+ if (forward && uri)
+ throw "Can't specify both forward and a uri";
+ if (reload && (forward || back || uri))
+ throw "Can't specify reload and another navigation type";
+ if (!back && !forward && !uri && !reload && !waitOnly)
+ throw "Must specify back or foward or reload or uri";
+ if (params.onNavComplete && eventsToListenFor.length == 0)
+ throw "Can't use onNavComplete when eventsToListenFor == []";
+ if (params.preventBFCache && eventsToListenFor.length == 0)
+ throw "Can't use preventBFCache when eventsToListenFor == []";
+ if (params.preventBFCache && waitOnly)
+ throw "Can't prevent bfcaching when only waiting for events";
+ if (waitOnly && typeof(params.onNavComplete) == "undefined")
+ throw "Must specify onNavComplete when specifying waitForEventsOnly";
+ if (waitOnly && (back || forward || reload || uri))
+ throw "Can't specify a navigation type when using waitForEventsOnly";
+ for (let anEventType of eventsToListenFor) {
+ let eventFound = false;
+ if ( (anEventType == "pageshow") && (!gExpectedEvents) )
+ eventFound = true;
+ if (gExpectedEvents) {
+ for (let anExpectedEvent of gExpectedEvents) {
+ if (anExpectedEvent.type == anEventType)
+ eventFound = true;
+ }
+ }
+ if (gUnexpectedEvents) {
+ for (let anExpectedEventType of gUnexpectedEvents) {
+ if (anExpectedEventType == anEventType)
+ eventFound = true;
+ }
+ }
+ if (!eventFound)
+ throw "Event type " + anEventType + " is specified in " +
+ "eventsToListenFor, but not in expectedEvents";
+ }
+
+ // If the test explicitly sets .eventsToListenFor to [], don't wait for any
+ // events.
+ gFinalEvent = eventsToListenFor.length == 0 ? true : false;
+
+ // Add an event listener for each type of event in the .eventsToListenFor
+ // property of the input parameters.
+ for (let eventType of eventsToListenFor) {
+ dump("TEST: registering a listener for " + eventType + " events\n");
+ TestWindow.getBrowser().addEventListener(eventType, pageEventListener,
+ true);
+ }
+
+ // Perform the specified navigation.
+ if (back) {
+ gNavType = NAV_BACK;
+ TestWindow.getBrowser().goBack();
+ }
+ else if (forward) {
+ gNavType = NAV_FORWARD;
+ TestWindow.getBrowser().goForward();
+ }
+ else if (uri) {
+ gNavType = NAV_URI;
+ TestWindow.getBrowser().loadURI(uri);
+ }
+ else if (reload) {
+ gNavType = NAV_RELOAD;
+ TestWindow.getBrowser().reload();
+ }
+ else if (waitOnly) {
+ gNavType = NAV_NONE;
+ }
+ else {
+ throw "No valid navigation type passed to doPageNavigation!";
+ }
+
+ // If we're listening for events and there is an .onNavComplete callback,
+ // wait for all events to occur, and then call doPageNavigation_complete().
+ if (eventsToListenFor.length > 0 && params.onNavComplete)
+ {
+ waitForTrue(
+ function() { return gFinalEvent; },
+ function() {
+ doPageNavigation_complete(eventsToListenFor, params.onNavComplete,
+ preventBFCache);
+ } );
+ }
+}
+
+/**
+ * Finish doPageNavigation(), by removing event listeners, adding an unload
+ * handler if appropriate, and calling the onNavComplete callback. This
+ * function is called after all the expected events for this navigation have
+ * occurred.
+ */
+function doPageNavigation_complete(eventsToListenFor, onNavComplete,
+ preventBFCache) {
+ // Unregister our event listeners.
+ dump("TEST: removing event listeners\n");
+ for (let eventType of eventsToListenFor) {
+ TestWindow.getBrowser().removeEventListener(eventType, pageEventListener,
+ true);
+ }
+
+ // If the .preventBFCache property was set, add an empty unload handler to
+ // prevent the page from being bfcached.
+ let uri = TestWindow.getBrowser().currentURI.spec;
+ if (preventBFCache) {
+ TestWindow.getWindow().addEventListener("unload", function() {
+ dump("TEST: Called dummy unload function to prevent page from " +
+ "being bfcached.\n");
+ }, true);
+
+ // Save the current uri in an array of uri's which shouldn't be
+ // stored in the bfcache, for later verification.
+ if (!(uri in gUrisNotInBFCache)) {
+ gUrisNotInBFCache.push(uri);
+ }
+ } else if (gNavType == NAV_URI) {
+ // If we're navigating to a uri and .preventBFCache was not
+ // specified, splice it out of gUrisNotInBFCache if it's there.
+ gUrisNotInBFCache.forEach(
+ function(element, index, array) {
+ if (element == uri) {
+ array.splice(index, 1);
+ }
+ }, this);
+ }
+
+ // Notify the callback now that we're done.
+ onNavComplete.call();
+}
+
+/**
+ * Allows a test to wait for page navigation events, and notify a
+ * callback when they've all been received. This works exactly the
+ * same as doPageNavigation(), except that no navigation is initiated.
+ */
+function waitForPageEvents(params) {
+ params.waitForEventsOnly = true;
+ doPageNavigation(params);
+}
+
+/**
+ * The event listener which listens for expectedEvents.
+ */
+function pageEventListener(event) {
+ try {
+ dump("TEST: eventListener received a " + event.type + " event for page " +
+ event.originalTarget.title + ", persisted=" + event.persisted + "\n");
+ } catch(e) {
+ // Ignore any exception.
+ }
+
+ // If this page shouldn't be in the bfcache because it was previously
+ // loaded with .preventBFCache, make sure that its pageshow event
+ // has .persisted = false, even if the test doesn't explicitly test
+ // for .persisted.
+ if ( (event.type == "pageshow") &&
+ (gNavType == NAV_BACK || gNavType == NAV_FORWARD) ) {
+ let uri = TestWindow.getBrowser().currentURI.spec;
+ if (uri in gUrisNotInBFCache) {
+ ok(!event.persisted, "pageshow event has .persisted = false, even " +
+ "though it was loaded with .preventBFCache previously\n");
+ }
+ }
+
+ if (typeof(gUnexpectedEvents) != "undefined") {
+ is(gUnexpectedEvents.indexOf(event.type), -1,
+ "Should not get unexpected event " + event.type);
+ }
+
+ // If no expected events were specified, mark the final event as having been
+ // triggered when a pageshow event is fired; this will allow
+ // doPageNavigation() to return.
+ if ((typeof(gExpectedEvents) == "undefined") && event.type == "pageshow")
+ {
+ setTimeout(function() { gFinalEvent = true; }, 0);
+ return;
+ }
+
+ // If there are explicitly no expected events, but we receive one, it's an
+ // error.
+ if (gExpectedEvents.length == 0) {
+ ok(false, "Unexpected event (" + event.type + ") occurred");
+ return;
+ }
+
+ // Grab the next expected event, and compare its attributes against the
+ // actual event.
+ let expected = gExpectedEvents.shift();
+
+ is(event.type, expected.type,
+ "A " + expected.type + " event was expected, but a " +
+ event.type + " event occurred");
+
+ if (typeof(expected.title) != "undefined") {
+ ok(event.originalTarget instanceof HTMLDocument,
+ "originalTarget for last " + event.type +
+ " event not an HTMLDocument");
+ is(event.originalTarget.title, expected.title,
+ "A " + event.type + " event was expected for page " +
+ expected.title + ", but was fired for page " +
+ event.originalTarget.title);
+ }
+
+ if (typeof(expected.persisted) != "undefined") {
+ is(event.persisted, expected.persisted,
+ "The persisted property of the " + event.type + " event on page " +
+ event.originalTarget.location + " had an unexpected value");
+ }
+
+ if ("visibilityState" in expected) {
+ is(event.originalTarget.visibilityState, expected.visibilityState,
+ "The visibilityState property of the document on page " +
+ event.originalTarget.location + " had an unexpected value");
+ }
+
+ if ("hidden" in expected) {
+ is(event.originalTarget.hidden, expected.hidden,
+ "The hidden property of the document on page " +
+ event.originalTarget.location + " had an unexpected value");
+ }
+
+ // If we're out of expected events, let doPageNavigation() return.
+ if (gExpectedEvents.length == 0)
+ setTimeout(function() { gFinalEvent = true; }, 0);
+}
+
+/**
+ * End a test.
+ */
+function finish() {
+ // Work around bug 467960.
+ var history = TestWindow.getBrowser().webNavigation.sessionHistory;
+ history.PurgeHistory(history.count);
+
+ // If the test changed the value of max_total_viewers via a call to
+ // enableBFCache(), then restore it now.
+ if (typeof(gOrigMaxTotalViewers) != "undefined") {
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ prefs.setIntPref("browser.sessionhistory.max_total_viewers",
+ gOrigMaxTotalViewers);
+ }
+
+ // Close the test window and signal the framework that the test is done.
+ let opener = window.opener;
+ let SimpleTest = opener.wrappedJSObject.SimpleTest;
+
+ // Wait for the window to be closed before finishing the test
+ let ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Components.interfaces.nsIWindowWatcher);
+ ww.registerNotification(function(subject, topic, data) {
+ if (topic == "domwindowclosed") {
+ ww.unregisterNotification(arguments.callee);
+ SimpleTest.waitForFocus(SimpleTest.finish, opener);
+ }
+ });
+
+ window.close();
+}
+
+/**
+ * Helper function which waits until another function returns true, or until a
+ * timeout occurs, and then notifies a callback.
+ *
+ * Parameters:
+ *
+ * fn: a function which is evaluated repeatedly, and when it turns true,
+ * the onWaitComplete callback is notified.
+ *
+ * onWaitComplete: a callback which will be notified when fn() returns
+ * true, or when a timeout occurs.
+ *
+ * timeout: a timeout, in seconds or ms, after which waitForTrue() will
+ * fail an assertion and then return, even if the fn function never
+ * returns true. If timeout is undefined, waitForTrue() will never
+ * time out.
+ */
+function waitForTrue(fn, onWaitComplete, timeout) {
+ var start = new Date().valueOf();
+ if (typeof(timeout) != "undefined") {
+ // If timeoutWait is less than 500, assume it represents seconds, and
+ // convert to ms.
+ if (timeout < 500)
+ timeout *= 1000;
+ }
+
+ // Loop until the test function returns true, or until a timeout occurs,
+ // if a timeout is defined.
+ var intervalid;
+ intervalid =
+ setInterval(
+ function() {
+ var timeoutHit = false;
+ if (typeof(timeout) != "undefined") {
+ timeoutHit = new Date().valueOf() - start >=
+ timeout ? true : false;
+ if (timeoutHit) {
+ ok(false, "Timed out waiting for condition");
+ }
+ }
+ if (timeoutHit || fn.call()) {
+ // Stop calling the test function and notify the callback.
+ clearInterval(intervalid);
+ onWaitComplete.call();
+ }
+ }, 20);
+}
+
+/**
+ * Enable or disable the bfcache.
+ *
+ * Parameters:
+ *
+ * enable: if true, set max_total_viewers to -1 (the default); if false, set
+ * to 0 (disabled), if a number, set it to that specific number
+ */
+function enableBFCache(enable) {
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+
+ // If this is the first time the test called enableBFCache(),
+ // store the original value of max_total_viewers, so it can
+ // be restored at the end of the test.
+ if (typeof(gOrigMaxTotalViewers) == "undefined") {
+ gOrigMaxTotalViewers =
+ prefs.getIntPref("browser.sessionhistory.max_total_viewers");
+ }
+
+ if (typeof(enable) == "boolean") {
+ if (enable)
+ prefs.setIntPref("browser.sessionhistory.max_total_viewers", -1);
+ else
+ prefs.setIntPref("browser.sessionhistory.max_total_viewers", 0);
+ }
+ else if (typeof(enable) == "number") {
+ prefs.setIntPref("browser.sessionhistory.max_total_viewers", enable);
+ }
+}
+
+/*
+ * get http root for local tests. Use a single extractJarToTmp instead of
+ * extracting for each test.
+ * Returns a file://path if we have a .jar file
+ */
+function getHttpRoot() {
+ var location = window.location.href;
+ location = getRootDirectory(location);
+ var jar = getJar(location);
+ if (jar != null) {
+ if (gExtractedPath == null) {
+ var resolved = extractJarToTmp(jar);
+ gExtractedPath = resolved.path;
+ }
+ } else {
+ return null;
+ }
+ return "file://" + gExtractedPath + '/';
+}
+
+/**
+ * Returns the full HTTP url for a file in the mochitest docshell test
+ * directory.
+ */
+function getHttpUrl(filename) {
+ var root = getHttpRoot();
+ if (root == null) {
+ root = "http://mochi.test:8888/chrome/docshell/test/chrome/";
+ }
+ return root + filename;
+}
+
+/**
+ * A convenience object with methods that return the current test window,
+ * browser, and document.
+ */
+var TestWindow = {};
+TestWindow.getWindow = function () {
+ return document.getElementById("content").contentWindow;
+}
+TestWindow.getBrowser = function () {
+ return document.getElementById("content");
+}
+TestWindow.getDocument = function () {
+ return document.getElementById("content").contentDocument;
+}
diff --git a/docshell/test/chrome/file_viewsource_forbidden_in_iframe.html b/docshell/test/chrome/file_viewsource_forbidden_in_iframe.html
new file mode 100644
index 0000000000..fdecbbdfe1
--- /dev/null
+++ b/docshell/test/chrome/file_viewsource_forbidden_in_iframe.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test ifranes for view-source forbidden in iframe tests</title>
+</head>
+<body>
+ <iframe id="testIframe"></iframe>
+ <iframe id="refIframe"></iframe>
+</body>
+</html>
diff --git a/docshell/test/chrome/gen_template.pl b/docshell/test/chrome/gen_template.pl
new file mode 100644
index 0000000000..5fe9e9ea41
--- /dev/null
+++ b/docshell/test/chrome/gen_template.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+
+# This script makes docshell test case templates. It takes one argument:
+#
+# -b: a bugnumber
+#
+# For example, this command:
+#
+# perl gen_template.pl -b 303267
+#
+# Writes test case template files test_bug303267.xul and bug303267_window.xul
+# to the current directory.
+
+use FindBin;
+use Getopt::Long;
+GetOptions("b=i"=> \$bug_number);
+
+$template = "$FindBin::RealBin/test.template.txt";
+
+open(IN,$template) or die("Failed to open input file for reading.");
+open(OUT, ">>test_bug" . $bug_number . ".xul") or die("Failed to open output file for appending.");
+while((defined(IN)) && ($line = <IN>)) {
+ $line =~ s/{BUGNUMBER}/$bug_number/g;
+ print OUT $line;
+}
+close(IN);
+close(OUT);
+
+$template = "$FindBin::RealBin/window.template.txt";
+
+open(IN,$template) or die("Failed to open input file for reading.");
+open(OUT, ">>bug" . $bug_number . "_window.xul") or die("Failed to open output file for appending.");
+while((defined(IN)) && ($line = <IN>)) {
+ $line =~ s/{BUGNUMBER}/$bug_number/g;
+ print OUT $line;
+}
+close(IN);
+close(OUT);
+
diff --git a/docshell/test/chrome/generic.html b/docshell/test/chrome/generic.html
new file mode 100644
index 0000000000..569a78c05a
--- /dev/null
+++ b/docshell/test/chrome/generic.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+ <title>
+ generic page
+ </title>
+ </head>
+<body>
+<div id="div1" style="height: 1000px; border: thin solid black;">
+ A generic page which can be used any time a test needs to load an arbitrary page via http.
+ </div>
+</body>
+</html>
diff --git a/docshell/test/chrome/mozFrameType_window.xul b/docshell/test/chrome/mozFrameType_window.xul
new file mode 100644
index 0000000000..aa811c333a
--- /dev/null
+++ b/docshell/test/chrome/mozFrameType_window.xul
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<window title="Test mozFrameType attribute"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTests();">
+
+ <html:iframe id="normalFrame"/>
+ <html:iframe id="typeContentFrame" mozframetype="content"/>
+
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ function runTests() {
+ let opener = window.opener;
+ let SimpleTest = opener.wrappedJSObject.SimpleTest;
+
+ let Ci = Components.interfaces;
+
+ function getDocShellType(frame) {
+ return frame.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell)
+ .QueryInterface(Ci.nsIDocShellTreeItem)
+ .itemType;
+ }
+
+ var normalFrame = document.getElementById("normalFrame");
+ var typeContentFrame = document.getElementById("typeContentFrame");
+
+ SimpleTest.is(getDocShellType(normalFrame), Ci.nsIDocShellTreeItem.typeChrome,
+ "normal iframe in chrome document is typeChrome");
+ SimpleTest.is(getDocShellType(typeContentFrame), Ci.nsIDocShellTreeItem.typeContent,
+ "iframe with mozFrameType='content' in chrome document is typeContent");
+
+ SimpleTest.executeSoon(function () {
+ // First focus the parent window and then close this one.
+ SimpleTest.waitForFocus(function() {
+ let ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Components.interfaces.nsIWindowWatcher);
+ ww.registerNotification(function windowObs(subject, topic, data) {
+ if (topic == "domwindowclosed") {
+ ww.unregisterNotification(windowObs);
+
+ // Don't start the next test synchronously!
+ SimpleTest.executeSoon(function() {
+ SimpleTest.finish();
+ });
+ }
+ });
+
+ window.close();
+ }, opener);
+ });
+ }
+ ]]></script>
+</window>
+
diff --git a/docshell/test/chrome/red.png b/docshell/test/chrome/red.png
new file mode 100644
index 0000000000..aa9ce25263
--- /dev/null
+++ b/docshell/test/chrome/red.png
Binary files differ
diff --git a/docshell/test/chrome/test.template.txt b/docshell/test/chrome/test.template.txt
new file mode 100644
index 0000000000..b7dd5e5c23
--- /dev/null
+++ b/docshell/test/chrome/test.template.txt
@@ -0,0 +1,41 @@
+<?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={BUGNUMBER}.xul
+-->
+<window title="Mozilla Bug {BUGNUMBER}"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <title>Test for Bug {BUGNUMBER}</title>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER}">
+ Mozilla Bug {BUGNUMBER}</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug {BUGNUMBER} **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug{BUGNUMBER}_window.xul", "bug{BUGNUMBER}",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_allowContentRetargeting.html b/docshell/test/chrome/test_allowContentRetargeting.html
new file mode 100644
index 0000000000..58e838ca01
--- /dev/null
+++ b/docshell/test/chrome/test_allowContentRetargeting.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <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">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runNextTest);
+
+var TEST_URL = "http://mochi.test:8888/tests/docshell/test/chrome/allowContentRetargeting.sjs";
+
+var Ci = Components.interfaces;
+
+function runNextTest() {
+ var test = tests.shift();
+ if (!test) {
+ SimpleTest.finish();
+ return;
+ }
+ test();
+}
+
+var tests = [
+
+ // Set allowContentRetargeting = false, load a downloadable URL, verify the
+ // downloadable stops loading.
+ function basic() {
+ var iframe = insertIframe();
+ docshellForWindow(iframe.contentWindow).allowContentRetargeting = false;
+ loadIframe(iframe);
+ },
+
+ // Set allowContentRetargeting = false on parent docshell, load a downloadable
+ // URL, verify the downloadable stops loading.
+ function inherit() {
+ var docshell = docshellForWindow(window);
+ docshell.allowContentRetargeting = false;
+ loadIframe(insertIframe());
+ },
+];
+
+function docshellForWindow(win) {
+ return win.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebNavigation).
+ QueryInterface(Ci.nsIDocShell);
+}
+
+function insertIframe() {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ return iframe;
+}
+
+function loadIframe(iframe) {
+ iframe.setAttribute("src", TEST_URL);
+ docshellForWindow(iframe.contentWindow).
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ addProgressListener(progressListener,
+ Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
+}
+
+var progressListener = {
+ onStateChange: function (webProgress, req, flags, status) {
+ if (!(flags & Ci.nsIWebProgressListener.STATE_STOP))
+ return;
+ is(Components.isSuccessCode(status), false,
+ "Downloadable should have failed to load");
+ document.querySelector("iframe").remove();
+ runNextTest();
+ },
+
+ QueryInterface: function (iid) {
+ var iids = [
+ Ci.nsIWebProgressListener,
+ Ci.nsISupportsWeakReference,
+ Ci.nsISupports,
+ ];
+ if (iids.some(function (i) { return iid.equals(i); }))
+ return this;
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ },
+};
+
+ </script>
+</head>
+<body>
+<p id="display">
+</p>
+</body>
+</html>
diff --git a/docshell/test/chrome/test_bug112564.xul b/docshell/test/chrome/test_bug112564.xul
new file mode 100644
index 0000000000..0706595d0b
--- /dev/null
+++ b/docshell/test/chrome/test_bug112564.xul
@@ -0,0 +1,38 @@
+<?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=112564
+-->
+<window title="Mozilla Bug 112564"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=112564">Mozilla Bug 112564</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 112564 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug112564_window.xul", "bug112564",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug113934.xul b/docshell/test/chrome/test_bug113934.xul
new file mode 100644
index 0000000000..ba297e0357
--- /dev/null
+++ b/docshell/test/chrome/test_bug113934.xul
@@ -0,0 +1,31 @@
+<?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=113934
+-->
+<window title="Mozilla Bug 113934"
+ 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/tests/SimpleTest/WindowSnapshot.js"></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=113934"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.open("bug113934_window.xul?content", "bug113934",
+ "chrome,width=800,height=800");
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug215405.xul b/docshell/test/chrome/test_bug215405.xul
new file mode 100644
index 0000000000..e934d76caf
--- /dev/null
+++ b/docshell/test/chrome/test_bug215405.xul
@@ -0,0 +1,38 @@
+<?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=215405
+-->
+<window title="Mozilla Bug 215405"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=215405">Mozilla Bug 215405</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 215405 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug215405_window.xul", "bug215405",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug293235.xul b/docshell/test/chrome/test_bug293235.xul
new file mode 100644
index 0000000000..8a42c0a6e7
--- /dev/null
+++ b/docshell/test/chrome/test_bug293235.xul
@@ -0,0 +1,39 @@
+<?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=293235.xul
+-->
+<window title="Mozilla Bug 293235"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=293235">
+ Mozilla Bug 293235</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 293235 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug293235_window.xul", "bug293235",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug294258.xul b/docshell/test/chrome/test_bug294258.xul
new file mode 100644
index 0000000000..4658a82de0
--- /dev/null
+++ b/docshell/test/chrome/test_bug294258.xul
@@ -0,0 +1,39 @@
+<?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=294258.xul
+-->
+<window title="Mozilla Bug 294258"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=294258">
+ Mozilla Bug 294258</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 294258 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug294258_window.xul", "bug294258",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug298622.xul b/docshell/test/chrome/test_bug298622.xul
new file mode 100644
index 0000000000..c3217c7e59
--- /dev/null
+++ b/docshell/test/chrome/test_bug298622.xul
@@ -0,0 +1,39 @@
+<?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=298622.xul
+-->
+<window title="Mozilla Bug 298622"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=298622">
+ Mozilla Bug 298622</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 298622 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug298622_window.xul", "bug298622",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug301397.xul b/docshell/test/chrome/test_bug301397.xul
new file mode 100644
index 0000000000..37fe479932
--- /dev/null
+++ b/docshell/test/chrome/test_bug301397.xul
@@ -0,0 +1,39 @@
+<?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=301397.xul
+-->
+<window title="Mozilla Bug 301397"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=301397">
+ Mozilla Bug 301397</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 301397 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug301397_window.xul", "bug301397",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug303267.xul b/docshell/test/chrome/test_bug303267.xul
new file mode 100644
index 0000000000..f68dbdcd24
--- /dev/null
+++ b/docshell/test/chrome/test_bug303267.xul
@@ -0,0 +1,40 @@
+<?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=303267.xul
+-->
+<window title="Mozilla Bug 303267"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=303267">Mozilla Bug 303267</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+SimpleTest.expectAssertions(0, 1);
+
+/** Test for Bug 303267 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug303267_window.xul", "bug303267",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug311007.xul b/docshell/test/chrome/test_bug311007.xul
new file mode 100644
index 0000000000..32f1085f00
--- /dev/null
+++ b/docshell/test/chrome/test_bug311007.xul
@@ -0,0 +1,45 @@
+<?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=311007.xul
+-->
+<window title="Mozilla Bug 311007"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/MochiKit/packed.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=311007">
+ Mozilla Bug 311007</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+/** Test for Bug 311007 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug311007_window.xul", "bug311007",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug321671.xul b/docshell/test/chrome/test_bug321671.xul
new file mode 100644
index 0000000000..46164018b1
--- /dev/null
+++ b/docshell/test/chrome/test_bug321671.xul
@@ -0,0 +1,39 @@
+<?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=321671.xul
+-->
+<window title="Mozilla Bug 321671"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=321671">
+ Mozilla Bug 321671</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 321671 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug321671_window.xul", "bug321671",
+ "chrome,width=600,height=600,scrollbars");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug360511.xul b/docshell/test/chrome/test_bug360511.xul
new file mode 100644
index 0000000000..ffa47fa276
--- /dev/null
+++ b/docshell/test/chrome/test_bug360511.xul
@@ -0,0 +1,40 @@
+<?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=360511.xul
+-->
+<window title="Mozilla Bug 360511"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=360511">
+ Mozilla Bug 360511</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 360511 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug360511_window.xul", "bug360511",
+ "chrome,scrollbars,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug364461.xul b/docshell/test/chrome/test_bug364461.xul
new file mode 100644
index 0000000000..85154f9d74
--- /dev/null
+++ b/docshell/test/chrome/test_bug364461.xul
@@ -0,0 +1,38 @@
+<?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=364461
+-->
+<window title="Mozilla Bug 364461"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=364461">Mozilla Bug 364461</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 364461 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug364461_window.xul", "bug364461",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug396519.xul b/docshell/test/chrome/test_bug396519.xul
new file mode 100644
index 0000000000..be1d148b7f
--- /dev/null
+++ b/docshell/test/chrome/test_bug396519.xul
@@ -0,0 +1,29 @@
+<?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=396519
+-->
+<window title="Mozilla Bug 396519"
+ 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">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=396519"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+ /** Test for Bug 396519 **/
+
+ SimpleTest.waitForExplicitFinish();
+ window.open("bug396519_window.xul", "bug396519",
+ "chrome,width=600,height=600");
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug396649.xul b/docshell/test/chrome/test_bug396649.xul
new file mode 100644
index 0000000000..3554c2f98a
--- /dev/null
+++ b/docshell/test/chrome/test_bug396649.xul
@@ -0,0 +1,41 @@
+<?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=396649.xul
+-->
+<window title="Mozilla Bug 396649"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=396649">
+ Mozilla Bug 396649</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 396649 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug396649_window.xul", "bug396649",
+ "chrome,width=600,height=600,scrollbars");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug428288.html b/docshell/test/chrome/test_bug428288.html
new file mode 100644
index 0000000000..83fcd20c61
--- /dev/null
+++ b/docshell/test/chrome/test_bug428288.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=428288
+-->
+<head>
+ <title>Test for Bug 428288</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" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=428288">Mozilla Bug 428288</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="target"></iframe>
+ <a id="crashy" target="target" href="about:blank">crash me</a>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 428288 **/
+
+function makeClick() {
+ var event = document.createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, window, 0, 0,0,0,0,
+ false, false, false, false, 0, null);
+ document.getElementById("crashy").dispatchEvent(event);
+ return true;
+}
+
+ok(makeClick(), "Crashes if bug 428288 is present");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/chrome/test_bug449778.xul b/docshell/test/chrome/test_bug449778.xul
new file mode 100644
index 0000000000..48c76c2e2b
--- /dev/null
+++ b/docshell/test/chrome/test_bug449778.xul
@@ -0,0 +1,31 @@
+<?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=449778
+-->
+<window title="Mozilla Bug 449778"
+ 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/tests/SimpleTest/WindowSnapshot.js"></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=449778"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.open("bug449778_window.xul", "bug449778",
+ "chrome,width=800,height=800");
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug449780.xul b/docshell/test/chrome/test_bug449780.xul
new file mode 100644
index 0000000000..fc5231d6b1
--- /dev/null
+++ b/docshell/test/chrome/test_bug449780.xul
@@ -0,0 +1,31 @@
+<?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=449780
+-->
+<window title="Mozilla Bug 449780"
+ 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/tests/SimpleTest/WindowSnapshot.js"></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=449780"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.open("bug449780_window.xul", "bug449780",
+ "chrome,width=800,height=800");
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug453650.xul b/docshell/test/chrome/test_bug453650.xul
new file mode 100644
index 0000000000..2837e56d84
--- /dev/null
+++ b/docshell/test/chrome/test_bug453650.xul
@@ -0,0 +1,115 @@
+<?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=453650
+-->
+<window title="Mozilla Bug 453650"
+ 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 code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 453650 **/
+ SimpleTest.waitForExplicitFinish();
+
+ var Ci = Components.interfaces;
+ var Cr = Components.results;
+
+ var iter = runTests();
+ nextTest();
+
+ function runTests() {
+ var iframe = document.createElement("iframe");
+ iframe.style.width = "300px";
+ iframe.style.height = "300px";
+ iframe.setAttribute("src", "data:text/html,<h1 id='h'>hello</h1>");
+
+ document.documentElement.appendChild(iframe);
+ yield whenLoaded(iframe);
+ info("iframe loaded");
+
+ var h1 = iframe.contentDocument.getElementById("h");
+ h1.style.width = "400px";
+ yield waitForInterruptibleReflow(iframe.docShell);
+
+ h1.style.width = "300px";
+ waitForReflow(iframe.docShell);
+ yield is(300, h1.offsetWidth, "h1 has correct width");
+ }
+
+ function waitForInterruptibleReflow(docShell) {
+ waitForReflow(docShell, true);
+ }
+
+ function waitForReflow(docShell, interruptible = false) {
+ function done() {
+ docShell.removeWeakReflowObserver(observer);
+ SimpleTest.executeSoon(nextTest);
+ }
+
+ var observer = {
+ reflow: function (start, end) {
+ if (interruptible) {
+ ok(false, "expected interruptible reflow");
+ } else {
+ ok(true, "observed uninterruptible reflow");
+ }
+
+ info("times: " + start + ", " + end);
+ ok(start < end, "reflow start time lower than end time");
+ done();
+ },
+
+ reflowInterruptible: function (start, end) {
+ if (!interruptible) {
+ ok(false, "expected uninterruptible reflow");
+ } else {
+ ok(true, "observed interruptible reflow");
+ }
+
+ info("times: " + start + ", " + end);
+ ok(start < end, "reflow start time lower than end time");
+ done();
+ },
+
+ QueryInterface: function (iid) {
+ if (Ci.nsIReflowObserver.equals(iid) ||
+ Ci.nsISupportsWeakReference.equals(iid) ||
+ Ci.nsISupports.equals(iid))
+ return this;
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ },
+ };
+
+ docShell.addWeakReflowObserver(observer);
+ }
+
+ function whenLoaded(iframe) {
+ iframe.addEventListener("load", function onLoad() {
+ iframe.removeEventListener("load", onLoad);
+ SimpleTest.executeSoon(nextTest);
+ });
+ }
+
+ function nextTest() {
+ try {
+ iter.next();
+ } catch (e if e instanceof StopIteration) {
+ SimpleTest.finish();
+ }
+ }
+
+ ]]>
+ </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=453650"
+ target="_blank">Mozilla Bug 453650</a>
+ </body>
+</window>
diff --git a/docshell/test/chrome/test_bug454235.xul b/docshell/test/chrome/test_bug454235.xul
new file mode 100644
index 0000000000..f9107a1865
--- /dev/null
+++ b/docshell/test/chrome/test_bug454235.xul
@@ -0,0 +1,56 @@
+<?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=454235
+-->
+<window title="Mozilla Bug 454235"
+ 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">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=454235"
+ target="_blank">Mozilla Bug 454235</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+ /** Test for Bug 454235 **/
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(doTest);
+
+function doTest() {
+ var shownBrowser = document.getElementById("shownBrowser");
+ var hiddenBrowser = document.getElementById("hiddenBrowser");
+ var offScreenBrowser = document.getElementById("offScreenBrowser");
+ var offScreenSubBrowser = offScreenBrowser.contentDocument.getElementById("topBrowser");
+ var offScreenBurriedBrowser = offScreenBrowser.contentDocument.getElementById("burriedBrowser");
+
+ hiddenBrowser.contentWindow.focus();
+ ok(!hiddenBrowser.contentDocument.hasFocus(),"hidden browser is visible");
+
+ offScreenBrowser.docShell.isOffScreenBrowser = true;
+ offScreenBrowser.contentWindow.focus();
+ ok(offScreenBrowser.contentDocument.hasFocus(),"offscreen browser is not visible");
+
+ offScreenSubBrowser.contentWindow.focus();
+ todo(offScreenSubBrowser.contentDocument.hasFocus(),"visible browser in offscreen browser is not visible");
+
+ offScreenBurriedBrowser.contentWindow.focus();
+ ok(!offScreenBurriedBrowser.contentDocument.hasFocus(),"hidden browser in offscreen browser is visible");
+
+ SimpleTest.finish();
+}
+
+
+
+ ]]></script>
+ <box flex="1" style="visibility: hidden; border:5px black solid">
+ <browser style="border:5px blue solid" id="hiddenBrowser" src="bug454235-subframe.xul"/>
+ <browser style="border:5px yellow solid" id="offScreenBrowser" src="bug454235-subframe.xul"/>
+ </box>
+</window>
diff --git a/docshell/test/chrome/test_bug456980.xul b/docshell/test/chrome/test_bug456980.xul
new file mode 100644
index 0000000000..9f4f972096
--- /dev/null
+++ b/docshell/test/chrome/test_bug456980.xul
@@ -0,0 +1,31 @@
+<?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=456980
+-->
+<window title="Mozilla Bug 456980"
+ 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/tests/SimpleTest/WindowSnapshot.js"></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=456980"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.open("bug113934_window.xul?chrome", "bug456980",
+ "chrome,width=800,height=800");
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug565388.xul b/docshell/test/chrome/test_bug565388.xul
new file mode 100644
index 0000000000..47b5c07e4e
--- /dev/null
+++ b/docshell/test/chrome/test_bug565388.xul
@@ -0,0 +1,83 @@
+<?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=565388
+-->
+<window title="Mozilla Bug 565388"
+ 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 code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 565388 **/
+ SimpleTest.waitForExplicitFinish();
+
+ var Ci = Components.interfaces;
+ var Cc = Components.classes;
+
+ var progressListener = {
+ add: function(docShell, callback) {
+ this.callback = callback;
+ this.docShell = docShell;
+ docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
+ },
+
+ finish: function() {
+ this.docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ removeProgressListener(this);
+ this.callback();
+ },
+
+ onStateChange: function (webProgress, req, flags, status) {
+ if (req.name.startsWith("data:application/vnd.mozilla.xul")) {
+ if (flags & Ci.nsIWebProgressListener.STATE_STOP)
+ this.finish();
+ }
+ },
+
+ QueryInterface: function(iid) {
+ if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
+ iid.equals(Components.interfaces.nsISupportsWeakReference))
+ return this;
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ }
+ }
+
+ var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].
+ createInstance(Ci.nsIPrincipal);
+ var webNav = Cc["@mozilla.org/appshell/appShellService;1"].
+ getService(Ci.nsIAppShellService).
+ createWindowlessBrowser(true);
+ var docShell = webNav.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIDocShell);
+ docShell.createAboutBlankContentViewer(systemPrincipal);
+ var win = docShell.contentViewer.DOMDocument.defaultView;
+
+ progressListener.add(docShell, function(){
+ is(win.document.documentURI, "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>");
+ webNav.close();
+ SimpleTest.finish();
+ });
+
+ win.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>";
+
+ ]]>
+ </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=565388"
+ target="_blank">Mozilla Bug 565388</a>
+ </body>
+</window>
diff --git a/docshell/test/chrome/test_bug582176.xul b/docshell/test/chrome/test_bug582176.xul
new file mode 100644
index 0000000000..98053b009a
--- /dev/null
+++ b/docshell/test/chrome/test_bug582176.xul
@@ -0,0 +1,39 @@
+<?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=582176.xul
+-->
+<window title="Mozilla Bug 582176"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=582176">
+ Mozilla Bug 582176</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 582176 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug582176_window.xul", "bug582176",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug608669.xul b/docshell/test/chrome/test_bug608669.xul
new file mode 100644
index 0000000000..51d6a3b7db
--- /dev/null
+++ b/docshell/test/chrome/test_bug608669.xul
@@ -0,0 +1,117 @@
+<?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=608669
+-->
+<window title="Mozilla Bug 608669"
+ 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">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=608669"
+ target="_blank">Mozilla Bug 608669</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+var gOrigMaxTotalViewers = undefined;
+function setCachePref(enabled) {
+ var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ if (enabled) {
+ is(typeof gOrigMaxTotalViewers, "undefined", "don't double-enable bfcache");
+ prefBranch.setBoolPref("browser.sessionhistory.cache_subframes", true);
+ gOrigMaxTotalViewers = prefBranch.getIntPref("browser.sessionhistory.max_total_viewers");
+ prefBranch.setIntPref("browser.sessionhistory.max_total_viewers", 10);
+ }
+ else {
+ is(typeof gOrigMaxTotalViewers, "number", "don't double-disable bfcache");
+ prefBranch.setIntPref("browser.sessionhistory.max_total_viewers", gOrigMaxTotalViewers);
+ gOrigMaxTotalViewers = undefined;
+ try {
+ prefBranch.clearUserPref("browser.sessionhistory.cache_subframes");
+ } catch (e) { /* Pref didn't exist, meh */ }
+ }
+}
+
+
+/** Test for Bug 608669 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(nextTest);
+
+gen = doTest();
+
+function nextTest() {
+ gen.next();
+}
+
+function doTest() {
+ var container = document.getElementById('container');
+
+ setCachePref(true);
+
+ var notificationCount = 0;
+ var observer = {
+ observe: function(aSubject, aTopic, aData) {
+ is(aTopic, "chrome-document-global-created",
+ "correct topic");
+ is(aData, "null",
+ "correct data");
+ notificationCount++;
+ }
+ };
+
+ var os = Components.classes["@mozilla.org/observer-service;1"].
+ getService(Components.interfaces.nsIObserverService);
+ os.addObserver(observer, "chrome-document-global-created", false);
+ os.addObserver(observer, "content-document-global-created", false);
+
+ is(notificationCount, 0, "initial count");
+
+ // create a new iframe
+ var iframe = document.createElement("iframe");
+ container.appendChild(iframe);
+ iframe.contentWindow.x = "y";
+ is(notificationCount, 1, "after created iframe");
+
+ // Try loading in an iframe
+ iframe.setAttribute("src", "bug608669.xul");
+ iframe.onload = nextTest;
+ yield undefined;
+ is(notificationCount, 1, "after first load");
+ is(iframe.contentWindow.x, "y", "reused window");
+
+ // Try loading again in an iframe
+ iframe.setAttribute("src", "bug608669.xul?x");
+ iframe.onload = nextTest;
+ yield undefined;
+ is(notificationCount, 2, "after second load");
+ is("x" in iframe.contentWindow, false, "didn't reuse window");
+
+ // Open a new window using window.open
+ popup = window.open("bug608669.xul", "bug 608669",
+ "chrome,width=600,height=600");
+ popup.onload = nextTest;
+ yield undefined;
+ is(notificationCount, 3, "after window.open load");
+ popup.close();
+
+ setCachePref(false);
+ os.removeObserver(observer, "chrome-document-global-created");
+ os.removeObserver(observer, "content-document-global-created");
+ SimpleTest.finish();
+ yield undefined;
+}
+
+
+
+ ]]></script>
+ <vbox id="container" flex="1">
+ <description>Below will an iframe be added</description>
+ </vbox>
+</window>
diff --git a/docshell/test/chrome/test_bug662200.xul b/docshell/test/chrome/test_bug662200.xul
new file mode 100644
index 0000000000..8b864c8afe
--- /dev/null
+++ b/docshell/test/chrome/test_bug662200.xul
@@ -0,0 +1,39 @@
+<?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=662200.xul
+-->
+<window title="Mozilla Bug 662200"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=662200">
+ Mozilla Bug 662200</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 662200 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug662200_window.xul", "bug662200",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug690056.xul b/docshell/test/chrome/test_bug690056.xul
new file mode 100644
index 0000000000..caeed09d3c
--- /dev/null
+++ b/docshell/test/chrome/test_bug690056.xul
@@ -0,0 +1,26 @@
+<?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=690056
+-->
+<window title="Mozilla Bug 690056"
+ 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=690056"
+ target="_blank">Mozilla Bug 690056</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 690056 **/
+SimpleTest.waitForExplicitFinish();
+window.open("bug690056_window.xul", "bug690056",
+ "chrome,width=600,height=600");
+ ]]>
+ </script>
+</window>
diff --git a/docshell/test/chrome/test_bug789773.xul b/docshell/test/chrome/test_bug789773.xul
new file mode 100644
index 0000000000..b7a2b3d1c3
--- /dev/null
+++ b/docshell/test/chrome/test_bug789773.xul
@@ -0,0 +1,71 @@
+<?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=789773
+-->
+<window title="Mozilla Bug 789773"
+ 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=789773"
+ target="_blank">Mozilla Bug 789773</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ const Cr = Components.results;
+ const Cu = Components.utils;
+
+ /* Test for Bug 789773.
+ *
+ * See comment 50 for the situation we're testing against here.
+ *
+ * Note that the failure mode of this test is to hang, and hang the browser on quit.
+ * This is an unfortunate occurance, but that's why we're testing it.
+ */
+ SimpleTest.waitForExplicitFinish();
+
+ var calledListenerForBrowserXUL = false;
+ var testProgressListener = {
+ START_DOC: Ci.nsIWebProgressListener.STATE_START | Ci.nsIWebProgressListener.STATE_IS_DOCUMENT,
+ onStateChange: function(wp, req, stateFlags, status) {
+ if (/browser.xul/.test(req.name)) {
+ wp.DOMWindow; // Force the lazy creation of a DOM window.
+ calledListenerForBrowserXUL = true;
+ }
+ if (/mozilla.xhtml/.test(req.name) && (stateFlags & Ci.nsIWebProgressListener.STATE_STOP))
+ finishTest();
+ },
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsISupportsWeakReference) ||
+ iid.equals(Ci.nsIWebProgressListener))
+ return this;
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ }
+
+ // Add our progress listener
+ var webProgress = Cc['@mozilla.org/docloaderservice;1'].getService(Ci.nsIWebProgress);
+ webProgress.addProgressListener(testProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_REQUEST);
+
+ // Open the window.
+ var popup = window.open("about:mozilla", "_blank", "width=640,height=400");
+
+ // Wait for the window to load.
+ function finishTest() {
+ webProgress.removeProgressListener(testProgressListener);
+ ok(true, "Loaded the popup window without spinning forever in the event loop!");
+ ok(calledListenerForBrowserXUL, "Should have called the progress listener for browser.xul");
+ popup.close();
+ SimpleTest.finish();
+ }
+
+ ]]>
+ </script>
+</window>
diff --git a/docshell/test/chrome/test_bug846906.xul b/docshell/test/chrome/test_bug846906.xul
new file mode 100644
index 0000000000..2003384f0b
--- /dev/null
+++ b/docshell/test/chrome/test_bug846906.xul
@@ -0,0 +1,96 @@
+<?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=846906
+-->
+<window title="Mozilla Bug 846906"
+ 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 code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 846906 **/
+ SimpleTest.waitForExplicitFinish();
+
+ var appShellService = Components.classes["@mozilla.org/appshell/appShellService;1"]
+ .getService(Components.interfaces.nsIAppShellService);
+ ok(appShellService, "Should be able to get app shell service");
+
+ var windowlessBrowser = appShellService.createWindowlessBrowser();
+ ok(windowlessBrowser, "Should be able to create windowless browser");
+
+ ok(windowlessBrowser instanceof Components.interfaces.nsIWindowlessBrowser,
+ "Windowless browser should implement nsIWindowlessBrowser");
+
+ var webNavigation = windowlessBrowser.QueryInterface(Components.interfaces.nsIWebNavigation);
+ ok(webNavigation, "Windowless browser should implement nsIWebNavigation");
+
+ var interfaceRequestor = windowlessBrowser.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
+ ok(interfaceRequestor, "Should be able to query interface requestor interface");
+
+ var docShell = interfaceRequestor.getInterface(Components.interfaces.nsIDocShell);
+ ok(docShell, "Should be able to get doc shell interface");
+
+ var document = webNavigation.document;
+ ok(document, "Should be able to get document");
+
+ var iframe = document.createElement("iframe");
+ ok(iframe, "Should be able to create iframe");
+
+ iframe.onload = function () {
+ ok(true, "Should receive initial onload event");
+
+ iframe.onload = function () {
+ ok(true, "Should receive onload event");
+
+ var contentDocument = iframe.contentDocument;
+ ok(contentDocument, "Should be able to get content document");
+
+ var div = contentDocument.getElementById("div1");
+ ok(div, "Should be able to get element by id");
+
+ var rect = div.getBoundingClientRect();
+ ok(rect, "Should be able to get bounding client rect");
+
+ // xxx: can we do better than hardcoding these values here?
+ is(rect.width, 1024);
+ is(rect.height, 768);
+
+ windowlessBrowser.close();
+
+ // Once the browser is closed, nsIWebNavigation and
+ // nsIInterfaceRequestor methods should no longer be accessible.
+ try {
+ windowlessBrowser.getInterface(Components.interfaces.nsIDocShell);
+ ok(false);
+ } catch (e) {
+ is(e.result, Components.results.NS_ERROR_NULL_POINTER);
+ }
+
+ try {
+ windowlessBrowser.document;
+ ok(false);
+ } catch (e) {
+ is(e.result, Components.results.NS_ERROR_NULL_POINTER);
+ }
+
+ SimpleTest.finish();
+ };
+ iframe.setAttribute("src", "http://mochi.test:8888/chrome/docshell/test/chrome/bug846906.html");
+ };
+ document.documentElement.appendChild(iframe);
+
+ ]]>
+ </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=846906"
+ target="_blank">Mozilla Bug 846906</a>
+ </body>
+</window>
diff --git a/docshell/test/chrome/test_bug89419.xul b/docshell/test/chrome/test_bug89419.xul
new file mode 100644
index 0000000000..26194c49b3
--- /dev/null
+++ b/docshell/test/chrome/test_bug89419.xul
@@ -0,0 +1,39 @@
+<?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=89419.xul
+-->
+<window title="Mozilla Bug 89419"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=89419">
+ Mozilla Bug 89419</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 89419 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug89419_window.xul", "bug89419",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug909218.html b/docshell/test/chrome/test_bug909218.html
new file mode 100644
index 0000000000..e635fdb118
--- /dev/null
+++ b/docshell/test/chrome/test_bug909218.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <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">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(test);
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+// The default flags we will stick on the docShell - every request made by the
+// docShell should include those flags.
+const TEST_FLAGS = Ci.nsIRequest.LOAD_ANONYMOUS |
+ Ci.nsIRequest.LOAD_BYPASS_CACHE |
+ Ci.nsIRequest.INHIBIT_CACHING |
+ Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY;
+
+var TEST_URL = "http://mochi.test:8888/chrome/docshell/test/chrome/bug909218.html";
+
+// These are the requests we expect to see loading TEST_URL into our iframe.
+
+// The test entry-point. The basic outline is:
+// * Create an iframe and set defaultLoadFlags on its docShell.
+// * Add a web progress listener to observe each request as the iframe is
+// loaded, and check that each request has the flags we specified.
+// * Load our test URL into the iframe and wait for the load to complete.
+function test() {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ var docShell = docshellForWindow(iframe.contentWindow);
+ // Add our progress listener - when it notices the top-level document is
+ // complete, the test will end.
+ RequestWatcher.init(docShell, SimpleTest.finish);
+ // Set the flags we care about, then load our test URL.
+ docShell.defaultLoadFlags = TEST_FLAGS;
+ iframe.setAttribute("src", TEST_URL);
+}
+
+// an nsIWebProgressListener that checks all requests made by the docShell
+// have the flags we expect.
+RequestWatcher = {
+ init: function(docShell, callback) {
+ this.callback = callback;
+ this.docShell = docShell;
+ docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
+ Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
+ // These are the requests we expect to see - initialize each to have a
+ // count of zero.
+ this.requestCounts = {};
+ for (var url of [
+ TEST_URL,
+ // content loaded by the above test html.
+ "http://mochi.test:8888/chrome/docshell/test/chrome/bug909218.js",
+ "http://mochi.test:8888/tests/SimpleTest/test.css",
+ "http://mochi.test:8888/tests/docshell/test/chrome/red.png",
+ // the content of an iframe in the test html.
+ "http://mochi.test:8888/chrome/docshell/test/chrome/generic.html"
+ ]) {
+ this.requestCounts[url] = 0;
+ }
+ },
+
+ // Finalize the test after we detect a completed load. We check we saw the
+ // correct requests and make a callback to exit.
+ finalize: function() {
+ ok(Object.keys(this.requestCounts).length, "we expected some requests");
+ for (var url in this.requestCounts) {
+ var count = this.requestCounts[url];
+ // As we are looking at all request states, we expect more than 1 for
+ // each URL - 0 or 1 would imply something went wrong - >1 just means
+ // multiple states for each request were recorded, which we don't care
+ // about (we do care they all have the correct flags though - but we
+ // do that in onStateChange)
+ ok(count > 1, url + " saw " + count + " requests");
+ }
+ this.docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ removeProgressListener(this);
+ this.callback();
+ },
+
+ onStateChange: function (webProgress, req, flags, status) {
+ // We are checking requests - if there isn't one, ignore it.
+ if (!req) {
+ return;
+ }
+ // We will usually see requests for 'about:document-onload-blocker' not
+ // have the flag, so we just ignore them.
+ // We also see, eg, resource://gre-resources/loading-image.png, so
+ // skip resource:// URLs too.
+ if (req.name.startsWith("about:") || req.name.startsWith("resource:")) {
+ return;
+ }
+ is(req.loadFlags & TEST_FLAGS, TEST_FLAGS, "request " + req.name + " has the expected flags");
+ this.requestCounts[req.name] += 1;
+ var stopFlags = Ci.nsIWebProgressListener.STATE_STOP |
+ Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
+ if (req.name == TEST_URL && (flags & stopFlags) == stopFlags) {
+ this.finalize();
+ }
+ },
+ QueryInterface: XPCOMUtils.generateQI([
+ Ci.nsIWebProgressListener,
+ Ci.nsISupportsWeakReference,
+ ])
+}
+
+function docshellForWindow(win) {
+ return win.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebNavigation).
+ QueryInterface(Ci.nsIDocShell);
+}
+
+</script>
+</head>
+</html>
diff --git a/docshell/test/chrome/test_bug92598.xul b/docshell/test/chrome/test_bug92598.xul
new file mode 100644
index 0000000000..8e81463be6
--- /dev/null
+++ b/docshell/test/chrome/test_bug92598.xul
@@ -0,0 +1,38 @@
+<?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=92598
+-->
+<window title="Mozilla Bug 92598"
+ 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 target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=92598">Mozilla Bug 92598</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 92598 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug92598_window.xul", "bug92598",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_mozFrameType.xul b/docshell/test/chrome/test_mozFrameType.xul
new file mode 100644
index 0000000000..225cd16cc2
--- /dev/null
+++ b/docshell/test/chrome/test_mozFrameType.xul
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/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=769771
+-->
+<window title="Test mozFrameType attribute"
+ 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">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+/** Test for Bug 769771 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function () {
+ window.open("mozFrameType_window.xul", "mozFrameType",
+ "chrome,width=600,height=600");
+});
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_principalInherit.xul b/docshell/test/chrome/test_principalInherit.xul
new file mode 100644
index 0000000000..87056c63dc
--- /dev/null
+++ b/docshell/test/chrome/test_principalInherit.xul
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/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=719994
+-->
+<window title="Test principal inheriting"
+ 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">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 719994 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var gFrame;
+
+// This test file is loaded in a type=content docshell whose principal is
+// the system principal.
+
+// Using data: URIs here instead of javascript: URIs, since javascript: URIs
+// fail to load when there's no principal to load them against. This only
+// matters when these tests fail (produces better error messages).
+var tests = [
+ function testInheritFromParent(cb) {
+ gFrame = document.createElement("iframe");
+ loadListener(gFrame, function () {
+ is(window.inheritedFromParent, true, "load in type=content iframe inherited principal of same type parent");
+ cb();
+ });
+ gFrame.setAttribute("type", "content");
+ gFrame.setAttribute("src", "data:text/html,<script>parent.inheritedFromParent = true;</script>");
+ document.documentElement.appendChild(gFrame);
+ },
+ function testInheritFromCurrent_system(cb) {
+ loadListener(gFrame, function () {
+ is(window.inheritedSystem, undefined, "load in type=content iframe shouldn't inherit system principal from current document");
+ cb();
+ }, true);
+ gFrame.setAttribute("src", "data:text/html,<script>parent.inheritedSystem = true;</script>");
+ },
+ function testInheritFromCreated(cb) {
+ // Open a new chrome window with a type="content" iframe, so that it has no
+ // same-type parent.
+ // Load a javascript: URI in it to ensure that GetInheritedPrincipal will
+ // force creation of a content viewer.
+ let xulWinURL = 'data:application/vnd.mozilla.xul+xml,<?xml version="1.0"?>' +
+ '<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>';
+ let newWin = window.openDialog(xulWinURL, "chrome_window", "chrome");
+ loadListener(newWin, function () {
+ let frame = newWin.document.createElement("iframe");
+ frame.setAttribute("type", "content");
+ frame.setAttribute("src", "javascript:'1';");
+ loadListener(frame, function () {
+ is(frame.contentWindow.document.body.textContent, "1", "content viewer was created");
+ SimpleTest.executeSoon(function () {
+ newWin.close();
+ cb();
+ })
+ });
+ newWin.document.documentElement.appendChild(frame);
+ });
+ }
+];
+
+addLoadEvent(function onLoad() {
+ ok(Components.stack, "this test must be run with the system principal");
+ SimpleTest.executeSoon(nextTest);
+});
+
+function loadListener(target, func) {
+ target.addEventListener("load", function lis() {
+ target.removeEventListener("load", lis, true);
+ func();
+ }, true);
+}
+
+function nextTest() {
+ if (tests.length) {
+ let test = tests.shift();
+ SimpleTest.executeSoon(function () {
+ info("running " + test.name);
+ test(nextTest);
+ });
+ } else
+ SimpleTest.executeSoon(SimpleTest.finish);
+}
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_private_hidden_window.html b/docshell/test/chrome/test_private_hidden_window.html
new file mode 100644
index 0000000000..3907e5de8a
--- /dev/null
+++ b/docshell/test/chrome/test_private_hidden_window.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=829383
+-->
+<head>
+ <title>Test for Bug 829383</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" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=829383">Mozilla Bug 829383</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="target"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+const Ci = Components.interfaces;
+var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow);
+
+// We need to wait for the hidden window to load, but can't access
+// an event target for a regular event listener.
+var hidden = mainWindow.Services.appShell.hiddenPrivateDOMWindow;
+mainWindow.PrivateBrowsingUtils.whenHiddenPrivateWindowReady(function(hidden) {
+ var iframe = hidden.document.createElement('iframe');
+ iframe.src = 'generic.html';
+ hidden.document.body.appendChild(iframe);
+
+ var win = mainWindow.OpenBrowserWindow({private: true});
+ win.addEventListener("load", function onLoad() {
+ win.removeEventListener("load", onLoad, false);
+ win.close();
+ win = null;
+ }, false);
+});
+
+function observer(aSubject, aTopic, aData) {
+ is(aTopic, "last-pb-context-exited", "Unexpected observer topic");
+ mainWindow.Services.obs.removeObserver(observer, "last-pb-context-exited");
+ SimpleTest.finish();
+}
+mainWindow.Services.obs.addObserver(observer, "last-pb-context-exited", false);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul b/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul
new file mode 100644
index 0000000000..536ca4d037
--- /dev/null
+++ b/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul
@@ -0,0 +1,180 @@
+<?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=624883
+-->
+<window title="Mozilla Bug 624883"
+ 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=624883"
+ target="_blank">Mozilla Bug 624883</a>
+ </body>
+
+ <!-- test code goes here -->
+ <iframe type="content" onload="startTest()" src="file_viewsource_forbidden_in_iframe.html"></iframe>
+
+ <script type="application/javascript">
+ <![CDATA[
+
+ const Ci = Components.interfaces;
+ const Cu = Components.utils;
+
+ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+ SimpleTest.waitForExplicitFinish();
+
+ // We create a promise that will resolve with the error message
+ // on a network error page load and reject on any other load.
+ function createNetworkErrorMessagePromise(frame) {
+ return new Promise(function(resolve, reject) {
+
+ // Error pages do not fire "load" events, so use a progressListener.
+ var originalDocumentURI = frame.contentDocument.documentURI;
+ var progressListener = {
+ onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
+ // Make sure nothing other than an error page is loaded.
+ if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) {
+ reject("location change was not to an error page");
+ }
+ },
+
+ onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
+ // Wait until the documentURI changes (from about:blank) this should
+ // be the error page URI.
+ var documentURI = frame.contentDocument.documentURI;
+ if (documentURI == originalDocumentURI) {
+ return;
+ }
+
+ aWebProgress.removeProgressListener(progressListener,
+ Ci.nsIWebProgress.NOTIFY_ALL);
+ var matchArray = /about:neterror\?.*&d=([^&]*)/.exec(documentURI);
+ if (!matchArray) {
+ reject("no network error message found in URI")
+ return;
+ }
+
+ var errorMsg = matchArray[1];
+ resolve(decodeURIComponent(errorMsg));
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+ Ci.nsISupportsWeakReference])
+ };
+
+ frame.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebProgress)
+ .addProgressListener(progressListener,
+ Ci.nsIWebProgress.NOTIFY_LOCATION |
+ Ci.nsIWebProgress.NOTIFY_STATE_REQUEST);
+ });
+ }
+
+ function startTest() {
+ // Get a reference message that we know will be an unknown protocol message,
+ // so we can use it for comparisons in the test cases.
+ var refIframe = window[0].document.getElementById("refIframe");
+ var refErrorPromise = createNetworkErrorMessagePromise(refIframe);
+
+ refErrorPromise.then(
+ function(msg) {
+ window.refErrorMsg = msg;
+ var testIframe = window[0].document.getElementById("testIframe");
+
+ // Run test cases on load of "about:blank", so that the URI always changes
+ // and we can detect this in our Promise.
+ testIframe.onload = runNextTestCase;
+ testIframe.src = "about:blank";
+ },
+ function(reason) {
+ ok(false, "Could not get reference error message", reason);
+ SimpleTest.finish();
+ })
+ .catch(function(e) {
+ ok(false, "Unexpected exception thrown getting reference error message", exception);
+ });
+
+ refIframe.src = "wibble://example.com";
+ }
+
+ function runTestCase(testCase) {
+ var testIframe = window[0].document.getElementById("testIframe");
+ var expectedErrorMsg = window.refErrorMsg.replace("wibble", testCase.expectedProtocolList);
+
+ var testErrorPromise = createNetworkErrorMessagePromise(testIframe);
+ testErrorPromise.then(
+ function(actualErrorMsg) {
+ is(actualErrorMsg, expectedErrorMsg, testCase.desc);
+ testIframe.src = "about:blank";
+ },
+ function(reason) {
+ ok(false, testCase.desc, reason);
+ testIframe.src = "about:blank";
+ })
+ .catch(function(e) {
+ ok(false, testCase.desc + " - unexpected exception thrown", exception);
+ });
+
+ testIframe.src = testCase.protocols + "://example.com/!/";
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: view-source should not be allowed in an iframe",
+ protocols: "view-source:http",
+ expectedProtocolList: "view-source, http"
+ },
+ {
+ desc: "Test 2: feed:view-source should not be allowed in an iframe",
+ protocols: "feed:view-source:http",
+ expectedProtocolList: "feed, view-source, http"
+ },
+ {
+ desc: "Test 3: jar:view-source should not be allowed in an iframe",
+ protocols: "jar:view-source:http",
+ expectedProtocolList: "jar, view-source, http"
+ },
+ {
+ desc: "Test 4: pcast:view-source should not be allowed in an iframe",
+ protocols: "pcast:view-source:http",
+ expectedProtocolList: "pcast, view-source, http"
+ },
+ {
+ desc: "Test 5: pcast:feed:view-source should not be allowed in an iframe",
+ protocols: "pcast:feed:view-source:http",
+ expectedProtocolList: "pcast, feed, view-source, http"
+ },
+ {
+ desc: "Test 6: if invalid protocol first should report before view-source",
+ protocols: "wibble:view-source:http",
+ // Nothing after the invalid protocol gets set as a proper nested URI,
+ // so the list stops there.
+ expectedProtocolList: "wibble"
+ },
+ {
+ desc: "Test 7: if view-source first should report before invalid protocol",
+ protocols: "view-source:wibble:http",
+ expectedProtocolList: "view-source, wibble"
+ }
+ ];
+
+ function runNextTestCase() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ runTestCase(testCases[testCaseIndex]);
+ }
+
+ ]]>
+ </script>
+</window>
diff --git a/docshell/test/chrome/window.template.txt b/docshell/test/chrome/window.template.txt
new file mode 100644
index 0000000000..a7fb0fac7c
--- /dev/null
+++ b/docshell/test/chrome/window.template.txt
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="{BUGNUMBER}Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug {BUGNUMBER} test">
+
+ <script type="application/javascript"
+ src="docshell_helpers.js">
+ </script>
+
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug {BUGNUMBER}:
+ // Description goes here.
+ //
+ function testIterator()
+ {
+ // Test steps go here. See bug303267_window.xul for an example.
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/file_anchor_scroll_after_document_open.html b/docshell/test/file_anchor_scroll_after_document_open.html
new file mode 100644
index 0000000000..7903380eac
--- /dev/null
+++ b/docshell/test/file_anchor_scroll_after_document_open.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script>
+ if (location.hash == "#target") {
+ parent.postMessage("haveHash", "*");
+ } else {
+ document.addEventListener("DOMContentLoaded", function() {
+ document.open();
+ document.write("<!DOCTYPE html><html style='height: 100%'><body style='height: 100%'><div style='height: 200%'></div><div id='target'></div></body></html>");
+ document.close();
+ // Notify parent via postMessage, since otherwise exceptions will not get
+ // caught by its onerror handler.
+ parent.postMessage("doTest", "*");
+ });
+ }
+</script>
diff --git a/docshell/test/file_bug385434_1.html b/docshell/test/file_bug385434_1.html
new file mode 100644
index 0000000000..5c951f1fa6
--- /dev/null
+++ b/docshell/test/file_bug385434_1.html
@@ -0,0 +1,29 @@
+<!--
+Inner frame for test of bug 385434.
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<html>
+<head>
+ <script type="application/javascript">
+ function hashchange() {
+ parent.onIframeHashchange();
+ }
+
+ function load() {
+ parent.onIframeLoad();
+ }
+
+ function scroll() {
+ parent.onIframeScroll();
+ }
+ </script>
+</head>
+
+<body onscroll="scroll()" onload="load()" onhashchange="hashchange()">
+<a href="#link1" id="link1">link1</a>
+<!-- Our parent loads us in an iframe with height 100px, so this spacer ensures
+ that switching between #link1 and #link2 causes us to scroll -->
+<div style="height:200px;"></div>
+<a href="#link2" id="link2">link2</a>
+</body>
+</html>
diff --git a/docshell/test/file_bug385434_2.html b/docshell/test/file_bug385434_2.html
new file mode 100644
index 0000000000..4aa5ef82b8
--- /dev/null
+++ b/docshell/test/file_bug385434_2.html
@@ -0,0 +1,26 @@
+<!--
+Inner frame for test of bug 385434.
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<html>
+<head>
+ <script type="application/javascript">
+ function hashchange(e) {
+ // pass the event back to the parent so it can check its properties.
+ parent.gSampleEvent = e;
+
+ parent.statusMsg("Hashchange in 2.");
+ parent.onIframeHashchange();
+ }
+
+ function load() {
+ parent.statusMsg("Loading 2.");
+ parent.onIframeLoad();
+ }
+ </script>
+</head>
+
+<frameset onload="load()" onhashchange="hashchange(event)">
+ <frame src="about:blank" />
+</frameset>
+</html>
diff --git a/docshell/test/file_bug385434_3.html b/docshell/test/file_bug385434_3.html
new file mode 100644
index 0000000000..984b85f1f3
--- /dev/null
+++ b/docshell/test/file_bug385434_3.html
@@ -0,0 +1,22 @@
+<!--
+Inner frame for test of bug 385434.
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<html>
+<head>
+ <script type="application/javascript">
+ // Notify our parent if we have a hashchange and once we're done loading.
+ window.addEventListener("hashchange", parent.onIframeHashchange, false);
+
+ window.addEventListener("DOMContentLoaded", function() {
+ // This also should trigger a hashchange, becuase the readystate is
+ // "interactive", not "complete" during DOMContentLoaded.
+ window.location.hash = "2";
+ }, false);
+
+ </script>
+</head>
+
+<body>
+</body>
+</html>
diff --git a/docshell/test/file_bug475636.sjs b/docshell/test/file_bug475636.sjs
new file mode 100644
index 0000000000..38da6a6a50
--- /dev/null
+++ b/docshell/test/file_bug475636.sjs
@@ -0,0 +1,90 @@
+jsURL = "javascript:" + escape('window.parent.postMessage("JS uri ran", "*");\
+return \'\
+<script>\
+window.parent.postMessage("Able to access private: " +\
+ window.parent.private, "*");\
+</script>\'');
+dataURL = "data:text/html," + escape('<!DOCTYPE HTML>\
+<script>\
+try {\
+ window.parent.postMessage("Able to access private: " +\
+ window.parent.private, "*");\
+}\
+catch (e) {\
+ window.parent.postMessage("pass", "*");\
+}\
+</script>');
+
+tests = [
+// Plain document should work as normal
+'<!DOCTYPE HTML>\
+<script>\
+try {\
+ window.parent.private;\
+ window.parent.postMessage("pass", "*");\
+}\
+catch (e) {\
+ window.parent.postMessage("Unble to access private", "*");\
+}\
+</script>',
+
+// refresh to plain doc
+{ refresh: "file_bug475636.sjs?1",
+ doc: '<!DOCTYPE HTML>' },
+
+// meta-refresh to plain doc
+'<!DOCTYPE HTML>\
+<head>\
+ <meta http-equiv="refresh" content="0; url=file_bug475636.sjs?1">\
+</head>',
+
+// refresh to data url
+{ refresh: dataURL,
+ doc: '<!DOCTYPE HTML>' },
+
+// meta-refresh to data url
+'<!DOCTYPE HTML>\
+<head>\
+ <meta http-equiv="refresh" content="0; url=' + dataURL + '">\
+</head>',
+
+// refresh to js url should not be followed
+{ refresh: jsURL,
+ doc:
+'<!DOCTYPE HTML>\
+<script>\
+setTimeout(function() {\
+ window.parent.postMessage("pass", "*");\
+}, 2000);\
+</script>' },
+
+// meta refresh to js url should not be followed
+'<!DOCTYPE HTML>\
+<head>\
+ <meta http-equiv="refresh" content="0; url=' + jsURL + '">\
+</head>\
+<script>\
+setTimeout(function() {\
+ window.parent.postMessage("pass", "*");\
+}, 2000);\
+</script>'
+];
+
+
+function handleRequest(request, response)
+{
+ dump("@@@@@@@@@hi there: " + request.queryString + "\n");
+ test = tests[parseInt(request.queryString, 10) - 1];
+ response.setHeader("Content-Type", "text/html");
+
+ if (!test) {
+ response.write('<script>parent.postMessage("done", "*");</script>');
+ }
+ else if (typeof test == "string") {
+ response.write(test);
+ }
+ else if (test.refresh) {
+ response.setHeader("Refresh", "0; url=" + test.refresh);
+ response.write(test.doc);
+ }
+}
diff --git a/docshell/test/file_bug509055.html b/docshell/test/file_bug509055.html
new file mode 100644
index 0000000000..ac30876bbf
--- /dev/null
+++ b/docshell/test/file_bug509055.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test inner frame for bug 509055</title>
+</head>
+<body onhashchange="hashchangeCallback()">
+ file_bug509055.html
+</body>
+</html>
diff --git a/docshell/test/file_bug511449.html b/docshell/test/file_bug511449.html
new file mode 100644
index 0000000000..637732dbbf
--- /dev/null
+++ b/docshell/test/file_bug511449.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<title>Used in test for bug 511449</title>
+<input type="text" id="input">
+<script type="text/javascript">
+ document.getElementById("input").focus();
+</script>
diff --git a/docshell/test/file_bug540462.html b/docshell/test/file_bug540462.html
new file mode 100644
index 0000000000..52d1580c7e
--- /dev/null
+++ b/docshell/test/file_bug540462.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <script>
+ //<!--
+ function test() {
+ document.open();
+ document.write("<html><body onload='opener.documentWriteLoad(); rel();'><a href='foo.html'>foo</a><script>function rel() { setTimeout('location.reload()', 0); }</script></body></html>");
+ document.close();
+ }
+ //-->
+ </script>
+ </head>
+ <body onload="setTimeout('test()', 0)">
+ Test for bug 540462
+ </body>
+</html>
diff --git a/docshell/test/file_bug580069_1.html b/docshell/test/file_bug580069_1.html
new file mode 100644
index 0000000000..7ab4610334
--- /dev/null
+++ b/docshell/test/file_bug580069_1.html
@@ -0,0 +1,8 @@
+<html>
+<body onload='parent.page1Load();'>
+file_bug580069_1.html
+
+<form id='form' action='file_bug580069_2.sjs' method='POST'></form>
+
+</body>
+</html>
diff --git a/docshell/test/file_bug580069_2.sjs b/docshell/test/file_bug580069_2.sjs
new file mode 100644
index 0000000000..0c76c1f16e
--- /dev/null
+++ b/docshell/test/file_bug580069_2.sjs
@@ -0,0 +1,5 @@
+function handleRequest(request, response)
+{
+ response.setHeader("Content-Type", "text/html", false);
+ response.write('<html><body onload=\'parent.page2Load("' + request.method + '")\'>file_bug580069_2.sjs</body></html>');
+}
diff --git a/docshell/test/file_bug590573_1.html b/docshell/test/file_bug590573_1.html
new file mode 100644
index 0000000000..850d418bde
--- /dev/null
+++ b/docshell/test/file_bug590573_1.html
@@ -0,0 +1,8 @@
+<html>
+<body onpopstate='opener.page1Popstate();' onload='opener.page1Load();'
+ onpageshow='opener.page1PageShow();'>
+
+<div style='height:10000px' id='div1'>This is a very tall div.</div>
+
+</body>
+</html>
diff --git a/docshell/test/file_bug590573_2.html b/docshell/test/file_bug590573_2.html
new file mode 100644
index 0000000000..5f9ca22be4
--- /dev/null
+++ b/docshell/test/file_bug590573_2.html
@@ -0,0 +1,8 @@
+<html>
+<body onpopstate='opener.page2Popstate();' onload='opener.page2Load();'
+ onpageshow='opener.page2PageShow();'>
+
+<div style='height:300%' id='div2'>The second page also has a big div.</div>
+
+</body>
+</html>
diff --git a/docshell/test/file_bug634834.html b/docshell/test/file_bug634834.html
new file mode 100644
index 0000000000..3ff0897451
--- /dev/null
+++ b/docshell/test/file_bug634834.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Nothing to see here; just an empty page.
+</body>
+</html>
diff --git a/docshell/test/file_bug640387.html b/docshell/test/file_bug640387.html
new file mode 100644
index 0000000000..3a939fb41e
--- /dev/null
+++ b/docshell/test/file_bug640387.html
@@ -0,0 +1,26 @@
+<html>
+<body onhashchange='hashchange()' onload='load()' onpopstate='popstate()'>
+
+<script>
+function hashchange() {
+ var f = (opener || parent).childHashchange;
+ if (f)
+ f();
+}
+
+function load() {
+ var f = (opener || parent).childLoad;
+ if (f)
+ f();
+}
+
+function popstate() {
+ var f = (opener || parent).childPopstate;
+ if (f)
+ f();
+}
+</script>
+
+Not much to see here...
+</body>
+</html>
diff --git a/docshell/test/file_bug653741.html b/docshell/test/file_bug653741.html
new file mode 100644
index 0000000000..3202b52573
--- /dev/null
+++ b/docshell/test/file_bug653741.html
@@ -0,0 +1,13 @@
+<html>
+<body onload='(parent || opener).childLoad()'>
+
+<div style='height:500px; background:yellow'>
+<a id='#top'>Top of the page</a>
+</div>
+
+<div id='bottom'>
+<a id='#bottom'>Bottom of the page</a>
+</div>
+
+</body>
+</html>
diff --git a/docshell/test/file_bug660404 b/docshell/test/file_bug660404
new file mode 100644
index 0000000000..0737a5c4d3
--- /dev/null
+++ b/docshell/test/file_bug660404
@@ -0,0 +1,5 @@
+--testingtesting
+Content-Type: text/html
+
+<script>opener.finishTest();</script>
+--testingtesting--
diff --git a/docshell/test/file_bug660404^headers^ b/docshell/test/file_bug660404^headers^
new file mode 100644
index 0000000000..5c821f3f48
--- /dev/null
+++ b/docshell/test/file_bug660404^headers^
@@ -0,0 +1 @@
+Content-Type: multipart/x-mixed-replace; boundary="testingtesting"
diff --git a/docshell/test/file_bug662170.html b/docshell/test/file_bug662170.html
new file mode 100644
index 0000000000..3202b52573
--- /dev/null
+++ b/docshell/test/file_bug662170.html
@@ -0,0 +1,13 @@
+<html>
+<body onload='(parent || opener).childLoad()'>
+
+<div style='height:500px; background:yellow'>
+<a id='#top'>Top of the page</a>
+</div>
+
+<div id='bottom'>
+<a id='#bottom'>Bottom of the page</a>
+</div>
+
+</body>
+</html>
diff --git a/docshell/test/file_bug668513.html b/docshell/test/file_bug668513.html
new file mode 100644
index 0000000000..1e43a51e00
--- /dev/null
+++ b/docshell/test/file_bug668513.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test file for Bug 668513</title>
+<script>
+ var SimpleTest = opener.SimpleTest;
+ var ok = opener.ok;
+ var is = opener.is;
+
+ function finish() {
+ SimpleTest.finish();
+ close();
+ }
+
+ function onload_test()
+ {
+ var win = frames[0];
+ ok(win.performance, 'Window.performance should be defined');
+ ok(win.performance.navigation, 'Window.performance.navigation should be defined');
+ var navigation = win.performance && win.performance.navigation;
+ if (navigation === undefined)
+ {
+ // avoid script errors
+ finish();
+ return;
+ }
+
+ // do this with a timeout to see the visuals of the navigations.
+ setTimeout("nav_frame();", 100);
+ }
+
+ var step = 1;
+ function nav_frame()
+ {
+ var navigation_frame = frames[0];
+ var navigation = navigation_frame.performance.navigation;
+ switch (step)
+ {
+ case 1:
+ {
+ navigation_frame.location.href = 'bug570341_recordevents.html';
+ step++;
+ break;
+ }
+ case 2:
+ {
+ is(navigation.type, navigation.TYPE_NAVIGATE,
+ 'Expected window.performance.navigation.type == TYPE_NAVIGATE');
+ navigation_frame.history.back();
+ step++;
+ break;
+ }
+ case 3:
+ {
+ is(navigation.type, navigation.TYPE_BACK_FORWARD,
+ 'Expected window.performance.navigation.type == TYPE_BACK_FORWARD');
+ step++;
+ navigation_frame.history.forward();
+ break;
+ }
+ case 4:
+ {
+ is(navigation.type, navigation.TYPE_BACK_FORWARD,
+ 'Expected window.performance.navigation.type == TYPE_BACK_FORWARD');
+ navigation_frame.location.href = 'bug668513_redirect.html';
+ step++;
+ break;
+ }
+ case 5:
+ {
+ is(navigation.type, navigation.TYPE_NAVIGATE,
+ 'Expected timing.navigation.type as TYPE_NAVIGATE');
+ is(navigation.redirectCount, 1,
+ 'Expected navigation.redirectCount == 1 on an server redirected navigation');
+
+ var timing = navigation_frame.performance && navigation_frame.performance.timing;
+ if (timing === undefined)
+ {
+ // avoid script errors
+ finish();
+ break;
+ }
+ ok(timing.navigationStart > 0, 'navigationStart should be > 0');
+ sequence = ['navigationStart', 'redirectStart', 'redirectEnd', 'fetchStart'];
+ for (var j = 1; j < sequence.length; ++j) {
+ var prop = sequence[j];
+ var prevProp = sequence[j-1];
+ ok(timing[prevProp] <= timing[prop],
+ ['Expected ', prevProp, ' to happen before ', prop,
+ ', got ', prevProp, ' = ', timing[prevProp],
+ ', ', prop, ' = ', timing[prop]].join(''));
+ }
+ step++;
+ finish();
+ }
+ default:
+ break;
+ }
+ }
+</script>
+</head>
+<body>
+<div id="frames">
+<iframe name="child0" onload="onload_test();" src="navigation/blank.html"></iframe>
+</div>
+</body>
+</html>
diff --git a/docshell/test/file_bug669671.sjs b/docshell/test/file_bug669671.sjs
new file mode 100644
index 0000000000..b6fd1ec7c5
--- /dev/null
+++ b/docshell/test/file_bug669671.sjs
@@ -0,0 +1,14 @@
+function handleRequest(request, response)
+{
+ var count = parseInt(getState('count'));
+ if (!count || request.queryString == 'countreset')
+ count = 0;
+
+ setState('count', count + 1 + '');
+
+ response.setHeader('Content-Type', 'text/html', false);
+ response.setHeader('Cache-Control', 'max-age=0');
+ response.write('<html><body onload="opener.onChildLoad()" ' +
+ 'onunload="parseInt(\'0\')">' +
+ count + '</body></html>');
+}
diff --git a/docshell/test/file_bug680257.html b/docshell/test/file_bug680257.html
new file mode 100644
index 0000000000..ff480e96a5
--- /dev/null
+++ b/docshell/test/file_bug680257.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <style type='text/css'>
+ a { color: black; }
+ a:target { color: red; }
+ </style>
+</head>
+
+<body onload='(opener || parent).popupLoaded()'>
+
+<a id='a' href='#a'>link</a>
+<a id='b' href='#b'>link2</a>
+
+</body>
+</html>
diff --git a/docshell/test/file_bug703855.html b/docshell/test/file_bug703855.html
new file mode 100644
index 0000000000..fe15b6e3df
--- /dev/null
+++ b/docshell/test/file_bug703855.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<!-- Just need an empty file here, as long as it's served over HTTP -->
diff --git a/docshell/test/file_bug728939.html b/docshell/test/file_bug728939.html
new file mode 100644
index 0000000000..1cd52a44e1
--- /dev/null
+++ b/docshell/test/file_bug728939.html
@@ -0,0 +1,3 @@
+<html>
+<body onload="opener.popupLoaded()">file_bug728939</body>
+</html>
diff --git a/docshell/test/file_framedhistoryframes.html b/docshell/test/file_framedhistoryframes.html
new file mode 100644
index 0000000000..314f9c72d8
--- /dev/null
+++ b/docshell/test/file_framedhistoryframes.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<iframe id="iframe" src="historyframes.html"></iframe>
+<script type="application/javascript">
+
+var SimpleTest = window.opener.SimpleTest;
+var is = window.opener.is;
+
+function done() {
+ window.opener.done();
+}
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/file_pushState_after_document_open.html b/docshell/test/file_pushState_after_document_open.html
new file mode 100644
index 0000000000..97a6954f2e
--- /dev/null
+++ b/docshell/test/file_pushState_after_document_open.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+ document.addEventListener("DOMContentLoaded", function() {
+ document.open();
+ document.write("<!DOCTYPE html>New Document here");
+ document.close();
+ // Notify parent via postMessage, since otherwise exceptions will not get
+ // caught by its onerror handler.
+ parent.postMessage("doTest", "*");
+ });
+</script>
diff --git a/docshell/test/historyframes.html b/docshell/test/historyframes.html
new file mode 100644
index 0000000000..30fca2c0a3
--- /dev/null
+++ b/docshell/test/historyframes.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602256
+-->
+<head>
+ <title>Test for Bug 602256</title>
+</head>
+<body onload="SimpleTest.executeSoon(run_test)">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602256">Mozilla Bug 602256</a>
+<div id="content">
+ <iframe id="iframe" src="data:text/html,<p%20id='text'>Start</p>"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 602256 **/
+
+var testWin = window.opener ? window.opener : window.parent;
+
+var SimpleTest = testWin.SimpleTest;
+function is() { testWin.is.apply(testWin, arguments); }
+
+var gFrame = null;
+
+function gState() {
+ return location.hash.replace(/^#/, "");
+}
+
+function waitForLoad(aCallback) {
+ function listener() {
+ gFrame.removeEventListener("load", listener, false);
+ SimpleTest.executeSoon(aCallback);
+ }
+
+ gFrame.addEventListener("load", listener, false);
+}
+
+function loadContent(aURL, aCallback) {
+ waitForLoad(aCallback);
+
+ gFrame.src = aURL;
+}
+
+function getURL() {
+ return gFrame.contentDocument.documentURI;
+}
+
+function getContent() {
+ return gFrame.contentDocument.getElementById("text").textContent;
+}
+
+var START = "data:text/html,<p%20id='text'>Start</p>";
+var URL1 = "data:text/html,<p%20id='text'>Test1</p>";
+var URL2 = "data:text/html,<p%20id='text'>Test2</p>";
+
+function run_test() {
+ window.location.hash = "START";
+
+ gFrame = document.getElementById("iframe");
+
+ test_basic_inner_navigation();
+}
+
+function end_test() {
+ testWin.done();
+}
+
+function test_basic_inner_navigation() {
+ // Navigate the inner frame a few times
+ loadContent(URL1, function() {
+ is(getURL(), URL1, "URL should be correct");
+ is(getContent(), "Test1", "Page should be correct");
+
+ loadContent(URL2, function() {
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ // Test that history is working
+ waitForLoad(function() {
+ is(getURL(), URL1, "URL should be correct");
+ is(getContent(), "Test1", "Page should be correct");
+
+ waitForLoad(function() {
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ test_state_navigation();
+ });
+ window.history.forward();
+ });
+ window.history.back();
+ });
+ });
+}
+
+function test_state_navigation() {
+ window.location.hash = "STATE1";
+
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.location.hash = "STATE2";
+
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.history.back();
+
+ is(gState(), "STATE1", "State should be correct after going back");
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.history.forward();
+
+ is(gState(), "STATE2", "State should be correct after going forward");
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.history.back();
+ window.history.back();
+
+ is(gState(), "START", "State should be correct");
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ waitForLoad(function() {
+ is(getURL(), URL1, "URL should be correct");
+ is(getContent(), "Test1", "Page should be correct");
+
+ waitForLoad(function() {
+ is(gState(), "START", "State should be correct");
+ is(getURL(), START, "URL should be correct");
+ is(getContent(), "Start", "Page should be correct");
+
+ end_test();
+ });
+
+ window.history.back();
+
+ is(gState(), "START", "State should be correct after going back twice");
+ });
+
+ window.history.back();
+ is(gState(), "START", "State should be correct");
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/file_marquee_event_handlers.html b/docshell/test/iframesandbox/file_marquee_event_handlers.html
new file mode 100644
index 0000000000..13ee31ddb7
--- /dev/null
+++ b/docshell/test/iframesandbox/file_marquee_event_handlers.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test marquee attribute event handlers in iframe sandbox</title>
+</head>
+<body>
+ <!-- Note that the width here is slightly longer than the contents, to make
+ sure we bounce and finish very quickly. -->
+ <marquee loop="2" width="145" behavior="alternate" truespeed scrolldelay="1"
+ onstart="parent.postMessage(window.name + ' marquee onstart', '*');"
+ onbounce="parent.postMessage(window.name + ' marquee onbounce', '*');"
+ onfinish="parent.postMessage(window.name + ' marquee onfinish', '*');">
+ Will bounce and finish
+ </marquee>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/file_other_auxiliary_navigation_by_location.html b/docshell/test/iframesandbox/file_other_auxiliary_navigation_by_location.html
new file mode 100644
index 0000000000..ad24c0f242
--- /dev/null
+++ b/docshell/test/iframesandbox/file_other_auxiliary_navigation_by_location.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test window for other auxiliary navigation by location tests</title>
+<script>
+ function onNav() {
+ opener.postMessage(window.name, "*");
+ }
+
+ window.onload = onNav;
+ window.onhashchange = onNav;
+</script>
+</head>
+</html>
diff --git a/docshell/test/iframesandbox/file_our_auxiliary_navigation_by_location.html b/docshell/test/iframesandbox/file_our_auxiliary_navigation_by_location.html
new file mode 100644
index 0000000000..978980df25
--- /dev/null
+++ b/docshell/test/iframesandbox/file_our_auxiliary_navigation_by_location.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test window for our auxiliary navigation by location tests</title>
+<script>
+ function onNav() {
+ opener.parent.postMessage(window.name, "*");
+ }
+
+ window.onload = onNav;
+ window.onhashchange = onNav;
+</script>
+</head>
+</html>
diff --git a/docshell/test/iframesandbox/file_parent_navigation_by_location.html b/docshell/test/iframesandbox/file_parent_navigation_by_location.html
new file mode 100644
index 0000000000..9a2e95fad0
--- /dev/null
+++ b/docshell/test/iframesandbox/file_parent_navigation_by_location.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test window for parent navigation by location tests</title>
+<script>
+ function onNav() {
+ parent.postMessage(window.name, "*");
+ }
+
+ window.onload = onNav;
+ window.onhashchange = onNav;
+</script>
+</head>
+<body>
+ <iframe name="childIframe" sandbox="allow-scripts allow-same-origin allow-top-navigation"></iframe>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/file_sibling_navigation_by_location.html b/docshell/test/iframesandbox/file_sibling_navigation_by_location.html
new file mode 100644
index 0000000000..51a52bb8eb
--- /dev/null
+++ b/docshell/test/iframesandbox/file_sibling_navigation_by_location.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test window for sibling navigation by location tests</title>
+<script>
+ function onNav() {
+ parent.postMessage(window.name, "*");
+ }
+
+ window.onload = onNav;
+ window.onhashchange = onNav;
+</script>
+</head>
+</html>
diff --git a/docshell/test/iframesandbox/file_top_navigation_by_location.html b/docshell/test/iframesandbox/file_top_navigation_by_location.html
new file mode 100644
index 0000000000..194430f38c
--- /dev/null
+++ b/docshell/test/iframesandbox/file_top_navigation_by_location.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test window for top navigation by location tests</title>
+<script>
+ function onNav() {
+ opener.postMessage(window.name, "*");
+ }
+
+ window.onload = onNav;
+ window.onhashchange = onNav;
+</script>
+</head>
+<body>
+ <iframe name="if1" sandbox="allow-scripts allow-same-origin"></iframe>
+ <iframe name="if2" sandbox="allow-scripts allow-same-origin allow-top-navigation"></iframe>
+ <iframe name="if3" sandbox="allow-scripts allow-top-navigation"></iframe>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/file_top_navigation_by_location_exotic.html b/docshell/test/iframesandbox/file_top_navigation_by_location_exotic.html
new file mode 100644
index 0000000000..1c7c6ce297
--- /dev/null
+++ b/docshell/test/iframesandbox/file_top_navigation_by_location_exotic.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test window for top navigation by location tests</title>
+<script>
+ function onBlock() {
+ opener.postMessage({ name: window.name, blocked: true }, '*');
+ }
+
+ function onNav() {
+ opener.postMessage({ name: window.name, blocked: false }, '*');
+ }
+
+ function setOwnHref() {
+ location.href = location.href;
+ }
+
+ window.onload = onNav;
+</script>
+</head>
+<body>
+ <iframe name="if1" sandbox="allow-scripts allow-same-origin"></iframe>
+ <iframe name="if2" sandbox="allow-scripts allow-same-origin allow-top-navigation"></iframe>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/mochitest.ini b/docshell/test/iframesandbox/mochitest.ini
new file mode 100644
index 0000000000..5f6b570e93
--- /dev/null
+++ b/docshell/test/iframesandbox/mochitest.ini
@@ -0,0 +1,24 @@
+[DEFAULT]
+support-files =
+ file_marquee_event_handlers.html
+ file_other_auxiliary_navigation_by_location.html
+ file_our_auxiliary_navigation_by_location.html
+ file_parent_navigation_by_location.html
+ file_sibling_navigation_by_location.html
+ file_top_navigation_by_location.html
+ file_top_navigation_by_location_exotic.html
+
+[test_child_navigation_by_location.html]
+[test_marquee_event_handlers.html]
+[test_other_auxiliary_navigation_by_location.html]
+tags = openwindow
+[test_our_auxiliary_navigation_by_location.html]
+tags = openwindow
+[test_parent_navigation_by_location.html]
+tags = openwindow
+[test_sibling_navigation_by_location.html]
+tags = openwindow
+[test_top_navigation_by_location_exotic.html]
+skip-if = android_version == '18' #bug 948948, NS_ERROR_FAILURE from nsWindowWatcher::GetPrompt
+[test_top_navigation_by_location.html]
+skip-if = android_version == '18' #bug 948948, NS_ERROR_FAILURE from nsWindowWatcher::GetPrompt
diff --git a/docshell/test/iframesandbox/test_child_navigation_by_location.html b/docshell/test/iframesandbox/test_child_navigation_by_location.html
new file mode 100644
index 0000000000..06605e3cd4
--- /dev/null
+++ b/docshell/test/iframesandbox/test_child_navigation_by_location.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785310
+html5 sandboxed iframe should not be able to perform top navigation with scripts allowed
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 785310 - iframe sandbox child navigation by location tests</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();
+
+ var testHtml = "<script>function onNav() { parent.parent.postMessage('childIframe', '*'); } window.onload = onNav; window.onhashchange = onNav;<\/script>";
+ var testDataUri = "data:text/html," + testHtml;
+
+ function runScriptNavigationTest(testCase) {
+ window.onmessage = function(event) {
+ if (event.data != 'childIframe') {
+ ok(false, "event.data: got '" + event.data + "', expected 'childIframe'");
+ }
+ ok(!testCase.shouldBeBlocked, testCase.desc, "child navigation was NOT blocked");
+ runNextTest();
+ };
+ try {
+ window["parentIframe"].eval(testCase.script);
+ } catch(e) {
+ ok(testCase.shouldBeBlocked, testCase.desc, e.message);
+ runNextTest();
+ }
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: cross origin child location.replace should NOT be blocked",
+ script: "window['crossOriginChildIframe'].location.replace(\"" + testDataUri + "\")",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 2: cross origin child location.assign should be blocked",
+ script: "window['crossOriginChildIframe'].location.assign(\"" + testDataUri + "\")",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 3: same origin child location.assign should NOT be blocked",
+ script: "window['sameOriginChildIframe'].location.assign(\"" + testDataUri + "\")",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 4: cross origin child location.href should NOT be blocked",
+ script: "window['crossOriginChildIframe'].location.href = \"" + testDataUri + "\"",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 5: cross origin child location.hash should be blocked",
+ script: "window['crossOriginChildIframe'].location.hash = 'wibble'",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 6: same origin child location.hash should NOT be blocked",
+ script: "window['sameOriginChildIframe'].location.hash = 'wibble'",
+ shouldBeBlocked: false
+ }
+ ];
+
+ function runNextTest() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ runScriptNavigationTest(testCases[testCaseIndex]);
+ }
+
+ addLoadEvent(runNextTest);
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785310">Mozilla Bug 785310</a>
+<p id="display"></p>
+<div id="content">
+Tests for Bug 785310
+</div>
+
+<iframe name="parentIframe" sandbox="allow-scripts allow-same-origin" src="data:text/html,<iframe name='sameOriginChildIframe'></iframe><iframe name='crossOriginChildIframe' sandbox='allow-scripts'></iframe>"</iframe>
+
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/test_marquee_event_handlers.html b/docshell/test/iframesandbox/test_marquee_event_handlers.html
new file mode 100644
index 0000000000..f243e4834f
--- /dev/null
+++ b/docshell/test/iframesandbox/test_marquee_event_handlers.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1277475
+html5 sandboxed iframe should not run marquee attribute event handlers without allow-scripts
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 1277475 - html5 sandboxed iframe should not run marquee attribute event handlers without allow-scripts</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=1277475">Mozilla Bug 1277475</a>
+<p id="display"></p>
+<div id="content">Tests for Bug 1277475</div>
+
+<iframe id="if1" name="if1" src="file_marquee_event_handlers.html"
+ sandbox="allow-same-origin allow-forms allow-top-navigation allow-pointer-lock allow-orientation-lock allow-popups allow-modals allow-popups-to-escape-sandbox">
+</iframe>
+
+<iframe id="if2" name="if2" src="file_marquee_event_handlers.html"
+ sandbox="allow-scripts"></iframe>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ var expectedMessages = new Set();
+ var numberOfMessagesExpected = 4;
+ var unexpectedMessages = new Set();
+
+ window.onmessage = function (event) {
+ info(event.data + " message received");
+ if (event.data.startsWith("if2") || event.data == "if1 chaser") {
+ expectedMessages.add(event.data);
+ if (expectedMessages.size == numberOfMessagesExpected) {
+ checkRecievedMessages();
+ }
+ } else {
+ unexpectedMessages.add(event.data);
+ }
+ }
+
+ function checkRecievedMessages() {
+ // Check the expected messages explicitly as a cross-check.
+ ok(expectedMessages.has("if1 chaser"),
+ "if1 chaser message should have been received");
+ ok(expectedMessages.has("if2 marquee onstart"),
+ "if2 marquee onstart should have run in iframe sandbox with allow-scripts");
+ ok(expectedMessages.has("if2 marquee onbounce"),
+ "if2 marquee onbounce should have run in iframe sandbox with allow-scripts");
+ ok(expectedMessages.has("if2 marquee onfinish"),
+ "if2 marquee onfinish should have run in iframe sandbox with allow-scripts");
+
+ unexpectedMessages.forEach(
+ (v) => {
+ ok(false, v + " should NOT have run in iframe sandbox without allow-scripts")
+ }
+ );
+
+ SimpleTest.finish();
+ }
+
+ // If things are working properly the attribute event handlers won't run on
+ // the marquee in if1, so add our own capturing listeners on its window, so we
+ // know when they have fired. (These will run as we are not sandboxed.)
+ var if1FiredEvents = new Set();
+ var if1NumberOfEventsExpected = 3;
+ var if1Win = document.getElementById("if1").contentWindow;
+ if1Win.addEventListener("start", () => { checkMarqueeEvent("start"); }, true);
+ if1Win.addEventListener("bounce", () => { checkMarqueeEvent("bounce"); }, true);
+ if1Win.addEventListener("finish", () => { checkMarqueeEvent("finish"); }, true);
+
+ function checkMarqueeEvent(eventType) {
+ info("if1 event " + eventType + " fired");
+ if1FiredEvents.add(eventType);
+ if (if1FiredEvents.size == if1NumberOfEventsExpected) {
+ // Only send the chasing message after a tick of the event loop to allow
+ // event handlers on the marquee to process.
+ SimpleTest.executeSoon(sendChasingMessage);
+ }
+ }
+
+ function sendChasingMessage() {
+ // Add our own message listener to if1's window and echo back a chasing
+ // message to make sure that any messages from incorrectly run marquee
+ // attribute event handlers should have arrived before it.
+ if1Win.addEventListener("message",
+ (e) => { if1Win.parent.postMessage(e.data, "*"); });
+ if1Win.postMessage("if1 chaser", "*");
+ info("if1 chaser message sent");
+ }
+</script>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/test_other_auxiliary_navigation_by_location.html b/docshell/test/iframesandbox/test_other_auxiliary_navigation_by_location.html
new file mode 100644
index 0000000000..05c86f0cc1
--- /dev/null
+++ b/docshell/test/iframesandbox/test_other_auxiliary_navigation_by_location.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785310
+html5 sandboxed iframe should not be able to perform top navigation with scripts allowed
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 785310 - iframe sandbox other auxiliary navigation by location tests</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 runScriptNavigationTest(testCase) {
+ window.onmessage = function(event) {
+ if (event.data != "otherWindow") {
+ ok(false, "event.data: got '" + event.data + "', expected 'otherWindow'");
+ }
+ ok(false, testCase.desc, "auxiliary navigation was NOT blocked");
+ runNextTest();
+ };
+ try {
+ window["testIframe"].eval(testCase.script);
+ } catch(e) {
+ ok(true, testCase.desc, e.message);
+ runNextTest();
+ }
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: location.replace on auxiliary NOT opened by us should be blocked",
+ script: "parent.openedWindow.location.replace('file_other_auxiliary_navigation_by_location.html')"
+ },
+ {
+ desc: "Test 2: location.assign on auxiliary NOT opened by us should be blocked",
+ script: "parent.openedWindow.location.assign('file_other_auxiliary_navigation_by_location.html')"
+ },
+ {
+ desc: "Test 3: location.href on auxiliary NOT opened by us should be blocked",
+ script: "parent.openedWindow.location.href = 'file_other_auxiliary_navigation_by_location.html'"
+ },
+ {
+ desc: "Test 4: location.hash on auxiliary NOT opened by us should be blocked",
+ script: "parent.openedWindow.location.hash = 'wibble'"
+ }
+ ];
+
+ function runNextTest() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ openedWindow.close();
+ SimpleTest.finish();
+ return;
+ }
+
+ runScriptNavigationTest(testCases[testCaseIndex]);
+ }
+
+ window.onmessage = runNextTest;
+
+ window.onload = function() {
+ window.openedWindow = window.open("file_other_auxiliary_navigation_by_location.html", "otherWindow");
+ }
+</script>
+
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785310">Mozilla Bug 785310</a>
+<p id="display"></p>
+<div id="content">
+Tests for Bug 785310
+</div>
+
+<iframe name="testIframe" sandbox="allow-scripts allow-same-origin allow-top-navigation allow-popups"></iframe>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/test_our_auxiliary_navigation_by_location.html b/docshell/test/iframesandbox/test_our_auxiliary_navigation_by_location.html
new file mode 100644
index 0000000000..01b371545a
--- /dev/null
+++ b/docshell/test/iframesandbox/test_our_auxiliary_navigation_by_location.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785310
+html5 sandboxed iframe should not be able to perform top navigation with scripts allowed
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 785310 - iframe sandbox our auxiliary navigation by location tests</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 runScriptNavigationTest(testCase) {
+ window.onmessage = function(event) {
+ if (event.data != "ourWindow") {
+ ok(false, "event.data: got '" + event.data + "', expected 'ourWindow'");
+ }
+ ok(!testCase.shouldBeBlocked, testCase.desc, "auxiliary navigation was NOT blocked");
+ runNextTest();
+ };
+ try {
+ SpecialPowers.wrap(window["testIframe"]).eval(testCase.script);
+ } catch(e) {
+ ok(testCase.shouldBeBlocked, testCase.desc, SpecialPowers.wrap(e).message);
+ runNextTest();
+ }
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: location.replace on auxiliary opened by us should NOT be blocked",
+ script: "openedWindow.location.replace('file_our_auxiliary_navigation_by_location.html')",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 2: location.assign on auxiliary opened by us should be blocked without allow-same-origin",
+ script: "openedWindow.location.assign('file_our_auxiliary_navigation_by_location.html')",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 3: location.href on auxiliary opened by us should NOT be blocked",
+ script: "openedWindow.location.href = 'file_our_auxiliary_navigation_by_location.html'",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 4: location.hash on auxiliary opened by us should be blocked without allow-same-origin",
+ script: "openedWindow.location.hash = 'wibble'",
+ shouldBeBlocked: true
+ }
+ ];
+
+ function runNextTest() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ SpecialPowers.wrap(window["testIframe"]).eval("openedWindow.close()");
+ SimpleTest.finish();
+ return;
+ }
+
+ runScriptNavigationTest(testCases[testCaseIndex]);
+ }
+
+ window.onmessage = runNextTest;
+
+ window.onload = function() {
+ SpecialPowers.wrap(window["testIframe"]).eval("var openedWindow = window.open('file_our_auxiliary_navigation_by_location.html', 'ourWindow')");
+ }
+</script>
+
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785310">Mozilla Bug 785310</a>
+<p id="display"></p>
+<div id="content">
+Tests for Bug 785310
+</div>
+
+<iframe name="testIframe" sandbox="allow-scripts allow-popups"></iframe>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/test_parent_navigation_by_location.html b/docshell/test/iframesandbox/test_parent_navigation_by_location.html
new file mode 100644
index 0000000000..06335cdecd
--- /dev/null
+++ b/docshell/test/iframesandbox/test_parent_navigation_by_location.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785310
+html5 sandboxed iframe should not be able to perform top navigation with scripts allowed
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 785310 - iframe sandbox parent navigation by location tests</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 runScriptNavigationTest(testCase) {
+ window.onmessage = function(event) {
+ if (event.data != "parentIframe") {
+ ok(false, "event.data: got '" + event.data + "', expected 'parentIframe'");
+ }
+ ok(false, testCase.desc, "parent navigation was NOT blocked");
+ runNextTest();
+ };
+ try {
+ window["parentIframe"]["childIframe"].eval(testCase.script);
+ } catch(e) {
+ ok(true, testCase.desc, e.message);
+ runNextTest();
+ }
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: parent.location.replace should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent.location.replace('file_parent_navigation_by_location.html')"
+ },
+ {
+ desc: "Test 2: parent.location.assign should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent.location.assign('file_parent_navigation_by_location.html')"
+ },
+ {
+ desc: "Test 3: parent.location.href should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent.location.href = 'file_parent_navigation_by_location.html'"
+ },
+ {
+ desc: "Test 4: parent.location.hash should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent.location.hash = 'wibble'"
+ }
+ ];
+
+ function runNextTest() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ runScriptNavigationTest(testCases[testCaseIndex]);
+ }
+
+ window.onmessage = runNextTest;
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785310">Mozilla Bug 785310</a>
+<p id="display"></p>
+<div id="content">
+Tests for Bug 785310
+</div>
+
+<iframe name="parentIframe" src="file_parent_navigation_by_location.html"></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/test_sibling_navigation_by_location.html b/docshell/test/iframesandbox/test_sibling_navigation_by_location.html
new file mode 100644
index 0000000000..a93c1ae0df
--- /dev/null
+++ b/docshell/test/iframesandbox/test_sibling_navigation_by_location.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785310
+html5 sandboxed iframe should not be able to perform top navigation with scripts allowed
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 785310 - iframe sandbox sibling navigation by location tests</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 runScriptNavigationTest(testCase) {
+ window.onmessage = function(event) {
+ if (event.data != "siblingIframe") {
+ ok(false, "event.data: got '" + event.data + "', expected 'siblingIframe'");
+ }
+
+ ok(false, testCase.desc, "sibling navigation was NOT blocked");
+ runNextTest();
+ };
+
+ try {
+ window["testIframe"].eval(testCase.script);
+ } catch(e) {
+ ok(true, testCase.desc, e.message);
+ runNextTest();
+ }
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: sibling location.replace should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent['siblingIframe'].location.replace('file_sibling_navigation_by_location.html')"
+ },
+ {
+ desc: "Test 2: sibling location.assign should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent['siblingIframe'].location.assign('file_sibling_navigation_by_location.html')"
+ },
+ {
+ desc: "Test 3: sibling location.href should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent['siblingIframe'].location.href = 'file_sibling_navigation_by_location.html'"
+ },
+ {
+ desc: "Test 4: sibling location.hash should be blocked even when sandboxed with allow-same-origin allow-top-navigation",
+ script: "parent['siblingIframe'].location.hash = 'wibble'"
+ }
+ ];
+
+ function runNextTest() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ runScriptNavigationTest(testCases[testCaseIndex]);
+ }
+
+ window.onmessage = runNextTest;
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785310">Mozilla Bug 785310</a>
+<p id="display"></p>
+<div id="content">
+Tests for Bug 785310
+</div>
+
+<iframe name="testIframe" sandbox="allow-scripts allow-same-origin allow-top-navigation"></iframe>
+<iframe name="siblingIframe" src="file_sibling_navigation_by_location.html"></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/test_top_navigation_by_location.html b/docshell/test/iframesandbox/test_top_navigation_by_location.html
new file mode 100644
index 0000000000..3191539a22
--- /dev/null
+++ b/docshell/test/iframesandbox/test_top_navigation_by_location.html
@@ -0,0 +1,167 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785310
+html5 sandboxed iframe should not be able to perform top navigation with scripts allowed
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 785310 - iframe sandbox top navigation by location tests</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();
+
+ var testWin;
+
+ function runScriptNavigationTest(testCase) {
+ window.onmessage = function(event) {
+ if (event.data != "newTop") {
+ ok(false, "event.data: got '" + event.data + "', expected 'newTop'");
+ }
+ ok(!testCase.shouldBeBlocked, testCase.desc, "top navigation was NOT blocked");
+ runNextTest();
+ };
+ try {
+ SpecialPowers.wrap(testWin[testCase.iframeName]).eval(testCase.script);
+ } catch(e) {
+ ok(testCase.shouldBeBlocked, testCase.desc, SpecialPowers.wrap(e).message);
+ runNextTest();
+ }
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: top.location.replace should be blocked when sandboxed without allow-top-navigation",
+ script: "top.location.replace('file_top_navigation_by_location.html')",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 2: top.location.assign should be blocked when sandboxed without allow-top-navigation",
+ script: "top.location.assign('file_top_navigation_by_location.html')",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 3: top.location.href should be blocked when sandboxed without allow-top-navigation",
+ script: "top.location.href = 'file_top_navigation_by_location.html'",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 4: top.location.pathname should be blocked when sandboxed without allow-top-navigation",
+ script: "top.location.pathname = top.location.pathname",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 5: top.location should be blocked when sandboxed without allow-top-navigation",
+ script: "top.location = 'file_top_navigation_by_location.html'",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 6: top.location.hash should be blocked when sandboxed without allow-top-navigation",
+ script: "top.location.hash = 'wibble'",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 7: top.location.replace should NOT be blocked when sandboxed with allow-same-origin allow-top-navigation",
+ script: "top.location.replace('file_top_navigation_by_location.html')",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 8: top.location.assign should NOT be blocked when sandboxed with allow-same-origin allow-top-navigation",
+ script: "top.location.assign('file_top_navigation_by_location.html')",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 9: top.location.href should NOT be blocked when sandboxed with allow-same-origin allow-top-navigation",
+ script: "top.location.href = 'file_top_navigation_by_location.html'",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 10: top.location.pathname should NOT be blocked when sandboxed with allow-same-origin allow-top-navigation",
+ script: "top.location.pathname = top.location.pathname",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 11: top.location should NOT be blocked when sandboxed with allow-same-origin allow-top-navigation",
+ script: "top.location = 'file_top_navigation_by_location.html'",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 12: top.location.hash should NOT be blocked when sandboxed with allow-same-origin allow-top-navigation",
+ script: "top.location.hash = 'wibble'",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 13: top.location.replace should NOT be blocked when sandboxed with allow-top-navigation, but without allow-same-origin",
+ script: "top.location.replace('file_top_navigation_by_location.html')",
+ iframeName: "if3",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 14: top.location.assign should be blocked when sandboxed with allow-top-navigation, but without allow-same-origin",
+ script: "top.location.assign('file_top_navigation_by_location.html')",
+ iframeName: "if3",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 15: top.location.href should NOT be blocked when sandboxed with allow-top-navigation, but without allow-same-origin",
+ script: "top.location.href = 'file_top_navigation_by_location.html'",
+ iframeName: "if3",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 16: top.location.pathname should be blocked when sandboxed with allow-top-navigation, but without allow-same-origin",
+ script: "top.location.pathname = top.location.pathname",
+ iframeName: "if3",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 17: top.location should NOT be blocked when sandboxed with allow-top-navigation, but without allow-same-origin",
+ script: "top.location = 'file_top_navigation_by_location.html'",
+ iframeName: "if3",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 18: top.location.hash should be blocked when sandboxed with allow-top-navigation, but without allow-same-origin",
+ script: "top.location.hash = 'wibble'",
+ iframeName: "if3",
+ shouldBeBlocked: true
+ }
+ ];
+
+ function runNextTest() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ testWin.close();
+ SimpleTest.finish();
+ return;
+ }
+
+ runScriptNavigationTest(testCases[testCaseIndex]);
+ }
+
+ window.onmessage = runNextTest;
+ testWin = window.open("file_top_navigation_by_location.html", "newTop");
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785310">Mozilla Bug 785310</a>
+<p id="display"></p>
+<div id="content">
+Tests for Bug 785310
+</div>
+</body>
+</html>
diff --git a/docshell/test/iframesandbox/test_top_navigation_by_location_exotic.html b/docshell/test/iframesandbox/test_top_navigation_by_location_exotic.html
new file mode 100644
index 0000000000..fcc1f86596
--- /dev/null
+++ b/docshell/test/iframesandbox/test_top_navigation_by_location_exotic.html
@@ -0,0 +1,204 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=785310
+html5 sandboxed iframe should not be able to perform top navigation with scripts allowed
+-->
+<head>
+<meta charset="utf-8">
+<title>Test for Bug 785310 - iframe sandbox top navigation by location via exotic means tests</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();
+
+ var testWin;
+
+ function runScriptNavigationTest(testCase) {
+ window.onmessage = function(event) {
+ if (event.data.name != 'newWindow') {
+ ok(false, "event.data.name: got '" + event.data.name + "', expected 'newWindow'");
+ }
+ var diag = "top navigation was " + (event.data.blocked ? "" : "NOT ") + "blocked";
+ ok((testCase.shouldBeBlocked == event.data.blocked), testCase.desc, diag);
+ runNextTest();
+ };
+ try {
+ testWin[testCase.iframeName].eval(testCase.script);
+ } catch(e) {
+ ok(testCase.shouldBeBlocked, testCase.desc, e.message);
+ runNextTest();
+ }
+ }
+
+ var testCaseIndex = -1;
+ testCases = [
+ {
+ desc: "Test 1: location.replace.call(top.location, ...) should be blocked when sandboxed without allow-top-navigation",
+ script: "location.replace.call(top.location, 'file_top_navigation_by_location_exotic.html')",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 2: location.replace.bind(top.location, ...) should be blocked when sandboxed without allow-top-navigation",
+ script: "location.replace.bind(top.location, 'file_top_navigation_by_location_exotic.html')()",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 3: Function.bind.call(location.replace, top.location, ...) should be blocked when sandboxed without allow-top-navigation",
+ script: "Function.bind.call(location.replace, top.location, 'file_top_navigation_by_location_exotic.html')()",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 4: location.replace.call(top.location, ...) should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "location.replace.call(top.location, 'file_top_navigation_by_location_exotic.html')",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 5: location.replace.bind(top.location, ...) should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "location.replace.bind(top.location, 'file_top_navigation_by_location_exotic.html')()",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 6: Function.bind.call(location.replace, top.location, ...) should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "Function.bind.call(location.replace, top.location, 'file_top_navigation_by_location_exotic.html')()",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 7: top.location.href, via setTimeout, should be blocked when sandboxed without allow-top-navigation",
+ script: "setTimeout(function() { try { top.location.href = 'file_top_navigation_by_location_exotic.html' } catch (e) { top.onBlock() } }, 0)",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 8: top.location.href, via setTimeout, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "setTimeout(function() { try { top.location.href = 'file_top_navigation_by_location_exotic.html' } catch(e) { top.onBlock() } }, 0)",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 9: top.location.href, via eval, should be blocked when sandboxed without allow-top-navigation",
+ script: "eval('top.location.href = \"file_top_navigation_by_location_exotic.html\"')",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 10: top.location.href, via eval, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "eval('top.location.href = \"file_top_navigation_by_location_exotic.html\"')",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 11: top.location.href, via anonymous function, should be blocked when sandboxed without allow-top-navigation",
+ script: "(function() { top.location.href = 'file_top_navigation_by_location_exotic.html' })()",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 12: top.location.href, via anonymous function, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "(function() { top.location.href = 'file_top_navigation_by_location_exotic.html' })()",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 13: top.location.href, via function inserted in top, should be blocked when sandboxed without allow-top-navigation",
+ script: "top.doTest = function() { top.location.href = 'file_top_navigation_by_location_exotic.html' }; top.doTest();",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 14: top.location.href, via function inserted in top, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "top.doTest = function() { top.location.href = 'file_top_navigation_by_location_exotic.html' }; top.doTest();",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 15: top.location.href, via function inserted in us by top, should NOT be blocked when sandboxed without allow-top-navigation",
+ script: "top.eval('window[\"if1\"].doTest = function() { top.location.href = \"file_top_navigation_by_location_exotic.html\" };'), doTest();",
+ iframeName: "if1",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 16: top.location.href, via function inserted in top, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "top.eval('window[\"if2\"].doTest = function() { top.location.href = \"file_top_navigation_by_location_exotic.html\" };'), doTest();",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 17: top.location.href, via function in top, should NOT be blocked when sandboxed without allow-top-navigation",
+ script: "top.setOwnHref()",
+ iframeName: "if1",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 18: top.location.href, via function in top, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "top.setOwnHref()",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 19: top.location.href, via eval in top, should NOT be blocked when sandboxed without allow-top-navigation",
+ script: "top.eval('location.href = \"file_top_navigation_by_location_exotic.html\"')",
+ iframeName: "if1",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 20: top.location.href, via eval in top, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "top.eval('location.href = \"file_top_navigation_by_location_exotic.html\"')",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 21: top.location.href, via eval in top calling us, should be blocked when sandboxed without allow-top-navigation",
+ script: "function doTest() { top.location.href = 'file_top_navigation_by_location_exotic.html' } top.eval('window[\"if1\"].doTest()');",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 22: top.location.href, via eval in top calling us, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "function doTest() { top.location.href = 'file_top_navigation_by_location_exotic.html' } top.eval('window[\"if2\"].doTest()');",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ },
+ {
+ desc: "Test 23: top.location.href, via function bound to top, should be blocked when sandboxed without allow-top-navigation",
+ script: "(function() { top.location.href = 'file_top_navigation_by_location_exotic.html' }).bind(top)();",
+ iframeName: "if1",
+ shouldBeBlocked: true
+ },
+ {
+ desc: "Test 24: top.location.href, via function bound to top, should NOT be blocked when sandboxed with allow-top-navigation",
+ script: "(function() { top.location.href = 'file_top_navigation_by_location_exotic.html' }).bind(top)();",
+ iframeName: "if2",
+ shouldBeBlocked: false
+ }
+ ];
+
+ function runNextTest() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ testWin.close();
+ SimpleTest.finish();
+ return;
+ }
+
+ runScriptNavigationTest(testCases[testCaseIndex]);
+ }
+
+ window.onmessage = runNextTest;
+ testWin = window.open('file_top_navigation_by_location_exotic.html', "newWindow");
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785310">Mozilla Bug 785310</a>
+<p id="display"></p>
+<div id="content">
+Tests for Bug 785310
+</div>
+</body>
+</html>
diff --git a/docshell/test/mochitest.ini b/docshell/test/mochitest.ini
new file mode 100644
index 0000000000..725486b771
--- /dev/null
+++ b/docshell/test/mochitest.ini
@@ -0,0 +1,94 @@
+[DEFAULT]
+support-files =
+ bug123696-subframe.html
+ bug369814.jar
+ bug369814.zip
+ bug404548-subframe.html
+ bug413310-post.sjs
+ bug413310-subframe.html
+ bug529119-window.html
+ bug570341_recordevents.html
+ bug668513_redirect.html
+ bug668513_redirect.html^headers^
+ bug691547_frame.html
+ file_anchor_scroll_after_document_open.html
+ file_bug385434_1.html
+ file_bug385434_2.html
+ file_bug385434_3.html
+ file_bug475636.sjs
+ file_bug509055.html
+ file_bug540462.html
+ file_bug580069_1.html
+ file_bug580069_2.sjs
+ file_bug590573_1.html
+ file_bug590573_2.html
+ file_bug634834.html
+ file_bug640387.html
+ file_bug653741.html
+ file_bug660404
+ file_bug660404^headers^
+ file_bug662170.html
+ file_bug669671.sjs
+ file_bug680257.html
+ file_bug703855.html
+ file_bug728939.html
+ file_pushState_after_document_open.html
+ historyframes.html
+
+[test_anchor_scroll_after_document_open.html]
+[test_bfcache_plus_hash.html]
+[test_bug123696.html]
+[test_bug369814.html]
+[test_bug384014.html]
+[test_bug385434.html]
+[test_bug387979.html]
+[test_bug402210.html]
+[test_bug404548.html]
+[test_bug413310.html]
+skip-if = true
+# Disabled for too many intermittent failures (bug 719186)
+[test_bug475636.html]
+[test_bug509055.html]
+[test_bug511449.html]
+skip-if = toolkit != "cocoa"
+support-files = file_bug511449.html
+[test_bug529119-1.html]
+[test_bug529119-2.html]
+[test_bug530396.html]
+support-files = bug530396-noref.sjs bug530396-subframe.html
+[test_bug540462.html]
+[test_bug551225.html]
+[test_bug570341.html]
+[test_bug580069.html]
+[test_bug590573.html]
+[test_bug598895.html]
+skip-if = toolkit == 'android'
+[test_bug634834.html]
+[test_bug637644.html]
+skip-if = toolkit == 'android'
+[test_bug640387_1.html]
+[test_bug640387_2.html]
+[test_bug653741.html]
+[test_bug660404.html]
+[test_bug662170.html]
+[test_bug668513.html]
+skip-if = toolkit == 'android'
+support-files = file_bug668513.html
+[test_bug669671.html]
+[test_bug675587.html]
+[test_bug680257.html]
+[test_bug691547.html]
+[test_bug694612.html]
+[test_bug703855.html]
+[test_bug713825.html]
+[test_bug728939.html]
+[test_bug797909.html]
+[test_bug1045096.html]
+[test_bug1121701.html]
+[test_bug1186774.html]
+[test_forceinheritprincipal_overrule_owner.html]
+[test_framedhistoryframes.html]
+skip-if = toolkit == 'android' # bug 784321
+support-files = file_framedhistoryframes.html
+[test_pushState_after_document_open.html]
+[test_windowedhistoryframes.html]
diff --git a/docshell/test/navigation/NavigationUtils.js b/docshell/test/navigation/NavigationUtils.js
new file mode 100644
index 0000000000..c90ea74d5b
--- /dev/null
+++ b/docshell/test/navigation/NavigationUtils.js
@@ -0,0 +1,213 @@
+/* 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/. */
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Utilities for navigation tests
+//
+///////////////////////////////////////////////////////////////////////////
+
+var body = "This frame was navigated.";
+var target_url = "data:text/html,<html><body>" + body + "</body></html>";
+
+var popup_body = "This is a popup";
+var target_popup_url = "data:text/html,<html><body>" + popup_body + "</body></html>";
+
+///////////////////////////////////////////////////////////////////////////
+// Functions that navigate frames
+///////////////////////////////////////////////////////////////////////////
+
+function navigateByLocation(wnd) {
+ try {
+ wnd.location = target_url;
+ } catch(ex) {
+ // We need to keep our finished frames count consistent.
+ // Oddly, this ends up simulating the behavior of IE7.
+ window.open(target_url, "_blank", "width=10,height=10");
+ }
+}
+
+function navigateByOpen(name) {
+ window.open(target_url, name, "width=10,height=10");
+}
+
+function navigateByForm(name) {
+ var form = document.createElement("form");
+ form.action = target_url;
+ form.method = "POST";
+ form.target = name; document.body.appendChild(form);
+ form.submit();
+}
+
+var hyperlink_count = 0;
+
+function navigateByHyperlink(name) {
+ var link = document.createElement("a");
+ link.href = target_url;
+ link.target = name;
+ link.id = "navigation_hyperlink_" + hyperlink_count++;
+ document.body.appendChild(link);
+ sendMouseEvent({type:"click"}, link.id);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Functions that call into Mochitest framework
+///////////////////////////////////////////////////////////////////////////
+
+function isNavigated(wnd, message) {
+ var result = null;
+ try {
+ result = SpecialPowers.wrap(wnd).document.body.innerHTML;
+ } catch(ex) {
+ result = ex;
+ }
+ is(result, body, message);
+}
+
+function isBlank(wnd, message) {
+ var result = null;
+ try {
+ result = wnd.document.body.innerHTML;
+ } catch(ex) {
+ result = ex;
+ }
+ is(result, "This is a blank document.", message);
+}
+
+function isAccessible(wnd, message) {
+ try {
+ wnd.document.body.innerHTML;
+ ok(true, message);
+ } catch(ex) {
+ ok(false, message);
+ }
+}
+
+function isInaccessible(wnd, message) {
+ try {
+ wnd.document.body.innerHTML;
+ ok(false, message);
+ } catch(ex) {
+ ok(true, message);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Functions that require UniversalXPConnect privilege
+///////////////////////////////////////////////////////////////////////////
+
+function xpcEnumerateContentWindows(callback) {
+
+ var Ci = SpecialPowers.Ci;
+ var ww = SpecialPowers.Cc["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Ci.nsIWindowWatcher);
+ var enumerator = ww.getWindowEnumerator();
+
+ var contentWindows = [];
+
+ while (enumerator.hasMoreElements()) {
+ var win = enumerator.getNext();
+ if (/ChromeWindow/.exec(win)) {
+ var docshellTreeNode = win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShellTreeItem);
+ var childCount = docshellTreeNode.childCount;
+ for (var i = 0; i < childCount; ++i) {
+ var childTreeNode = docshellTreeNode.getChildAt(i);
+
+ // we're only interested in content docshells
+ if (SpecialPowers.unwrap(childTreeNode.itemType) != Ci.nsIDocShellTreeItem.typeContent)
+ continue;
+
+ var webNav = childTreeNode.QueryInterface(Ci.nsIWebNavigation);
+ contentWindows.push(webNav.document.defaultView);
+ }
+ } else {
+ contentWindows.push(win);
+ }
+ }
+
+ while (contentWindows.length > 0)
+ callback(contentWindows.pop());
+}
+
+// Note: This only searches for top-level frames with this name.
+function xpcGetFramesByName(name) {
+ var results = [];
+
+ xpcEnumerateContentWindows(function(win) {
+ if (win.name == name)
+ results.push(win);
+ });
+
+ return results;
+}
+
+function xpcCleanupWindows() {
+ xpcEnumerateContentWindows(function(win) {
+ if (win.location && win.location.protocol == "data:")
+ win.close();
+ });
+}
+
+function xpcWaitForFinishedFrames(callback, numFrames) {
+ var finishedFrameCount = 0;
+ function frameFinished() {
+ finishedFrameCount++;
+
+ if (finishedFrameCount == numFrames) {
+ clearInterval(frameWaitInterval);
+ setTimeout(callback, 0);
+ return;
+ }
+
+ if (finishedFrameCount > numFrames)
+ throw "Too many frames loaded.";
+ }
+
+ var finishedWindows = [];
+
+ function contains(obj, arr) {
+ for (var i = 0; i < arr.length; i++) {
+ if (obj === arr[i])
+ return true;
+ }
+ return false;
+ }
+
+ function searchForFinishedFrames(win) {
+ if ((escape(unescape(win.location)) == escape(target_url) ||
+ escape(unescape(win.location)) == escape(target_popup_url)) &&
+ win.document &&
+ win.document.body &&
+ (win.document.body.textContent == body ||
+ win.document.body.textContent == popup_body) &&
+ win.document.readyState == "complete") {
+
+ var util = win.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
+ var windowId = util.outerWindowID;
+ if (!contains(windowId, finishedWindows)) {
+ finishedWindows.push(windowId);
+ frameFinished();
+ }
+ }
+ for (var i = 0; i < win.frames.length; i++)
+ searchForFinishedFrames(win.frames[i]);
+ }
+
+ function poll() {
+ try {
+ // This only gives us UniversalXPConnect for the current stack frame
+ // We're using setInterval, so the main page's privileges are still normal
+ xpcEnumerateContentWindows(searchForFinishedFrames);
+ } catch(ex) {
+ // We might be accessing windows before they are fully constructed,
+ // which can throw. We'll find those frames on our next poll().
+ }
+ }
+
+ var frameWaitInterval = setInterval(poll, 500);
+}
+
diff --git a/docshell/test/navigation/blank.html b/docshell/test/navigation/blank.html
new file mode 100644
index 0000000000..5360333f1d
--- /dev/null
+++ b/docshell/test/navigation/blank.html
@@ -0,0 +1 @@
+<html><body>This is a blank document.</body></html> \ No newline at end of file
diff --git a/docshell/test/navigation/browser.ini b/docshell/test/navigation/browser.ini
new file mode 100644
index 0000000000..f25853f898
--- /dev/null
+++ b/docshell/test/navigation/browser.ini
@@ -0,0 +1,12 @@
+[DEFAULT]
+support-files =
+ bug343515_pg1.html
+ bug343515_pg2.html
+ bug343515_pg3.html
+ bug343515_pg3_1.html
+ bug343515_pg3_1_1.html
+ bug343515_pg3_2.html
+
+[browser_bug343515.js]
+[browser_test-content-chromeflags.js]
+tags = openwindow \ No newline at end of file
diff --git a/docshell/test/navigation/browser_bug343515.js b/docshell/test/navigation/browser_bug343515.js
new file mode 100644
index 0000000000..74152b493e
--- /dev/null
+++ b/docshell/test/navigation/browser_bug343515.js
@@ -0,0 +1,262 @@
+// Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden
+
+// Globals
+var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/";
+var ctx = {};
+
+// We need to wait until the page from each testcase is fully loaded,
+// including all of its descendant iframes. To do that we manually count
+// how many load events should happen on that page (one for the toplevel doc
+// and one for each subframe) and wait until we receive the expected number
+// of events.
+function nShotsListener(aElem, aType, aCallback, aCount) {
+ let count = aCount;
+ aElem.addEventListener(aType, function listenerCallback() {
+ if (--count == 0) {
+ aElem.removeEventListener(aType, listenerCallback, true);
+
+ // aCallback is executed asynchronously, which is handy because load
+ // events fire before mIsDocumentLoaded is actually set to true. :(
+ executeSoon(aCallback);
+ }
+ }, true);
+}
+
+function oneShotListener(aElem, aType, aCallback) {
+ nShotsListener(aElem, aType, aCallback, 1);
+}
+
+function waitForPageshow(aBrowser, callback) {
+ return ContentTask.spawn(aBrowser, null, function* () {
+ yield ContentTaskUtils.waitForEvent(this, "pageshow");
+ }).then(callback);
+}
+
+// Entry point from Mochikit
+function test() {
+
+ // Lots of callbacks going on here
+ waitForExplicitFinish();
+
+ // Begin the test
+ step1();
+}
+
+function step1() {
+
+ // Get a handle on the initial tab
+ ctx.tab0 = gBrowser.selectedTab;
+ ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0);
+
+ // Our current tab should be active
+ ok(ctx.tab0Browser.docShellIsActive, "Tab 0 should be active at test start");
+
+ // Open a New Tab
+ ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html");
+ ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
+ oneShotListener(ctx.tab1Browser, "load", step2);
+}
+
+function step2() {
+ is(testPath + "bug343515_pg1.html", ctx.tab1Browser.currentURI.spec,
+ "Got expected tab 1 url in step 2");
+
+ // Our current tab should still be active
+ ok(ctx.tab0Browser.docShellIsActive, "Tab 0 should still be active");
+ ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should not be active");
+
+ // Switch to tab 1
+ BrowserTestUtils.switchTab(gBrowser, ctx.tab1).then(() => {
+ // Tab 1 should now be active
+ ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+ ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
+
+ // Open another tab
+ ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
+ ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
+
+ // bug343515_pg2.html consists of a page with two iframes,
+ // which will therefore generate 3 load events.
+ nShotsListener(ctx.tab2Browser, "load", step3, 3);
+ });
+}
+
+function step3() {
+ is(testPath + "bug343515_pg2.html", ctx.tab2Browser.currentURI.spec,
+ "Got expected tab 2 url in step 3");
+
+ // Tab 0 should be inactive, Tab 1 should be active
+ ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+ ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
+
+ // Tab 2's window _and_ its iframes should be inactive
+ ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
+ ContentTask.spawn(ctx.tab2Browser, null, function* () {
+ Assert.equal(content.frames.length, 2, "Tab 2 should have 2 iframes");
+ for (var i = 0; i < content.frames.length; i++) {
+ info("step 3, frame " + i + " info: " + content.frames[i].location);
+ let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+
+ Assert.ok(!docShell.isActive, `Tab2 iframe ${i} should be inactive`);
+ }
+ }).then(() => {
+ // Navigate tab 2 to a different page
+ ctx.tab2Browser.loadURI(testPath + "bug343515_pg3.html");
+
+ // bug343515_pg3.html consists of a page with two iframes, one of which
+ // contains another iframe, so there'll be a total of 4 load events
+ nShotsListener(ctx.tab2Browser, "load", step4, 4);
+ });
+}
+
+function step4() {
+ function checkTab2Active(expected) {
+ return ContentTask.spawn(ctx.tab2Browser, expected, function* (expected) {
+ function isActive(aWindow) {
+ var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ return docshell.isActive;
+ }
+
+ let active = expected ? "active" : "inactive";
+ Assert.equal(content.frames.length, 2, "Tab 2 should have 2 iframes");
+ for (var i = 0; i < content.frames.length; i++)
+ info("step 4, frame " + i + " info: " + content.frames[i].location);
+ Assert.equal(content.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
+ Assert.equal(isActive(content.frames[0]), expected, `Tab2 iframe 0 should be ${active}`);
+ Assert.equal(isActive(content.frames[0].frames[0]), expected,
+ `Tab2 iframe 0 subiframe 0 should be ${active}`);
+ Assert.equal(isActive(content.frames[1]), expected, `Tab2 iframe 1 should be ${active}`);
+ });
+ }
+
+ is(testPath + "bug343515_pg3.html", ctx.tab2Browser.currentURI.spec,
+ "Got expected tab 2 url in step 4");
+
+ // Tab 0 should be inactive, Tab 1 should be active
+ ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+ ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
+
+ // Tab2 and all descendants should be inactive
+ checkTab2Active(false).then(() => {
+ // Switch to Tab 2
+ return BrowserTestUtils.switchTab(gBrowser, ctx.tab2);
+ }).then(() => {
+ // Check everything
+ ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+ ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should be inactive");
+ ok(ctx.tab2Browser.docShellIsActive, "Tab 2 should be active");
+
+ return checkTab2Active(true);
+ }).then(() => {
+ // Go back
+ waitForPageshow(ctx.tab2Browser, step5);
+ ctx.tab2Browser.goBack();
+ });
+}
+
+function step5() {
+ // Check everything
+ ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+ ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should be inactive");
+ ok(ctx.tab2Browser.docShellIsActive, "Tab 2 should be active");
+ ContentTask.spawn(ctx.tab2Browser, null, function* () {
+ for (var i = 0; i < content.frames.length; i++) {
+ let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+
+ Assert.ok(docShell.isActive, `Tab2 iframe ${i} should be active`);
+ }
+ }).then(() => {
+ // Switch to tab 1
+ return BrowserTestUtils.switchTab(gBrowser, ctx.tab1);
+ }).then(() => {
+ // Navigate to page 3
+ ctx.tab1Browser.loadURI(testPath + "bug343515_pg3.html");
+
+ // bug343515_pg3.html consists of a page with two iframes, one of which
+ // contains another iframe, so there'll be a total of 4 load events
+ nShotsListener(ctx.tab1Browser, "load", step6, 4);
+ });
+}
+
+function step6() {
+
+ // Check everything
+ ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+ ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
+ ContentTask.spawn(ctx.tab1Browser, null, function* () {
+ function isActive(aWindow) {
+ var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ return docshell.isActive;
+ }
+
+ Assert.ok(isActive(content.frames[0]), "Tab1 iframe 0 should be active");
+ Assert.ok(isActive(content.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
+ Assert.ok(isActive(content.frames[1]), "Tab1 iframe 1 should be active");
+ }).then(() => {
+ ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
+ return ContentTask.spawn(ctx.tab2Browser, null, function* () {
+ for (var i = 0; i < content.frames.length; i++) {
+ let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+
+ Assert.ok(!docShell.isActive, `Tab2 iframe ${i} should be inactive`);
+ }
+ });
+ }).then(() => {
+ // Go forward on tab 2
+ waitForPageshow(ctx.tab2Browser, step7);
+ ctx.tab2Browser.goForward();
+ });
+}
+
+function step7() {
+ function checkBrowser(browser, tabNum, active) {
+ return ContentTask.spawn(browser, { tabNum, active },
+ function* ({ tabNum, active }) {
+ function isActive(aWindow) {
+ var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ return docshell.isActive;
+ }
+
+ let activestr = active ? "active" : "inactive";
+ Assert.equal(isActive(content.frames[0]), active,
+ `Tab${tabNum} iframe 0 should be ${activestr}`);
+ Assert.equal(isActive(content.frames[0].frames[0]), active,
+ `Tab${tabNum} iframe 0 subiframe 0 should be ${activestr}`);
+ Assert.equal(isActive(content.frames[1]), active,
+ `Tab${tabNum} iframe 1 should be ${activestr}`);
+ });
+ }
+
+ // Check everything
+ ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+ ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
+ checkBrowser(ctx.tab1Browser, 1, true).then(() => {
+ ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
+ return checkBrowser(ctx.tab2Browser, 2, false);
+ }).then(() => {
+ // That's probably enough
+ allDone();
+ });
+}
+
+function allDone() {
+
+ // Close the tabs we made
+ gBrowser.removeTab(ctx.tab1);
+ gBrowser.removeTab(ctx.tab2);
+
+ // Tell the framework we're done
+ finish();
+}
diff --git a/docshell/test/navigation/browser_test-content-chromeflags.js b/docshell/test/navigation/browser_test-content-chromeflags.js
new file mode 100644
index 0000000000..64559897cd
--- /dev/null
+++ b/docshell/test/navigation/browser_test-content-chromeflags.js
@@ -0,0 +1,45 @@
+const TEST_PAGE = `data:text/html,<html><body><a href="about:blank" target="_blank">Test</a></body></html>`;
+const CHROME_ALL = Ci.nsIWebBrowserChrome.CHROME_ALL;
+const CHROME_REMOTE_WINDOW = Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW;
+
+/**
+ * Tests that when we open new browser windows from content they
+ * get the full browser chrome.
+ */
+add_task(function* () {
+ // Make sure that the window.open call will open a new
+ // window instead of a new tab.
+ yield new Promise(resolve => {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["browser.link.open_newwindow", 2],
+ ]
+ }, resolve);
+ });
+
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: TEST_PAGE
+ }, function*(browser) {
+ let openedPromise = BrowserTestUtils.waitForNewWindow();
+ BrowserTestUtils.synthesizeMouse("a", 0, 0, {}, browser);
+ let win = yield openedPromise;
+
+ let chromeFlags = win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShellTreeItem)
+ .treeOwner
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIXULWindow)
+ .chromeFlags;
+
+ // In the multi-process case, the new window will have the
+ // CHROME_REMOTE_WINDOW flag set.
+ const EXPECTED = gMultiProcessBrowser ? CHROME_ALL | CHROME_REMOTE_WINDOW
+ : CHROME_ALL;
+
+ is(chromeFlags, EXPECTED, "Window should have opened with all chrome");
+
+ BrowserTestUtils.closeWindow(win);
+ });
+});
diff --git a/docshell/test/navigation/bug343515_pg1.html b/docshell/test/navigation/bug343515_pg1.html
new file mode 100644
index 0000000000..a8337c7f70
--- /dev/null
+++ b/docshell/test/navigation/bug343515_pg1.html
@@ -0,0 +1,5 @@
+<html>
+ <head><meta charset="UTF-8"/></head>
+ <body>Page 1
+ </body>
+</html>
diff --git a/docshell/test/navigation/bug343515_pg2.html b/docshell/test/navigation/bug343515_pg2.html
new file mode 100644
index 0000000000..c5f5665de5
--- /dev/null
+++ b/docshell/test/navigation/bug343515_pg2.html
@@ -0,0 +1,7 @@
+<html>
+ <head><meta charset="UTF-8"/></head>
+ <body>Page 2
+ <iframe src="data:text/html;charset=UTF8,<html><head></head><body>pg2 iframe 0</body></html>"></iframe>
+ <iframe src="data:text/html;charset=UTF8,<html><head></head><body>pg2 iframe 1</body></html>"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/navigation/bug343515_pg3.html b/docshell/test/navigation/bug343515_pg3.html
new file mode 100644
index 0000000000..fdc79fbf7a
--- /dev/null
+++ b/docshell/test/navigation/bug343515_pg3.html
@@ -0,0 +1,7 @@
+<html>
+ <head><meta charset="UTF-8"/></head>
+ <body>Page 3
+ <iframe src="bug343515_pg3_1.html"></iframe>
+ <iframe src="bug343515_pg3_2.html"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/navigation/bug343515_pg3_1.html b/docshell/test/navigation/bug343515_pg3_1.html
new file mode 100644
index 0000000000..254164c9f0
--- /dev/null
+++ b/docshell/test/navigation/bug343515_pg3_1.html
@@ -0,0 +1,6 @@
+<html>
+ <head><meta charset="UTF-8"/></head>
+ <body>pg3 - iframe 0
+ <iframe src="bug343515_pg3_1_1.html"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/navigation/bug343515_pg3_1_1.html b/docshell/test/navigation/bug343515_pg3_1_1.html
new file mode 100644
index 0000000000..be05b74888
--- /dev/null
+++ b/docshell/test/navigation/bug343515_pg3_1_1.html
@@ -0,0 +1 @@
+<html><head><meta charset="UTF-8"/></head><body>How far does the rabbit hole go?</body></html>
diff --git a/docshell/test/navigation/bug343515_pg3_2.html b/docshell/test/navigation/bug343515_pg3_2.html
new file mode 100644
index 0000000000..7655eb526d
--- /dev/null
+++ b/docshell/test/navigation/bug343515_pg3_2.html
@@ -0,0 +1 @@
+<html><head><meta charset="UTF-8"/></head><body>pg3 iframe 1</body></html>
diff --git a/docshell/test/navigation/file_bug1300461.html b/docshell/test/navigation/file_bug1300461.html
new file mode 100644
index 0000000000..1ba935046d
--- /dev/null
+++ b/docshell/test/navigation/file_bug1300461.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Bug 1300461</title>
+ </head>
+ <body onload="test();">
+ <script>
+ /**
+ * Bug 1300461 identifies that if a history entry was not bfcached, and
+ * a http redirection happens when navigating to that entry, the history
+ * index would mess up.
+ *
+ * The test case emulates the circumstance by the following steps
+ * 1) Navigate to file_bug1300461_back.html which is not bf-cachable.
+ * 2) In file_bug1300461_back.html, replace its own history state to
+ * file_bug1300461_redirect.html.
+ * 3) Back, and then forward. Since the document is not in bfcache, it
+ * tries to load file_bug1300461_redirect.html directly.
+ * 4) file_bug1300461_redirect.html redirects UA to
+ * file_bug1300461_back.html through HTTP 301 header.
+ *
+ * We verify the history index, canGoBack, canGoForward, etc. keep correct
+ * in this process.
+ */
+ let Ci = SpecialPowers.Ci;
+ let webNav = SpecialPowers.wrap(window)
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation);
+ let shistory = webNav.sessionHistory;
+ let testSteps = [
+ function() {
+ opener.is(shistory.count, 1, 'check history length');
+ opener.is(shistory.index, 0, 'check history index');
+ opener.ok(!webNav.canGoForward, 'check canGoForward');
+ setTimeout(() => window.location = 'file_bug1300461_back.html', 0);
+ },
+ function() {
+ opener.is(shistory.count, 2, 'check history length');
+ opener.is(shistory.index, 0, 'check history index');
+ opener.ok(webNav.canGoForward, 'check canGoForward');
+ window.history.forward();
+ opener.is(shistory.requestedIndex, 1, 'check requestedIndex');
+ },
+ function() {
+ opener.is(shistory.count, 2, 'check history length');
+ opener.is(shistory.index, 0, 'check history index');
+ opener.ok(webNav.canGoForward, 'check canGoForward');
+ opener.info('file_bug1300461.html tests finished');
+ opener.nextTest();
+ window.close();
+ }
+ ];
+
+ function test() {
+ if (opener) {
+ opener.info('file_bug1300461.html test ' + opener.testCount);
+ testSteps[opener.testCount++]();
+ }
+ }
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_bug1300461_back.html b/docshell/test/navigation/file_bug1300461_back.html
new file mode 100644
index 0000000000..7b187742fa
--- /dev/null
+++ b/docshell/test/navigation/file_bug1300461_back.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Bug 1300461</title>
+ </head>
+ <!-- The empty unload handler is to prevent bfcache. -->
+ <body onload="test();" onunload="">
+ <script>
+ let Ci = SpecialPowers.Ci;
+ let webNav = SpecialPowers.wrap(window)
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation);
+ let shistory = webNav.sessionHistory;
+ function test() {
+ if (opener) {
+ opener.info("file_bug1300461_back.html");
+ opener.is(shistory.count, 2, 'check history length');
+ opener.is(shistory.index, 1, 'check history index');
+ opener.is(shistory.requestedIndex, -1, 'check requestedIndex');
+ opener.ok(webNav.canGoBack, 'check canGoBack');
+ if (opener.testCount == 1) {
+ opener.info('replaceState to redirect.html');
+ window.history.replaceState({}, '', 'file_bug1300461_redirect.html');
+ }
+ window.history.back();
+ }
+ }
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_bug1300461_redirect.html b/docshell/test/navigation/file_bug1300461_redirect.html
new file mode 100644
index 0000000000..979530c5cf
--- /dev/null
+++ b/docshell/test/navigation/file_bug1300461_redirect.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Bug 1300461</title>
+ </head>
+ <body>
+ Redirect to file_bug1300461_back.html.
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_bug1300461_redirect.html^headers^ b/docshell/test/navigation/file_bug1300461_redirect.html^headers^
new file mode 100644
index 0000000000..241b891826
--- /dev/null
+++ b/docshell/test/navigation/file_bug1300461_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: file_bug1300461_back.html
diff --git a/docshell/test/navigation/file_bug462076_1.html b/docshell/test/navigation/file_bug462076_1.html
new file mode 100644
index 0000000000..5b7bf2b110
--- /dev/null
+++ b/docshell/test/navigation/file_bug462076_1.html
@@ -0,0 +1,55 @@
+<html>
+ <head>
+ <title>Bug 462076</title>
+ <script>
+ var srcs = [ "frame0.html",
+ "frame1.html",
+ "frame2.html",
+ "frame3.html" ];
+
+ var checkCount = 0;
+
+ function makeFrame(index) {
+ var ifr = document.createElement("iframe");
+ ifr.src = srcs[index];
+ ifr.onload = checkFrame;
+ document.getElementById("container" + index).appendChild(ifr);
+ }
+
+ function runTest() {
+ var randomNumber = Math.floor(Math.random() * 4);
+ for (var i = randomNumber; i < 4; ++i) {
+ makeFrame(i);
+ }
+ for (var i = 0; i < randomNumber; ++i) {
+ makeFrame(i);
+ }
+ }
+
+ function checkFrame(evt) {
+ var ifr = evt.target;
+ opener.ok(new String(ifr.contentWindow.location).indexOf(ifr.src) >= 0,
+ "Wrong document loaded (" + ifr.src + ", " +
+ ifr.contentWindow.location + ")!");
+
+ if (++checkCount == 4) {
+ if (++opener.testCount == 10) {
+ opener.nextTest();
+ window.close();
+ } else {
+ window.location.reload();
+ }
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <div id="container0"></div>
+ <div id="container1"></div>
+ <div id="container2"></div>
+ <div id="container3"></div>
+ <script>
+ runTest();
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_bug462076_2.html b/docshell/test/navigation/file_bug462076_2.html
new file mode 100644
index 0000000000..813a6d8405
--- /dev/null
+++ b/docshell/test/navigation/file_bug462076_2.html
@@ -0,0 +1,52 @@
+<html>
+ <head>
+ <title>Bug 462076</title>
+ <script>
+ var srcs = [ "frame0.html",
+ "frame1.html",
+ "frame2.html",
+ "frame3.html" ];
+
+ var checkCount = 0;
+
+ function makeFrame(index) {
+ var ifr = document.createElement("iframe");
+ ifr.src = srcs[index];
+ ifr.onload = checkFrame;
+ document.getElementById("container" + index).appendChild(ifr);
+ }
+
+ function runTest() {
+ var randomNumber = Math.floor(Math.random() * 4);
+ for (var i = randomNumber; i < 4; ++i) {
+ makeFrame(i);
+ }
+ for (var i = 0; i < randomNumber; ++i) {
+ makeFrame(i);
+ }
+ }
+
+ function checkFrame(evt) {
+ var ifr = evt.target;
+ opener.ok(new String(ifr.contentWindow.location).indexOf(ifr.src) >= 0,
+ "Wrong document loaded (" + ifr.src + ", " +
+ ifr.contentWindow.location + ")!");
+
+ if (++checkCount == 4) {
+ if (++opener.testCount == 10) {
+ opener.nextTest();
+ window.close();
+ } else {
+ window.location.reload();
+ }
+ }
+ }
+ </script>
+ </head>
+ <body onload="runTest();">
+ <div id="container0"></div>
+ <div id="container1"></div>
+ <div id="container2"></div>
+ <div id="container3"></div>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_bug462076_3.html b/docshell/test/navigation/file_bug462076_3.html
new file mode 100644
index 0000000000..0079b9cdff
--- /dev/null
+++ b/docshell/test/navigation/file_bug462076_3.html
@@ -0,0 +1,52 @@
+<html>
+ <head>
+ <title>Bug 462076</title>
+ <script>
+ var srcs = [ "frame0.html",
+ "frame1.html",
+ "frame2.html",
+ "frame3.html" ];
+
+ var checkCount = 0;
+
+ function makeFrame(index) {
+ var ifr = document.createElement("iframe");
+ ifr.src = srcs[index];
+ ifr.onload = checkFrame;
+ document.getElementById("container" + index).appendChild(ifr);
+ }
+
+ function runTest() {
+ var randomNumber = Math.floor(Math.random() * 4);
+ for (var i = randomNumber; i < 4; ++i) {
+ makeFrame(i);
+ }
+ for (var i = 0; i < randomNumber; ++i) {
+ makeFrame(i);
+ }
+ }
+
+ function checkFrame(evt) {
+ var ifr = evt.target;
+ opener.ok(new String(ifr.contentWindow.location).indexOf(ifr.src) >= 0,
+ "Wrong document loaded (" + ifr.src + ", " +
+ ifr.contentWindow.location + ")!");
+
+ if (++checkCount == 4) {
+ if (++opener.testCount == 10) {
+ opener.nextTest();
+ window.close();
+ } else {
+ window.location.reload();
+ }
+ }
+ }
+ </script>
+ </head>
+ <body onload="setTimeout(runTest, 0);">
+ <div id="container0"></div>
+ <div id="container1"></div>
+ <div id="container2"></div>
+ <div id="container3"></div>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_bug508537_1.html b/docshell/test/navigation/file_bug508537_1.html
new file mode 100644
index 0000000000..194165f43e
--- /dev/null
+++ b/docshell/test/navigation/file_bug508537_1.html
@@ -0,0 +1,34 @@
+<html>
+ <head>
+ <script>
+ function dynFrameLoad() {
+ var ifrs = document.getElementsByTagName("iframe");
+ opener.ok(new String(ifrs[0].contentWindow.location).indexOf(ifrs[0].src) >= 0,
+ "Wrong document loaded (1)\n");
+ opener.ok(new String(ifrs[1].contentWindow.location).indexOf(ifrs[1].src) >= 0,
+ "Wrong document loaded (2)\n");
+ if (opener && ++opener.testCount == 1) {
+ window.location = "goback.html";
+ } else {
+ opener.nextTest();
+ window.close();
+ }
+ }
+
+ window.addEventListener("load",
+ function () {
+ var container = document.getElementById("t1");
+ container.addEventListener("load", dynFrameLoad, true);
+ container.appendChild(container.appendChild(document.getElementById("i1")));
+ }, false);
+ </script>
+ </head>
+ <body>
+ <h5>Container:</h5>
+ <div id="t1"></div>
+ <h5>Original frames:</h5>
+ <iframe id="i1" src="frame0.html"></iframe>
+ <iframe src="frame1.html"></iframe>
+ </body>
+</html>
+
diff --git a/docshell/test/navigation/file_bug534178.html b/docshell/test/navigation/file_bug534178.html
new file mode 100644
index 0000000000..8bcedb6fba
--- /dev/null
+++ b/docshell/test/navigation/file_bug534178.html
@@ -0,0 +1,31 @@
+<html>
+ <head>
+ <script>
+
+ function testDone() {
+ document.body.removeChild(document.body.firstChild);
+ var isOK = false;
+ try {
+ isOK = history.previous != location;
+ } catch(ex) {
+ // history.previous should throw if this is the first page in shistory.
+ isOK = true;
+ }
+ document.body.textContent = isOK ? "PASSED" : "FAILED";
+ opener.ok(isOK, "Duplicate session history transactions should have been removed!");
+ opener.nextTest();
+ window.close();
+ }
+ function ifrload() {
+ setTimeout(testDone, 0);
+ }
+ function test() {
+ var ifr = document.getElementsByTagName("iframe")[0];
+ ifr.onload = ifrload;
+ ifr.src = "data:text/html,doc2";
+ }
+ </script>
+ </head>
+ <body onload="setTimeout(test, 0)"><iframe src="data:text/html,doc1"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_document_write_1.html b/docshell/test/navigation/file_document_write_1.html
new file mode 100644
index 0000000000..e0281f7cdb
--- /dev/null
+++ b/docshell/test/navigation/file_document_write_1.html
@@ -0,0 +1,30 @@
+<html>
+ <head>
+ <script>
+ function run() {
+ document.open();
+ document.write("<h5 id='dynamic'>document.written content</h5>");
+ document.close();
+ window.history.go(-1);
+ }
+
+ function start() {
+ if (++opener.testCount == 1) {
+ setTimeout(run, 0);
+ }
+ }
+
+ window.addEventListener("pageshow",
+ function() {
+ ++opener.file_document_write_1_loadCount;
+ if (opener.file_document_write_1_loadCount == 2) {
+ opener.setTimeout("isTestDynamic()", 0);
+ }
+ opener.ok(opener.file_document_write_1_loadCount <= 2);
+ });
+ </script>
+ </head>
+ <body onload="start();">
+ <h5>static content</h5>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_fragment_handling_during_load.html b/docshell/test/navigation/file_fragment_handling_during_load.html
new file mode 100644
index 0000000000..fbfa0cb384
--- /dev/null
+++ b/docshell/test/navigation/file_fragment_handling_during_load.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <script>
+ var timerID = 0;
+ function testDone() {
+ clearTimeout(timerID);
+ var l = document.body.firstChild.contentWindow.location.href;
+ opener.is(l, "data:text/html,bar", "Should have loaded a new document");
+ opener.nextTest();
+ window.close();
+ }
+ function test() {
+ var ifr = document.getElementsByTagName("iframe")[0];
+ ifr.onload = testDone;
+ ifr.contentWindow.location.hash = "b";
+ ifr.contentWindow.location.href = "data:text/html,bar";
+ history.back();
+ timerID = setTimeout(testDone, 2000);
+ }
+ </script>
+ </head>
+ <body onload="setTimeout(test, 0)"><iframe src="data:text/html,foo#a"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_nested_frames.html b/docshell/test/navigation/file_nested_frames.html
new file mode 100644
index 0000000000..f65d8e01b4
--- /dev/null
+++ b/docshell/test/navigation/file_nested_frames.html
@@ -0,0 +1,28 @@
+<html>
+ <head>
+ <script>
+ function nestedIframeLoaded() {
+ var tf = document.getElementById("testframe");
+ var innerf = tf.contentDocument.getElementsByTagName("iframe")[0];
+ if (innerf.contentDocument.documentURI.indexOf("frame0") < 0) {
+ innerf.contentWindow.location.href = "http://mochi.test:8888/tests/docshell/test/navigation/frame0.html";
+ return;
+ }
+ innerf.onload = null;
+ innerf.src = "about:blank";
+ var d = innerf.contentDocument;
+ d.open();
+ d.write("test");
+ d.close();
+ opener.is(window.history.length, 1, "Unexpected history length");
+ opener.nextTest();
+ window.close();
+ }
+ </script>
+ </head>
+ <body>
+ <iframe id="testframe" src="data:text/html,<iframe onload='parent.nestedIframeLoaded();'></iframe>" onload="frameLoaded()"></iframe>
+ <script>
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_scrollRestoration.html b/docshell/test/navigation/file_scrollRestoration.html
new file mode 100644
index 0000000000..5450c27246
--- /dev/null
+++ b/docshell/test/navigation/file_scrollRestoration.html
@@ -0,0 +1,137 @@
+<html>
+ <head>
+ <script>
+ var oldHistoryObject = null;
+
+ function test(event) {
+ if (!opener.scrollRestorationTest) {
+ opener.scrollRestorationTest = 0;
+ }
+ ++opener.scrollRestorationTest;
+
+ switch (opener.scrollRestorationTest) {
+ case 1: {
+ opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
+ opener.ok(history.scrollRestoration, "History object has scrollRestoration property.");
+ opener.ok(history.scrollRestoration, "auto", "history.scrollRestoration's default value should be 'auto'.");
+ history.scrollRestoration = "foobar";
+ opener.ok(history.scrollRestoration, "auto", "Invalid enum value should not change the value of an attribute.");
+ history.scrollRestoration = "manual";
+ opener.ok(history.scrollRestoration, "manual", "Valid enum value should change the value of an attribute.");
+ history.scrollRestoration = "auto";
+ opener.ok(history.scrollRestoration, "auto", "Valid enum value should change the value of an attribute.");
+ document.getElementById("bottom").scrollIntoView();
+ window.location.reload(false);
+ break;
+ }
+ case 2: {
+ opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
+ opener.isnot(window.scrollY, 0, "Should have restored scrolling.");
+ opener.is(history.scrollRestoration, "auto", "Should have the same scrollRestoration as before reload.");
+ history.scrollRestoration = "manual";
+ window.onunload = function() {} // Disable bfcache.
+ window.location.reload(false);
+ break;
+ }
+ case 3: {
+ opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
+ opener.is(window.scrollY, 0, "Should not have restored scrolling.");
+ opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration as before reload.");
+ document.getElementById("bottom").scrollIntoView();
+ window.onunload = null; // Should get bfcache behavior.
+ opener.setTimeout("testWindow.history.back();", 250);
+ window.location.href = 'data:text/html,';
+ break;
+ }
+ case 4: {
+ opener.is(event.persisted, true, "Should have persisted session history entry.");
+ opener.isnot(window.scrollY, 0, "Should have kept the old scroll position.");
+ opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration as before reload.");
+ window.scrollTo(0, 0);
+ window.location.hash = "hash";
+ requestAnimationFrame(test);
+ break;
+ }
+ case 5: {
+ opener.isnot(window.scrollY, 0, "Should have scrolled to #hash.");
+ opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration mode as before fragment navigation.");
+ window.onunload = function() {} // Disable bfcache.
+ opener.setTimeout("is(testWindow.history.scrollRestoration, 'auto'); testWindow.history.back();", 250);
+ window.location.href = 'data:text/html,';
+ break;
+ }
+ case 6: {
+ opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
+ opener.is(window.scrollY, 0, "Shouldn't have kept the old scroll position.");
+ opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration mode as before fragment navigation.");
+ history.scrollRestoration = "auto";
+ document.getElementById("bottom").scrollIntoView();
+ history.pushState({ state: "state1" }, "state1");
+ history.pushState({ state: "state2" }, "state2");
+ window.scrollTo(0, 0);
+ history.back();
+ opener.isnot(window.scrollY, 0, "Should have scrolled back to the state1's position");
+ opener.is(history.state.state, "state1", "Unexpected state.");
+
+ history.scrollRestoration = "manual";
+ document.getElementById("bottom").scrollIntoView();
+ history.pushState({ state: "state3" }, "state3");
+ history.pushState({ state: "state4" }, "state4");
+ window.scrollTo(0, 0);
+ history.back();
+ opener.is(window.scrollY, 0, "Shouldn't have scrolled back to the state3's position");
+ opener.is(history.state.state, "state3", "Unexpected state.");
+
+ history.pushState({ state: "state5" }, "state5");
+ history.scrollRestoration = "auto";
+ document.getElementById("bottom").scrollIntoView();
+ opener.isnot(window.scrollY, 0, "Should have scrolled to 'bottom'.");
+ history.back();
+ window.scrollTo(0, 0);
+ history.forward();
+ opener.isnot(window.scrollY, 0, "Should have scrolled back to the state5's position");
+
+ var ifr = document.createElement("iframe");
+ ifr.src = "data:text/html,";
+ document.body.appendChild(ifr);
+ ifr.onload = test;
+ break;
+ }
+ case 7: {
+ oldHistoryObject = event.target.contentWindow.history;
+ event.target.src = "about:blank";
+ break;
+ }
+ case 8: {
+ try {
+ var sr = oldHistoryObject.scrollRestoration;
+ opener.ok(false, "Should have thrown an exception.");
+ } catch(ex) {
+ opener.isnot(ex, null, "Did get an exception");
+ }
+ try {
+ oldHistoryObject.scrollRestoration = "auto";
+ opener.ok(false, "Should have thrown an exception.");
+ } catch(ex) {
+ opener.isnot(ex, null, "Did get an exception");
+ }
+ opener.nextTest();
+ window.close();
+ break;
+ }
+ }
+ }
+
+ window.addEventListener("pageshow",
+ function(e) {
+ setTimeout(test, 0, e);
+ });
+ </script>
+ </head>
+ <body>
+ <div style="border: 1px solid black; height: 5000px;">
+ &nbsp;</div>
+ <div id="bottom">Hello world</div>
+ <a href="#hash" name="hash">hash</a>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_shiftReload_and_pushState.html b/docshell/test/navigation/file_shiftReload_and_pushState.html
new file mode 100644
index 0000000000..5a777894b6
--- /dev/null
+++ b/docshell/test/navigation/file_shiftReload_and_pushState.html
@@ -0,0 +1,29 @@
+<html>
+ <head>
+ <script>
+ function test() {
+ try {
+ frames[0].history.pushState({}, "state", "?pushed");
+ } catch(ex) {
+ opener.ok(false, "history.pushState shouldn't throw");
+ }
+
+ if (!opener.shiftReloadPushStateFirstRound) {
+ opener.shiftReloadPushStateFirstRound = true;
+ window.location.reload(true);
+ } else {
+ opener.ok(true, "Did run history.push");
+ opener.nextTest();
+ window.close();
+ }
+ }
+
+ window.addEventListener("load", function() { setTimeout(test, 0); });
+ </script>
+ </head>
+ <body>
+ <iframe src="frame0.html"></iframe>
+ <script>
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_static_and_dynamic_1.html b/docshell/test/navigation/file_static_and_dynamic_1.html
new file mode 100644
index 0000000000..692a5a9ab7
--- /dev/null
+++ b/docshell/test/navigation/file_static_and_dynamic_1.html
@@ -0,0 +1,32 @@
+<html>
+ <head>
+ <script>
+ function test() {
+ var ifr = document.createElement("iframe");
+ ifr.src = "frame0.html";
+ document.getElementById("dynamic").appendChild(ifr);
+ var staticFrame = document.getElementById("staticframe");
+ staticFrame.onload = window.location = "goback.html";
+ staticFrame.contentWindow.location = "frame1.html";
+ }
+
+ function start() {
+ if (++opener.testCount == 1) {
+ test();
+ } else {
+ var staticFrame = document.getElementById("staticframe");
+ opener.ok(new String(staticFrame.contentWindow.location).indexOf(staticFrame.src) >= 0,
+ "Wrong document loaded!");
+ opener.nextTest();
+ window.close();
+ }
+ }
+ </script>
+ </head>
+ <body onload="setTimeout('start()', 0)">
+ <h5>Dynamic</h5>
+ <div id="dynamic"></div>
+ <h5>Static</h5>
+ <div id="static"><iframe id="staticframe" src="frame0.html"></iframe></div>
+ </body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_frame_1.html b/docshell/test/navigation/file_triggeringprincipal_frame_1.html
new file mode 100644
index 0000000000..1e21e64211
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_frame_1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head><meta charset="utf-8"></head>
+<body>
+<b>Frame 1</b><br/>
+<a href="#"" id="testlink" onclick="parent.frames[1].frames[0].location='http://test2.mochi.test:8888/tests/docshell/test/navigation/file_triggeringprincipal_subframe_nav.html'">click me</a>
+
+<script type="application/javascript">
+ // make sure to set document.domain to the same domain as the subframe
+ window.onload = function() {
+ document.domain = 'mochi.test';
+ };
+ window.addEventListener('message', receiveMessage, false);
+ function receiveMessage(event) {
+ // make sure to get the right start command, otherwise
+ // let the parent know and fail the test
+ if (event.data.start !== 'startTest') {
+ window.removeEventListener("message", receiveMessage, false);
+ window.parent.postMessage({triggeringPrincipalURI: 'false'}, '*');
+ }
+ // click the link to navigate the subframe
+ document.getElementById('testlink').click();
+ }
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_frame_2.html b/docshell/test/navigation/file_triggeringprincipal_frame_2.html
new file mode 100644
index 0000000000..ef7cdfc178
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_frame_2.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head><meta charset="utf-8"></head>
+<body>
+<b>Frame 2</b><br/>
+<iframe src="http://test2.mochi.test:8888/tests/docshell/test/navigation/file_triggeringprincipal_subframe.html"></iframe>
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a.html b/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a.html
new file mode 100644
index 0000000000..75b2933c1b
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+Frame A
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html b/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html
new file mode 100644
index 0000000000..0479f5e1e5
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+Frame A navigated by Frame B
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_b.html b/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_b.html
new file mode 100644
index 0000000000..e5d40b267a
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_b.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+Frame B navigating Frame A
+
+<script type="text/javascript">
+
+window.open("file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html", "framea");
+
+</script>
+
+</body>
+</html>
+
+
diff --git a/docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_base.html b/docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_base.html
new file mode 100644
index 0000000000..caa6b275b9
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_base.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+base test frame
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_nav.html b/docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_nav.html
new file mode 100644
index 0000000000..f4a4d0e631
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_parent_iframe_window_open_nav.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+navigated by window.open()
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_subframe.html b/docshell/test/navigation/file_triggeringprincipal_subframe.html
new file mode 100644
index 0000000000..0db1349f2f
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_subframe.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head><meta charset='utf-8'></head>
+<body>
+<b>Sub Frame 2</b><br/>
+<script type='application/javascript'>
+ // make sure to set document.domain to same domain as frame 1
+ window.onload = function() {
+ document.domain = 'mochi.test';
+ // let Frame 1 know that we are ready to run the test
+ window.parent.parent.frames[0].postMessage({start: 'startTest'}, '*');
+ };
+</script>
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_subframe_nav.html b/docshell/test/navigation/file_triggeringprincipal_subframe_nav.html
new file mode 100644
index 0000000000..3bf7097a6c
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_subframe_nav.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head><meta charset="utf-8"></head>
+<body onload="checkResults()">
+<b>Sub Frame 2 Navigated</b><br/>
+
+<script type='application/javascript'>
+ function checkResults() {
+ // query the uri of the loadingPrincipal and the TriggeringPrincipal and pass
+ // that information on to the parent for verification.
+ var channel = SpecialPowers.wrap(document).docShell.currentDocumentChannel;
+ var triggeringPrincipalURI = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
+ var loadingPrincipalURI = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
+ var referrerURI = document.referrer;
+ window.parent.parent.postMessage({triggeringPrincipalURI,
+ loadingPrincipalURI,
+ referrerURI}, '*');
+ }
+</script>
+</body>
+</html>
diff --git a/docshell/test/navigation/file_triggeringprincipal_window_open.html b/docshell/test/navigation/file_triggeringprincipal_window_open.html
new file mode 100644
index 0000000000..d0644a4d5c
--- /dev/null
+++ b/docshell/test/navigation/file_triggeringprincipal_window_open.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+http
+</body>
+</html>
diff --git a/docshell/test/navigation/frame0.html b/docshell/test/navigation/frame0.html
new file mode 100644
index 0000000000..93d1c9c822
--- /dev/null
+++ b/docshell/test/navigation/frame0.html
@@ -0,0 +1,3 @@
+<html>
+ <body>Frame 0</body>
+</html>
diff --git a/docshell/test/navigation/frame1.html b/docshell/test/navigation/frame1.html
new file mode 100644
index 0000000000..4d06c09d1c
--- /dev/null
+++ b/docshell/test/navigation/frame1.html
@@ -0,0 +1,3 @@
+<html>
+ <body>Frame 1</body>
+</html>
diff --git a/docshell/test/navigation/frame2.html b/docshell/test/navigation/frame2.html
new file mode 100644
index 0000000000..7a3b5e0b9b
--- /dev/null
+++ b/docshell/test/navigation/frame2.html
@@ -0,0 +1,3 @@
+<html>
+ <body>Frame 2</body>
+</html>
diff --git a/docshell/test/navigation/frame3.html b/docshell/test/navigation/frame3.html
new file mode 100644
index 0000000000..fd24293873
--- /dev/null
+++ b/docshell/test/navigation/frame3.html
@@ -0,0 +1,3 @@
+<html>
+ <body>Frame 3</body>
+</html>
diff --git a/docshell/test/navigation/goback.html b/docshell/test/navigation/goback.html
new file mode 100644
index 0000000000..ce2968374e
--- /dev/null
+++ b/docshell/test/navigation/goback.html
@@ -0,0 +1,5 @@
+<html>
+ <body onload="setTimeout('window.history.go(-1)', 1000);">
+ window.history.go(-1);
+ </body>
+</html>
diff --git a/docshell/test/navigation/iframe.html b/docshell/test/navigation/iframe.html
new file mode 100644
index 0000000000..4685fea7b7
--- /dev/null
+++ b/docshell/test/navigation/iframe.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<script>
+var src = window.location.hash.substring(1);
+document.write('<iframe src="' + src + '"></iframe>');
+</script>
+</body>
+</html>
diff --git a/docshell/test/navigation/mochitest.ini b/docshell/test/navigation/mochitest.ini
new file mode 100644
index 0000000000..0c35cf352c
--- /dev/null
+++ b/docshell/test/navigation/mochitest.ini
@@ -0,0 +1,64 @@
+[DEFAULT]
+support-files =
+ NavigationUtils.js
+ blank.html
+ file_bug462076_1.html
+ file_bug462076_2.html
+ file_bug462076_3.html
+ file_bug508537_1.html
+ file_bug534178.html
+ file_document_write_1.html
+ file_fragment_handling_during_load.html
+ file_nested_frames.html
+ file_scrollRestoration.html
+ file_shiftReload_and_pushState.html
+ file_static_and_dynamic_1.html
+ frame0.html
+ frame1.html
+ frame2.html
+ frame3.html
+ goback.html
+ iframe.html
+ navigate.html
+ open.html
+ parent.html
+ file_triggeringprincipal_frame_1.html
+ file_triggeringprincipal_frame_2.html
+ file_triggeringprincipal_subframe.html
+ file_triggeringprincipal_subframe_nav.html
+ file_triggeringprincipal_window_open.html
+ file_triggeringprincipal_parent_iframe_window_open_base.html
+ file_triggeringprincipal_parent_iframe_window_open_nav.html
+ file_triggeringprincipal_iframe_iframe_window_open_frame_a.html
+ file_triggeringprincipal_iframe_iframe_window_open_frame_b.html
+ file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html
+ file_bug1300461.html
+ file_bug1300461_redirect.html
+ file_bug1300461_redirect.html^headers^
+ file_bug1300461_back.html
+
+[test_bug13871.html]
+[test_bug270414.html]
+[test_bug278916.html]
+[test_bug279495.html]
+[test_bug344861.html]
+skip-if = toolkit == "android" || toolkit == "windows" # disabled on Windows because of bug 1234520
+[test_bug386782.html]
+[test_bug430624.html]
+[test_bug430723.html]
+skip-if = (toolkit == 'android') || (!debug && (os == 'mac' || os == 'win')) # Bug 874423
+[test_child.html]
+[test_grandchild.html]
+[test_not-opener.html]
+[test_opener.html]
+[test_popup-navigates-children.html]
+[test_reserved.html]
+skip-if = (toolkit == 'android') || (debug && e10s) #too slow on Android 4.3 aws only; bug 1030403; bug 1263213 for debug e10s
+[test_sessionhistory.html]
+skip-if = toolkit == 'android' #RANDOM
+[test_sibling-matching-parent.html]
+[test_sibling-off-domain.html]
+[test_triggeringprincipal_frame_nav.html]
+[test_triggeringprincipal_window_open.html]
+[test_triggeringprincipal_parent_iframe_window_open.html]
+[test_triggeringprincipal_iframe_iframe_window_open.html]
diff --git a/docshell/test/navigation/navigate.html b/docshell/test/navigation/navigate.html
new file mode 100644
index 0000000000..e686da4236
--- /dev/null
+++ b/docshell/test/navigation/navigate.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="NavigationUtils.js"></script>
+ <script>
+ function navigate() {
+ var arguments = window.location.hash.substring(1).split(",");
+ var target = arguments[0];
+ var mechanism = arguments[1];
+
+ switch(mechanism) {
+ case "location":
+ navigateByLocation(eval(target));
+ break;
+ case "open":
+ navigateByOpen(target);
+ break;
+ case "form":
+ navigateByForm(target);
+ break;
+ case "hyperlink":
+ navigateByHyperlink(target);
+ break;
+ }
+ }
+ </script>
+</head>
+<body onload="navigate();">
+<script>
+var arguments = window.location.hash.substring(1).split(",");
+var target = arguments[0];
+var mechanism = arguments[1];
+document.write("target=" + target + " mechanism=" + mechanism);
+</script>
+</body>
+</html>
diff --git a/docshell/test/navigation/open.html b/docshell/test/navigation/open.html
new file mode 100644
index 0000000000..1bb70f865b
--- /dev/null
+++ b/docshell/test/navigation/open.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+<script>
+var target = window.location.hash.substring(1);
+document.write("target=" + target);
+window.open("data:text/html,<html><body>This is a popup</body></html>", target, "width=10,height=10");
+</script>
+</body>
+</html>
diff --git a/docshell/test/navigation/parent.html b/docshell/test/navigation/parent.html
new file mode 100644
index 0000000000..74722b8bdf
--- /dev/null
+++ b/docshell/test/navigation/parent.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+This document contains a frame.
+<div><iframe src="blank.html"></iframe></div>
+<script>
+frames[0].name = window.name + "_child0";
+window.onload = function() {
+ opener.postMessage("ready", "*");
+};
+</script>
+</body>
+</html>
+
diff --git a/docshell/test/navigation/test_bug13871.html b/docshell/test/navigation/test_bug13871.html
new file mode 100644
index 0000000000..e0b563a4a8
--- /dev/null
+++ b/docshell/test/navigation/test_bug13871.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+function runTest() {
+ navigateByLocation(window0.frames[0]);
+ navigateByOpen("window1_child0");
+ navigateByForm("window2_child0");
+ navigateByHyperlink("window3_child0");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window0.frames[0], "Should not be able to navigate off-domain frame by setting location.");
+ isInaccessible(window1.frames[0], "Should not be able to navigate off-domain frame by calling window.open.");
+ isInaccessible(window2.frames[0], "Should not be able to navigate off-domain frame by submitting form.");
+ isInaccessible(window3.frames[0], "Should not be able to navigate off-domain frame by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 4);
+}
+
+// Because our open()'d windows are cross-origin, we can't wait for onload.
+// We instead wait for a postMessage from parent.html.
+var windows = new Map();
+addEventListener("message", function windowLoaded(evt) {
+ // Because window.open spins the event loop in order to open new windows,
+ // we might receive the "ready" message before we call waitForLoad.
+ // In that case, windows won't contain evt.source and we just note that the
+ // window is ready. Otherwise, windows contains the "resolve" function for
+ // that window's promise and we just have to call it.
+ if (windows.has(evt.source)) {
+ windows.get(evt.source)();
+ } else {
+ windows.set(evt.source, true);
+ }
+});
+
+var window0 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window0", "width=10,height=10");
+var window1 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window1", "width=10,height=10");
+var window2 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window2", "width=10,height=10");
+var window3 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window3", "width=10,height=10");
+
+function waitForLoad(w) {
+ return new Promise(function(resolve, reject) {
+ // If we already got the "ready" message, resolve immediately.
+ if (windows.has(w)) {
+ resolve();
+ } else {
+ windows.set(w, resolve);
+ }
+ });
+}
+
+Promise.all([ waitForLoad(window0),
+ waitForLoad(window1),
+ waitForLoad(window2),
+ waitForLoad(window3) ])
+ .then(runTest);
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=13871">Mozilla Bug 13871</a>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_bug270414.html b/docshell/test/navigation/test_bug270414.html
new file mode 100644
index 0000000000..98dcf42f8d
--- /dev/null
+++ b/docshell/test/navigation/test_bug270414.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+var headerHTML = "<html><head>" +
+ "<script src='/tests/SimpleTest/EventUtils.js'></scr" + "ipt>" +
+ "<script src='NavigationUtils.js'></scr" + "ipt>" +
+ "</head><body>";
+var footerHTML = "</body></html>";
+
+function testChild0() {
+ if (!window.window0) {
+ window0 = window.open("", "window0", "width=10,height=10");
+ window0.document.open();
+ window0.document.write(headerHTML);
+ window0.document.write("<script>navigateByLocation(opener.frames[0])</scr" + "ipt>");
+ window0.document.write(footerHTML);
+ window0.document.close();
+ }
+}
+
+function testChild1() {
+ if (!window.window1) {
+ window1 = window.open("", "window1", "width=10,height=10");
+ window1.document.open();
+ window1.document.write(headerHTML);
+ window1.document.write("<script>navigateByOpen('child1');</scr" + "ipt>");
+ window1.document.write(footerHTML);
+ window1.document.close();
+ }
+}
+
+function testChild2() {
+ if (!window.window2) {
+ window2 = window.open("", "window2", "width=10,height=10");
+ window2.document.open();
+ window2.document.write(headerHTML);
+ window2.document.write("<script>navigateByForm('child2');</scr" + "ipt>");
+ window2.document.write(footerHTML);
+ window2.document.close();
+ }
+}
+
+function testChild3() {
+ if (!window.window3) {
+ window3 = window.open("", "window3", "width=10,height=10");
+ window3.document.open();
+ window3.document.write(headerHTML);
+ window3.document.write("<script>navigateByHyperlink('child3');</scr" + "ipt>");
+ window3.document.write(footerHTML);
+ window3.document.close();
+ }
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate on-domain opener's children by setting location.");
+ isNavigated(frames[1], "Should be able to navigate on-domain opener's children by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate on-domain opener's children by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate on-domain opener's children by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=270414">Mozilla Bug 270414</a>
+<div id="frames">
+<iframe onload="testChild0();" name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild1();" name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild2();" name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild3();" name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_bug278916.html b/docshell/test/navigation/test_bug278916.html
new file mode 100644
index 0000000000..3ad6a9666c
--- /dev/null
+++ b/docshell/test/navigation/test_bug278916.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+<script>
+window.onload = function () {
+ document.getElementById("link0").href = target_url;
+ sendMouseEvent({type:"click"}, "link0");
+
+ xpcWaitForFinishedFrames(function() {
+ var array_of_frames = xpcGetFramesByName("window0");
+ is(array_of_frames.length, 1, "Should only open one window using a fancy hyperlink.");
+
+ for (var i=0; i < array_of_frames.length; ++i)
+ array_of_frames[i].close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 1);
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=278916">Mozilla Bug 278916</a>
+<div id="links">
+<a id="link0" target="window0" onclick="window.open('', 'window0', 'width=10,height=10');">This is a fancy hyperlink</a>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_bug279495.html b/docshell/test/navigation/test_bug279495.html
new file mode 100644
index 0000000000..79a1695677
--- /dev/null
+++ b/docshell/test/navigation/test_bug279495.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+<script>
+window.onload = function () {
+ document.getElementById("link0").href = target_url;
+ document.getElementById("link1").href = target_url;
+
+ sendMouseEvent({type:"click"}, "link0");
+ sendMouseEvent({type:"click"}, "link1");
+
+ xpcWaitForFinishedFrames(function() {
+ countAndClose("window0", 1);
+ countAndClose("window1", 1);
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 2);
+}
+
+function countAndClose(name, expected_count) {
+ var array_of_frames = xpcGetFramesByName(name);
+ is(array_of_frames.length, expected_count,
+ "Should only open " + expected_count +
+ " window(s) with name " + name + " using a fancy hyperlink.");
+
+ for (var i=0; i < array_of_frames.length; ++i)
+ array_of_frames[i].close();
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=279495">Mozilla Bug 279495</a>
+<div id="links">
+<a id="link0" target="window0" onclick="window.open('blank.html', 'window0', 'width=10,height=10');">This is a fancy hyperlink</a>
+<a id="link1" target="window1" onclick="window.open('http://test1.example.org:80/tests/docshell/test/navigation/blank.html', 'window1', 'width=10,height=10');">This is a fancy hyperlink</a>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_bug344861.html b/docshell/test/navigation/test_bug344861.html
new file mode 100644
index 0000000000..f9759751c9
--- /dev/null
+++ b/docshell/test/navigation/test_bug344861.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=344861
+-->
+<head>
+ <title>Test for Bug 344861</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=344861">Mozilla Bug 344861</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 344861 **/
+SimpleTest.waitForExplicitFinish();
+
+var newwindow = window.open("/", "testwindow", "width=200,height=200");
+newwindow.onload = function() {
+ is(newwindow.innerHeight, 200, "window.open has correct height dimensions");
+ is(newwindow.innerWidth, 200, "window.open has correct width dimensions");
+ SimpleTest.finish();
+ newwindow.close();
+}
+</script>
+</pre>
+</body>
+</html>
+
+
diff --git a/docshell/test/navigation/test_bug386782.html b/docshell/test/navigation/test_bug386782.html
new file mode 100644
index 0000000000..2434963f15
--- /dev/null
+++ b/docshell/test/navigation/test_bug386782.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=386782
+-->
+<head>
+ <title>Test for Bug 386782</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" />
+
+ <script>
+
+ // This tests if we can load a document whose root is in designMode,
+ // edit it, navigate to a new page, navigate back, still edit, and still
+ // undo/redo. Note that this is different from the case where the
+ // designMode document is in a frame inside the window, as this means
+ // the editable region is not in the root docshell (a less complicated case).
+
+ var pageShowChecker = '<scr' + 'ipt>' +
+ 'window.addEventListener("pageshow", function(event) {' +
+ 'window.opener.postMessage({persisted:event.persisted}, "*");' +
+ '});</scr' + 'ipt>';
+
+ var gTests = [
+ {
+ // <html><body><p>designModeDocument</p></body></html>
+ url: "data:text/html;charset=utf-8,<html><head>" + pageShowChecker + "</head><body><p>designModeDocument</p></body></html>",
+ name: 'designModeNavigate',
+ onload(doc) { doc.designMode = "on"; },
+ expectedBodyBeforeEdit: '<p>designModeDocument</p>',
+ expectedBodyAfterEdit: '<p>EDITED designModeDocument</p>',
+ expectedBodyAfterSecondEdit: '<p>EDITED TWICE designModeDocument</p>',
+ },
+ {
+ // <html><body contentEditable="true"><p>contentEditable</p></body></html>
+ url: "data:text/html;charset=utf-8,<html><head>" + pageShowChecker + "</head><body contentEditable=\"true\"><p>contentEditable</p></body></html>",
+ name: 'contentEditableNavigate',
+ expectedBodyBeforeEdit: '<p>contentEditable</p>',
+ expectedBodyAfterEdit: 'EDITED <br><p>contentEditable</p>',
+ expectedBodyAfterSecondEdit: 'EDITED TWICE <br><p>contentEditable</p>',
+ }
+ ];
+
+ var gTestNum = -1;
+ var gTest = null;
+
+ window.onload = goNext();
+
+ function goNext() {
+ gTestNum++;
+ if (gTestNum >= gTests.length) {
+ SimpleTest.finish();
+ return;
+ }
+ gTest = gTests[gTestNum];
+ gTest.window = window.open(gTest.url, gTest.name, "width=500,height=500");
+ window.onmessage = function(e) {
+ is(e.data.persisted, false, "Initial load cannot be persisted");
+ window.onmessage = null;
+ if ("onload" in gTest) {
+ gTest.onload(gTest.window.document);
+ }
+ SimpleTest.waitForFocus(beginTest, gTest.window);
+ };
+ }
+
+ function beginTest() {
+ gTest.window.document.body.focus();
+
+ // WARNING: If the following test fails, give the setTimeout() in the onload()
+ // a bit longer; the doc hasn't had enough time to setup its editor.
+ is(gTest.window.document.body.innerHTML, gTest.expectedBodyBeforeEdit, "Is doc setup yet");
+ sendString('EDITED ', gTest.window);
+ is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterEdit, "Editing failed.");
+
+ gTest.window.location = 'data:text/html;charset=utf-8,SomeOtherDocument';
+ SimpleTest.waitForFocus(goBack, gTest.window);
+ }
+
+ function goBack() {
+ window.onmessage = function(e) {
+ window.onmessage = null;
+ // Skip the test if the page is not loaded from the bf-cache when going back.
+ if (e.data.persisted) {
+ checkStillEditable();
+ } else {
+ gTest.window.close();
+ goNext();
+ }
+ };
+ gTest.window.history.back();
+ }
+
+ function checkStillEditable() {
+
+ // Check that the contents are correct.
+ is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterEdit, "Edited contents still correct?");
+
+ // Check that we can undo/redo and the contents are correct.
+ gTest.window.document.execCommand("undo", false, null);
+ is(gTest.window.document.body.innerHTML, gTest.expectedBodyBeforeEdit, "Can we undo?");
+
+ gTest.window.document.execCommand("redo", false, null);
+ is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterEdit, "Can we redo?");
+
+ // Check that we can still edit the page.
+ gTest.window.document.body.focus();
+ sendString('TWICE ', gTest.window);
+ is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterSecondEdit, "Can we still edit?");
+
+ gTest.window.close();
+ goNext();
+
+ }
+
+ </script>
+
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386782">Mozilla Bug 386782</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 386782 **/
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/navigation/test_bug430624.html b/docshell/test/navigation/test_bug430624.html
new file mode 100644
index 0000000000..9fc92e4cd3
--- /dev/null
+++ b/docshell/test/navigation/test_bug430624.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=430624
+-->
+<head>
+ <title>Test for Bug 430624</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430624">Mozilla Bug 430624</a>
+<p id="display"></p>
+
+
+
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 430624 **/
+
+function onLoad() {
+ window.frames[0].frameElement.onload = onReload;
+ window.frames[0].location = window.frames[0].location;
+}
+
+function onReload() {
+ var iframe = window.frames[0].frameElement;
+ SimpleTest.waitForFocus(doTest, iframe.contentWindow);
+ iframe.contentDocument.body.focus();
+}
+
+function doTest() {
+ var bodyElement = window.frames[0].frameElement.contentDocument.body;
+ bodyElement.focus();
+ sendString('Still ', window.frames[0].frameElement.contentWindow);
+
+ is(bodyElement.innerHTML, "Still contentEditable", "Check we're contentEditable after reload");
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+
+<iframe onload="onLoad()" src="data:text/html;charset=utf-8,<body contenteditable>contentEditable</body>"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/navigation/test_bug430723.html b/docshell/test/navigation/test_bug430723.html
new file mode 100644
index 0000000000..eb53e0d220
--- /dev/null
+++ b/docshell/test/navigation/test_bug430723.html
@@ -0,0 +1,138 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=430723
+-->
+<head>
+ <title>Test for Bug 430723</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=430723">Mozilla Bug 430723</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+//<![CDATA[
+
+/** Test for Bug 430723 **/
+
+var gTallRedBoxURI = "data:text/html;charset=utf-8;base64,PGh0bWw%2BPGhlYWQ%2BPHNjcmlwdD53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncGFnZXNob3cnLCBmdW5jdGlvbigpe29wZW5lci5uZXh0VGVzdCgpO30sIGZhbHNlKTs8L3NjcmlwdD48L2hlYWQ%2BPGJvZHk%2BPGRpdiBzdHlsZT0icG9zaXRpb246YWJzb2x1dGU7IGxlZnQ6MHB4OyB0b3A6MHB4OyB3aWR0aDo1MCU7IGhlaWdodDoxNTAlOyBiYWNrZ3JvdW5kLWNvbG9yOnJlZCI%2BPHA%2BVGhpcyBpcyBhIHZlcnkgdGFsbCByZWQgYm94LjwvcD48L2Rpdj48L2JvZHk%2BPC9odG1sPg%3D%3D";
+// <html><head>
+// < script > window.addEventListener("pageshow", function(){opener.nextTest();}, false); < /script >
+// </head><body>
+// <div style="position:absolute; left:0px; top:0px; width:50%; height:150%; background-color:red">
+// <p>This is a very tall red box.</p>
+// </div></body></html>
+
+var gTallBlueBoxURI = "data:text/html;charset=utf-8;base64,PGh0bWw%2BPGhlYWQ%2BPHNjcmlwdD53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncGFnZXNob3cnLCBmdW5jdGlvbigpe29wZW5lci5uZXh0VGVzdCgpO30sIGZhbHNlKTs8L3NjcmlwdD48L2hlYWQ%2BPGJvZHk%2BPGRpdiBzdHlsZT0icG9zaXRpb246YWJzb2x1dGU7IGxlZnQ6MHB4OyB0b3A6MHB4OyB3aWR0aDo1MCU7IGhlaWdodDoxNTAlOyBiYWNrZ3JvdW5kLWNvbG9yOmJsdWUiPjxwPlRoaXMgaXMgYSB2ZXJ5IHRhbGwgYmx1ZSBib3guPC9wPjwvZGl2PjwvYm9keT48L2h0bWw%2B";
+// <html><head>
+// < script > window.addEventListener("pageshow", function(){opener.nextTest();}, false); < /script >
+// </head><body>
+// <div style="position:absolute; left:0px; top:0px; width:50%; height:150%; background-color:blue">
+// <p>This is a very tall blue box.</p>
+// </div></body></html>
+
+window.onload = runTest;
+
+var testWindow;
+var testNum = 0;
+
+var smoothScrollPref = "general.smoothScroll";
+function runTest() {
+ SpecialPowers.pushPrefEnv({"set":[[smoothScrollPref, false]]}, function(){
+ testWindow = window.open(gTallRedBoxURI, "testWindow", "width=300,height=300,location=yes,scrollbars=yes");
+ });
+}
+
+var nextTest =function() {
+ testNum++;
+ switch (testNum) {
+ case 1: setTimeout(step1, 0); break;
+ case 2: setTimeout(step2, 0); break;
+ case 3: setTimeout(step3, 0); break;
+ };
+}
+
+var step1 =function() {
+ window.is(String(testWindow.location), gTallRedBoxURI, "Ensure red page loaded.");
+
+ // Navigate down and up.
+ is(testWindow.document.body.scrollTop, 0,
+ "Page1: Ensure the scrollpane is at the top before we start scrolling.");
+ testWindow.addEventListener("scroll", function () {
+ testWindow.removeEventListener("scroll", arguments.callee, true);
+ isnot(testWindow.document.body.scrollTop, 0,
+ "Page1: Ensure we can scroll down.");
+ SimpleTest.executeSoon(step1_2);
+ }, true);
+ sendKey('DOWN', testWindow);
+
+ function step1_2() {
+ testWindow.addEventListener("scroll", function () {
+ testWindow.removeEventListener("scroll", arguments.callee, true);
+ is(testWindow.document.body.scrollTop, 0,
+ "Page1: Ensure we can scroll up, back to the top.");
+
+ // Nav to blue box page. This should fire step2.
+ testWindow.location = gTallBlueBoxURI;
+ }, true);
+ sendKey('UP', testWindow);
+ }
+}
+
+
+var step2 =function() {
+ window.is(String(testWindow.location), gTallBlueBoxURI, "Ensure blue page loaded.");
+
+ // Scroll around a bit.
+ is(testWindow.document.body.scrollTop, 0,
+ "Page2: Ensure the scrollpane is at the top before we start scrolling.");
+
+ var count = 0;
+ testWindow.addEventListener("scroll", function () {
+ if (++count < 2) {
+ SimpleTest.executeSoon(function () { sendKey('DOWN', testWindow); });
+ } else {
+ testWindow.removeEventListener("scroll", arguments.callee, true);
+
+ isnot(testWindow.document.body.scrollTop, 0,
+ "Page2: Ensure we could scroll.");
+
+ // Navigate backwards. This should fire step3.
+ testWindow.history.back();
+ }
+ }, true);
+ sendKey('DOWN', testWindow);
+}
+
+var step3 =function() {
+ window.is(String(testWindow.location), gTallRedBoxURI,
+ "Ensure red page restored from history.");
+
+ // Check we can still scroll with the keys.
+ is(testWindow.document.body.scrollTop, 0,
+ "Page1Again: Ensure scroll pane at top before we scroll.");
+ testWindow.addEventListener("scroll", function () {
+ testWindow.removeEventListener("scroll", arguments.callee, true);
+
+ isnot(testWindow.document.body.scrollTop, 0,
+ "Page2Again: Ensure we can still scroll.");
+
+ testWindow.close();
+ window.SimpleTest.finish();
+ }, true);
+ sendKey('DOWN', testWindow);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+//]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_child.html b/docshell/test/navigation/test_child.html
new file mode 100644
index 0000000000..c43e1a6cf0
--- /dev/null
+++ b/docshell/test/navigation/test_child.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+if (!navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+window.onload = function() {
+ navigateByLocation(frames[0]);
+ navigateByOpen("child1");
+ navigateByForm("child2");
+ navigateByHyperlink("child3");
+
+ xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate off-domain child by setting location.");
+ isNavigated(frames[1], "Should be able to navigate off-domain child by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate off-domain child by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate off-domain child by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 4);
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_grandchild.html b/docshell/test/navigation/test_grandchild.html
new file mode 100644
index 0000000000..439145b3ed
--- /dev/null
+++ b/docshell/test/navigation/test_grandchild.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 200px; }
+ </style>
+<script>
+if (!navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+window.onload = function () {
+ navigateByLocation(frames[0].frames[0]);
+ navigateByOpen("child1_child0");
+ navigateByForm("child2_child0");
+ navigateByHyperlink("child3_child0");
+
+ xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0].frames[0], "Should be able to navigate off-domain grandchild by setting location.");
+ isNavigated(frames[1].frames[0], "Should be able to navigate off-domain grandchild by calling window.open.");
+ isNavigated(frames[2].frames[0], "Should be able to navigate off-domain grandchild by submitting form.");
+ isNavigated(frames[3].frames[0], "Should be able to navigate off-domain grandchild by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 4);
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+<iframe name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+<iframe name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+<iframe name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_not-opener.html b/docshell/test/navigation/test_not-opener.html
new file mode 100644
index 0000000000..d778f71d9c
--- /dev/null
+++ b/docshell/test/navigation/test_not-opener.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+if (!navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+window.onload = function () {
+ //navigateByLocation(window0); // Don't have a handle to the window.
+ navigateByOpen("window1");
+ navigateByForm("window2");
+ navigateByHyperlink("window3");
+
+ xpcWaitForFinishedFrames(function() {
+ is(xpcGetFramesByName("window1").length, 2, "Should not be able to navigate popup's popup by calling window.open.");
+ is(xpcGetFramesByName("window2").length, 2, "Should not be able to navigate popup's popup by submitting form.");
+ is(xpcGetFramesByName("window3").length, 2, "Should not be able to navigate popup's popup by targeted hyperlink.");
+
+ //opener0.close();
+ opener1.close();
+ opener2.close();
+ opener3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 6);
+}
+
+//opener0 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window0", "_blank", "width=10,height=10");
+opener1 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window1", "_blank", "width=10,height=10");
+opener2 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window2", "_blank", "width=10,height=10");
+opener3 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window3", "_blank", "width=10,height=10");
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_opener.html b/docshell/test/navigation/test_opener.html
new file mode 100644
index 0000000000..bfb1dde9f7
--- /dev/null
+++ b/docshell/test/navigation/test_opener.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+if (navigator.platform.startsWith("Linux")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+window.onload = function () {
+ navigateByLocation(window0);
+ navigateByOpen("window1");
+ navigateByForm("window2");
+ navigateByHyperlink("window3");
+
+ xpcWaitForFinishedFrames(function() {
+ isNavigated(window0, "Should be able to navigate popup by setting location.");
+ isNavigated(window1, "Should be able to navigate popup by calling window.open.");
+ isNavigated(window2, "Should be able to navigate popup by submitting form.");
+ isNavigated(window3, "Should be able to navigate popup by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 4);
+}
+
+var window0 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window0", "width=10,height=10");
+var window1 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window1", "width=10,height=10");
+var window2 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window2", "width=10,height=10");
+var window3 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window3", "width=10,height=10");
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_popup-navigates-children.html b/docshell/test/navigation/test_popup-navigates-children.html
new file mode 100644
index 0000000000..692f35713c
--- /dev/null
+++ b/docshell/test/navigation/test_popup-navigates-children.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+function testChild0() {
+ if (!window.window0)
+ window0 = window.open("navigate.html#opener.frames[0],location", "window0", "width=10,height=10");
+}
+
+function testChild1() {
+ if (!window.window1)
+ window1 = window.open("navigate.html#child1,open", "window1", "width=10,height=10");
+}
+
+function testChild2() {
+ if (!window.window2)
+ window2 = window.open("navigate.html#child2,form", "window2", "width=10,height=10");
+}
+
+function testChild3() {
+ if (!window.window3)
+ window3 = window.open("navigate.html#child3,hyperlink", "window3", "width=10,height=10");
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate on-domain opener's children by setting location.");
+ isNavigated(frames[1], "Should be able to navigate on-domain opener's children by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate on-domain opener's children by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate on-domain opener's children by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+
+</script>
+</head>
+<body>
+<div id="frames">
+<iframe onload="testChild0()" name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild1()" name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild2()" name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild3()" name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_reserved.html b/docshell/test/navigation/test_reserved.html
new file mode 100644
index 0000000000..b2389078c7
--- /dev/null
+++ b/docshell/test/navigation/test_reserved.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 200px; }
+ </style>
+<script>
+if (navigator.platform.startsWith("Mac")) {
+ SimpleTest.expectAssertions(0, 2);
+}
+
+function testTop() {
+ window0 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#top,location", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window0, "Should be able to navigate off-domain top by setting location.");
+ window0.close();
+ xpcCleanupWindows();
+
+ window1 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_top,open", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window1, "Should be able to navigate off-domain top by calling window.open.");
+ window1.close();
+ xpcCleanupWindows();
+
+ window2 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_top,form", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window2, "Should be able to navigate off-domain top by submitting form.");
+ window2.close();
+ xpcCleanupWindows();
+
+ window3 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_top,hyperlink", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window3, "Should be able to navigate off-domain top by targeted hyperlink.");
+ window3.close();
+ xpcCleanupWindows();
+
+ testParent();
+ }, 1);
+ }, 1);
+ }, 1);
+ }, 1);
+}
+
+function testParent() {
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#parent,location"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by setting location.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_parent,open"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by calling window.open.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_parent,form"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by submitting form.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_parent,hyperlink"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by targeted hyperlink.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = "";
+ SimpleTest.finish();
+ }, 1);
+ }, 1);
+ }, 1);
+ }, 1);
+}
+
+window.onload = function() {
+ testTop();
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_sessionhistory.html b/docshell/test/navigation/test_sessionhistory.html
new file mode 100644
index 0000000000..452271a41f
--- /dev/null
+++ b/docshell/test/navigation/test_sessionhistory.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=
+-->
+<head>
+ <title>Test for Bug </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="nextTest()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug **/
+
+var testFiles =
+ [ "file_bug462076_1.html", // Dynamic frames before onload
+ "file_bug462076_2.html", // Dynamic frames when handling onload
+ "file_bug462076_3.html", // Dynamic frames after onload
+ "file_bug508537_1.html", // Dynamic frames and forward-back
+ "file_document_write_1.html", // Session history + document.write
+ //"file_static_and_dynamic_1.html",// Static and dynamic frames and forward-back
+ "file_bug534178.html", // Session history transaction clean-up.
+ "file_fragment_handling_during_load.html",
+ "file_nested_frames.html",
+ "file_shiftReload_and_pushState.html",
+ "file_scrollRestoration.html",
+ "file_bug1300461.html"
+ ];
+var testCount = 0; // Used by the test files.
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var testWindow;
+function nextTest_() {
+ if (testFiles.length) {
+ testCount = 0;
+ testWindow = window.open(testFiles.shift(), "", "width=300,height=300");
+ testWindow.onunload = function () { } // to prevent bfcache
+ } else {
+ SimpleTest.finish();
+ }
+}
+
+// Needed by file_document_write_1.html
+window.file_document_write_1_loadCount = 0;
+function isTestDynamic() {
+ var dyn = testWindow.document.getElementById("dynamic");
+ is(dyn, null, "Should have gone back to the static page!");
+ nextTest();
+ testWindow.close();
+}
+
+function nextTest() {
+ setTimeout(nextTest_, 0);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_sibling-matching-parent.html b/docshell/test/navigation/test_sibling-matching-parent.html
new file mode 100644
index 0000000000..dc8ec2f905
--- /dev/null
+++ b/docshell/test/navigation/test_sibling-matching-parent.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function () {
+ document.getElementById('active').innerHTML =
+ '<iframe src="navigate.html#parent.frames[0],location"></iframe>' +
+ '<iframe src="navigate.html#child1,open"></iframe>' +
+ '<iframe src="navigate.html#child2,form"></iframe>' +
+ '<iframe src="navigate.html#child3,hyperlink"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate sibling with on-domain parent by setting location.");
+ isNavigated(frames[1], "Should be able to navigate sibling with on-domain parent by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate sibling with on-domain parent by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate sibling with on-domain parent by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 4);
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<div id="active"></div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_sibling-off-domain.html b/docshell/test/navigation/test_sibling-off-domain.html
new file mode 100644
index 0000000000..ba7942798e
--- /dev/null
+++ b/docshell/test/navigation/test_sibling-off-domain.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function () {
+ document.getElementById('active').innerHTML =
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#parent.frames[0],location"></iframe>' +
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child1,open"></iframe>' +
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child2,form"></iframe>' +
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child3,hyperlink"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isBlank(frames[0], "Should not be able to navigate off-domain sibling by setting location.");
+ isBlank(frames[1], "Should not be able to navigate off-domain sibling by calling window.open.");
+ isBlank(frames[2], "Should not be able to navigate off-domain sibling by submitting form.");
+ isBlank(frames[3], "Should not be able to navigate off-domain sibling by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+ }, 4);
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="blank.html"></iframe>
+<iframe name="child1" src="blank.html"></iframe>
+<iframe name="child2" src="blank.html"></iframe>
+<iframe name="child3" src="blank.html"></iframe>
+</div>
+<div id="active"></div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_triggeringprincipal_frame_nav.html b/docshell/test/navigation/test_triggeringprincipal_frame_nav.html
new file mode 100644
index 0000000000..f8f97c678a
--- /dev/null
+++ b/docshell/test/navigation/test_triggeringprincipal_frame_nav.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Bug 1181370 - Test triggeringPrincipal for iframe navigations</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe1"></iframe>
+<iframe style="width:100%;" id="testframe2"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ *
+ * +------------------------------------+
+ * | +----------+ +--------------+ |
+ * | | Frame 1 | | Frame 2 | |
+ * | +----------+ | | |
+ * | | +----------+ | |
+ * | | | Subframe | | |
+ * | | +----------+ | |
+ * | +--------------+ |
+ * +------------------------------------+
+ *
+ * Frame1: test1.mochi.test
+ * Frame2: test2.mochi.test
+ * Subframe: test2.mochi.test
+ *
+ * (*) Frame1 and Subframe set their document.domain to mochi.test
+ * (*) Frame1 navigates the Subframe
+ * (*) TriggeringPrincipal for the Subframe navigation should be
+ * ==> test1.mochi.test
+ * (*) LoadingPrincipal for the Subframe navigation should be
+ * ==> test2.mochi.test
+ */
+
+const BASEURL1 = "http://test1.mochi.test:8888/tests/docshell/test/navigation/";
+const BASEURL2 = "http://test2.mochi.test:8888/tests/docshell/test/navigation/";
+const TRIGGERINGPRINCIPALURI = BASEURL1 + "file_triggeringprincipal_frame_1.html";
+const LOADINGPRINCIPALURI = BASEURL2 + "file_triggeringprincipal_frame_2.html";
+
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event) {
+ is(event.data.triggeringPrincipalURI, TRIGGERINGPRINCIPALURI,
+ "TriggeringPrincipal should be the navigating iframe (Frame 1)");
+ is(event.data.loadingPrincipalURI, LOADINGPRINCIPALURI,
+ "LoadingPrincipal should be the enclosing iframe (Frame 2)");
+ is(event.data.referrerURI, TRIGGERINGPRINCIPALURI,
+ "Referrer and TriggeringPrincipal should be identical (Frame 1)");
+
+ window.removeEventListener("message", receiveMessage, false);
+ SimpleTest.finish();
+}
+
+var frame1 = document.getElementById("testframe1");
+frame1.src = BASEURL1 + "file_triggeringprincipal_frame_1.html";
+
+var frame2 = document.getElementById("testframe2");
+frame2.src = BASEURL2 + "file_triggeringprincipal_frame_2.html";
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html b/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html
new file mode 100644
index 0000000000..cd6a9c056f
--- /dev/null
+++ b/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+</head>
+<body>
+
+<iframe name="framea" id="framea" src="file_triggeringprincipal_iframe_iframe_window_open_frame_a.html"></iframe>
+<iframe name="frameb" id="frameb"></iframe>
+
+<script type="text/javascript">
+
+/* We load an iframe (Frame A) which then gets navigated by another iframe (Frame B)
+ * by calling window.open("http://", "Frame A") later in the test. We then verify the
+ * TriggeringPrincipal and LoadingPrincipal of the navigated iframe (Frame A).
+ *
+ * +---------------------------------------+
+ * | Parent |
+ * | |
+ * | +----------------------------+ |
+ * | | Frame A | |
+ * | | | |
+ * | | | |
+ * | +----------------------------+ |
+ * | |
+ * | +----------------------------+ |
+ * | | Frame B | |
+ * | | | |
+ * | | win.open("http://", "A") | |
+ * | +----------------------------+ |
+ * | |
+ * +---------------------------------------+
+ *
+ * Sequence of the test:
+ * [1] load Frame A
+ * [2] load Frame B which navigates A
+ * [3] load navigated Frame A and check triggeringPrincipal and loadingPrincipal
+ */
+
+const TRIGGERING_PRINCIPAL_URI =
+ "http://mochi.test:8888/tests/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_b.html";
+
+const LOADING_PRINCIPAL_URI =
+ "http://mochi.test:8888/tests/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html";
+
+var frameA = document.getElementById("framea");
+
+function checkResults() {
+ frameA.removeEventListener('load', checkResults, false);
+
+ var channel = SpecialPowers.wrap(frameA.contentDocument).docShell.currentDocumentChannel;
+ var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
+ var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
+
+ is(triggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
+ "TriggeringPrincipal for targeted window.open() should be the iframe triggering the load");
+
+ is(frameA.contentDocument.referrer, TRIGGERING_PRINCIPAL_URI,
+ "Referrer for targeted window.open() should be the principal of the iframe triggering the load");
+
+ is(loadingPrincipal, LOADING_PRINCIPAL_URI,
+ "LoadingPrincipal for targeted window.open() should be the containing document");
+
+ SimpleTest.finish();
+}
+
+function performNavigation() {
+ frameA.removeEventListener('load', performNavigation, false);
+ frameA.addEventListener('load', checkResults, false);
+
+ // load Frame B which then navigates Frame A
+ var frameB = document.getElementById("frameb");
+ frameB.src = "file_triggeringprincipal_iframe_iframe_window_open_frame_b.html";
+}
+
+// start the test
+SimpleTest.waitForExplicitFinish();
+
+frameA.addEventListener('load', performNavigation, false);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html b/docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html
new file mode 100644
index 0000000000..7cc6ee97d9
--- /dev/null
+++ b/docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+</head>
+<body>
+
+<iframe name="testframe" id="testframe" src="file_triggeringprincipal_iframe_iframe_window_open_base.html"></iframe>
+
+<script type="text/javascript">
+
+/* We load an iframe which then gets navigated by the iframe's parent by calling
+ * window.open("http://", iframe) later in the test. We then verify the
+ * TriggeringPrincipal and LoadingPrincipal of the navigated iframe.
+ *
+ * +------------------------------------------+
+ * | |
+ * | +------------------+ |
+ * | | testframe | |
+ * | +------------------+ |
+ * | |
+ * | window.open("http://", "testframe"); |
+ * | |
+ * +------------------------------------------+
+ */
+
+const TRIGGERING_PRINCIPAL_URI =
+ "http://mochi.test:8888/tests/docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html";
+
+const LOADING_PRINCIPAL_URI = TRIGGERING_PRINCIPAL_URI;
+
+var testframe = document.getElementById("testframe");
+
+function checkResults() {
+ testframe.removeEventListener('load', checkResults, false);
+
+ var channel = SpecialPowers.wrap(testframe.contentDocument).docShell.currentDocumentChannel;
+ var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
+ var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
+
+ is(triggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
+ "TriggeringPrincipal for targeted window.open() should be the principal of the document");
+
+ is(testframe.contentDocument.referrer, TRIGGERING_PRINCIPAL_URI,
+ "Referrer for targeted window.open() should be the principal of the document");
+
+ is(loadingPrincipal, LOADING_PRINCIPAL_URI,
+ "LoadingPrincipal for targeted window.open() should be the <iframe>.ownerDocument");
+
+ SimpleTest.finish();
+}
+
+function performNavigation() {
+ testframe.removeEventListener('load', performNavigation, false);
+ testframe.addEventListener('load', checkResults, false);
+ win = window.open("file_triggeringprincipal_parent_iframe_window_open_nav.html", "testframe");
+}
+
+// start the test
+SimpleTest.waitForExplicitFinish();
+
+testframe.addEventListener('load', performNavigation, false);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/navigation/test_triggeringprincipal_window_open.html b/docshell/test/navigation/test_triggeringprincipal_window_open.html
new file mode 100644
index 0000000000..d5d7f210be
--- /dev/null
+++ b/docshell/test/navigation/test_triggeringprincipal_window_open.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <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" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+</head>
+<body>
+
+<script type="text/javascript">
+
+/* We call window.open() using different URIs and make sure the triggeringPrincipal
+ * loadingPrincipal are correct.
+ * Test1: window.open(http:)
+ * Test2: window.open(data:)
+ * Test3: window.open(javascript:)
+ */
+
+const TRIGGERING_PRINCIPAL_URI =
+ "http://mochi.test:8888/tests/docshell/test/navigation/test_triggeringprincipal_window_open.html";
+
+SimpleTest.waitForExplicitFinish();
+
+const NUM_TESTS = 3;
+var test_counter = 0;
+
+function checkFinish() {
+ test_counter++;
+ if (test_counter === NUM_TESTS) {
+ SimpleTest.finish();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Test 1: window.open(http:)
+var httpWin = window.open("file_triggeringprincipal_window_open.html", "_blank", "width=10,height=10");
+httpWin.onload = function() {
+ var httpChannel = SpecialPowers.wrap(httpWin.document).docShell.currentDocumentChannel;
+ var httpTriggeringPrincipal = httpChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
+ var httpLoadingPrincipal = httpChannel.loadInfo.loadingPrincipal;
+
+ is(httpTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
+ "TriggeringPrincipal for window.open(http:) should be the principal of the document");
+
+ is(httpWin.document.referrer, TRIGGERING_PRINCIPAL_URI,
+ "Referrer for window.open(http:) should be the principal of the document");
+
+ is(httpLoadingPrincipal, null,
+ "LoadingPrincipal for window.open(http:) should be null");
+
+ httpWin.close();
+ checkFinish();
+}
+
+// ----------------------------------------------------------------------------
+// Test 2: window.open(data:)
+var dataWin = window.open("data:text/html,<html><body>data</body></html>", "_blank", "width=10,height=10");
+dataWin.onload = function() {
+ var dataChannel = SpecialPowers.wrap(dataWin.document).docShell.currentDocumentChannel;
+ var dataTriggeringPrincipal = dataChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
+ var dataLoadingPrincipal = dataChannel.loadInfo.loadingPrincipal;
+
+ is(dataTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
+ "TriggeringPrincipal for window.open(data:) should be the principal of the document");
+
+ is(dataWin.document.referrer, "",
+ "Referrer for window.open(data:) should be empty");
+
+ is(dataLoadingPrincipal, null,
+ "LoadingPrincipal for window.open(data:) should be null");
+
+ dataWin.close();
+ checkFinish();
+}
+
+// ----------------------------------------------------------------------------
+// Test 3: window.open(javascript:)
+var jsWin = window.open("javascript:'<html><body>js</body></html>';", "_blank", "width=10,height=10");
+jsWin.onload = function() {
+ var jsChannel = SpecialPowers.wrap(jsWin.document).docShell.currentDocumentChannel;
+ var jsTriggeringPrincipal = jsChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
+ var jsLoadingPrincipal = jsChannel.loadInfo.loadingPrincipal;
+
+ is(jsTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
+ "TriggeringPrincipal for window.open(javascript:) should be the principal of the document");
+
+ is(jsWin.document.referrer, "",
+ "Referrer for window.open(javascript:) should be empty");
+
+ is(jsLoadingPrincipal, null,
+ "LoadingPrincipal for window.open(javascript:) should be null");
+
+ jsWin.close();
+ checkFinish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_anchor_scroll_after_document_open.html b/docshell/test/test_anchor_scroll_after_document_open.html
new file mode 100644
index 0000000000..93fa4615b4
--- /dev/null
+++ b/docshell/test/test_anchor_scroll_after_document_open.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=881487
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 881487</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 881487 **/
+ SimpleTest.waitForExplicitFinish();
+ // Child needs to invoke us, otherwise our onload will fire before the child
+ // has done the write/close bit.
+ var gotOnload = false;
+ addLoadEvent(function() {
+ gotOnload = true;
+ });
+ onmessage = function handleMessage(msg) {
+ if (msg.data == "doTest") {
+ if (!gotOnload) {
+ addLoadEvent(function() { handleMessage(msg); });
+ return;
+ }
+ frames[0].onscroll = function() {
+ ok(true, "Got a scroll event");
+ SimpleTest.finish();
+ }
+ frames[0].location.hash = "#target";
+ return;
+ }
+ if (msg.data == "haveHash") {
+ ok(false, "Child got reloaded");
+ } else {
+ ok(false, "Unexpected message");
+ }
+ SimpleTest.finish();
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=881487">Mozilla Bug 881487</a>
+<p id="display">
+ <!-- iframe goes here so it can scroll -->
+<iframe src="file_anchor_scroll_after_document_open.html"></iframe>
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bfcache_plus_hash.html b/docshell/test/test_bfcache_plus_hash.html
new file mode 100644
index 0000000000..30c0b6b502
--- /dev/null
+++ b/docshell/test/test_bfcache_plus_hash.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=646641
+-->
+<head>
+ <title>Test for Bug 646641</title>
+ <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"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=646641">Mozilla Bug 646641</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+
+/** Test for Bug 646641 **/
+
+/*
+ * In a popup (because navigating the main frame confuses Mochitest), do the
+ * following:
+ *
+ * * Call history.pushState().
+ * * Navigate to a new page.
+ * * Go back two history entries.
+ *
+ * Check that we go back, we retrieve the document from bfcache.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+function debug(msg) {
+ // Wrap dump so we can turn debug messages on and off easily.
+ dump(msg + '\n');
+}
+
+var expectedLoadNum = -1;
+function childLoad(n) {
+ if (n == expectedLoadNum) {
+ debug('Got load ' + n);
+ expectedLoadNum = -1;
+
+ // Spin the event loop before calling gGen.next() so the generator runs
+ // outside the onload handler. This prevents us from encountering all
+ // sorts of docshell quirks.
+ //
+ // (I don't know why I need to wrap gGen.next() in a function, but it
+ // throws an error otherwise.)
+ setTimeout(function() { gGen.next() }, 0);
+ }
+ else {
+ debug('Got unexpected load ' + n);
+ ok(false, 'Got unexpected load ' + n);
+ }
+}
+
+var expectedPageshowNum = -1;
+function childPageshow(n) {
+ if (n == expectedPageshowNum) {
+ debug('Got expected pageshow ' + n);
+ expectedPageshowNum = -1;
+ ok(true, 'Got expected pageshow ' + n);
+ setTimeout(function() { gGen.next() }, 0);
+ }
+ else {
+ debug('Got pageshow ' + n);
+ }
+
+ // Since a pageshow comes along with an onload, don't fail the test if we get
+ // an unexpected pageshow.
+}
+
+function waitForLoad(n) {
+ debug('Waiting for load ' + n);
+ expectedLoadNum = n;
+}
+
+function waitForShow(n) {
+ debug('Waiting for show ' + n);
+ expectedPageshowNum = n;
+}
+
+function test() {
+ var popup = window.open('data:text/html,' +
+ '<html><body onload="opener.childLoad(1)" ' +
+ 'onpageshow="opener.childPageshow(1)">' +
+ 'Popup 1' +
+ '</body></html>');
+ waitForLoad(1);
+ yield undefined;
+
+ popup.history.pushState('', '', '');
+
+ popup.location = 'data:text/html,<html><body onload="opener.childLoad(2)">Popup 2</body></html>';
+ waitForLoad(2);
+ yield undefined;
+
+ // Now go back 2. The first page should be retrieved from bfcache.
+ popup.history.go(-2);
+ waitForShow(1);
+ yield undefined;
+
+ popup.close();
+ SimpleTest.finish();
+
+ // Yield once more so we don't throw a StopIteration exception.
+ yield undefined;
+}
+
+var gGen = test();
+gGen.next();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug1045096.html b/docshell/test/test_bug1045096.html
new file mode 100644
index 0000000000..8a0b4a223d
--- /dev/null
+++ b/docshell/test/test_bug1045096.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1045096
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1045096</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=1045096">Mozilla Bug 1045096</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+ <script type="application/javascript">
+
+ /** Test for Bug 1045096 **/
+ var i = document.createElement('iframe');
+ i.src = "javascript:false"; // This is required!
+ $("content").appendChild(i);
+ ok(i.contentWindow.performance, "Should have a performance object");
+ </script>
+</body>
+</html>
diff --git a/docshell/test/test_bug1121701.html b/docshell/test/test_bug1121701.html
new file mode 100644
index 0000000000..8beb2d8d06
--- /dev/null
+++ b/docshell/test/test_bug1121701.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1121701
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1121701</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 1121701 **/
+
+ var testUrl1 = "data:text/html,<script>window.onpageshow = function(e) { opener.child1PageShow(e); } <" + "/script>";
+ var testUrl2 = "data:text/html,<script>window.onpageshow = function(e) { opener.child2PageShow(e); } <" + "/script>";
+ var testWin;
+
+ var page1LoadCount = 0;
+ function child1PageShow(e) {
+ ++page1LoadCount;
+ if (page1LoadCount == 1) {
+ SimpleTest.executeSoon(function() {
+ is(e.persisted, false, "Initial page load shouldn't be persisted.");
+ testWin.document.body.innerHTML = "modified";
+ testWin.onpagehide = function(e) {
+ testWin.onpagehide = null;
+ ok(e.persisted, "test page 1 should have been persisted");
+ is(testWin.document.body.innerHTML, "modified");
+ }
+ testWin.location.href = testUrl2;
+ });
+ } else if (page1LoadCount == 2) {
+ is(e.persisted, true, "Page load from bfcache should be persisted.");
+ is(testWin.document.body.innerHTML, "modified");
+ testWin.close();
+ SimpleTest.finish();
+ }
+ }
+
+ function child2PageShow(e) {
+ testWin.document.body.innerHTML = "<img>";
+ SimpleTest.executeSoon(function() {
+ testWin.onmessage = function() {
+ ok(true, "Got message");
+ testWin.document.body.firstChild.src = location.href;
+ }
+ testWin.onbeforeunload = function() {
+ testWin.postMessage("foo", "*");
+ }
+ testWin.history.back();
+ });
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ testWin = window.open(testUrl1);
+ });
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121701">Mozilla Bug 1121701</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug1186774.html b/docshell/test/test_bug1186774.html
new file mode 100644
index 0000000000..52ef5f62cb
--- /dev/null
+++ b/docshell/test/test_bug1186774.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1186774
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1186774</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 1186774 **/
+
+var child;
+
+function runTest() {
+ child = window.open("data:text/html,<div style='height: 9000px;'></div>", "", "width=100,height=100");
+ child.onload = function() {
+ setTimeout(function() {
+ child.scrollTo(0, 0);
+ child.history.pushState({}, "initial");
+ child.scrollTo(0, 3000);
+ child.history.pushState({}, "scrolled");
+ child.scrollTo(0, 6000);
+ child.history.back();
+ });
+ }
+
+ child.onpopstate = function() {
+ is(child.scrollY, 6000, "Shouldn't have scrolled before popstate");
+ child.close();
+ SimpleTest.finish();
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1186774">Mozilla Bug 1186774</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug123696.html b/docshell/test/test_bug123696.html
new file mode 100644
index 0000000000..11d14e8078
--- /dev/null
+++ b/docshell/test/test_bug123696.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=123696
+-->
+<head>
+ <title>Test for Bug 123696</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=123696">Mozilla Bug 123696</a>
+<p id="display">
+ <iframe src="bug123696-subframe.html"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 123696 **/
+SimpleTest.waitForExplicitFinish();
+
+function finishTest() {
+ is(window.frames[0].frames[0].document.documentElement.textContent,
+ "change2", "Reload should have reloaded correctly!");
+ SimpleTest.finish();
+}
+
+function doReload() {
+ window.frames[0].frameElement.onload = finishTest;
+ window.frames[0].location.reload();
+}
+
+addLoadEvent(function() {
+ window.frames[0].frames[0].frameElement.onload = doReload;
+ window.frames[0].frames[0].frameElement.src = "javascript:parent.change2()";
+});
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug369814.html b/docshell/test/test_bug369814.html
new file mode 100644
index 0000000000..8667710555
--- /dev/null
+++ b/docshell/test/test_bug369814.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=369814
+-->
+<head>
+ <title>Test for Bug 369814</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=384014">Mozilla Bug 369814</a>
+
+<p>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Tests for Bug 369814 **/
+
+SimpleTest.waitForExplicitFinish();
+
+// Because child scripts won't be able to run to tell us they're done,
+// we need to just wait for them. Wait this many event loop spins before
+// checking the results.
+const gLoadEventLoopCount = 100;
+
+var gCurrentTest;
+var gTargetWindow;
+var gNumPokes;
+var gTestFrame;
+
+/**
+ * Called by documents loaded from jar files to indicate that they can access
+ * this document.
+ */
+function poke(description) {
+ ok(false, gCurrentTest['name'] + ": got unexpected poke: " + description);
+ gNumPokes++;
+}
+
+function loadEvent(window, callback)
+{
+ var fn = function() {
+ window.removeEventListener("load", fn, false);
+ callback();
+ };
+ window.addEventListener("load", fn, false);
+}
+
+function loadTestTarget(callback)
+{
+ gTargetWindow = window.open("http://mochi.test:8888", "bug369814target");
+ loadEvent(gTargetWindow, callback);
+}
+
+function closeTestTarget()
+{
+ gTargetWindow.close();
+ gTargetWindow = null;
+}
+
+function loadErrorTest(test)
+{
+ // Give the frame a chance to fail at loading.
+ // How do detect failure to load? Error pages don't fire load
+ // events. But we can load another page before the error page and
+ // then use its unload handler to know when the error page is just
+ // about loaded; at that point a single trip through the event loop
+ // should do the trick.
+ loadEvent(gTestFrame, function() {
+ gTestFrame.src = test['url'];
+ });
+ gTestFrame.unloading = function() {
+ gTestFrame.unloading = null;
+ // Go out to the event loop once so that unload processing finishes and
+ // the new document is set up.
+ setTimeout(function() {
+ // XXX: There doesn't seem to be a reliable check for "got an error,"
+ // but reaching in to an error document will throw an exception
+ var errorPage;
+ try {
+ var item = gTestFrame.contentDocument.getElementById(gCurrentTest['data-iframe']);
+ errorPage = false;
+ } catch (e) {
+ errorPage = true;
+ }
+ ok(errorPage, gCurrentTest["name"] + ": should block a suspicious JAR load.");
+
+ finishTest();
+ }, 0);
+ }
+ var unloadDetector = "data:text/html,<script>window.onunload = function() { frameElement.unloading(); }</" + "script>";
+ gTestFrame.src = unloadDetector;
+}
+
+function iframeTest(test) {
+ gTestFrame.src = test['url'];
+ loadEvent(gTestFrame, function() {
+ finishTest();
+ });
+}
+
+
+function hitEventLoop(func, times) {
+ if (times > 0) {
+ SimpleTest.executeSoon(function() { hitEventLoop(func, times-1); });
+ } else {
+ SimpleTest.executeSoon(func);
+ }
+}
+
+function refreshTest(test) {
+ gTestFrame.src = test['url'];
+ loadEvent(gTestFrame, function() {
+ // Wait for the frame to try and refresh
+ // XXX: a "blocked redirect" signal would be needed to get rid of
+ // this timeout.
+ hitEventLoop(function() {
+ finishTest();
+ }, gLoadEventLoopCount);
+ });
+}
+
+function anchorTest(test) {
+ loadTestTarget(function() {
+ gTestFrame.src = test['url'];
+ loadEvent(gTestFrame, function() {
+ sendMouseEvent({type:'click'}, 'target', gTestFrame.contentWindow);
+ sendMouseEvent({type:'click'}, 'notarget', gTestFrame.contentWindow);
+
+ // Give the clicks a chance to load
+ hitEventLoop(function() {
+ closeTestTarget();
+ finishTest();
+ }, gLoadEventLoopCount);
+ });
+ });
+}
+
+var gTests = [
+ { "name" : "iframes.html loaded from non-jar type, pref disabled",
+ "url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/iframes.html",
+ "pref" : false,
+ "pokes" : { },
+ "func" : loadErrorTest,
+ },
+ { "name" : "refresh.html loaded from non-jar type, pref enabled",
+ "url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/refresh.html",
+ "pref" : true,
+ "pokes" : { },
+ "func" : refreshTest,
+ },
+ { "name" : "iframes.html loaded from non-jar type, pref enabled",
+ "url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/iframes.html",
+ "pref" : true,
+ "pokes" : { },
+ "func" : iframeTest,
+ },
+ { "name" : "anchors.html loaded from non-jar type, pref enabled",
+ "url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/anchors.html",
+ "pref" : true,
+ "pokes" : { },
+ "func" : anchorTest,
+ },
+];
+
+var gNextTest = 0;
+
+function runNextTest()
+{
+ if (gNextTest < gTests.length) {
+ gCurrentTest = gTests[gNextTest++];
+ gNumPokes = 0;
+
+ SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false],
+ ["network.jar.open-unsafe-types", gCurrentTest['pref']]]}, function() {
+
+ // Create a new frame each time, so our restictions on loads in a
+ // jar:-loaded iframe don't interfere with the test.
+ if (gTestFrame) {
+ document.body.removeChild(gTestFrame);
+ }
+ gTestFrame = document.createElement("iframe");
+ document.body.insertBefore(gTestFrame, $("test"));
+
+ gCurrentTest['func'](gCurrentTest);
+ });
+ } else {
+ SimpleTest.finish();
+ }
+}
+
+function finishTest()
+{
+ SpecialPowers.pushPrefEnv({"set": [["network.jar.open-unsafe-types", false]]}, function() {
+ if (gNumPokes == 0) {
+ ok(true, gCurrentTest["name"] + ": no unexpected pokes");
+ }
+
+ runNextTest();
+ });
+}
+
+addLoadEvent(runNextTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug384014.html b/docshell/test/test_bug384014.html
new file mode 100644
index 0000000000..1f115a6ec2
--- /dev/null
+++ b/docshell/test/test_bug384014.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=384014
+-->
+<head>
+ <title>Test for Bug 384014</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=384014">Mozilla Bug 384014</a>
+<p id="display">
+<iframe id="f" src="javascript:try { window.x = 'PASS'; s = 'PASS' } catch(e) { s = 'FAIL' } s;"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 384014 **/
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+ $("f").onload = function () {
+ is($("f").contentDocument.documentElement.textContent, "PASS",
+ "We fail");
+ SimpleTest.finish();
+ }
+
+ $("f").contentWindow.location.reload();
+}
+
+addLoadEvent(runTest);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/test_bug385434.html b/docshell/test/test_bug385434.html
new file mode 100644
index 0000000000..660f522e8a
--- /dev/null
+++ b/docshell/test/test_bug385434.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<head>
+ <title>Test for Bug 385434</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=385434">Mozilla Bug 385434</a>
+<p id="display"></p>
+<div id="content">
+ <iframe id="frame" style="height:100px; width:100px; border:0"></iframe>
+ <div id="status" style="display: none"></div>
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+
+/** Test for Bug 385434 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var gNumHashchanges = 0;
+var gCallbackOnIframeLoad = false;
+
+function statusMsg(msg) {
+ var msgElem = document.createElement("p");
+ msgElem.appendChild(document.createTextNode(msg));
+
+ document.getElementById("status").appendChild(msgElem);
+}
+
+function longWait() {
+ setTimeout(function() { gGen.next() }, 1000);
+}
+
+// onIframeHashchange, onIframeLoad, and onIframeScroll are all called by the
+// content we load into our iframe in order to notify the parent frame of an
+// event which was fired.
+function onIframeHashchange() {
+ gNumHashchanges++;
+ gGen.next();
+}
+
+function onIframeLoad() {
+ if (gCallbackOnIframeLoad) {
+ gCallbackOnIframeLoad = false;
+ gGen.next();
+ }
+}
+
+function onIframeScroll() {
+ is(gNumHashchanges, 0, "onscroll should fire before onhashchange.");
+}
+
+function enableIframeLoadCallback() {
+ gCallbackOnIframeLoad = true;
+}
+
+function noEventExpected(msg) {
+ is(gNumHashchanges, 0, msg);
+
+ // Even if there's an error, set gNumHashchanges to 0 so other tests don't
+ // fail.
+ gNumHashchanges = 0;
+}
+
+function eventExpected(msg) {
+ is(gNumHashchanges, 1, msg);
+
+ // Eat up this event, whether the test above was true or not
+ gNumHashchanges = 0;
+}
+
+/*
+ * The hashchange event is dispatched asynchronously, so if we want to observe
+ * it, we have to yield within run_test(), transferring control back to the
+ * event loop.
+ *
+ * When we're expecting our iframe to observe a hashchange event after we poke
+ * it, we just yield and wait for onIframeHashchange() to call gGen.next() and
+ * wake us up.
+ *
+ * When we're testing to ensure that the iframe doesn't dispatch a hashchange
+ * event, we try to hook onto the iframe's load event. We call
+ * enableIframeLoadCallback(), which causes onIframeLoad() to call gGen.next()
+ * upon the next observed load. After we get our callback, we check that a
+ * hashchange didn't occur.
+ *
+ * We can't always just wait for page load in order to observe that a
+ * hashchange didn't happen. In these cases, we call longWait() and yield
+ * until either a hashchange occurs or longWait's callback is scheduled. This
+ * is something of a hack; it's entirely possible that longWait won't wait long
+ * enough, and we won't observe what should have been a failure of the test.
+ * But it shouldn't happen that good code will randomly *fail* this test.
+ */
+function run_test() {
+ /*
+ * TEST 1 tests that:
+ * <body onhashchange = ... > works,
+ * the event is (not) fired at the correct times
+ */
+ var frame = document.getElementById("frame");
+ var frameCw = frame.contentWindow;
+
+ enableIframeLoadCallback();
+ frameCw.document.location = "file_bug385434_1.html";
+ // Wait for the iframe to load and for our callback to fire
+ yield undefined;
+
+ noEventExpected("No hashchange expected initially.");
+
+ sendMouseEvent({type: "click"}, "link1", frameCw);
+ yield undefined;
+ eventExpected("Clicking link1 should trigger a hashchange.");
+
+ sendMouseEvent({type: "click"}, "link1", frameCw);
+ longWait();
+ yield undefined;
+ // succeed if a hashchange event wasn't triggered while we were waiting
+ noEventExpected("Clicking link1 again should not trigger a hashchange.");
+
+ sendMouseEvent({type: "click"}, "link2", frameCw);
+ yield undefined;
+ eventExpected("Clicking link2 should trigger a hashchange.");
+
+ frameCw.history.go(-1);
+ yield undefined;
+ eventExpected("Going back should trigger a hashchange.");
+
+ frameCw.history.go(1);
+ yield undefined;
+ eventExpected("Going forward should trigger a hashchange.");
+
+ // window.location has a trailing '#' right now, so we append "link1", not
+ // "#link1".
+ frameCw.window.location = frameCw.window.location + "link1";
+ yield undefined;
+ eventExpected("Assigning to window.location should trigger a hashchange.");
+
+ // Set up history in the iframe which looks like:
+ // file_bug385434_1.html#link1
+ // file_bug385434_2.html
+ // file_bug385434_1.html#foo <-- current page
+ enableIframeLoadCallback();
+ frameCw.window.location = "file_bug385434_2.html";
+ yield undefined;
+
+ enableIframeLoadCallback();
+ frameCw.window.location = "file_bug385434_1.html#foo";
+ yield undefined;
+
+ // Now when we do history.go(-2) on the frame, it *shouldn't* fire a
+ // hashchange. Although the URIs differ only by their hashes, they belong to
+ // two different Documents.
+ frameCw.history.go(-2);
+ longWait();
+ yield undefined;
+ noEventExpected("Moving between different Documents shouldn't " +
+ "trigger a hashchange.");
+
+ /*
+ * TEST 2 tests that:
+ * <frameset onhashchange = ... > works,
+ * the event is targeted at the window object
+ * the event's cancelable, bubbles settings are correct
+ */
+ enableIframeLoadCallback();
+ frameCw.document.location = "file_bug385434_2.html";
+ yield undefined;
+
+ frameCw.document.location = "file_bug385434_2.html#foo";
+ yield undefined;
+
+ eventExpected("frame onhashchange should fire events.");
+ // iframe should set gSampleEvent
+ is(gSampleEvent.target, frameCw,
+ "The hashchange event should be targeted to the window.");
+ is(gSampleEvent.type, "hashchange",
+ "Event type should be 'hashchange'.");
+ is(gSampleEvent.cancelable, false,
+ "The hashchange event shouldn't be cancelable.");
+ is(gSampleEvent.bubbles, true,
+ "The hashchange event should bubble.");
+
+ /*
+ * TEST 3 tests that:
+ * hashchange is dispatched if the current document readyState is
+ * not "complete" (bug 504837).
+ */
+ frameCw.document.location = "file_bug385434_3.html";
+ yield undefined;
+ eventExpected("Hashchange should fire even if the document " +
+ "hasn't finished loading.");
+
+ SimpleTest.finish();
+ yield undefined;
+}
+
+var gGen = run_test();
+gGen.next();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug387979.html b/docshell/test/test_bug387979.html
new file mode 100644
index 0000000000..9e337e2c2c
--- /dev/null
+++ b/docshell/test/test_bug387979.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=387979
+-->
+<head>
+ <title>Test for Bug 387979</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=387979">Mozilla Bug 387979</a>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 387979 **/
+function a(s) {
+ var r;
+ try { r = frames[0].document.body; }
+ catch (e) { r = e; }
+ is(r instanceof frames[0].HTMLBodyElement, true,
+ "Can't get body" + s);
+}
+var p = 0;
+function b() {
+ switch (++p) {
+ case 1:
+ frames[0].location = "about:blank";
+ break;
+ case 2:
+ a("before reload");
+ frames[0].location.reload();
+ break;
+ case 3:
+ a("after reload");
+ SimpleTest.finish();
+ break;
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<p id="display">
+ <iframe onload="b()"></iframe>
+ <pre id="p">-</pre>
+</p>
+</body>
+</html>
+
diff --git a/docshell/test/test_bug402210.html b/docshell/test/test_bug402210.html
new file mode 100644
index 0000000000..78fa025e03
--- /dev/null
+++ b/docshell/test/test_bug402210.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+While working on bug 402210, it came up that the code was doing
+
+a.href = proto + host
+
+which technically produces "https:host" instead of "https://host" and
+that the code was relying on href's setting having fixup behaviour
+for this kind of thing.
+
+If we rely on it, we might as well test for it, even if it isn't the
+problem 402210 was meant to fix.
+
+https://bugzilla.mozilla.org/show_bug.cgi?id=402210
+-->
+<head>
+ <title>Test for Bug 402210</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=402210">Mozilla Bug 402210</a>
+<p id="display">
+ <a id="testlink">Test Link</a>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+ $("testlink").href = "https:example.com";
+ is($("testlink").href, "https://example.com/", "Setting href on an anchor tag should fixup missing slashes after https protocol");
+
+ $("testlink").href = "ftp:example.com";
+ is($("testlink").href, "ftp://example.com/", "Setting href on an anchor tag should fixup missing slashes after non-http protocol");
+
+ SimpleTest.finish();
+}
+
+addLoadEvent(runTest);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/test_bug404548.html b/docshell/test/test_bug404548.html
new file mode 100644
index 0000000000..edde15c9d4
--- /dev/null
+++ b/docshell/test/test_bug404548.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=404548
+-->
+<head>
+ <title>Test for Bug 404548</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=404548">Mozilla Bug 404548</a>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 404548 **/
+var firstRemoved = false;
+var secondHidden = false;
+
+SimpleTest.waitForExplicitFinish();
+
+var w = window.open("bug404548-subframe.html", "", "width=10,height=10");
+
+function finishTest() {
+ is(firstRemoved, true, "Should have removed iframe from the DOM")
+ is(secondHidden, true, "Should have fired pagehide on second kid");
+ w.close();
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/test_bug413310.html b/docshell/test/test_bug413310.html
new file mode 100644
index 0000000000..e030c99d8b
--- /dev/null
+++ b/docshell/test/test_bug413310.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=413310
+-->
+<head>
+ <title>Test for Bug 413310</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=413310">Mozilla Bug 413310</a>
+<p id="display">
+<script class="testbody" type="text/javascript">
+
+if (navigator.platform.startsWith("Mac")) {
+ SimpleTest.expectAssertions(0, 2);
+} else {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+/** Test for Bug 413310 **/
+
+// NOTE: If we ever make subframes do bfcache stuff, this test will need to be
+// modified accordingly! It assumes that subframes do NOT get bfcached.
+var onloadCount = 0;
+
+var step = -1; // One increment will come from the initial subframe onload.
+ // Note that this script should come before the subframe,
+ // so that doNextStep is defined when its onload handler fires.
+
+var textContent;
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(doNextStep);
+
+function doNextStep() {
+ ++step;
+ switch (step) {
+ case 1:
+ is(onloadCount, 1, "Loaded initial page");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-subframe.html"),
+ "Unexpected subframe location after initial load");
+ $("i").contentDocument.forms[0].submit();
+ break;
+ case 2:
+ is(onloadCount, 2, "Loaded POST result");
+
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-post.sjs"),
+ "Unexpected subframe location after POST load");
+
+ textContent = $("i").contentDocument.body.textContent;
+ isDeeply(textContent.match(/^POST /), ["POST "], "Not a POST?");
+
+ $("i").contentWindow.location.hash = "foo";
+ setTimeout(doNextStep, 0);
+ break;
+ case 3:
+ is(onloadCount, 2, "Anchor scroll should not fire onload");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-post.sjs#foo"),
+ "Unexpected subframe location after anchor scroll");
+ is(textContent, $("i").contentDocument.body.textContent,
+ "Did a load when scrolling?");
+ $("i").contentWindow.location.href = "bug413310-subframe.html";;
+ break;
+ case 4:
+ is(onloadCount, 3, "Done new load");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-subframe.html"),
+ "Unexpected subframe location after new load");
+ history.back();
+ break;
+ case 5:
+ is(onloadCount, 4,
+ "History traversal didn't fire onload: bfcache issues!");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-post.sjs#foo"),
+ "Unexpected subframe location");
+ is(textContent, $("i").contentDocument.body.textContent,
+ "Did a load when going back?");
+ SimpleTest.finish();
+ break;
+ }
+}
+</script>
+<!-- Use a timeout in onload so that we don't do a load immediately inside onload -->
+<iframe id="i" src="bug413310-subframe.html" onload="setTimeout(doNextStep, 20)">
+</iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/test_bug475636.html b/docshell/test/test_bug475636.html
new file mode 100644
index 0000000000..eaea3bcb81
--- /dev/null
+++ b/docshell/test/test_bug475636.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=475636
+Test that refresh to data: URIs don't inherit the principal
+-->
+<head>
+ <title>Test for Bug 475636</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="gen.next()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=475636">Mozilla Bug 475636</a>
+
+<div id="content" style="display: none">
+
+</div>
+<iframe id=loader></iframe>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+SimpleTest.waitForExplicitFinish();
+
+gen = runTests();
+
+window.private = 42;
+
+window.addEventListener("message", function(e) {
+ gen.send(e.data);
+}, false);
+
+var url = "file_bug475636.sjs?";
+
+function runTests() {
+ var loader = document.getElementById('loader');
+ for (var testNum = 1; ; ++testNum) {
+ loader.src = url + testNum;
+ let res = (yield);
+ if (res == "done") {
+ SimpleTest.finish();
+ yield undefined;
+ }
+ is(res, "pass");
+ }
+}
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug509055.html b/docshell/test/test_bug509055.html
new file mode 100644
index 0000000000..be163cafaa
--- /dev/null
+++ b/docshell/test/test_bug509055.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=509055
+-->
+<head>
+ <title>Test for Bug 509055</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=509055">Mozilla Bug 509055</a>
+<p id="display"></p>
+<div id="status"></div>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+
+/** Test for Bug 509055 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var gGen;
+
+function shortWait() {
+ setTimeout(function() { gGen.next(); }, 0, false);
+}
+
+function onChildHashchange(e) {
+ // gGen might be undefined when we refresh the page, so we have to check here
+ dump("onChildHashchange() called.\n");
+ if(gGen)
+ gGen.next();
+}
+
+function onChildLoad(e) {
+ if(gGen)
+ gGen.next();
+}
+
+function runTest() {
+ var popup = window.open("file_bug509055.html", "popup 0",
+ "height=200,width=200,location=yes," +
+ "menubar=yes,status=yes,toolbar=yes,dependent=yes");
+ popup.hashchangeCallback = onChildHashchange;
+ popup.onload = onChildLoad;
+ dump('Waiting for initial load.\n');
+ yield undefined;
+
+ // Without this wait, the change to location.hash below doesn't create a
+ // SHEntry or enable the back button.
+ shortWait();
+ dump('Got initial load. Spinning event loop.\n');
+ yield undefined;
+
+ popup.location.hash = "#1";
+ dump('Waiting for hashchange.\n');
+ yield undefined;
+
+ popup.history.back();
+ dump('Waiting for second hashchange.\n');
+ yield undefined; // wait for hashchange
+
+ popup.document.title = "Changed";
+
+ // Wait for listeners to be notified of the title change.
+ shortWait();
+ dump('Got second hashchange. Spinning event loop.\n');
+ yield undefined;
+
+ var sh = SpecialPowers.wrap(popup)
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .sessionHistory;
+
+ // Get the title of the inner popup's current SHEntry
+ var sheTitle = sh.getEntryAtIndex(sh.index, false).title;
+ is(sheTitle, "Changed", "SHEntry's title should change when we change.");
+
+ popup.close();
+
+ SimpleTest.executeSoon(SimpleTest.finish);
+ dump('Final yield.\n');
+ yield undefined;
+}
+
+window.addEventListener('load', function() {
+ gGen = runTest();
+ gGen.next();
+}, false);
+
+</script>
+
+</body>
+</html>
+
diff --git a/docshell/test/test_bug511449.html b/docshell/test/test_bug511449.html
new file mode 100644
index 0000000000..dcea4cf3db
--- /dev/null
+++ b/docshell/test/test_bug511449.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=511449
+-->
+<head>
+ <title>Test for Bug 511449</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/NativeKeyCodes.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=511449">Mozilla Bug 511449</a>
+<p id="display"></p>
+<div id="status"></div>
+<div id="content">
+</div>
+<input type="text" id="input">
+<pre id="test">
+<script type="application/javascript;version=1.7">
+
+/** Test for Bug 511449 **/
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+window.addEventListener('load', runTest, false);
+
+var win = null;
+
+function runTest() {
+ document.getElementById("input").focus();
+ win = window.open("file_bug511449.html", "");
+ SimpleTest.waitForFocus(runNextTest, win);
+}
+
+function runNextTest() {
+ var didClose = false;
+ win.onunload = function() {
+ didClose = true;
+ }
+ synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, MAC_VK_ANSI_W, {metaKey:1}, "w", "w");
+
+ setTimeout(function () {
+ ok(didClose, "Cmd+W should have closed the tab");
+ if (!didClose) {
+ win.close();
+ }
+ SimpleTest.finish();
+ }, 1000);
+}
+
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug529119-1.html b/docshell/test/test_bug529119-1.html
new file mode 100644
index 0000000000..573885dc0f
--- /dev/null
+++ b/docshell/test/test_bug529119-1.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var workingURL = "http://mochi.test:8888/tests/docshell/test/bug529119-window.html";
+var faultyURL = "http://some-nonexistent-domain-27489274c892748217cn2384.com/";
+
+var w = null;
+var phase = 0;
+var gotWrongPageOnTryAgainClick = false;
+
+function pollForPage(f, w)
+{
+ // Start with polling after a delay, we might mistakenly take the current page
+ // as an expected one.
+ window.setTimeout(function() {
+ var iterationsLeft = 200;
+ var int = window.setInterval(function() {
+ iterationsLeft--;
+
+ var haveErrorPage = false;
+ try {
+ var title = w.document.title;
+ }
+ catch (ex) {
+ haveErrorPage = true;
+ }
+
+ if (iterationsLeft == 0 || haveErrorPage) {
+ window.clearInterval(int);
+ f(iterationsLeft > 0);
+ }
+ }, 100);
+ }, 1000);
+}
+
+function windowLoaded()
+{
+ switch (phase)
+ {
+ case 0:
+ /* 2. We have succeededfully loaded a page, now go to a faulty URL */
+ window.setTimeout(function() {
+ w.location.href = faultyURL;
+ }, 0);
+
+ phase = 1;
+
+ pollForPage(function(succeeded) {
+ ok(succeeded, "Waiting for error page succeeded");
+
+ /* 3. now, while we are on the error page, try to reload it, actually
+ click the "Try Again" button */
+ SpecialPowers.wrap(w).location.reload();
+
+ pollForPage(function(succeeded) {
+ ok(succeeded, "Waiting for error page succeeded");
+
+ /* 4-finish, check we are still on the error page */
+ is(SpecialPowers.wrap(w).location.href, faultyURL, "Is on an error page");
+ isnot(SpecialPowers.wrap(w).location.href, workingURL, "Is not on the previous page");
+ is(gotWrongPageOnTryAgainClick, false,
+ "Must not get www.example.com page on reload of an error page");
+ w.close();
+ SimpleTest.finish();
+ }, w);
+ }, w);
+ break;
+
+ case 1:
+ /* 4-check, we must not get here! */
+ gotWrongPageOnTryAgainClick = true;
+ break;
+ }
+}
+
+function startTest()
+{
+ /* 1. load a URL that leads to an error page */
+ w = window.open(workingURL);
+}
+
+</script>
+</head>
+<body onload="startTest();">
+</body>
+</html>
diff --git a/docshell/test/test_bug529119-2.html b/docshell/test/test_bug529119-2.html
new file mode 100644
index 0000000000..fb3d191193
--- /dev/null
+++ b/docshell/test/test_bug529119-2.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var workingURL = "http://mochi.test:8888/tests/docshell/test/bug529119-window.html";
+var faultyURL = "http://some-nonexistent-domain-27489274c892748217cn2384.com/";
+
+var w = null;
+var phase = 0;
+var isWindowLoaded = false;
+
+function pollForPage(expectErrorPage, f, w)
+{
+ // Start with polling after a delay, we might mistakenly take the current page
+ // as an expected one.
+ window.setTimeout(function() {
+ var iterationsLeft = 200;
+ var int = window.setInterval(function() {
+ iterationsLeft--;
+
+ var haveErrorPage = false;
+ try {
+ var title = w.document.title;
+ }
+ catch (ex) {
+ haveErrorPage = true;
+ }
+
+ if (iterationsLeft == 0 || expectErrorPage == haveErrorPage) {
+ window.clearInterval(int);
+ f(iterationsLeft > 0);
+ }
+ }, 100);
+ }, 1000);
+}
+
+function windowLoaded()
+{
+ // The code under here should only be run once
+ // The test popup window workingURL was already opened
+ if (isWindowLoaded)
+ return;
+ isWindowLoaded = true;
+
+ /* 2. We have successfully loaded a page, now go to a faulty URL */
+ // XXX The test fails when we change the location synchronously
+ window.setTimeout(function() {
+ w.location.href = faultyURL;
+ }, 0);
+
+ pollForPage(true, function(succeeded) {
+ ok(succeeded, "Waiting for error page succeeded");
+ /* 3. now, while we are on the error page, navigate back */
+ try {
+ SpecialPowers.wrap(w).back();
+ }
+ catch(ex) {
+ ok(false, "w.back() threw " + ex);
+ }
+
+ pollForPage(false, function(succeeded) {
+ ok(succeeded, "Waiting for original page succeeded");
+ /* 4-finish, check we are back at the original page */
+ isnot(SpecialPowers.wrap(w).location.href, faultyURL, "Is on an error page");
+ is(SpecialPowers.wrap(w).location.href, workingURL, "Is not on the previous page");
+ w.close();
+ SimpleTest.finish();
+ }, w);
+ }, w);
+}
+
+function startTest()
+{
+ /* 1. load a URL that leads to an error page */
+ w = window.open(workingURL);
+}
+
+</script>
+</head>
+<body onload="startTest();">
+</body>
+</html>
diff --git a/docshell/test/test_bug530396.html b/docshell/test/test_bug530396.html
new file mode 100644
index 0000000000..f9fb79b4b7
--- /dev/null
+++ b/docshell/test/test_bug530396.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=530396
+-->
+<head>
+ <title>Test for Bug 530396</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>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=530396">Mozilla Bug 530396</a>
+
+<p>
+
+<iframe id="testFrame" src="http://mochi.test:8888/tests/docshell/test/bug530396-subframe.html"></iframe>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+// NOTE: If we ever make subframes do bfcache stuff, this test will need to be
+// modified accordingly! It assumes that subframes do NOT get bfcached.
+var onloadCount = 0;
+
+var step = 0;
+
+var gTestFrame = document.getElementById('testFrame');
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+addLoadEvent(doNextStep);
+
+function doNextStep() {
+ ++step;
+ switch (step) {
+ case 1:
+ is(onloadCount, 1, "Loaded initial page");
+ sendMouseEvent({type: "click"}, "target2", gTestFrame.contentWindow);
+ window.setTimeout(doNextStep, 1000);
+ break;
+
+ case 2:
+ is(onloadCount, 1, "opener must be null");
+ sendMouseEvent({type: "click"}, "target1", gTestFrame.contentWindow);
+ break;
+
+ case 3:
+ is(onloadCount, 2, "don't send referrer with rel=referrer");
+ SimpleTest.finish();
+ break;
+ }
+}
+</script>
+</pre>
+</html>
diff --git a/docshell/test/test_bug540462.html b/docshell/test/test_bug540462.html
new file mode 100644
index 0000000000..65447114f1
--- /dev/null
+++ b/docshell/test/test_bug540462.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=540462
+-->
+<head>
+ <title>Test for Bug 540462</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()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=540462">Mozilla Bug 540462</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 540462 **/
+
+var win;
+function runTest() {
+ win = window.open("file_bug540462.html", "", "width=100,height=100");
+}
+
+var dwlCount = 0;
+var originalURL;
+function documentWriteLoad() {
+ if (++dwlCount == 1) {
+ originalURL = win.document.body.firstChild.href;
+ } else if (dwlCount == 2) {
+ is(win.document.body.firstChild.href, originalURL, "Wrong href!");
+ win.close();
+ SimpleTest.finish();
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug551225.html b/docshell/test/test_bug551225.html
new file mode 100644
index 0000000000..00dc5e076b
--- /dev/null
+++ b/docshell/test/test_bug551225.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=551225
+-->
+<head>
+ <title>Test for Bug 551225</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=551225">Mozilla Bug 551225</a>
+
+<script type="application/javascript;version=1.7">
+
+/** Test for Bug 551225 **/
+
+obj = {
+ a: new Date('1/1/2000'),
+ b: /^foo$/,
+ c: 'bar'
+};
+
+history.replaceState(obj, '', '');
+is(history.state.a.toString(), new Date('1/1/2000').toString(), 'Date object.');
+is(history.state.b.toString(), '/^foo$/', 'Regex');
+is(history.state.c, 'bar', 'Other state');
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/test_bug570341.html b/docshell/test/test_bug570341.html
new file mode 100644
index 0000000000..d09afa4bd0
--- /dev/null
+++ b/docshell/test/test_bug570341.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=570341
+-->
+<head>
+ <title>Test for Bug 570341</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<script>
+ var start = Date.now();
+ var moments = {};
+
+ var unload = 0;
+ var wasEnabled = true;
+
+ function collectMoments() {
+ var win = frames[0];
+ var timing = (win.performance && win.performance.timing) || {};
+ for (var p in timing) {
+ moments[p] = timing[p];
+ }
+ for (var p in win) {
+ if (p.substring(0,9) == '_testing_') {
+ moments[p.substring(9)] = win[p];
+ }
+ }
+ moments['evt_unload'] = unload;
+ return moments;
+ }
+
+ function showSequence(node){
+ while(node.firstChild) {
+ node.removeChild(node.firstChild);
+ }
+ var sequence = [];
+ for (var p in moments) {
+ sequence.push(p);
+ }
+ sequence.sort(function(a, b){
+ return moments[a] - moments[b];
+ });
+ table = document.createElement('table');
+ node.appendChild(table);
+ row = document.createElement('tr');
+ table.appendChild(row);
+ cell = document.createElement('td');
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode('start'));
+ cell = document.createElement('td');
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode(start));
+ for (var i = 0; i < sequence.length; ++i) {
+ var prop = sequence[i];
+ row = document.createElement('tr');
+ table.appendChild(row);
+ cell = document.createElement('td');
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode(prop));
+ cell = document.createElement('td');
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode(moments[prop]));
+ }
+ }
+
+ function checkValues(){
+ var win = frames[0];
+ ok(win.performance,
+ 'window.performance is missing or not accessible for frame');
+ ok(!win.performance || win.performance.timing,
+ 'window.performance.timing is missing or not accessible for frame');
+ collectMoments();
+
+ var sequences = [
+ ['navigationStart', 'unloadEventStart', 'unloadEventEnd'],
+ ['navigationStart', 'fetchStart', 'domainLookupStart', 'domainLookupEnd',
+ 'connectStart', 'connectEnd', 'requestStart', 'responseStart', 'responseEnd'],
+ ['responseStart', 'domLoading', 'domInteractive', 'domComplete'],
+ ['domContentLoadedEventStart', 'domContentLoadedEventEnd',
+ 'loadEventStart', 'loadEventEnd']
+ ]
+
+ for (var i = 0; i < sequences.length; ++i) {
+ var seq = sequences[i];
+ for (var j = 0; j < seq.length; ++j) {
+ var prop = seq[j];
+ if (j > 0) {
+ var prevProp = seq[j-1];
+ ok(moments[prevProp] <= moments[prop],
+ ['Expected ', prevProp, ' to happen before ', prop,
+ ', got ', prevProp, ' = ', moments[prevProp],
+ ', ', prop, ' = ', moments[prop]].join(''));
+ }
+ }
+ }
+
+ SimpleTest.finish()
+ }
+
+window.onload = function() {
+ var win = frames[0];
+ win.addEventListener('unload', function(){
+ unload = Date.now();
+ }, true);
+ var seenLoad = 0;
+ win.addEventListener('load', function (){
+ seenLoad = Date.now();
+ }, true);
+ frames[0].location = 'bug570341_recordevents.html'
+ var interval = setInterval(function () {
+ // time constants here are arbitrary, chosen to allow the test to pass
+ var stopPolling = (win.performance && win.performance.loadEventEnd) ||
+ (seenLoad && Date.now() >= seenLoad + 3000) ||
+ Date.now() >= start + 30000;
+ if (stopPolling) {
+ clearInterval(interval);
+ checkValues();
+ } else if (win._testing_evt_load) {
+ seenLoad = Date.now();
+ }
+ }, 100);
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570341">Mozilla Bug 570341</a>
+<div id="frames">
+<iframe name="child0" src="navigation/blank.html"></iframe>
+</div>
+<button type="button" onclick="showSequence(document.getElementById('display'))">
+ Show Events</button>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug580069.html b/docshell/test/test_bug580069.html
new file mode 100644
index 0000000000..70d3b4a3e6
--- /dev/null
+++ b/docshell/test/test_bug580069.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=580069
+-->
+<head>
+ <title>Test for Bug 580069</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=580069">Mozilla Bug 580069</a>
+
+<iframe id='iframe' src='file_bug580069_1.html'></iframe>
+
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var iframe = document.getElementById('iframe');
+var iframeCw = iframe.contentWindow;
+
+// Called when file_bug580069_1.html loads.
+function page1Load() {
+ // This should cause us to load file 2.
+ dump('page1Load\n');
+ iframeCw.document.getElementById('form').submit();
+}
+
+// Called when file_bug580069_2.html loads.
+var page2Loads = 0;
+function page2Load(method) {
+
+ dump("iframe's location is: " + iframeCw.location + ", method is " + method + "\n");
+
+ if (page2Loads == 0) {
+ is(method, "POST", "Method for first load should be POST.");
+ iframeCw.history.replaceState('', '', '?replaced');
+
+ // This refresh shouldn't pop up the "are you sure you want to refresh a page
+ // with POST data?" dialog. If it does, this test will hang and fail, and
+ // we'll see 'Refreshing iframe...' at the end of the test log.
+ dump('Refreshing iframe...\n');
+ iframeCw.location.reload();
+ }
+ else if (page2Loads == 1) {
+ is(method, "GET", "Method for second load should be GET.");
+ is(iframeCw.location.search, "?replaced", "Wrong search on iframe after refresh.");
+ SimpleTest.finish();
+ }
+ else {
+ ok(false, "page2Load should only be called twice.");
+ }
+
+ page2Loads++;
+}
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug590573.html b/docshell/test/test_bug590573.html
new file mode 100644
index 0000000000..aa6d3bd79f
--- /dev/null
+++ b/docshell/test/test_bug590573.html
@@ -0,0 +1,232 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=590573
+-->
+<head>
+ <title>Test for Bug 590573</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=590573">Mozilla Bug 590573</a>
+
+<script type='application/javascript;version=1.7'>
+SimpleTest.waitForExplicitFinish();
+
+// Listen to the first callback, since this indicates that the page loaded.
+var page1LoadCallbackEnabled = true;
+function page1Load()
+{
+ if (page1LoadCallbackEnabled) {
+ page1LoadCallbackEnabled = false;
+ dump('Got page1 load.\n');
+ pageLoad();
+ }
+ else {
+ dump('Ignoring page1 load.\n');
+ }
+}
+
+var page1PopstateCallbackEnabled = false;
+function page1Popstate()
+{
+ if (page1PopstateCallbackEnabled) {
+ page1PopstateCallbackEnabled = false;
+ dump('Got page1 popstate.\n');
+ pageLoad();
+ }
+ else {
+ dump('Ignoring page1 popstate.\n');
+ }
+}
+
+var page1PageShowCallbackEnabled = false;
+function page1PageShow()
+{
+ if (page1PageShowCallbackEnabled) {
+ page1PageShowCallbackEnabled = false;
+ dump('Got page1 pageshow.\n');
+ pageLoad();
+ }
+ else {
+ dump('Ignoring page1 pageshow.\n');
+ }
+}
+
+var page2LoadCallbackEnabled = false;
+function page2Load()
+{
+ if (page2LoadCallbackEnabled) {
+ page2LoadCallbackEnabled = false;
+ dump('Got page2 popstate.\n');
+ pageLoad();
+ }
+ else {
+ dump('Ignoring page2 popstate.\n');
+ }
+}
+
+var page2PopstateCallbackEnabled = false;
+function page2Popstate()
+{
+ if (page2PopstateCallbackEnabled) {
+ page2PopstateCallbackEnabled = false;
+ dump('Got page2 popstate.\n');
+ pageLoad();
+ }
+ else {
+ dump('Ignoring page2 popstate.\n');
+ }
+}
+
+var page2PageShowCallbackEnabled = false;
+function page2PageShow()
+{
+ if (page2PageShowCallbackEnabled) {
+ page2PageShowCallbackEnabled = false;
+ dump('Got page2 pageshow.\n');
+ pageLoad();
+ }
+ else {
+ dump('Ignoring page2 pageshow.\n');
+ }
+}
+
+function dumpSHistory(theWindow)
+{
+ let sh = SpecialPowers.wrap(theWindow).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .sessionHistory;
+ if (!sh) {
+ dump(" window has no shistory.\n");
+ return;
+ }
+
+ dump(" count: " + sh.count + "\n");
+ dump(" index: " + sh.index + "\n");
+ dump(" requestedIndex: " + sh.requestedIndex + "\n");
+
+ for (let i = 0; i < sh.count; i++) {
+ let shentry = sh.getEntryAtIndex(i, false);
+ dump(" " + i + ": " + shentry.URI.spec + '\n');
+ shentry.QueryInterface(SpecialPowers.Ci.nsISHContainer);
+ for (let j = 0; j < shentry.childCount; j++) {
+ let child = shentry.GetChildAt(j);
+ dump(" child " + j + ": " + child.URI.spec + '\n');
+ }
+ }
+
+ return sh;
+}
+
+var popup = window.open('file_bug590573_1.html');
+
+var gTestContinuation = null;
+var loads = 0;
+function pageLoad()
+{
+ loads++;
+ dump('pageLoad(loads=' + loads + ', page location=' + popup.location + ')\n');
+
+ dumpSHistory(window);
+
+ if (!gTestContinuation) {
+ gTestContinuation = testBody();
+ }
+ var ret = gTestContinuation.next();
+ if (ret.done) {
+ SimpleTest.finish();
+ }
+}
+
+function* testBody()
+{
+ is(popup.scrollY, 0, "test 1");
+ popup.scroll(0, 100);
+
+ popup.history.pushState('', '', '?pushed');
+ is(popup.scrollY, 100, "test 2");
+ popup.scroll(0, 200); // set state-2's position to 200
+
+ popup.history.back();
+ is(popup.scrollY, 100, "test 3");
+ popup.scroll(0, 150); // set original page's position to 150
+
+ popup.history.forward();
+ is(popup.scrollY, 200, "test 4");
+
+ popup.history.back();
+ is(popup.scrollY, 150, "test 5");
+
+ popup.history.forward();
+ is(popup.scrollY, 200, "test 6");
+
+ // At this point, the history looks like:
+ // PATH POSITION
+ // file_bug590573_1.html 150 <-- oldest
+ // file_bug590573_1.html?pushed 200 <-- newest, current
+
+ // Now test that the scroll position is persisted when we have real
+ // navigations involved. First, we need to spin the event loop so that the
+ // navigation doesn't replace our current history entry.
+
+ setTimeout(pageLoad, 0);
+ yield;
+
+ page2LoadCallbackEnabled = true;
+ popup.location = 'file_bug590573_2.html';
+ yield;
+
+ ok(popup.location.href.match('file_bug590573_2.html$'),
+ "Location was " + popup.location +
+ " but should end with file_bug590573_2.html");
+
+ is(popup.scrollY, 0, "test 7");
+ popup.scroll(0, 300);
+
+ // We need to spin the event loop again before we go back, otherwise the
+ // scroll positions don't get updated properly.
+ setTimeout(pageLoad, 0);
+ yield;
+
+ page1PageShowCallbackEnabled = true;
+ popup.history.back();
+ yield;
+
+ // Spin the event loop again so that we get the right scroll positions.
+ setTimeout(pageLoad, 0);
+ yield;
+
+ is(popup.location.search, "?pushed");
+ ok(popup.document.getElementById('div1'), 'page should have div1.');
+
+ is(popup.scrollY, 200, "test 8");
+
+ popup.history.back();
+ is(popup.scrollY, 150, "test 9");
+ popup.history.forward();
+
+ is(popup.scrollY, 200, "test 10");
+
+ // Spin one last time...
+ setTimeout(pageLoad, 0);
+ yield;
+
+ page2PageShowCallbackEnabled = true;
+ popup.history.forward();
+ yield;
+
+ // Bug 821821, on Android tegras we get 299 instead of 300 sometimes
+ if (popup.scrollY >= 299 && popup.scrollY <= 300) {
+ is(1, 1, "test 11");
+ } else {
+ is(1, 0, "test 11, got " + popup.scrollY + " for popup.scrollY instead of 299|300");
+ }
+ popup.close();
+}
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug598895.html b/docshell/test/test_bug598895.html
new file mode 100644
index 0000000000..52b9537be0
--- /dev/null
+++ b/docshell/test/test_bug598895.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=598895
+-->
+<head>
+ <title>Test for Bug 598895</title>
+ <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"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=598895">Mozilla Bug 598895</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 598895 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+var win1 = window.open();
+win1.document.body.textContent = "Should show";
+
+var windowsLoaded = 0;
+
+window.onmessage = function (ev) {
+ is(ev.data, "loaded", "Message should be 'loaded'");
+ if (++windowsLoaded == 2) {
+ var one = snapshotWindow(win1);
+ var two = snapshotWindow(win2);
+ var three = snapshotWindow(win3);
+ win1.close();
+ win2.close();
+ win3.close();
+ ok(compareSnapshots(one, two, true)[0], "Popups should look identical");
+ ok(compareSnapshots(one, three, false)[0], "Popups should not look identical");
+
+ SimpleTest.finish();
+ }
+}
+
+var win2 = window.open("data:text/html,<script>window.onload = function() { opener.postMessage('loaded', '*'); }</" + "script><body>Should show</body>");
+
+var win3 = window.open("data:text/html,<script>window.onload = function() { opener.postMessage('loaded', '*'); }</" + "script><body></body>");
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug634834.html b/docshell/test/test_bug634834.html
new file mode 100644
index 0000000000..88f068518f
--- /dev/null
+++ b/docshell/test/test_bug634834.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=634834
+-->
+<head>
+ <title>Test for Bug 634834</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=634834">Mozilla Bug 634834</a>
+
+<script type='application/javascript;version=1.7'>
+SimpleTest.waitForExplicitFinish();
+
+function iframe_loaded() {
+ var loadedAfterPushstate = false;
+ $('iframe').onload = function() {
+ loadedAfterPushstate = true;
+ }
+
+ var obj = { name: 'name' };
+ obj.__defineGetter__('a', function() {
+ $('iframe').contentWindow.location = 'http://example.com';
+
+ // Wait until we've loaded example.com.
+ do {
+ var r = new XMLHttpRequest();
+ r.open("GET", location.href, false);
+ r.overrideMimeType("text/plain");
+ try { r.send(null); }
+ catch (e) {}
+ } while (!loadedAfterPushstate);
+ });
+
+ try {
+ $('iframe').contentWindow.history.pushState(obj, '');
+ ok(false, 'pushState should throw exception.');
+ }
+ catch(e) {
+ ok(true, 'pushState threw an exception.');
+ }
+ SimpleTest.finish();
+}
+
+</script>
+
+<iframe id='iframe' src='file_bug634834.html' onload='iframe_loaded()'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug637644.html b/docshell/test/test_bug637644.html
new file mode 100644
index 0000000000..d172ada4a1
--- /dev/null
+++ b/docshell/test/test_bug637644.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=637644
+-->
+<head>
+ <title>Test for Bug 637644</title>
+ <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"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=637644">Mozilla Bug 637644</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 637644 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+var win1 = window.open("", "", "height=500,width=500");
+win1.document.body.textContent = "Should show";
+
+var windowsLoaded = 0;
+
+window.onmessage = function (ev) {
+ is(ev.data, "loaded", "Message should be 'loaded'");
+ if (++windowsLoaded == 2) {
+ var one = snapshotWindow(win1);
+ var two = snapshotWindow(win2);
+ var three = snapshotWindow(win3);
+ win1.close();
+ win2.close();
+ win3.close();
+ ok(compareSnapshots(one, two, true)[0], "Popups should look identical");
+ ok(compareSnapshots(one, three, false)[0], "Popups should not look identical");
+
+ SimpleTest.finish();
+ }
+}
+
+var win2 = window.open("data:text/html,<script>window.onload = function() { opener.postMessage('loaded', '*'); }</" + "script><body>Should show</body>", "", "height=500,width=500");
+
+var win3 = window.open("data:text/html,<script>window.onload = function() { opener.postMessage('loaded', '*'); }</" + "script><body></body>", "", "height=500,width=500");
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug640387_1.html b/docshell/test/test_bug640387_1.html
new file mode 100644
index 0000000000..e324787d49
--- /dev/null
+++ b/docshell/test/test_bug640387_1.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=640387
+-->
+<head>
+ <title>Test for Bug 640387</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=640387">Mozilla Bug 640387</a>
+
+<script type='application/javascript;version=1.7'>
+SimpleTest.waitForExplicitFinish();
+
+function test() {
+ /* Spin the event loop so we get out of the onload handler. */
+ SimpleTest.executeSoon(function() { gGen.next() });
+ yield undefined;
+
+ popup.history.pushState('', '', '#hash1');
+ popup.history.pushState('', '', '#hash2');
+
+ // Now the history looks like:
+ // file_bug640387.html
+ // file_bug640387.html#hash1
+ // file_bug640387.html#hash2 <-- current
+
+ // Going back should trigger a hashchange, which will wake us up from the
+ // yield.
+ popup.history.back();
+ yield undefined;
+ ok(true, 'Got first hashchange.');
+
+ // Going back should wake us up again.
+ popup.history.back();
+ yield undefined;
+ ok(true, 'Got second hashchange.');
+
+ // Now the history looks like:
+ // file_bug640387.html <-- current
+ // file_bug640387.html#hash1
+ // file_bug640387.html#hash2
+
+ // Going forward should trigger a hashchange.
+ popup.history.forward();
+ yield undefined;
+ ok(true, 'Got third hashchange.');
+
+ // Now modify the history so it looks like:
+ // file_bug640387.html
+ // file_bug640387.html#hash1
+ // file_bug640387.html#hash1 <-- current
+ popup.history.pushState('', '', '#hash1');
+
+ // Now when we go back, we should not get a hashchange. Instead, wait for a
+ // popstate. We need to asynchronously go back because popstate is fired
+ // sync.
+ gHashchangeExpected = false;
+ gCallbackOnPopstate = true;
+ SimpleTest.executeSoon(function() { popup.history.back() });
+ yield undefined;
+ ok(true, 'Got popstate.');
+ gCallbackOnPopstate = false;
+
+ // Spin the event loop so hashchange has a chance to fire, if it's going to.
+ SimpleTest.executeSoon(function() { gGen.next() });
+ yield undefined;
+
+ popup.close();
+ SimpleTest.finish();
+ yield undefined;
+}
+
+gGen = null;
+function childLoad() {
+ gGen = test();
+ gGen.next();
+}
+
+gHashchangeExpected = true;
+function childHashchange() {
+ if (gHashchangeExpected) {
+ gGen.next();
+ }
+ else {
+ ok(false, "Got hashchange when we weren't expecting one.");
+ }
+}
+
+gCallbackOnPopstate = false;
+function childPopstate() {
+ if (gCallbackOnPopstate) {
+ gGen.next();
+ }
+}
+
+/* We need to run this test in a popup, because navigating an iframe
+ * back/forwards tends to cause intermittent orange. */
+popup = window.open('file_bug640387.html');
+
+/* Control now flows up to childLoad(), called once the popup loads. */
+
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug640387_2.html b/docshell/test/test_bug640387_2.html
new file mode 100644
index 0000000000..00c27fdda4
--- /dev/null
+++ b/docshell/test/test_bug640387_2.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=640387
+-->
+<head>
+ <title>Test for Bug 640387</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=640387">Mozilla Bug 640387</a>
+
+<!-- Test that, when going from
+
+ http://example.com/#foo
+
+to
+
+ http://example.com/
+
+via a non-history load, we do a true load, rather than a scroll. -->
+
+<script type='application/javascript;version=1.7'>
+SimpleTest.waitForExplicitFinish();
+
+callbackOnLoad = false;
+function childLoad() {
+ if (callbackOnLoad) {
+ callbackOnLoad = false;
+ gGen.next();
+ }
+}
+
+errorOnHashchange = false;
+callbackOnHashchange = false;
+function childHashchange() {
+ if (errorOnHashchange) {
+ ok(false, 'Got unexpected hashchange.');
+ }
+ if (callbackOnHashchange) {
+ callbackOnHashchange = false;
+ gGen.next();
+ }
+}
+
+function run_test() {
+ var iframe = $('iframe').contentWindow;
+
+ ok(true, 'Got first load');
+
+ // Spin the event loop so we exit the onload handler.
+ SimpleTest.executeSoon(function() { gGen.next() });
+ yield undefined;
+
+ let origLocation = iframe.location + '';
+ callbackOnHashchange = true;
+ iframe.location.hash = '#1';
+ // Wait for a hashchange event.
+ yield undefined;
+
+ ok(true, 'Got hashchange.');
+
+ iframe.location = origLocation;
+ // This should produce a load event and *not* a hashchange, because the
+ // result of the load is a different document than we had previously.
+ callbackOnLoad = true;
+ errorOnHashchange = true;
+ yield undefined;
+
+ ok(true, 'Got final load.');
+
+ // Spin the event loop to give hashchange a chance to fire, if it's going to.
+ SimpleTest.executeSoon(function() { gGen.next() });
+ yield undefined;
+
+ SimpleTest.finish();
+ yield undefined;
+}
+
+callbackOnLoad = true;
+gGen = run_test();
+
+</script>
+
+<iframe id='iframe' src='file_bug640387.html'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug653741.html b/docshell/test/test_bug653741.html
new file mode 100644
index 0000000000..f4d4587b8c
--- /dev/null
+++ b/docshell/test/test_bug653741.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=653741
+-->
+<head>
+ <title>Test for Bug 653741</title>
+ <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"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=653741">Mozilla Bug 653741</a>
+
+<script type="application/javascript;version=1.7">
+
+/** Test for Bug 653741 **/
+SimpleTest.waitForExplicitFinish();
+
+function childLoad() {
+ // Spin the event loop so we leave the onload handler.
+ SimpleTest.executeSoon(childLoad2);
+}
+
+function childLoad2() {
+ let cw = $('iframe').contentWindow;
+
+ // Save the Y offset. For sanity's sake, make sure it's not 0, because we
+ // should be at the bottom of the page!
+ let origYOffset = cw.pageYOffset;
+ ok(origYOffset != 0, 'Original Y offset is not 0.');
+
+ // Scroll the iframe to the top, then navigate to #bottom again.
+ cw.scrollTo(0, 0);
+
+ // Our current location is #bottom, so this should scroll us down to the
+ // bottom again.
+ cw.location = cw.location + '';
+
+ is(cw.pageYOffset, origYOffset, 'Correct offset after reloading page.');
+ SimpleTest.finish();
+}
+
+</script>
+
+<iframe height='100px' id='iframe' src='file_bug653741.html#bottom'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug660404.html b/docshell/test/test_bug660404.html
new file mode 100644
index 0000000000..df45793a9d
--- /dev/null
+++ b/docshell/test/test_bug660404.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660404
+-->
+<head>
+ <title>Test for Bug 660404</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=660404">Mozilla Bug 660404</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 660404 **/
+SimpleTest.waitForExplicitFinish();
+
+var w;
+
+function continueTest() {
+ // Do this async so the load event can finish firing
+ SimpleTest.executeSoon(function() {
+ w.onpagehide = function(ev) {
+ is(ev.persisted, true, "Should be bfcached when navigating to multipart");
+ }
+ w.location.href = "file_bug660404";
+ });
+}
+
+function finishTest() {
+ is(w.document.documentElement.textContent, "opener.finishTest();");
+ is(w.document.documentElement.innerHTML, "<head><script>opener.finishTest();</"+"script></head>");
+ w.close();
+ SimpleTest.finish();
+}
+
+// Have to open a new window, since there's no bfcache in subframes
+w = window.open("data:text/html,<script>window.onload = function() { opener.continueTest(); }</"+"script>");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug662170.html b/docshell/test/test_bug662170.html
new file mode 100644
index 0000000000..514bb55b16
--- /dev/null
+++ b/docshell/test/test_bug662170.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=662170
+-->
+<head>
+ <title>Test for Bug 662170</title>
+ <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"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=662170">Mozilla Bug 662170</a>
+
+<script type="application/javascript;version=1.7">
+
+/** Test for Bug 662170 **/
+SimpleTest.waitForExplicitFinish();
+
+function childLoad() {
+ // Spin the event loop so we leave the onload handler.
+ SimpleTest.executeSoon(childLoad2);
+}
+
+function childLoad2() {
+ let cw = $('iframe').contentWindow;
+
+ // When we initially load the page, we should be at the top.
+ is(cw.pageYOffset, 0, 'Initial Y offset should be 0.');
+
+ // Scroll the iframe to the bottom.
+ cw.scrollTo(0, 300);
+
+ // Did we actually scroll somewhere?
+ isnot(cw.pageYOffset, 0, 'Y offset should be non-zero after scrolling.');
+
+ // Now load file_bug662170.html#, which should take us to the top of the
+ // page.
+ cw.location = cw.location + '#';
+
+ is(cw.pageYOffset, 0, 'Correct Y offset after loading #.');
+ SimpleTest.finish();
+}
+
+</script>
+
+<!-- When the iframe loads, it calls childLoad(). -->
+<iframe height='100px' id='iframe' src='file_bug662170.html'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/test_bug668513.html b/docshell/test/test_bug668513.html
new file mode 100644
index 0000000000..78df4b1352
--- /dev/null
+++ b/docshell/test/test_bug668513.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=668513
+-->
+<head>
+ <title>Test for Bug 668513</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=668513">Mozilla Bug 668513</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+if (navigator.platform.startsWith("Linux")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+SimpleTest.waitForExplicitFinish();
+window.open("file_bug668513.html");
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug669671.html b/docshell/test/test_bug669671.html
new file mode 100644
index 0000000000..6070ecc82e
--- /dev/null
+++ b/docshell/test/test_bug669671.html
@@ -0,0 +1,146 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=669671
+-->
+<head>
+ <title>Test for Bug 669671</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=669671">Mozilla Bug 669671</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+
+/**
+ * Test for Bug 669671.
+ *
+ * This is a bit complicated. We have a script, file_bug669671.sjs, which counts
+ * how many times it's loaded and returns that count in the body of an HTML
+ * document. For brevity, call this page X.
+ *
+ * X is sent with Cache-Control: max-age=0 and can't be bfcached (it has an
+ * onunload handler). Our test does the following in a popup:
+ *
+ * 1) Load X?pushed, to prime the cache.
+ * 2) Navigate to X.
+ * 3) Call pushState and navigate from X to X?pushed.
+ * 4) Navigate to X?navigated.
+ * 5) Go back (to X?pushed).
+ *
+ * We do all this work so we can check that in step 5, we fetch X?pushed from
+ * the network -- we shouldn't use our cached copy, because of the
+ * cache-control header X sends.
+ *
+ * Then we go back and repeat the whole process but call history.replaceState
+ * instead of pushState. And for good measure, we test once more, this time
+ * modifying only the hash of the URI using replaceState. In this case, we
+ * *should* load from the cache.
+ *
+ **/
+SimpleTest.requestLongerTimeout(2);
+SimpleTest.waitForExplicitFinish();
+
+function onChildLoad()
+{
+ SimpleTest.executeSoon(function() { gGen.next() });
+}
+
+var _loadCount = 0;
+function checkPopupLoadCount()
+{
+ is(popup.document.body.innerHTML, _loadCount + '', 'Load count');
+
+ // We normally want to increment _loadCount here. But if the test fails
+ // because we didn't do a load we should have, let's not cause a cascade of
+ // failures by incrementing _loadCount.
+ var origCount = _loadCount;
+ if (popup.document.body.innerHTML >= _loadCount + '')
+ _loadCount++;
+ return origCount;
+}
+
+function test()
+{
+ // Step 0 - Make sure the count is reset to 0 in case of reload
+ popup.location = 'file_bug669671.sjs?countreset';
+ yield;
+ is(popup.document.body.innerHTML, '0',
+ 'Load count should be reset to 0');
+
+ // Step 1 - The popup's body counts how many times we've requested the
+ // resource. This is the first time we've requested it, so it should be '0'.
+ checkPopupLoadCount();
+
+ // Step 2 - We'll get another onChildLoad when this finishes.
+ popup.location = 'file_bug669671.sjs';
+ yield undefined;
+
+ // Step 3 - Call pushState and change the URI back to ?pushed.
+ checkPopupLoadCount();
+ popup.history.pushState('', '', '?pushed');
+
+ // Step 4 - Navigate away. This should trigger another onChildLoad.
+ popup.location = 'file_bug669671.sjs?navigated-1';
+ yield undefined;
+
+ // Step 5 - Go back. This should result in another onload (because the file is
+ // not in bfcache) and should be the fourth time we've requested the sjs file.
+ checkPopupLoadCount();
+ SpecialPowers.wrap(popup).back();
+ yield undefined;
+
+ // This is the check which was failing before we fixed the bug.
+ checkPopupLoadCount();
+
+ popup.close();
+
+ // Do the whole thing again, but with replaceState.
+ popup = window.open('file_bug669671.sjs?replaced');
+ yield undefined;
+ checkPopupLoadCount();
+ popup.location = 'file_bug669671.sjs';
+ yield undefined;
+ checkPopupLoadCount();
+ popup.history.replaceState('', '', '?replaced');
+ popup.location = 'file_bug669671.sjs?navigated-2';
+ yield undefined;
+ checkPopupLoadCount();
+ SpecialPowers.wrap(popup).back();
+ yield undefined;
+ checkPopupLoadCount();
+ popup.close();
+
+ // Once more, with feeling. Notice that we don't have to prime the cache
+ // with an extra load here, because X and X#hash share the same cache entry.
+ popup = window.open('file_bug669671.sjs?hash-test');
+ yield undefined;
+ var initialCount = checkPopupLoadCount();
+ popup.history.replaceState('', '', '#hash');
+ popup.location = 'file_bug669671.sjs?navigated-3';
+ yield undefined;
+ checkPopupLoadCount();
+ SpecialPowers.wrap(popup).back();
+ yield undefined;
+ is(popup.document.body.innerHTML, initialCount + '',
+ 'Load count (should be cached)');
+ popup.close();
+
+ SimpleTest.finish();
+ yield undefined;
+}
+
+// This will call into onChildLoad once it loads.
+var popup = window.open('file_bug669671.sjs?pushed');
+
+var gGen = test();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug675587.html b/docshell/test/test_bug675587.html
new file mode 100644
index 0000000000..9a283d3acc
--- /dev/null
+++ b/docshell/test/test_bug675587.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=675587
+-->
+<head>
+ <title>Test for Bug 675587</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=675587">Mozilla Bug 675587</a>
+<p id="display">
+ <iframe src="data:text/html,<script>location.hash='';</script>#hash"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 675587 **/
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ is(window.frames[0].location.href,
+ "data:text/html,<script>location.hash='';</" + "script>#",
+ "Should have the right href");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug680257.html b/docshell/test/test_bug680257.html
new file mode 100644
index 0000000000..bf7c32d118
--- /dev/null
+++ b/docshell/test/test_bug680257.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=680257
+-->
+<head>
+ <title>Test for Bug 680257</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=680257">Mozilla Bug 680257</a>
+
+<script type="application/javascript;version=1.7">
+
+SimpleTest.waitForExplicitFinish();
+
+var popup = window.open('file_bug680257.html');
+
+// The popup will call into popupLoaded() once it loads.
+function popupLoaded() {
+ // runTests() needs to be called from outside popupLoaded's onload handler.
+ // Otherwise, the navigations we do in runTests won't create new SHEntries.
+ SimpleTest.executeSoon(runTests);
+}
+
+function runTests() {
+ checkPopupLinkStyle(false, 'Initial');
+
+ popup.location.hash = 'a';
+ checkPopupLinkStyle(true, 'After setting hash');
+
+ popup.history.back();
+ checkPopupLinkStyle(false, 'After going back');
+
+ popup.history.forward();
+ checkPopupLinkStyle(true, 'After going forward');
+
+ popup.close();
+ SimpleTest.finish();
+}
+
+function checkPopupLinkStyle(isTarget, desc) {
+ var link = popup.document.getElementById('a');
+ var style = popup.getComputedStyle(link);
+ var color = style.getPropertyValue('color');
+
+ // Color is red if isTarget, black otherwise.
+ if (isTarget) {
+ is(color, 'rgb(255, 0, 0)', desc);
+ }
+ else {
+ is(color, 'rgb(0, 0, 0)', desc);
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/test_bug691547.html b/docshell/test/test_bug691547.html
new file mode 100644
index 0000000000..9bf4f1004b
--- /dev/null
+++ b/docshell/test/test_bug691547.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=691547
+-->
+<head>
+ <title>Test for Bug 691547</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">
+ var navStart = 0;
+ var beforeReload = 0;
+ function onContentLoad() {
+ var frame = frames[0];
+ if (!navStart) {
+ // First time we perform navigation in subframe. The bug is that
+ // load in subframe causes timing.navigationStart to be recorded
+ // as if it was a start of the next navigation.
+ var innerFrame = frame.frames[0];
+ navStart = frame.performance.timing.navigationStart;
+ innerFrame.location = 'bug570341_recordevents.html';
+ // Let's wait a bit so the difference is clear anough.
+ setTimeout(reload, 3000);
+ }
+ else {
+ // Content reloaded, time to check. We are allowing a huge time slack,
+ // in case clock is imprecise. If we have a bug, the difference is
+ // expected to be about the timeout value set above.
+ var diff = frame.performance.timing.navigationStart - beforeReload;
+ ok(diff >= -200,
+ 'navigationStart should be set after reload request. ' +
+ 'Measured difference: ' + diff + ' (should be positive)');
+ SimpleTest.finish();
+ }
+ }
+ function reload() {
+ var frame = frames[0];
+ ok(navStart == frame.performance.timing.navigationStart,
+ 'navigationStart should not change when frame loads.');
+ beforeReload = Date.now();
+ frame.location.reload();
+ }
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570341">Mozilla Bug 570341</a>
+<div id="frames">
+<iframe name="frame0" id="frame0" src="bug691547_frame.html" onload="onContentLoad()"></iframe>
+</div>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug694612.html b/docshell/test/test_bug694612.html
new file mode 100644
index 0000000000..85c2401467
--- /dev/null
+++ b/docshell/test/test_bug694612.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=694612
+-->
+<head>
+ <title>Test for Bug 694612</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=694612">Mozilla Bug 694612</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 694612 **/
+SimpleTest.waitForExplicitFinish();
+</script>
+<object type="text/html"
+ data="data:text/html,<script>parent.isnot(performance, null, 'should have performance API in an <object>'); parent.SimpleTest.finish();</script>">
+</object>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug703855.html b/docshell/test/test_bug703855.html
new file mode 100644
index 0000000000..0804f70bc3
--- /dev/null
+++ b/docshell/test/test_bug703855.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=703855
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 703855</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=703855">Mozilla Bug 703855</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe id="f" src="file_bug703855.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 703855 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var timingAttributes = [
+ 'connectEnd',
+ 'connectStart',
+ 'domComplete',
+ 'domContentLoadedEventEnd',
+ 'domContentLoadedEventStart',
+ 'domInteractive',
+ 'domLoading',
+ 'domainLookupEnd',
+ 'domainLookupStart',
+ 'fetchStart',
+ 'loadEventEnd',
+ 'loadEventStart',
+ 'navigationStart',
+ 'redirectEnd',
+ 'redirectStart',
+ 'requestStart',
+ 'responseEnd',
+ 'responseStart',
+ 'unloadEventEnd',
+ 'unloadEventStart'
+];
+var originalTiming = {};
+
+function runTest() {
+ var timing = $("f").contentWindow.performance.timing;
+ for (i in timingAttributes) {
+ originalTiming[timingAttributes[i]] = timing[timingAttributes[i]];
+ }
+
+ var doc = $("f").contentDocument;
+ doc.open();
+ doc.write("<!DOCTYPE html>");
+ doc.close();
+
+ SimpleTest.executeSoon(function() {
+ var newTiming = $("f").contentWindow.performance.timing;
+ for (var i in timingAttributes) {
+ is(timing[timingAttributes[i]], originalTiming[timingAttributes[i]],
+ "document.open should not affect value of " + timingAttributes[i]);
+ }
+ SimpleTest.finish();
+ });
+}
+
+addLoadEvent(function() {
+ SimpleTest.executeSoon(runTest);
+});
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug713825.html b/docshell/test/test_bug713825.html
new file mode 100644
index 0000000000..5f30dd0b66
--- /dev/null
+++ b/docshell/test/test_bug713825.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=713825
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 713825</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=713825">Mozilla Bug 713825</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 713825
+ * test that nsIDocCharset still works backward compatibly
+ */
+var Ci = SpecialPowers.Ci;
+var docShell = SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebNavigation).
+ QueryInterface(Ci.nsIDocShell);
+
+var charset1 = docShell.charset;
+var charset2 = docShell.QueryInterface(Ci.nsIDocCharset).charset;
+var charset3 = SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIDocCharset).charset;
+
+/* if we get here without throwing and the three charsets are equal, all is OK */
+is(charset1, charset2, "QI'd nsIDocCharset.charset should equal nsIDocShell.charset");
+is(charset1, charset3, "getInterface'd nsIDocCharset.charset should equal nsIDocShell.charset");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_bug728939.html b/docshell/test/test_bug728939.html
new file mode 100644
index 0000000000..c29f18668d
--- /dev/null
+++ b/docshell/test/test_bug728939.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=728939
+-->
+<head>
+ <title>Test for Bug 728939</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=728939">Mozilla Bug 728939</a>
+
+<script type="application/javascript;version=1.7">
+
+SimpleTest.waitForExplicitFinish();
+
+// Called when the popup finishes loading.
+function popupLoaded() {
+ popup.location.hash = '#foo';
+ is(popup.document.URL, popup.location.href, 'After hashchange.');
+
+ popup.history.pushState('', '', 'bar');
+ is(popup.document.URL, popup.location.href, 'After pushState.');
+
+ popup.history.replaceState('', '', 'baz');
+ is(popup.document.URL, popup.location.href, 'After replaceState.');
+
+ popup.close();
+ SimpleTest.finish();
+}
+
+var popup = window.open('file_bug728939.html');
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/test_bug797909.html b/docshell/test/test_bug797909.html
new file mode 100644
index 0000000000..a47aa0c6d1
--- /dev/null
+++ b/docshell/test/test_bug797909.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=797909
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 797909</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()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=797909">Mozilla Bug 797909</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+ /** Test for Bug 797909 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ function runTest() {
+ iframe = document.getElementById("ifr");
+ try {
+ var iframeDoc = iframe.contentWindow.document;
+ ok(false, "Should have thrown an exception");
+ } catch (ex) {
+ ok(true, "Got an exception");
+ }
+
+ iframe = document.createElement("iframe");
+ // set sandbox attribute
+ iframe.sandbox = "allow-scripts";
+ // and then insert into the doc
+ document.body.appendChild(iframe);
+
+ try {
+ var iframeDoc = iframe.contentWindow.document;
+ ok(false, "Should have thrown an exception");
+ } catch (ex) {
+ ok(true, "Got an exception");
+ }
+
+ iframe = document.createElement("iframe");
+ // set sandbox attribute
+ iframe.sandbox = "allow-same-origin";
+ // and then insert into the doc
+ document.body.appendChild(iframe);
+
+ try {
+ var iframeDoc = iframe.contentWindow.document;
+ ok(true, "Shouldn't have thrown an exception");
+ } catch (ex) {
+ ok(false, "Got an unexpected exception");
+ }
+
+ SimpleTest.finish();
+ }
+
+</script>
+</pre>
+<iframe id="ifr" sandbox = "allow-scripts"></iframe>
+</body>
+</html>
diff --git a/docshell/test/test_forceinheritprincipal_overrule_owner.html b/docshell/test/test_forceinheritprincipal_overrule_owner.html
new file mode 100644
index 0000000000..b3a48d7ea0
--- /dev/null
+++ b/docshell/test/test_forceinheritprincipal_overrule_owner.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<script type="text/javascript">
+
+var channel = SpecialPowers.wrap(document).docShell.currentDocumentChannel;
+var loadInfo = channel.loadInfo;
+
+// 1) perform some sanity checks
+var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
+var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
+var principalToInherit = channel.loadInfo.principalToInherit.URI.asciiSpec;
+
+ok(triggeringPrincipal.startsWith("http://mochi.test:8888/"),
+ "initial triggeringPrincipal correct");
+ok(loadingPrincipal.startsWith("http://mochi.test:8888/"),
+ "initial loadingPrincipal correct");
+ok(principalToInherit.startsWith("http://mochi.test:8888/"),
+ "initial principalToInherit correct");
+
+// reset principals on the loadinfo
+loadInfo.resetPrincipalsToNullPrincipal();
+
+// 2) verify loadInfo contains the correct principals
+var triggeringPrincipal = channel.loadInfo.triggeringPrincipal;
+var loadingPrincipal = channel.loadInfo.loadingPrincipal;
+var principalToInherit = channel.loadInfo.principalToInherit;
+
+ok(triggeringPrincipal.isNullPrincipal,
+ "triggeringPrincipal after resetting correct");
+ok(loadingPrincipal.isNullPrincipal,
+ "triggeringPrincipal after resetting correct");
+ok(triggeringPrincipal.isNullPrincipal,
+ "principalToInherit after resetting correct");
+
+// 3) verify that getChannelResultPrincipal returns right principal
+var resultPrincipal = SpecialPowers.Services.scriptSecurityManager
+ .getChannelResultPrincipal(channel);
+
+ok(resultPrincipal.isNullPrincipal,
+ "resultPrincipal after resetting correct");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_framedhistoryframes.html b/docshell/test/test_framedhistoryframes.html
new file mode 100644
index 0000000000..916a6229d3
--- /dev/null
+++ b/docshell/test/test_framedhistoryframes.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602256
+-->
+<head>
+ <title>Test for Bug 602256</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=602256">Mozilla Bug 602256</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 602256 **/
+
+SimpleTest.waitForExplicitFinish();
+var win = window.open("file_framedhistoryframes.html");
+
+function done() {
+ win.close();
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_pushState_after_document_open.html b/docshell/test/test_pushState_after_document_open.html
new file mode 100644
index 0000000000..51ba1050c2
--- /dev/null
+++ b/docshell/test/test_pushState_after_document_open.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=957479
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 957479</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 957479 **/
+ SimpleTest.waitForExplicitFinish();
+ // Child needs to invoke us, otherwise our onload will fire before the child
+ // has done the write/close bit.
+ onmessage = function doTest() {
+ is(frames[0].location.pathname, "/tests/docshell/test/file_pushState_after_document_open.html", "Should have the right path here");
+ is(frames[0].location.hash, "", "Should have the right hash here");
+ frames[0].history.pushState({}, '', frames[0].document.URL + "#foopy");
+ is(frames[0].location.pathname, "/tests/docshell/test/file_pushState_after_document_open.html", "Pathname should not have changed");
+ is(frames[0].location.hash, "#foopy", "Hash should have changed");
+ SimpleTest.finish();
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=957479">Mozilla Bug 957479</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe src="file_pushState_after_document_open.html"></iframe>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/test_windowedhistoryframes.html b/docshell/test/test_windowedhistoryframes.html
new file mode 100644
index 0000000000..d27987beb4
--- /dev/null
+++ b/docshell/test/test_windowedhistoryframes.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602256
+-->
+<head>
+ <title>Test for Bug 602256</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=602256">Mozilla Bug 602256</a>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 602256 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function done() {
+ subWin.close();
+ SimpleTest.finish();
+}
+
+var subWin = window.open("historyframes.html", "_blank");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/unit/head_docshell.js b/docshell/test/unit/head_docshell.js
new file mode 100644
index 0000000000..a5c7546c04
--- /dev/null
+++ b/docshell/test/unit/head_docshell.js
@@ -0,0 +1,11 @@
+/* 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/. */
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cr = Components.results;
+
+var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
+ getService(Ci.nsIProperties);
+var profileDir = do_get_profile();
diff --git a/docshell/test/unit/test_bug414201_jfif.js b/docshell/test/unit/test_bug414201_jfif.js
new file mode 100644
index 0000000000..6a689ec080
--- /dev/null
+++ b/docshell/test/unit/test_bug414201_jfif.js
@@ -0,0 +1,27 @@
+/* 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/. */
+
+/*
+ * Test for bug 414201
+ */
+
+function run_test()
+{
+ var ms = Components.classes["@mozilla.org/mime;1"].getService(Components.interfaces.nsIMIMEService);
+
+ /* Test a few common image types to make sure that they get the right extension */
+ var types = {
+ "image/jpeg": ["jpg", "jpeg"], /* accept either */
+ "image/gif": ["gif"],
+ "image/png": ["png"]
+ };
+
+ /* Check whether the primary extension is what we'd expect */
+ for (var mimetype in types) {
+ var exts = types[mimetype];
+ var primary = ms.getFromTypeAndExtension(mimetype, null).primaryExtension.toLowerCase();
+
+ do_check_true (exts.indexOf(primary) != -1);
+ }
+}
diff --git a/docshell/test/unit/test_bug442584.js b/docshell/test/unit/test_bug442584.js
new file mode 100644
index 0000000000..174bdb7e30
--- /dev/null
+++ b/docshell/test/unit/test_bug442584.js
@@ -0,0 +1,30 @@
+var prefetch = Cc["@mozilla.org/prefetch-service;1"].
+ getService(Ci.nsIPrefetchService);
+var ios = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+var prefs = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch);
+
+function run_test() {
+ // Fill up the queue
+ prefs.setBoolPref("network.prefetch-next", true);
+ for (var i = 0; i < 5; i++) {
+ var uri = ios.newURI("http://localhost/" + i, null, null);
+ prefetch.prefetchURI(uri, uri, null, true);
+ }
+
+ // Make sure the queue has items in it...
+ do_check_true(prefetch.hasMoreElements());
+
+ // Now disable the pref to force the queue to empty...
+ prefs.setBoolPref("network.prefetch-next", false);
+ do_check_false(prefetch.hasMoreElements());
+
+ // Now reenable the pref, and add more items to the queue.
+ prefs.setBoolPref("network.prefetch-next", true);
+ for (var i = 0; i < 5; i++) {
+ var uri = ios.newURI("http://localhost/" + i, null, null);
+ prefetch.prefetchURI(uri, uri, null, true);
+ }
+ do_check_true(prefetch.hasMoreElements());
+}
diff --git a/docshell/test/unit/test_nsDefaultURIFixup.js b/docshell/test/unit/test_nsDefaultURIFixup.js
new file mode 100644
index 0000000000..371bdea174
--- /dev/null
+++ b/docshell/test/unit/test_nsDefaultURIFixup.js
@@ -0,0 +1,93 @@
+var urifixup = Cc["@mozilla.org/docshell/urifixup;1"].
+ getService(Ci.nsIURIFixup);
+var prefs = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch);
+
+var pref = "browser.fixup.typo.scheme";
+
+var data = [
+ {
+ // ttp -> http.
+ wrong: 'ttp://www.example.com/',
+ fixed: 'http://www.example.com/',
+ },
+ {
+ // ttps -> https.
+ wrong: 'ttps://www.example.com/',
+ fixed: 'https://www.example.com/',
+ },
+ {
+ // tps -> https.
+ wrong: 'tps://www.example.com/',
+ fixed: 'https://www.example.com/',
+ },
+ {
+ // ps -> https.
+ wrong: 'ps://www.example.com/',
+ fixed: 'https://www.example.com/',
+ },
+ {
+ // ile -> file.
+ wrong: 'ile:///this/is/a/test.html',
+ fixed: 'file:///this/is/a/test.html',
+ },
+ {
+ // le -> file.
+ wrong: 'le:///this/is/a/test.html',
+ fixed: 'file:///this/is/a/test.html',
+ },
+ {
+ // Valid should not be changed.
+ wrong: 'https://example.com/this/is/a/test.html',
+ fixed: 'https://example.com/this/is/a/test.html',
+ },
+ {
+ // Unmatched should not be changed.
+ wrong: 'whatever://this/is/a/test.html',
+ fixed: 'whatever://this/is/a/test.html',
+ },
+];
+
+var len = data.length;
+
+function run_test() {
+ run_next_test();
+}
+
+// Make sure we fix what needs fixing when there is no pref set.
+add_task(function test_unset_pref_fixes_typos() {
+ prefs.clearUserPref(pref);
+ for (let i = 0; i < len; ++i) {
+ let item = data[i];
+ let result =
+ urifixup.createFixupURI(item.wrong,
+ urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS).spec;
+ do_check_eq(result, item.fixed);
+ }
+});
+
+// Make sure we don't do anything when the pref is explicitly
+// set to false.
+add_task(function test_false_pref_keeps_typos() {
+ prefs.setBoolPref(pref, false);
+ for (let i = 0; i < len; ++i) {
+ let item = data[i];
+ let result =
+ urifixup.createFixupURI(item.wrong,
+ urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS).spec;
+ do_check_eq(result, item.wrong);
+ }
+});
+
+// Finally, make sure we still fix what needs fixing if the pref is
+// explicitly set to true.
+add_task(function test_true_pref_fixes_typos() {
+ prefs.setBoolPref(pref, true);
+ for (let i = 0; i < len; ++i) {
+ let item = data[i];
+ let result =
+ urifixup.createFixupURI(item.wrong,
+ urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS).spec;
+ do_check_eq(result, item.fixed);
+ }
+});
diff --git a/docshell/test/unit/test_nsDefaultURIFixup_info.js b/docshell/test/unit/test_nsDefaultURIFixup_info.js
new file mode 100644
index 0000000000..9e33ea484f
--- /dev/null
+++ b/docshell/test/unit/test_nsDefaultURIFixup_info.js
@@ -0,0 +1,620 @@
+var urifixup = Cc["@mozilla.org/docshell/urifixup;1"].
+ getService(Ci.nsIURIFixup);
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+var prefList = ["browser.fixup.typo.scheme", "keyword.enabled",
+ "browser.fixup.domainwhitelist.whitelisted"];
+for (let pref of prefList) {
+ Services.prefs.setBoolPref(pref, true);
+}
+
+const kSearchEngineID = "test_urifixup_search_engine";
+const kSearchEngineURL = "http://www.example.org/?search={searchTerms}";
+Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
+ kSearchEngineURL);
+
+var oldDefaultEngine = Services.search.defaultEngine;
+Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+
+var selectedName = Services.search.defaultEngine.name;
+do_check_eq(selectedName, kSearchEngineID);
+
+const kForceHostLookup = "browser.fixup.dns_first_for_single_words";
+do_register_cleanup(function() {
+ if (oldDefaultEngine) {
+ Services.search.defaultEngine = oldDefaultEngine;
+ }
+ let engine = Services.search.getEngineByName(kSearchEngineID);
+ if (engine) {
+ Services.search.removeEngine(engine);
+ }
+ Services.prefs.clearUserPref("keyword.enabled");
+ Services.prefs.clearUserPref("browser.fixup.typo.scheme");
+ Services.prefs.clearUserPref(kForceHostLookup);
+});
+
+var flagInputs = [
+ urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
+ urifixup.FIXUP_FLAGS_MAKE_ALTERNATE_URI,
+ urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS,
+];
+
+flagInputs.concat([
+ flagInputs[0] | flagInputs[1],
+ flagInputs[1] | flagInputs[2],
+ flagInputs[0] | flagInputs[2],
+ flagInputs[0] | flagInputs[1] | flagInputs[2]
+]);
+
+/*
+ The following properties are supported for these test cases:
+ {
+ input: "", // Input string, required
+ fixedURI: "", // Expected fixedURI
+ alternateURI: "", // Expected alternateURI
+ keywordLookup: false, // Whether a keyword lookup is expected
+ protocolChange: false, // Whether a protocol change is expected
+ inWhitelist: false, // Whether the input host is in the whitelist
+ affectedByDNSForSingleHosts: false, // Whether the input host could be a host, but is normally assumed to be a keyword query
+ }
+*/
+var testcases = [ {
+ input: "http://www.mozilla.org",
+ fixedURI: "http://www.mozilla.org/",
+ }, {
+ input: "http://127.0.0.1/",
+ fixedURI: "http://127.0.0.1/",
+ }, {
+ input: "file:///foo/bar",
+ fixedURI: "file:///foo/bar",
+ }, {
+ input: "://www.mozilla.org",
+ fixedURI: "http://www.mozilla.org/",
+ protocolChange: true,
+ }, {
+ input: "www.mozilla.org",
+ fixedURI: "http://www.mozilla.org/",
+ protocolChange: true,
+ }, {
+ input: "http://mozilla/",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ }, {
+ input: "http://test./",
+ fixedURI: "http://test./",
+ alternateURI: "http://www.test./",
+ }, {
+ input: "127.0.0.1",
+ fixedURI: "http://127.0.0.1/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3.4/",
+ fixedURI: "http://1.2.3.4/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3.4/foo",
+ fixedURI: "http://1.2.3.4/foo",
+ protocolChange: true,
+ }, {
+ input: "1.2.3.4:8000",
+ fixedURI: "http://1.2.3.4:8000/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3.4:8000/",
+ fixedURI: "http://1.2.3.4:8000/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3.4:8000/foo",
+ fixedURI: "http://1.2.3.4:8000/foo",
+ protocolChange: true,
+ }, {
+ input: "192.168.10.110",
+ fixedURI: "http://192.168.10.110/",
+ protocolChange: true,
+ }, {
+ input: "192.168.10.110/123",
+ fixedURI: "http://192.168.10.110/123",
+ protocolChange: true,
+ }, {
+ input: "192.168.10.110/123foo",
+ fixedURI: "http://192.168.10.110/123foo",
+ protocolChange: true,
+ }, {
+ input: "192.168.10.110:1234/123",
+ fixedURI: "http://192.168.10.110:1234/123",
+ protocolChange: true,
+ }, {
+ input: "192.168.10.110:1234/123foo",
+ fixedURI: "http://192.168.10.110:1234/123foo",
+ protocolChange: true,
+ }, {
+ input: "1.2.3",
+ fixedURI: "http://1.2.0.3/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3/",
+ fixedURI: "http://1.2.0.3/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3/foo",
+ fixedURI: "http://1.2.0.3/foo",
+ protocolChange: true,
+ }, {
+ input: "1.2.3/123",
+ fixedURI: "http://1.2.0.3/123",
+ protocolChange: true,
+ }, {
+ input: "1.2.3:8000",
+ fixedURI: "http://1.2.0.3:8000/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3:8000/",
+ fixedURI: "http://1.2.0.3:8000/",
+ protocolChange: true,
+ }, {
+ input: "1.2.3:8000/foo",
+ fixedURI: "http://1.2.0.3:8000/foo",
+ protocolChange: true,
+ }, {
+ input: "1.2.3:8000/123",
+ fixedURI: "http://1.2.0.3:8000/123",
+ protocolChange: true,
+ }, {
+ input: "http://1.2.3",
+ fixedURI: "http://1.2.0.3/",
+ }, {
+ input: "http://1.2.3/",
+ fixedURI: "http://1.2.0.3/",
+ }, {
+ input: "http://1.2.3/foo",
+ fixedURI: "http://1.2.0.3/foo",
+ }, {
+ input: "[::1]",
+ fixedURI: "http://[::1]/",
+ alternateURI: "http://[::1]/",
+ protocolChange: true,
+ }, {
+ input: "[::1]/",
+ fixedURI: "http://[::1]/",
+ alternateURI: "http://[::1]/",
+ protocolChange: true,
+ }, {
+ input: "[::1]:8000",
+ fixedURI: "http://[::1]:8000/",
+ alternateURI: "http://[::1]:8000/",
+ protocolChange: true,
+ }, {
+ input: "[::1]:8000/",
+ fixedURI: "http://[::1]:8000/",
+ alternateURI: "http://[::1]:8000/",
+ protocolChange: true,
+ }, {
+ input: "[[::1]]/",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "[fe80:cd00:0:cde:1257:0:211e:729c]",
+ fixedURI: "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
+ alternateURI: "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
+ protocolChange: true,
+ }, {
+ input: "[64:ff9b::8.8.8.8]",
+ fixedURI: "http://[64:ff9b::8.8.8.8]/",
+ protocolChange: true
+ }, {
+ input: "[64:ff9b::8.8.8.8]/~moz",
+ fixedURI: "http://[64:ff9b::8.8.8.8]/~moz",
+ protocolChange: true
+ }, {
+ input: "[::1][::1]",
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "[::1][100",
+ fixedURI: null,
+ alternateURI: null,
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "[::1]]",
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "1234",
+ fixedURI: "http://0.0.4.210/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "host/foo.txt",
+ fixedURI: "http://host/foo.txt",
+ alternateURI: "http://www.host.com/foo.txt",
+ protocolChange: true,
+ }, {
+ input: "mozilla",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "test.",
+ fixedURI: "http://test./",
+ alternateURI: "http://www.test./",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: ".test",
+ fixedURI: "http://.test/",
+ alternateURI: "http://www..test/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "mozilla is amazing",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "search ?mozilla",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "mozilla .com",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "what if firefox?",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "london's map",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "mozilla ",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: " mozilla ",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "mozilla \\",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "mozilla \\ foo.txt",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "mozilla \\\r foo.txt",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "mozilla\n",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "mozilla \r\n",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "moz\r\nfirefox\nos\r",
+ fixedURI: "http://mozfirefoxos/",
+ alternateURI: "http://www.mozfirefoxos.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "moz\r\n firefox\n",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "[]",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "http://whitelisted/",
+ fixedURI: "http://whitelisted/",
+ alternateURI: "http://www.whitelisted.com/",
+ inWhitelist: true,
+ }, {
+ input: "café.local",
+ fixedURI: "http://café.local/",
+ alternateURI: "http://www.café.local/",
+ protocolChange: true
+ }, {
+ input: "47.6182,-122.830",
+ fixedURI: "http://47.6182,-122.830/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "-47.6182,-23.51",
+ fixedURI: "http://-47.6182,-23.51/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "-22.14,23.51-",
+ fixedURI: "http://-22.14,23.51-/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "32.7",
+ fixedURI: "http://32.0.0.7/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "5+2",
+ fixedURI: "http://5+2/",
+ alternateURI: "http://www.5+2.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "5/2",
+ fixedURI: "http://0.0.0.5/2",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "moz ?.::%27",
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "mozilla.com/?q=search",
+ fixedURI: "http://mozilla.com/?q=search",
+ alternateURI: "http://www.mozilla.com/?q=search",
+ protocolChange: true
+ }, {
+ input: "mozilla.com?q=search",
+ fixedURI: "http://mozilla.com/?q=search",
+ alternateURI: "http://www.mozilla.com/?q=search",
+ protocolChange: true
+ }, {
+ input: "mozilla.com ?q=search",
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "mozilla.com.?q=search",
+ fixedURI: "http://mozilla.com./?q=search",
+ protocolChange: true
+ }, {
+ input: "mozilla.com'?q=search",
+ fixedURI: "http://mozilla.com'/?q=search",
+ alternateURI: "http://www.mozilla.com'/?q=search",
+ protocolChange: true
+ }, {
+ input: "mozilla.com':search",
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "[mozilla]",
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "':?",
+ fixedURI: "http://'/?",
+ alternateURI: "http://www.'.com/?",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "a?.com",
+ fixedURI: "http://a/?.com",
+ alternateURI: "http://www.a.com/?.com",
+ protocolChange: true,
+ }, {
+ input: "?'.com",
+ fixedURI: "http:///?%27.com",
+ alternateURI: "http://www..com/?%27.com",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "' ?.com",
+ keywordLookup: true,
+ protocolChange: true
+ }, {
+ input: "?mozilla",
+ fixedURI: "http:///?mozilla",
+ alternateURI: "http://www..com/?mozilla",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "??mozilla",
+ fixedURI: "http:///??mozilla",
+ alternateURI: "http://www..com/??mozilla",
+ keywordLookup: true,
+ protocolChange: true,
+ }, {
+ input: "mozilla/",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ protocolChange: true,
+ }, {
+ input: "mozilla",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ protocolChange: true,
+ keywordLookup: true,
+ affectedByDNSForSingleHosts: true,
+ }, {
+ input: "mozilla5/2",
+ fixedURI: "http://mozilla5/2",
+ alternateURI: "http://www.mozilla5.com/2",
+ protocolChange: true,
+ }, {
+ input: "mozilla/foo",
+ fixedURI: "http://mozilla/foo",
+ alternateURI: "http://www.mozilla.com/foo",
+ protocolChange: true,
+ }, {
+ input: "mozilla\\",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ keywordLookup: true,
+ protocolChange: true,
+ affectedByDNSForSingleHosts: true,
+ }];
+
+if (Services.appinfo.OS.toLowerCase().startsWith("win")) {
+ testcases.push({
+ input: "C:\\some\\file.txt",
+ fixedURI: "file:///C:/some/file.txt",
+ protocolChange: true,
+ });
+ testcases.push({
+ input: "//mozilla",
+ fixedURI: "http://mozilla/",
+ alternateURI: "http://www.mozilla.com/",
+ protocolChange: true,
+ });
+} else {
+ testcases.push({
+ input: "/some/file.txt",
+ fixedURI: "file:///some/file.txt",
+ protocolChange: true,
+ });
+ testcases.push({
+ input: "//mozilla",
+ fixedURI: "file:////mozilla",
+ protocolChange: true,
+ });
+}
+
+function sanitize(input) {
+ return input.replace(/\r|\n/g, "").trim();
+}
+
+
+var gSingleWordHostLookup = false;
+function run_test() {
+ // Only keywordlookup things should be affected by requiring a DNS lookup for single-word hosts:
+ do_print("Check only keyword lookup testcases should be affected by requiring DNS for single hosts");
+ let affectedTests = testcases.filter(t => !t.keywordLookup && t.affectedByDNSForSingleHosts);
+ if (affectedTests.length) {
+ for (let testcase of affectedTests) {
+ do_print("Affected: " + testcase.input);
+ }
+ }
+ do_check_eq(affectedTests.length, 0);
+ do_single_test_run();
+ gSingleWordHostLookup = true;
+ do_single_test_run();
+}
+
+function do_single_test_run() {
+ Services.prefs.setBoolPref(kForceHostLookup, gSingleWordHostLookup);
+
+ let relevantTests = gSingleWordHostLookup ? testcases.filter(t => t.keywordLookup) :
+ testcases;
+
+ for (let { input: testInput,
+ fixedURI: expectedFixedURI,
+ alternateURI: alternativeURI,
+ keywordLookup: expectKeywordLookup,
+ protocolChange: expectProtocolChange,
+ inWhitelist: inWhitelist,
+ affectedByDNSForSingleHosts: affectedByDNSForSingleHosts,
+ } of relevantTests) {
+
+ // Explicitly force these into a boolean
+ expectKeywordLookup = !!expectKeywordLookup;
+ expectProtocolChange = !!expectProtocolChange;
+ inWhitelist = !!inWhitelist;
+ affectedByDNSForSingleHosts = !!affectedByDNSForSingleHosts;
+
+ expectKeywordLookup = expectKeywordLookup && (!affectedByDNSForSingleHosts || !gSingleWordHostLookup);
+
+ for (let flags of flagInputs) {
+ let info;
+ let fixupURIOnly = null;
+ try {
+ fixupURIOnly = urifixup.createFixupURI(testInput, flags);
+ } catch (ex) {
+ do_print("Caught exception: " + ex);
+ do_check_eq(expectedFixedURI, null);
+ }
+
+ try {
+ info = urifixup.getFixupURIInfo(testInput, flags);
+ } catch (ex) {
+ // Both APIs should return an error in the same cases.
+ do_print("Caught exception: " + ex);
+ do_check_eq(expectedFixedURI, null);
+ do_check_eq(fixupURIOnly, null);
+ continue;
+ }
+
+ do_print("Checking \"" + testInput + "\" with flags " + flags +
+ " (host lookup for single words: " + (gSingleWordHostLookup ? "yes" : "no") + ")");
+
+ // Both APIs should then also be using the same spec.
+ do_check_eq(!!fixupURIOnly, !!info.preferredURI);
+ if (fixupURIOnly)
+ do_check_eq(fixupURIOnly.spec, info.preferredURI.spec);
+
+ let isFileURL = expectedFixedURI && expectedFixedURI.startsWith("file");
+
+ // Check the fixedURI:
+ let makeAlternativeURI = flags & urifixup.FIXUP_FLAGS_MAKE_ALTERNATE_URI;
+ if (makeAlternativeURI && alternativeURI != null) {
+ do_check_eq(info.fixedURI.spec, alternativeURI);
+ } else {
+ do_check_eq(info.fixedURI && info.fixedURI.spec, expectedFixedURI);
+ }
+
+ // Check booleans on input:
+ let couldDoKeywordLookup = flags & urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
+ do_check_eq(!!info.keywordProviderName, couldDoKeywordLookup && expectKeywordLookup);
+ do_check_eq(info.fixupChangedProtocol, expectProtocolChange);
+ do_check_eq(info.fixupCreatedAlternateURI, makeAlternativeURI && alternativeURI != null);
+
+ // Check the preferred URI
+ if (couldDoKeywordLookup) {
+ if (expectKeywordLookup) {
+ if (!inWhitelist) {
+ let urlparamInput = encodeURIComponent(sanitize(testInput)).replace(/%20/g, "+");
+ // If the input starts with `?`, then info.preferredURI.spec will omit it
+ // In order to test this behaviour, remove `?` only if it is the first character
+ if (urlparamInput.startsWith("%3F")) {
+ urlparamInput = urlparamInput.replace("%3F", "");
+ }
+ let searchURL = kSearchEngineURL.replace("{searchTerms}", urlparamInput);
+ let spec = info.preferredURI.spec.replace(/%27/g, "'");
+ do_check_eq(spec, searchURL);
+ } else {
+ do_check_eq(info.preferredURI, null);
+ }
+ } else {
+ do_check_eq(info.preferredURI.spec, info.fixedURI.spec);
+ }
+ } else {
+ // In these cases, we should never be doing a keyword lookup and
+ // the fixed URI should be preferred:
+ do_check_eq(info.preferredURI.spec, info.fixedURI.spec);
+ }
+ do_check_eq(sanitize(testInput), info.originalInput);
+ }
+ }
+}
diff --git a/docshell/test/unit/test_nsDefaultURIFixup_search.js b/docshell/test/unit/test_nsDefaultURIFixup_search.js
new file mode 100644
index 0000000000..c00b6a85f5
--- /dev/null
+++ b/docshell/test/unit/test_nsDefaultURIFixup_search.js
@@ -0,0 +1,117 @@
+var urifixup = Cc["@mozilla.org/docshell/urifixup;1"].
+ getService(Ci.nsIURIFixup);
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/AppConstants.jsm");
+
+Services.prefs.setBoolPref("keyword.enabled", true);
+
+const kSearchEngineID = "test_urifixup_search_engine";
+const kSearchEngineURL = "http://www.example.org/?search={searchTerms}";
+Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
+ kSearchEngineURL);
+
+var oldDefaultEngine = Services.search.defaultEngine;
+Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+
+var selectedName = Services.search.defaultEngine.name;
+do_check_eq(selectedName, kSearchEngineID);
+
+do_register_cleanup(function() {
+ if (oldDefaultEngine) {
+ Services.search.defaultEngine = oldDefaultEngine;
+ }
+ let engine = Services.search.getEngineByName(kSearchEngineID);
+ if (engine) {
+ Services.search.removeEngine(engine);
+ }
+ Services.prefs.clearUserPref("keyword.enabled");
+});
+
+var isWin = AppConstants.platform == "win";
+
+var data = [
+ {
+ // Valid should not be changed.
+ wrong: 'https://example.com/this/is/a/test.html',
+ fixed: 'https://example.com/this/is/a/test.html',
+ },
+ {
+ // Unrecognized protocols should be changed.
+ wrong: 'whatever://this/is/a/test.html',
+ fixed: kSearchEngineURL.replace("{searchTerms}", encodeURIComponent('whatever://this/is/a/test.html')),
+ },
+
+ // The following tests check that when a user:password is present in the URL
+ // `user:` isn't treated as an unknown protocol thus leaking the user and
+ // password to the search engine.
+ {
+ wrong: 'user:pass@example.com/this/is/a/test.html',
+ fixed: 'http://user:pass@example.com/this/is/a/test.html',
+ },
+ {
+ wrong: 'user@example.com:8080/this/is/a/test.html',
+ fixed: 'http://user@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: 'https:pass@example.com/this/is/a/test.html',
+ fixed: 'https://pass@example.com/this/is/a/test.html',
+ },
+ {
+ wrong: 'user:pass@example.com:8080/this/is/a/test.html',
+ fixed: 'http://user:pass@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: 'http:user:pass@example.com:8080/this/is/a/test.html',
+ fixed: 'http://user:pass@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: 'ttp:user:pass@example.com:8080/this/is/a/test.html',
+ fixed: 'http://user:pass@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: 'gobbledygook:user:pass@example.com:8080/this/is/a/test.html',
+ fixed: 'http://gobbledygook:user%3Apass@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: 'user:@example.com:8080/this/is/a/test.html',
+ fixed: 'http://user:@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: '//user:pass@example.com:8080/this/is/a/test.html',
+ fixed: (isWin ? "http:" : "file://") + '//user:pass@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: '://user:pass@example.com:8080/this/is/a/test.html',
+ fixed: 'http://user:pass@example.com:8080/this/is/a/test.html',
+ },
+ {
+ wrong: 'whatever://this/is/a@b/test.html',
+ fixed: kSearchEngineURL.replace("{searchTerms}", encodeURIComponent('whatever://this/is/a@b/test.html')),
+ },
+];
+
+var extProtocolSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"]
+ .getService(Ci.nsIExternalProtocolService);
+
+if (extProtocolSvc && extProtocolSvc.externalProtocolHandlerExists("mailto")) {
+ data.push({
+ wrong: "mailto:foo@bar.com",
+ fixed: "mailto:foo@bar.com"
+ });
+}
+
+function run_test() {
+ run_next_test();
+}
+
+var len = data.length;
+// Make sure we fix what needs fixing
+add_task(function test_fix_unknown_schemes() {
+ for (let i = 0; i < len; ++i) {
+ let item = data[i];
+ let result =
+ urifixup.createFixupURI(item.wrong,
+ urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS).spec;
+ do_check_eq(result, item.fixed);
+ }
+});
diff --git a/docshell/test/unit/test_nsIDownloadHistory.js b/docshell/test/unit/test_nsIDownloadHistory.js
new file mode 100644
index 0000000000..2030f0702c
--- /dev/null
+++ b/docshell/test/unit/test_nsIDownloadHistory.js
@@ -0,0 +1,68 @@
+/* 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/. */
+
+const NS_DOWNLOADHISTORY_CID = "{2ee83680-2af0-4bcb-bfa0-c9705f6554f1}";
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "Services", function() {
+ Components.utils.import("resource://gre/modules/Services.jsm");
+ return Services;
+});
+
+function testLinkVistedObserver()
+{
+ const NS_LINK_VISITED_EVENT_TOPIC = "link-visited";
+ var ios = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+ var testURI = ios.newURI("http://google.com/", null, null);
+
+ var gh = Cc["@mozilla.org/browser/global-history;2"].
+ getService(Ci.nsIGlobalHistory2);
+ do_check_false(gh.isVisited(testURI));
+
+ var topicReceived = false;
+ var obs = {
+ observe: function tlvo_observe(aSubject, aTopic, aData)
+ {
+ if (NS_LINK_VISITED_EVENT_TOPIC == aTopic) {
+ do_check_eq(testURI, aSubject);
+ topicReceived = true;
+ }
+ }
+ };
+
+ var os = Cc["@mozilla.org/observer-service;1"].
+ getService(Ci.nsIObserverService);
+ os.addObserver(obs, NS_LINK_VISITED_EVENT_TOPIC, false);
+
+ var dh = Components.classesByID[NS_DOWNLOADHISTORY_CID].
+ getService(Ci.nsIDownloadHistory);
+ dh.addDownload(testURI);
+ do_check_true(topicReceived);
+ do_check_true(gh.isVisited(testURI));
+}
+
+var tests = [testLinkVistedObserver];
+
+function run_test()
+{
+ // Not everyone uses/defines an nsGlobalHistory* service. Especially if
+ // MOZ_PLACES is not defined. If getService fails, then abort gracefully.
+ try {
+ Cc["@mozilla.org/browser/global-history;2"].
+ getService(Ci.nsIGlobalHistory2);
+ }
+ catch (ex) {
+ return;
+ }
+
+ // Needed to properly setup and shutdown the profile.
+ do_get_profile();
+
+ for (var i = 0; i < tests.length; i++)
+ tests[i]();
+
+ cleanup();
+}
diff --git a/docshell/test/unit/test_pb_notification.js b/docshell/test/unit/test_pb_notification.js
new file mode 100644
index 0000000000..82018f5852
--- /dev/null
+++ b/docshell/test/unit/test_pb_notification.js
@@ -0,0 +1,23 @@
+if (typeof Cc === "undefined")
+ Cc = Components.classes;
+if (typeof Ci === "undefined")
+ Ci = Components.interfaces;
+
+function destroy_transient_docshell() {
+ var docshell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
+ docshell.setOriginAttributes({privateBrowsingId : 1});
+ do_test_pending();
+ do_timeout(0, Components.utils.forceGC);
+}
+
+function run_test() {
+ var obs = {
+ observe: function(aSubject, aTopic, aData) {
+ do_check_eq(aTopic, "last-pb-context-exited");
+ do_test_finished();
+ }
+ };
+ var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+ os.addObserver(obs, "last-pb-context-exited", false);
+ destroy_transient_docshell();
+}
diff --git a/docshell/test/unit/test_privacy_transition.js b/docshell/test/unit/test_privacy_transition.js
new file mode 100644
index 0000000000..829e25c3c2
--- /dev/null
+++ b/docshell/test/unit/test_privacy_transition.js
@@ -0,0 +1,23 @@
+var gNotifications = 0;
+
+var observer = {
+ QueryInterface: function(iid) {
+ if (Ci.nsIPrivacyTransitionObserver.equals(iid) ||
+ Ci.nsISupportsWeakReference.equals(iid) ||
+ Ci.nsISupports.equals(iid))
+ return this;
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ },
+
+ privateModeChanged: function(enabled) {
+ gNotifications++;
+ }
+}
+
+function run_test() {
+ var docshell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
+ docshell.addWeakPrivacyTransitionObserver(observer);
+ docshell.setOriginAttributes({ privateBrowsingId : 1 });
+ docshell.setOriginAttributes({ privateBrowsingId : 0 });
+ do_check_eq(gNotifications, 2);
+} \ No newline at end of file
diff --git a/docshell/test/unit/test_setUsePrivateBrowsing.js b/docshell/test/unit/test_setUsePrivateBrowsing.js
new file mode 100644
index 0000000000..7391868954
--- /dev/null
+++ b/docshell/test/unit/test_setUsePrivateBrowsing.js
@@ -0,0 +1,65 @@
+"use strict";
+
+const {utils: Cu} = Components;
+
+Cu.import("resource://gre/modules/AppConstants.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+add_task(function*() {
+ let webNav = Services.appShell.createWindowlessBrowser(false);
+
+ let loadContext = webNav.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsILoadContext);
+
+ let docShell = webNav.getInterface(Ci.nsIDocShell);
+
+ equal(loadContext.usePrivateBrowsing, false, "Should start out in non-private mode");
+
+ loadContext.usePrivateBrowsing = true;
+ equal(loadContext.usePrivateBrowsing, true,
+ "Should be able to change to private mode prior to a document load");
+
+ loadContext.usePrivateBrowsing = false;
+ equal(loadContext.usePrivateBrowsing, false,
+ "Should be able to change to non-private mode prior to a document load");
+
+ let oa = docShell.getOriginAttributes();
+
+ oa.privateBrowsingId = 1;
+ docShell.setOriginAttributes(oa);
+
+ equal(loadContext.usePrivateBrowsing, true,
+ "Should be able to change origin attributes prior to a document load");
+
+ oa.privateBrowsingId = 0;
+ docShell.setOriginAttributes(oa);
+
+ equal(loadContext.usePrivateBrowsing, false,
+ "Should be able to change origin attributes prior to a document load");
+
+ webNav.loadURI("data:text/html,", webNav.LOAD_FLAGS_NONE, null, null, null);
+
+ // Return to the event loop so the load can begin.
+ yield new Promise(do_execute_soon);
+
+ // This causes a failed assertion rather than an exception on debug
+ // builds.
+ if (!AppConstants.DEBUG) {
+ Assert.throws(() => { loadContext.usePrivateBrowsing = true; },
+ /NS_ERROR_FAILURE/,
+ "Should not be able to change private browsing state after initial load has started");
+
+ oa.privateBrowsingId = 1;
+ Assert.throws(() => { docShell.setOriginAttributes(oa); },
+ /NS_ERROR_FAILURE/,
+ "Should not be able to change origin attributes after initial load has started");
+
+ equal(loadContext.usePrivateBrowsing, false,
+ "Should not be able to change private browsing state after initial load has started");
+
+ loadContext.usePrivateBrowsing = false;
+ ok(true, "Should be able to set usePrivateBrowsing to its current value even after initial load");
+ }
+
+ webNav.close();
+});
diff --git a/docshell/test/unit/xpcshell.ini b/docshell/test/unit/xpcshell.ini
new file mode 100644
index 0000000000..ce8ec8b63a
--- /dev/null
+++ b/docshell/test/unit/xpcshell.ini
@@ -0,0 +1,17 @@
+[DEFAULT]
+head = head_docshell.js
+tail =
+
+[test_bug414201_jfif.js]
+[test_bug442584.js]
+[test_nsDefaultURIFixup.js]
+[test_nsDefaultURIFixup_search.js]
+skip-if = os == 'android'
+[test_nsDefaultURIFixup_info.js]
+skip-if = os == 'android'
+[test_nsIDownloadHistory.js]
+[test_pb_notification.js]
+# Bug 751575: unrelated JS changes cause timeouts on random platforms
+skip-if = true
+[test_privacy_transition.js]
+[test_setUsePrivateBrowsing.js]
diff --git a/docshell/test/unit_ipc/test_pb_notification_ipc.js b/docshell/test/unit_ipc/test_pb_notification_ipc.js
new file mode 100644
index 0000000000..1517a479fd
--- /dev/null
+++ b/docshell/test/unit_ipc/test_pb_notification_ipc.js
@@ -0,0 +1,20 @@
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+
+function run_test() {
+ var notifications = 0;
+ var obs = {
+ observe: function(aSubject, aTopic, aData) {
+ do_check_eq(aTopic, "last-pb-context-exited");
+ notifications++;
+ }
+ };
+ var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+ os.addObserver(obs, "last-pb-context-exited", false);
+
+ run_test_in_child("../unit/test_pb_notification.js",
+ function() {
+ do_check_eq(notifications, 1);
+ do_test_finished();
+ });
+} \ No newline at end of file
diff --git a/docshell/test/unit_ipc/xpcshell.ini b/docshell/test/unit_ipc/xpcshell.ini
new file mode 100644
index 0000000000..7a2df27c09
--- /dev/null
+++ b/docshell/test/unit_ipc/xpcshell.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+head =
+tail =
+skip-if = toolkit == 'android'
+
+[test_pb_notification_ipc.js]
+# Bug 751575: Perma-fails with: command timed out: 1200 seconds without output
+skip-if = true