From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- dom/xhr/tests/browser.toml | 18 + dom/xhr/tests/browser_blobFromFile.js | 64 +++ .../browser_sync_xhr_event_handing_switch_bcg.js | 144 ++++++ dom/xhr/tests/browser_temporaryFile.js | 71 +++ dom/xhr/tests/browser_xhr_onchange_leak.html | 25 ++ dom/xhr/tests/browser_xhr_onchange_leak.js | 31 ++ ...browser_xhr_substituted_protocol_responseURL.js | 27 ++ dom/xhr/tests/common_temporaryFileBlob.js | 126 ++++++ dom/xhr/tests/crashtests/1546185.html | 42 ++ dom/xhr/tests/crashtests/crashtests.list | 1 + dom/xhr/tests/echo.sjs | 26 ++ dom/xhr/tests/empty.html | 0 dom/xhr/tests/empty_parent.html | 0 dom/xhr/tests/file_XHRDocURI.html | 9 + dom/xhr/tests/file_XHRDocURI.html^headers^ | 3 + dom/xhr/tests/file_XHRDocURI.sjs | 12 + dom/xhr/tests/file_XHRDocURI.text | 1 + dom/xhr/tests/file_XHRDocURI.text^headers^ | 3 + dom/xhr/tests/file_XHRDocURI.xml | 1 + dom/xhr/tests/file_XHRDocURI.xml^headers^ | 3 + dom/xhr/tests/file_XHRResponseURL.js | 388 ++++++++++++++++ dom/xhr/tests/file_XHRResponseURL.sjs | 13 + dom/xhr/tests/file_XHRResponseURL.text | 1 + dom/xhr/tests/file_XHRResponseURL.text^headers^ | 3 + dom/xhr/tests/file_XHRResponseURL_nocors.text | 1 + dom/xhr/tests/file_XHRSendData.sjs | 34 ++ dom/xhr/tests/file_XHRSendData_doc.xml | 2 + dom/xhr/tests/file_XHRSendData_doc.xml^headers^ | 1 + dom/xhr/tests/file_XHR_anon.sjs | 24 + dom/xhr/tests/file_XHR_binary1.bin | Bin 0 -> 12 bytes dom/xhr/tests/file_XHR_binary1.bin^headers^ | 1 + dom/xhr/tests/file_XHR_binary2.bin | Bin 0 -> 65536 bytes dom/xhr/tests/file_XHR_fail1.txt | 1 + dom/xhr/tests/file_XHR_fail1.txt^headers^ | 2 + dom/xhr/tests/file_XHR_fail1b.txt | 1 + dom/xhr/tests/file_XHR_header.sjs | 8 + dom/xhr/tests/file_XHR_pass1.xml | 1 + dom/xhr/tests/file_XHR_pass2.txt | 1 + dom/xhr/tests/file_XHR_pass3.txt | 1 + dom/xhr/tests/file_XHR_pass3.txt^headers^ | 2 + dom/xhr/tests/file_XHR_system_redirect.html | 5 + .../tests/file_XHR_system_redirect.html^headers^ | 2 + dom/xhr/tests/file_XHR_timeout.sjs | 16 + dom/xhr/tests/file_html_in_xhr.html | 16 + dom/xhr/tests/file_html_in_xhr.sjs | 19 + dom/xhr/tests/file_html_in_xhr2.html | 1 + dom/xhr/tests/file_html_in_xhr3.html | 1 + .../file_sync_xhr_document_write_with_iframe.html | 22 + .../tests/file_sync_xhr_event_handling_helper.html | 37 ++ dom/xhr/tests/file_sync_xhr_nested_helper.html | 30 ++ dom/xhr/tests/iframe_sync_xhr_unload.html | 17 + dom/xhr/tests/mochitest.toml | 242 ++++++++++ dom/xhr/tests/progressserver.sjs | 56 +++ dom/xhr/tests/relativeLoad_import.js | 5 + dom/xhr/tests/relativeLoad_worker.js | 31 ++ dom/xhr/tests/relativeLoad_worker2.js | 11 + dom/xhr/tests/responseIdentical.sjs | 19 + dom/xhr/tests/slow.sjs | 13 + dom/xhr/tests/subdir/relativeLoad_sub_import.js | 5 + dom/xhr/tests/subdir/relativeLoad_sub_worker.js | 28 ++ dom/xhr/tests/subdir/relativeLoad_sub_worker2.js | 11 + dom/xhr/tests/sync_xhr_unload.sjs | 16 + dom/xhr/tests/temporaryFileBlob.sjs | 45 ++ dom/xhr/tests/terminateSyncXHR_worker.js | 20 + dom/xhr/tests/test_XHR.html | 17 + dom/xhr/tests/test_XHR.js | 438 ++++++++++++++++++ dom/xhr/tests/test_XHRDocURI.html | 487 +++++++++++++++++++++ dom/xhr/tests/test_XHRResponseURL.html | 69 +++ dom/xhr/tests/test_XHRSendData.html | 270 ++++++++++++ dom/xhr/tests/test_XHR_anon.html | 180 ++++++++ dom/xhr/tests/test_XHR_header.html | 32 ++ dom/xhr/tests/test_XHR_http2.html | 17 + dom/xhr/tests/test_XHR_onuploadprogress.html | 40 ++ dom/xhr/tests/test_XHR_parameters.html | 97 ++++ dom/xhr/tests/test_XHR_system.html | 99 +++++ dom/xhr/tests/test_XHR_timeout.html | 59 +++ dom/xhr/tests/test_XHR_timeout.js | 415 ++++++++++++++++++ dom/xhr/tests/test_bug1070763.html | 58 +++ dom/xhr/tests/test_bug1300552.html | 29 ++ dom/xhr/tests/test_bug1697539.html | 27 ++ dom/xhr/tests/test_bug1752863.html | 32 ++ dom/xhr/tests/test_bug1752863_worker.js | 34 ++ dom/xhr/tests/test_bug1788125.html | 59 +++ dom/xhr/tests/test_event_listener_leaks.html | 45 ++ dom/xhr/tests/test_html_in_xhr.html | 97 ++++ dom/xhr/tests/test_nestedSyncXHR.html | 101 +++++ dom/xhr/tests/test_relativeLoad.html | 51 +++ dom/xhr/tests/test_sharedworker_xhr.html | 23 + .../test_sync_xhr_document_write_with_iframe.html | 28 ++ dom/xhr/tests/test_sync_xhr_event_handling.html | 39 ++ dom/xhr/tests/test_sync_xhr_nested.html | 47 ++ dom/xhr/tests/test_sync_xhr_timer.xhtml | 52 +++ dom/xhr/tests/test_sync_xhr_unload.html | 36 ++ dom/xhr/tests/test_temporaryFileBlob.html | 40 ++ dom/xhr/tests/test_worker_terminateSyncXHR.html | 44 ++ dom/xhr/tests/test_worker_xhr.html | 76 ++++ dom/xhr/tests/test_worker_xhr2.html | 37 ++ dom/xhr/tests/test_worker_xhrAbort.html | 44 ++ dom/xhr/tests/test_worker_xhr_3rdparty.html | 51 +++ dom/xhr/tests/test_worker_xhr_cors_redirect.html | 35 ++ dom/xhr/tests/test_worker_xhr_doubleSend.html | 30 ++ dom/xhr/tests/test_worker_xhr_headers.html | 86 ++++ dom/xhr/tests/test_worker_xhr_implicit_cancel.html | 43 ++ dom/xhr/tests/test_worker_xhr_parameters.html | 66 +++ dom/xhr/tests/test_worker_xhr_parameters.js | 84 ++++ dom/xhr/tests/test_worker_xhr_responseURL.html | 76 ++++ dom/xhr/tests/test_worker_xhr_system.html | 54 +++ dom/xhr/tests/test_worker_xhr_system.js | 30 ++ dom/xhr/tests/test_worker_xhr_timeout.html | 57 +++ dom/xhr/tests/test_xhr_abort_after_load.html | 96 ++++ dom/xhr/tests/test_xhr_forbidden_headers.html | 96 ++++ ...r_overridemimetype_throws_on_invalid_state.html | 62 +++ dom/xhr/tests/test_xhr_progressevents.html | 307 +++++++++++++ dom/xhr/tests/test_xhr_send.html | 83 ++++ dom/xhr/tests/test_xhr_send_readystate.html | 39 ++ dom/xhr/tests/test_xhr_withCredentials.html | 35 ++ dom/xhr/tests/window_worker_xhr_3rdparty.html | 75 ++++ dom/xhr/tests/worker_bug1300552.js | 37 ++ dom/xhr/tests/worker_bug1697539.js | 19 + dom/xhr/tests/worker_file_getcookie.sjs | 15 + dom/xhr/tests/worker_temporaryFileBlob.js | 30 ++ dom/xhr/tests/worker_terminateSyncXHR_frame.html | 25 ++ dom/xhr/tests/worker_testXHR.txt | 1 + dom/xhr/tests/worker_xhr_cors_redirect.js | 10 + dom/xhr/tests/worker_xhr_cors_redirect.sjs | 10 + dom/xhr/tests/worker_xhr_headers_server.sjs | 69 +++ dom/xhr/tests/worker_xhr_headers_worker.js | 16 + dom/xhr/tests/xhr2_worker.js | 102 +++++ dom/xhr/tests/xhrAbort_worker.js | 101 +++++ dom/xhr/tests/xhr_implicit_cancel_worker.js | 10 + dom/xhr/tests/xhr_sharedworker.js | 105 +++++ dom/xhr/tests/xhr_worker.js | 84 ++++ dom/xhr/tests/xhr_worker_doubleSend.js | 11 + 133 files changed, 7029 insertions(+) create mode 100644 dom/xhr/tests/browser.toml create mode 100644 dom/xhr/tests/browser_blobFromFile.js create mode 100644 dom/xhr/tests/browser_sync_xhr_event_handing_switch_bcg.js create mode 100644 dom/xhr/tests/browser_temporaryFile.js create mode 100644 dom/xhr/tests/browser_xhr_onchange_leak.html create mode 100644 dom/xhr/tests/browser_xhr_onchange_leak.js create mode 100644 dom/xhr/tests/browser_xhr_substituted_protocol_responseURL.js create mode 100644 dom/xhr/tests/common_temporaryFileBlob.js create mode 100644 dom/xhr/tests/crashtests/1546185.html create mode 100644 dom/xhr/tests/crashtests/crashtests.list create mode 100644 dom/xhr/tests/echo.sjs create mode 100644 dom/xhr/tests/empty.html create mode 100644 dom/xhr/tests/empty_parent.html create mode 100644 dom/xhr/tests/file_XHRDocURI.html create mode 100644 dom/xhr/tests/file_XHRDocURI.html^headers^ create mode 100644 dom/xhr/tests/file_XHRDocURI.sjs create mode 100644 dom/xhr/tests/file_XHRDocURI.text create mode 100644 dom/xhr/tests/file_XHRDocURI.text^headers^ create mode 100644 dom/xhr/tests/file_XHRDocURI.xml create mode 100644 dom/xhr/tests/file_XHRDocURI.xml^headers^ create mode 100644 dom/xhr/tests/file_XHRResponseURL.js create mode 100644 dom/xhr/tests/file_XHRResponseURL.sjs create mode 100644 dom/xhr/tests/file_XHRResponseURL.text create mode 100644 dom/xhr/tests/file_XHRResponseURL.text^headers^ create mode 100644 dom/xhr/tests/file_XHRResponseURL_nocors.text create mode 100644 dom/xhr/tests/file_XHRSendData.sjs create mode 100644 dom/xhr/tests/file_XHRSendData_doc.xml create mode 100644 dom/xhr/tests/file_XHRSendData_doc.xml^headers^ create mode 100644 dom/xhr/tests/file_XHR_anon.sjs create mode 100644 dom/xhr/tests/file_XHR_binary1.bin create mode 100644 dom/xhr/tests/file_XHR_binary1.bin^headers^ create mode 100644 dom/xhr/tests/file_XHR_binary2.bin create mode 100644 dom/xhr/tests/file_XHR_fail1.txt create mode 100644 dom/xhr/tests/file_XHR_fail1.txt^headers^ create mode 100644 dom/xhr/tests/file_XHR_fail1b.txt create mode 100644 dom/xhr/tests/file_XHR_header.sjs create mode 100644 dom/xhr/tests/file_XHR_pass1.xml create mode 100644 dom/xhr/tests/file_XHR_pass2.txt create mode 100644 dom/xhr/tests/file_XHR_pass3.txt create mode 100644 dom/xhr/tests/file_XHR_pass3.txt^headers^ create mode 100644 dom/xhr/tests/file_XHR_system_redirect.html create mode 100644 dom/xhr/tests/file_XHR_system_redirect.html^headers^ create mode 100644 dom/xhr/tests/file_XHR_timeout.sjs create mode 100644 dom/xhr/tests/file_html_in_xhr.html create mode 100644 dom/xhr/tests/file_html_in_xhr.sjs create mode 100644 dom/xhr/tests/file_html_in_xhr2.html create mode 100644 dom/xhr/tests/file_html_in_xhr3.html create mode 100644 dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html create mode 100644 dom/xhr/tests/file_sync_xhr_event_handling_helper.html create mode 100644 dom/xhr/tests/file_sync_xhr_nested_helper.html create mode 100644 dom/xhr/tests/iframe_sync_xhr_unload.html create mode 100644 dom/xhr/tests/mochitest.toml create mode 100644 dom/xhr/tests/progressserver.sjs create mode 100644 dom/xhr/tests/relativeLoad_import.js create mode 100644 dom/xhr/tests/relativeLoad_worker.js create mode 100644 dom/xhr/tests/relativeLoad_worker2.js create mode 100644 dom/xhr/tests/responseIdentical.sjs create mode 100644 dom/xhr/tests/slow.sjs create mode 100644 dom/xhr/tests/subdir/relativeLoad_sub_import.js create mode 100644 dom/xhr/tests/subdir/relativeLoad_sub_worker.js create mode 100644 dom/xhr/tests/subdir/relativeLoad_sub_worker2.js create mode 100644 dom/xhr/tests/sync_xhr_unload.sjs create mode 100644 dom/xhr/tests/temporaryFileBlob.sjs create mode 100644 dom/xhr/tests/terminateSyncXHR_worker.js create mode 100644 dom/xhr/tests/test_XHR.html create mode 100644 dom/xhr/tests/test_XHR.js create mode 100644 dom/xhr/tests/test_XHRDocURI.html create mode 100644 dom/xhr/tests/test_XHRResponseURL.html create mode 100644 dom/xhr/tests/test_XHRSendData.html create mode 100644 dom/xhr/tests/test_XHR_anon.html create mode 100644 dom/xhr/tests/test_XHR_header.html create mode 100644 dom/xhr/tests/test_XHR_http2.html create mode 100644 dom/xhr/tests/test_XHR_onuploadprogress.html create mode 100644 dom/xhr/tests/test_XHR_parameters.html create mode 100644 dom/xhr/tests/test_XHR_system.html create mode 100644 dom/xhr/tests/test_XHR_timeout.html create mode 100644 dom/xhr/tests/test_XHR_timeout.js create mode 100644 dom/xhr/tests/test_bug1070763.html create mode 100644 dom/xhr/tests/test_bug1300552.html create mode 100644 dom/xhr/tests/test_bug1697539.html create mode 100644 dom/xhr/tests/test_bug1752863.html create mode 100644 dom/xhr/tests/test_bug1752863_worker.js create mode 100644 dom/xhr/tests/test_bug1788125.html create mode 100644 dom/xhr/tests/test_event_listener_leaks.html create mode 100644 dom/xhr/tests/test_html_in_xhr.html create mode 100644 dom/xhr/tests/test_nestedSyncXHR.html create mode 100644 dom/xhr/tests/test_relativeLoad.html create mode 100644 dom/xhr/tests/test_sharedworker_xhr.html create mode 100644 dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html create mode 100644 dom/xhr/tests/test_sync_xhr_event_handling.html create mode 100644 dom/xhr/tests/test_sync_xhr_nested.html create mode 100644 dom/xhr/tests/test_sync_xhr_timer.xhtml create mode 100644 dom/xhr/tests/test_sync_xhr_unload.html create mode 100644 dom/xhr/tests/test_temporaryFileBlob.html create mode 100644 dom/xhr/tests/test_worker_terminateSyncXHR.html create mode 100644 dom/xhr/tests/test_worker_xhr.html create mode 100644 dom/xhr/tests/test_worker_xhr2.html create mode 100644 dom/xhr/tests/test_worker_xhrAbort.html create mode 100644 dom/xhr/tests/test_worker_xhr_3rdparty.html create mode 100644 dom/xhr/tests/test_worker_xhr_cors_redirect.html create mode 100644 dom/xhr/tests/test_worker_xhr_doubleSend.html create mode 100644 dom/xhr/tests/test_worker_xhr_headers.html create mode 100644 dom/xhr/tests/test_worker_xhr_implicit_cancel.html create mode 100644 dom/xhr/tests/test_worker_xhr_parameters.html create mode 100644 dom/xhr/tests/test_worker_xhr_parameters.js create mode 100644 dom/xhr/tests/test_worker_xhr_responseURL.html create mode 100644 dom/xhr/tests/test_worker_xhr_system.html create mode 100644 dom/xhr/tests/test_worker_xhr_system.js create mode 100644 dom/xhr/tests/test_worker_xhr_timeout.html create mode 100644 dom/xhr/tests/test_xhr_abort_after_load.html create mode 100644 dom/xhr/tests/test_xhr_forbidden_headers.html create mode 100644 dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html create mode 100644 dom/xhr/tests/test_xhr_progressevents.html create mode 100644 dom/xhr/tests/test_xhr_send.html create mode 100644 dom/xhr/tests/test_xhr_send_readystate.html create mode 100644 dom/xhr/tests/test_xhr_withCredentials.html create mode 100644 dom/xhr/tests/window_worker_xhr_3rdparty.html create mode 100644 dom/xhr/tests/worker_bug1300552.js create mode 100644 dom/xhr/tests/worker_bug1697539.js create mode 100644 dom/xhr/tests/worker_file_getcookie.sjs create mode 100644 dom/xhr/tests/worker_temporaryFileBlob.js create mode 100644 dom/xhr/tests/worker_terminateSyncXHR_frame.html create mode 100644 dom/xhr/tests/worker_testXHR.txt create mode 100644 dom/xhr/tests/worker_xhr_cors_redirect.js create mode 100644 dom/xhr/tests/worker_xhr_cors_redirect.sjs create mode 100644 dom/xhr/tests/worker_xhr_headers_server.sjs create mode 100644 dom/xhr/tests/worker_xhr_headers_worker.js create mode 100644 dom/xhr/tests/xhr2_worker.js create mode 100644 dom/xhr/tests/xhrAbort_worker.js create mode 100644 dom/xhr/tests/xhr_implicit_cancel_worker.js create mode 100644 dom/xhr/tests/xhr_sharedworker.js create mode 100644 dom/xhr/tests/xhr_worker.js create mode 100644 dom/xhr/tests/xhr_worker_doubleSend.js (limited to 'dom/xhr/tests') diff --git a/dom/xhr/tests/browser.toml b/dom/xhr/tests/browser.toml new file mode 100644 index 0000000000..2034b903a7 --- /dev/null +++ b/dom/xhr/tests/browser.toml @@ -0,0 +1,18 @@ +[DEFAULT] +support-files = ["browser_xhr_onchange_leak.html"] + +["browser_blobFromFile.js"] + +["browser_sync_xhr_event_handing_switch_bcg.js"] +support-files = [ + "empty.html", + "empty_parent.html", + "slow.sjs", +] + +["browser_temporaryFile.js"] +support-files = ["temporaryFileBlob.sjs"] + +["browser_xhr_onchange_leak.js"] + +["browser_xhr_substituted_protocol_responseURL.js"] diff --git a/dom/xhr/tests/browser_blobFromFile.js b/dom/xhr/tests/browser_blobFromFile.js new file mode 100644 index 0000000000..deaec142ae --- /dev/null +++ b/dom/xhr/tests/browser_blobFromFile.js @@ -0,0 +1,64 @@ +add_task(async function test() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.tabs.remote.separateFileUriProcess", true]], + }); + + let fileData = ""; + for (var i = 0; i < 100; ++i) { + fileData += "hello world!"; + } + + let file = Services.dirsvc.get("ProfD", Ci.nsIFile); + file.append("file.txt"); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + + let outStream = Cc[ + "@mozilla.org/network/file-output-stream;1" + ].createInstance(Ci.nsIFileOutputStream); + outStream.init( + file, + 0x02 | 0x08 | 0x20, // write, create, truncate + // eslint-disable-next-line no-octal + 0666, + 0 + ); + outStream.write(fileData, fileData.length); + outStream.close(); + + let fileHandler = Services.io + .getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler); + + let fileURL = fileHandler.getURLSpecFromActualFile(file); + + info("Opening url: " + fileURL); + let tab = BrowserTestUtils.addTab(gBrowser, fileURL); + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let blob = await SpecialPowers.spawn( + browser, + [file.leafName], + function (fileName) { + return new content.window.Promise(resolve => { + let xhr = new content.window.XMLHttpRequest(); + xhr.responseType = "blob"; + xhr.open("GET", fileName); + xhr.send(); + xhr.onload = function () { + resolve(xhr.response); + }; + }); + } + ); + + ok(File.isInstance(blob), "We have a file"); + + is(blob.size, file.fileSize, "The size matches"); + is(blob.name, file.leafName, "The name is correct"); + + file.remove(false); + + gBrowser.removeTab(tab); +}); diff --git a/dom/xhr/tests/browser_sync_xhr_event_handing_switch_bcg.js b/dom/xhr/tests/browser_sync_xhr_event_handing_switch_bcg.js new file mode 100644 index 0000000000..d7966b2dac --- /dev/null +++ b/dom/xhr/tests/browser_sync_xhr_event_handing_switch_bcg.js @@ -0,0 +1,144 @@ +const baseURL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" +); + +const childURL = `${baseURL}empty.html`; +const parentURL = `${baseURL}empty_parent.html`; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["dom.input_events.canSuspendInBCG.enabled", true]], + }); + if (!Services.appinfo.fissionAutostart) { + // Make sure the tab that is opened with noopener + // also in the same process as the parent. + await SpecialPowers.pushPrefEnv({ + set: [["dom.ipc.processCount", 1]], + }); + } +}); + +async function checkInputManagerStatus(openChildInSameBCG) { + let childTabPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + childURL, + true, + true + ); + + let xhrTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + parentURL, + true + ); + + let xhrTabIsHidden = BrowserTestUtils.waitForContentEvent( + xhrTab.linkedBrowser, + "visibilitychange" + ); + + await SpecialPowers.spawn( + xhrTab.linkedBrowser.browsingContext, + [openChildInSameBCG, childURL], + async function (sameBCG, url) { + if (sameBCG) { + content.open(url); + } else { + content.open(url, "", "noopener"); + } + } + ); + + await childTabPromise; + await xhrTabIsHidden; + + let xhrRequestIsReady = BrowserTestUtils.waitForContentEvent( + xhrTab.linkedBrowser, + "xhrRequestIsReady" + ); + + let xhrRequest = SpecialPowers.spawn( + xhrTab.linkedBrowser.browsingContext, + [], + () => { + var xhr = new content.XMLHttpRequest(); + xhr.open("GET", "slow.sjs", false); + content.document.dispatchEvent( + new content.Event("xhrRequestIsReady", { bubbles: true }) + ); + xhr.send(null); + } + ); + + // Need to wait for the xhrIsReady event because spawn is async, + // so the content needs to give us a signal that the sync XHR request + // has started + await xhrRequestIsReady; + + let childTab = gBrowser.tabs[2]; + + // Since the xhrTab has started the sync XHR request, + // the InputTaskManager should be suspended here + // if it is in the same browsing context as the opener + let isSuspendedBeforeSwitch = await SpecialPowers.spawn( + childTab.linkedBrowser.browsingContext, + [], + () => { + var utils = SpecialPowers.getDOMWindowUtils(content); + return utils.isInputTaskManagerSuspended; + } + ); + + is( + isSuspendedBeforeSwitch, + openChildInSameBCG, + "InputTaskManager should be suspended before tab switching" + ); + + // Switching away from the childTab and switching back to + // test the status of InputTaskManager gets updated accordingly + // based on whether the childTab is in the same BCG as the xhrTab or not. + await BrowserTestUtils.switchTab(gBrowser, xhrTab); + await BrowserTestUtils.switchTab(gBrowser, childTab); + + let isSuspendedAfterTabSwitch = await SpecialPowers.spawn( + childTab.linkedBrowser.browsingContext, + [], + () => { + var utils = SpecialPowers.getDOMWindowUtils(content); + return utils.isInputTaskManagerSuspended; + } + ); + + is( + isSuspendedAfterTabSwitch, + openChildInSameBCG, + "InputTaskManager should be either suspended or not suspended based whether childTab was opened in the same BCG" + ); + + await xhrRequest; + + let isSuspendedAfterXHRRequest = await SpecialPowers.spawn( + xhrTab.linkedBrowser.browsingContext, + [], + () => { + var utils = SpecialPowers.getDOMWindowUtils(content); + return utils.isInputTaskManagerSuspended; + } + ); + + is( + isSuspendedAfterXHRRequest, + false, + "InputTaskManager should not be suspended before after the sync XHR is done" + ); + + gBrowser.removeTab(xhrTab); + gBrowser.removeTab(childTab); +} + +add_task(async function switchBCG() { + await checkInputManagerStatus(true); + await checkInputManagerStatus(false); +}); diff --git a/dom/xhr/tests/browser_temporaryFile.js b/dom/xhr/tests/browser_temporaryFile.js new file mode 100644 index 0000000000..c3694d9237 --- /dev/null +++ b/dom/xhr/tests/browser_temporaryFile.js @@ -0,0 +1,71 @@ +add_task(async _ => { + await new Promise(resolve => { + var xhr = new XMLHttpRequest(); + xhr.open( + "POST", + "http://mochi.test:8888/browser/dom/xhr/tests/temporaryFileBlob.sjs" + ); + xhr.responseType = "blob"; + xhr.send(""); + xhr.onloadend = __ => { + is(xhr.response.blobImplType, "EmptyBlobImpl", "We want a EmptyBlobImpl"); + resolve(); + }; + }); +}); + +add_task(async _ => { + var data = new Array(2).join("1234567890ABCDEF"); + + await new Promise(resolve => { + var xhr = new XMLHttpRequest(); + xhr.open( + "POST", + "http://mochi.test:8888/browser/dom/xhr/tests/temporaryFileBlob.sjs" + ); + xhr.responseType = "blob"; + xhr.send({ + toString() { + return data; + }, + }); + xhr.onloadend = __ => { + is( + xhr.response.blobImplType, + "MemoryBlobImpl", + "We want a MemoryBlobImpl" + ); + resolve(); + }; + }); +}); + +add_task(async _ => { + await SpecialPowers.pushPrefEnv({ + set: [["dom.blob.memoryToTemporaryFile", 1]], + }); + + var data = new Array(2).join("1234567890ABCDEF"); + + await new Promise(resolve => { + var xhr = new XMLHttpRequest(); + xhr.open( + "POST", + "http://mochi.test:8888/browser/dom/xhr/tests/temporaryFileBlob.sjs" + ); + xhr.responseType = "blob"; + xhr.send({ + toString() { + return data; + }, + }); + xhr.onloadend = __ => { + is( + xhr.response.blobImplType, + "StreamBlobImpl[TemporaryFileBlobImpl]", + "We want a StreamBlobImpl holding a TemporaryFileBlobImpl on the parent side" + ); + resolve(); + }; + }); +}); diff --git a/dom/xhr/tests/browser_xhr_onchange_leak.html b/dom/xhr/tests/browser_xhr_onchange_leak.html new file mode 100644 index 0000000000..56eb455330 --- /dev/null +++ b/dom/xhr/tests/browser_xhr_onchange_leak.html @@ -0,0 +1,25 @@ + + + + + + Test page for Bug 1336811 + + +

sample page

+ + + diff --git a/dom/xhr/tests/browser_xhr_onchange_leak.js b/dom/xhr/tests/browser_xhr_onchange_leak.js new file mode 100644 index 0000000000..4d13e33ee4 --- /dev/null +++ b/dom/xhr/tests/browser_xhr_onchange_leak.js @@ -0,0 +1,31 @@ +/* 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/. + */ + +// Bug 1336811 - An XHR that has a .onreadystatechange waiting should +// not leak forever once the tab is closed. CC optimizations need to be +// turned off once it is closed. + +add_task(async function test() { + // We need to reuse the content process when we navigate so the entire process + // with the possible-leaking window doesn't get torn down. + await SpecialPowers.pushPrefEnv({ + set: [["dom.ipc.keepProcessesAlive.webIsolated.perOrigin", 1]], + }); + + const url = + "http://mochi.test:8888/browser/dom/xhr/tests/browser_xhr_onchange_leak.html"; + let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url); + let browser = gBrowser.selectedBrowser; + let pageShowPromise = BrowserTestUtils.waitForContentEvent( + browser, + "pageshow", + true + ); + BrowserTestUtils.startLoadingURIString(browser, "http://mochi.test:8888/"); + await pageShowPromise; + + ok(pageShowPromise, "need to check something"); + BrowserTestUtils.removeTab(newTab); +}); diff --git a/dom/xhr/tests/browser_xhr_substituted_protocol_responseURL.js b/dom/xhr/tests/browser_xhr_substituted_protocol_responseURL.js new file mode 100644 index 0000000000..b5556d549f --- /dev/null +++ b/dom/xhr/tests/browser_xhr_substituted_protocol_responseURL.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/. + */ + +// Bug 1411725 - An XHR using a SubstitutingProtocolHandler channel +// (web-extension:, resource:, etc) should return the original URL, +// not the jar/file it was actually substituted for. + +const TEST_URL = "resource://gre/modules/XPCOMUtils.sys.mjs"; + +add_task(async function test() { + await new Promise(resolve => { + const xhr = new XMLHttpRequest(); + xhr.responseType = "text"; + xhr.open("get", TEST_URL); + xhr.addEventListener("loadend", () => { + is( + xhr.responseURL, + TEST_URL, + "original URL is given instead of substitution" + ); + resolve(); + }); + xhr.send(); + }); +}); diff --git a/dom/xhr/tests/common_temporaryFileBlob.js b/dom/xhr/tests/common_temporaryFileBlob.js new file mode 100644 index 0000000000..a84d58dd77 --- /dev/null +++ b/dom/xhr/tests/common_temporaryFileBlob.js @@ -0,0 +1,126 @@ +// This file expects next() to be defined in the scope it is imported into. +/* global next */ +var data = new Array(256).join("1234567890ABCDEF"); + +function createXHR() { + var xhr = new XMLHttpRequest(); + xhr.open("POST", "temporaryFileBlob.sjs"); + xhr.responseType = "blob"; + xhr.send({ + toString() { + return data; + }, + }); + return xhr; +} + +function test_simple() { + info("Simple test"); + + var xhr = createXHR(); + + xhr.onloadend = function () { + ok(xhr.response instanceof Blob, "We have a blob!"); + ok(!(xhr.response instanceof File), "Our blob is not a file!"); + if ("SpecialPowers" in self) { + is( + SpecialPowers.wrap(xhr.response).blobImplType, + "StreamBlobImpl[TemporaryFileBlobImpl]", + "We have a blob stored into a stream file" + ); + } + is(xhr.response.size, data.length, "Data length matches"); + + var fr = new FileReader(); + fr.readAsText(xhr.response); + fr.onload = function () { + is(fr.result, data, "Data content matches"); + next(); + }; + }; +} + +function test_abort() { + info("Aborting during onloading"); + + var xhr = createXHR(); + + xhr.onprogress = function () { + xhr.abort(); + }; + + xhr.onloadend = function () { + ok(!xhr.response, "We should not have a Blob!"); + next(); + }; +} + +function test_reuse() { + info("Reuse test"); + + var xhr = createXHR(); + + var count = 0; + xhr.onloadend = function () { + ok(xhr.response instanceof Blob, "We have a blob!"); + ok(!(xhr.response instanceof File), "Our blob is not a file!"); + if ("SpecialPowers" in self) { + is( + SpecialPowers.wrap(xhr.response).blobImplType, + "StreamBlobImpl[TemporaryFileBlobImpl]", + "We have a blob stored into a stream file" + ); + } + is(xhr.response.size, data.length, "Data length matches"); + + var fr = new FileReader(); + fr.readAsText(xhr.response); + fr.onload = function () { + is(fr.result, data, "Data content matches"); + if (++count > 2) { + next(); + return; + } + + xhr.open("POST", "temporaryFileBlob.sjs"); + xhr.responseType = "blob"; + xhr.send({ + toString() { + return data; + }, + }); + }; + }; +} + +function test_worker_generic(test) { + var w = new Worker("worker_temporaryFileBlob.js"); + w.onmessage = function (e) { + if (e.data.type == "info") { + info(e.data.msg); + } else if (e.data.type == "check") { + ok(e.data.what, e.data.msg); + } else if (e.data.type == "finish") { + next(); + } else { + ok(false, "Something wrong happened"); + } + }; + + w.postMessage(test); +} + +function test_worker() { + info("XHR in workers"); + test_worker_generic("simple"); +} + +function test_worker_abort() { + info("XHR in workers"); + test_worker_generic("abort"); +} + +function test_worker_reuse() { + info("XHR in workers"); + test_worker_generic("reuse"); +} diff --git a/dom/xhr/tests/crashtests/1546185.html b/dom/xhr/tests/crashtests/1546185.html new file mode 100644 index 0000000000..98eb673592 --- /dev/null +++ b/dom/xhr/tests/crashtests/1546185.html @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/dom/xhr/tests/crashtests/crashtests.list b/dom/xhr/tests/crashtests/crashtests.list new file mode 100644 index 0000000000..bd78bc54dc --- /dev/null +++ b/dom/xhr/tests/crashtests/crashtests.list @@ -0,0 +1 @@ +load 1546185.html diff --git a/dom/xhr/tests/echo.sjs b/dom/xhr/tests/echo.sjs new file mode 100644 index 0000000000..e2a1553cb4 --- /dev/null +++ b/dom/xhr/tests/echo.sjs @@ -0,0 +1,26 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain"); + if (request.method == "GET") { + response.write(request.queryString); + return; + } + + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var body = ""; + var bodyAvail; + while ((bodyAvail = bodyStream.available()) > 0) { + body += String.fromCharCode.apply( + null, + bodyStream.readByteArray(bodyAvail) + ); + } + + response.write(body); +} diff --git a/dom/xhr/tests/empty.html b/dom/xhr/tests/empty.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dom/xhr/tests/empty_parent.html b/dom/xhr/tests/empty_parent.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dom/xhr/tests/file_XHRDocURI.html b/dom/xhr/tests/file_XHRDocURI.html new file mode 100644 index 0000000000..8dbbb05491 --- /dev/null +++ b/dom/xhr/tests/file_XHRDocURI.html @@ -0,0 +1,9 @@ + + + + XMLHttpRequest return document URIs + + +
data
+ + diff --git a/dom/xhr/tests/file_XHRDocURI.html^headers^ b/dom/xhr/tests/file_XHRDocURI.html^headers^ new file mode 100644 index 0000000000..ddfd8c0a9e --- /dev/null +++ b/dom/xhr/tests/file_XHRDocURI.html^headers^ @@ -0,0 +1,3 @@ +HTTP 200 OK +Access-Control-Allow-Origin: * +Content-Type: text/html diff --git a/dom/xhr/tests/file_XHRDocURI.sjs b/dom/xhr/tests/file_XHRDocURI.sjs new file mode 100644 index 0000000000..452cb77f94 --- /dev/null +++ b/dom/xhr/tests/file_XHRDocURI.sjs @@ -0,0 +1,12 @@ +function handleRequest(aRequest, aResponse) { + var url = aRequest.queryString.match(/\burl=([^#&]*)/); + if (!url) { + aResponse.setStatusLine(aRequest.httpVersion, 404, "Not Found"); + return; + } + + url = decodeURIComponent(url[1]); + aResponse.setStatusLine(aRequest.httpVersion, 302, "Found"); + aResponse.setHeader("Cache-Control", "no-cache", false); + aResponse.setHeader("Location", url, false); +} diff --git a/dom/xhr/tests/file_XHRDocURI.text b/dom/xhr/tests/file_XHRDocURI.text new file mode 100644 index 0000000000..c1dead8d7a --- /dev/null +++ b/dom/xhr/tests/file_XHRDocURI.text @@ -0,0 +1 @@ +data diff --git a/dom/xhr/tests/file_XHRDocURI.text^headers^ b/dom/xhr/tests/file_XHRDocURI.text^headers^ new file mode 100644 index 0000000000..b2fe7cdeb4 --- /dev/null +++ b/dom/xhr/tests/file_XHRDocURI.text^headers^ @@ -0,0 +1,3 @@ +HTTP 200 OK +Access-Control-Allow-Origin: * +Content-Type: text/plain diff --git a/dom/xhr/tests/file_XHRDocURI.xml b/dom/xhr/tests/file_XHRDocURI.xml new file mode 100644 index 0000000000..c1a9a52566 --- /dev/null +++ b/dom/xhr/tests/file_XHRDocURI.xml @@ -0,0 +1 @@ +data diff --git a/dom/xhr/tests/file_XHRDocURI.xml^headers^ b/dom/xhr/tests/file_XHRDocURI.xml^headers^ new file mode 100644 index 0000000000..f47804337a --- /dev/null +++ b/dom/xhr/tests/file_XHRDocURI.xml^headers^ @@ -0,0 +1,3 @@ +HTTP 200 OK +Access-Control-Allow-Origin: * +Content-Type: application/xml diff --git a/dom/xhr/tests/file_XHRResponseURL.js b/dom/xhr/tests/file_XHRResponseURL.js new file mode 100644 index 0000000000..1ab1694bfa --- /dev/null +++ b/dom/xhr/tests/file_XHRResponseURL.js @@ -0,0 +1,388 @@ +"use strict"; + +// utility functions for worker/window communication + +function isInWorker() { + try { + return !(self instanceof Window); + } catch (e) { + return true; + } +} + +function message(aData) { + if (isInWorker()) { + self.postMessage(aData); + } else { + self.postMessage(aData, "*"); + } +} +message.ping = 0; +message.pong = 0; + +function is(aActual, aExpected, aMessage) { + var obj = { + type: "is", + actual: aActual, + expected: aExpected, + message: aMessage, + }; + ++message.ping; + message(obj); +} + +function ok(aBool, aMessage) { + var obj = { + type: "ok", + bool: aBool, + message: aMessage, + }; + ++message.ping; + message(obj); +} + +function info(aMessage) { + var obj = { + type: "info", + message: aMessage, + }; + ++message.ping; + message(obj); +} + +function request(aURL) { + return new Promise(function (aResolve, aReject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", aURL); + xhr.addEventListener("load", function () { + xhr.succeeded = true; + aResolve(xhr); + }); + xhr.addEventListener("error", function () { + xhr.succeeded = false; + aResolve(xhr); + }); + xhr.send(); + }); +} + +function createSequentialRequest(aParameters, aTest) { + var sequence = aParameters.reduce(function (aPromise, aParam) { + return aPromise + .then(function () { + return request(aParam.requestURL); + }) + .then(function (aXHR) { + return aTest(aXHR, aParam); + }); + }, Promise.resolve()); + + return sequence; +} + +function testSuccessResponse() { + var blob = new Blob(["data"], { type: "text/plain" }); + var blobURL = URL.createObjectURL(blob); + + var parameters = [ + // tests that start with same-origin request + { + message: "request to same-origin without redirect", + requestURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + responseURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: "request to same-origin redirect to same-origin URL", + requestURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + responseURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: + "request to same-origin redirects several times and finally go to same-origin URL", + requestURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + + encodeURIComponent( + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text" + ), + responseURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: "request to same-origin redirect to cross-origin URL", + requestURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + responseURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: + "request to same-origin redirects several times and finally go to cross-origin URL", + requestURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + + encodeURIComponent( + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text" + ), + responseURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + + // tests that start with cross-origin request + { + message: "request to cross-origin without redirect", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + responseURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: "request to cross-origin redirect back to same-origin URL", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + responseURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: "request to cross-origin redirect to the same cross-origin URL", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + responseURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: "request to cross-origin redirect to another cross-origin URL", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text", + responseURL: + "http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: + "request to cross-origin redirects several times and finally go to same-origin URL", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + + encodeURIComponent( + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text" + ), + responseURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: + "request to cross-origin redirects several times and finally go to the same cross-origin URL", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + + encodeURIComponent( + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text" + ), + responseURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: + "request to cross-origin redirects several times and finally go to another cross-origin URL", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + + encodeURIComponent( + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text" + ), + responseURL: + "http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: + "request to cross-origin redirects to another cross-origin and finally go to the other cross-origin URL", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + + encodeURIComponent( + "http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://test1.example.com/tests/dom/xhr/tests/file_XHRResponseURL.text" + ), + responseURL: + "http://test1.example.com/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + { + message: "request URL has fragment", + requestURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text#fragment", + responseURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text", + }, + + // tests for non-http(s) URL + { + message: "request to data: URL", + requestURL: "data:text/plain,data", + responseURL: "data:text/plain,data", + }, + { + message: "request to blob: URL", + requestURL: blobURL, + responseURL: blobURL, + }, + ]; + + var sequence = createSequentialRequest(parameters, function (aXHR, aParam) { + ok(aXHR.succeeded, "assert request succeeded"); + is(aXHR.responseURL, aParam.responseURL, aParam.message); + }); + + sequence.then(function () { + URL.revokeObjectURL(blobURL); + }); + + return sequence; +} + +function testFailedResponse() { + info("test not to leak responseURL for denied cross-origin request"); + var parameters = [ + { + message: + "should be empty for denied cross-origin request without redirect", + requestURL: + "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL_nocors.text", + }, + { + message: "should be empty for denied cross-origin request with redirect", + requestURL: + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL_nocors.text", + }, + ]; + + var sequence = createSequentialRequest(parameters, function (aXHR, aParam) { + ok(!aXHR.succeeded, "assert request failed"); + is(aXHR.responseURL, "", aParam.message); + }); + + return sequence; +} + +function testNotToLeakResponseURLWhileDoingRedirects() { + info("test not to leak responeseURL while doing redirects"); + + if (isInWorker()) { + return testNotToLeakResponseURLWhileDoingRedirectsInWorker(); + } + return testNotToLeakResponseURLWhileDoingRedirectsInWindow(); +} + +function testNotToLeakResponseURLWhileDoingRedirectsInWindow() { + var xhr = new XMLHttpRequest(); + var requestObserver = { + observe(aSubject, aTopic, aData) { + is(xhr.readyState, XMLHttpRequest.OPENED, "assert for XHR state"); + is( + xhr.responseURL, + "", + "responseURL should return empty string before HEADERS_RECEIVED" + ); + }, + }; + SpecialPowers.addObserver( + requestObserver, + "specialpowers-http-notify-request" + ); + + return new Promise(function (aResolve, aReject) { + xhr.open( + "GET", + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text" + ); + xhr.addEventListener("load", function () { + SpecialPowers.removeObserver( + requestObserver, + "specialpowers-http-notify-request" + ); + aResolve(); + }); + xhr.addEventListener("error", function () { + ok(false, "unexpected request falilure"); + SpecialPowers.removeObserver( + requestObserver, + "specialpowers-http-notify-request" + ); + aResolve(); + }); + xhr.send(); + }); +} + +function testNotToLeakResponseURLWhileDoingRedirectsInWorker() { + var xhr = new XMLHttpRequest(); + var testRedirect = function (e) { + if (e.data === "request" && xhr.readyState === XMLHttpRequest.OPENED) { + is( + xhr.responseURL, + "", + "responseURL should return empty string before HEADERS_RECEIVED" + ); + } + }; + + return new Promise(function (aResolve, aReject) { + self.addEventListener("message", testRedirect); + message({ type: "redirect_test", status: "start" }); + xhr.open( + "GET", + "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text" + ); + xhr.addEventListener("load", function () { + self.removeEventListener("message", testRedirect); + message({ type: "redirect_test", status: "end" }); + aResolve(); + }); + xhr.addEventListener("error", function (e) { + ok(false, "unexpected request falilure"); + self.removeEventListener("message", testRedirect); + message({ type: "redirect_test", status: "end" }); + aResolve(); + }); + xhr.send(); + }); +} + +function waitForAllMessagesProcessed() { + return new Promise(function (aResolve, aReject) { + var id = setInterval(function () { + if (message.ping === message.pong) { + clearInterval(id); + aResolve(); + } + }, 100); + }); +} + +self.addEventListener("message", function (aEvent) { + if (aEvent.data === "start") { + ok( + "responseURL" in new XMLHttpRequest(), + "XMLHttpRequest should have responseURL attribute" + ); + is( + new XMLHttpRequest().responseURL, + "", + "responseURL should be empty string if response's url is null" + ); + + var promise = testSuccessResponse(); + promise + .then(function () { + return testFailedResponse(); + }) + .then(function () { + return testNotToLeakResponseURLWhileDoingRedirects(); + }) + .then(function () { + return waitForAllMessagesProcessed(); + }) + .then(function () { + message("done"); + }); + } + if (aEvent.data === "pong") { + ++message.pong; + } +}); diff --git a/dom/xhr/tests/file_XHRResponseURL.sjs b/dom/xhr/tests/file_XHRResponseURL.sjs new file mode 100644 index 0000000000..792680dfce --- /dev/null +++ b/dom/xhr/tests/file_XHRResponseURL.sjs @@ -0,0 +1,13 @@ +function handleRequest(aRequest, aResponse) { + var url = aRequest.queryString.match(/\burl=([^#&]*)/); + if (!url) { + aResponse.setStatusLine(aRequest.httpVersion, 404, "Not Found"); + return; + } + url = decodeURIComponent(url[1]); + + aResponse.setStatusLine(aRequest.httpVersion, 302, "Found"); + aResponse.setHeader("Access-Control-Allow-Origin", "*", false); + aResponse.setHeader("Cache-Control", "no-cache", false); + aResponse.setHeader("Location", url, false); +} diff --git a/dom/xhr/tests/file_XHRResponseURL.text b/dom/xhr/tests/file_XHRResponseURL.text new file mode 100644 index 0000000000..1269488f7f --- /dev/null +++ b/dom/xhr/tests/file_XHRResponseURL.text @@ -0,0 +1 @@ +data diff --git a/dom/xhr/tests/file_XHRResponseURL.text^headers^ b/dom/xhr/tests/file_XHRResponseURL.text^headers^ new file mode 100644 index 0000000000..b2fe7cdeb4 --- /dev/null +++ b/dom/xhr/tests/file_XHRResponseURL.text^headers^ @@ -0,0 +1,3 @@ +HTTP 200 OK +Access-Control-Allow-Origin: * +Content-Type: text/plain diff --git a/dom/xhr/tests/file_XHRResponseURL_nocors.text b/dom/xhr/tests/file_XHRResponseURL_nocors.text new file mode 100644 index 0000000000..1269488f7f --- /dev/null +++ b/dom/xhr/tests/file_XHRResponseURL_nocors.text @@ -0,0 +1 @@ +data diff --git a/dom/xhr/tests/file_XHRSendData.sjs b/dom/xhr/tests/file_XHRSendData.sjs new file mode 100644 index 0000000000..a39d888fdc --- /dev/null +++ b/dom/xhr/tests/file_XHRSendData.sjs @@ -0,0 +1,34 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function handleRequest(request, response) { + if (request.hasHeader("Content-Type")) { + response.setHeader( + "Result-Content-Type", + request.getHeader("Content-Type") + ); + } + + response.setHeader("Content-Type", "text/plain; charset=ISO-8859-1"); + + 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.setHeader("Result-Content-Length", "" + data.length); + if (data.includes("TEST_REDIRECT_STR")) { + var newURL = "http://" + data.split("&url=")[1]; + response.setStatusLine(null, 307, "redirect"); + response.setHeader("Location", newURL, false); + } else { + response.write(data); + } +} diff --git a/dom/xhr/tests/file_XHRSendData_doc.xml b/dom/xhr/tests/file_XHRSendData_doc.xml new file mode 100644 index 0000000000..2e385258cb --- /dev/null +++ b/dom/xhr/tests/file_XHRSendData_doc.xml @@ -0,0 +1,2 @@ + +hi diff --git a/dom/xhr/tests/file_XHRSendData_doc.xml^headers^ b/dom/xhr/tests/file_XHRSendData_doc.xml^headers^ new file mode 100644 index 0000000000..b0f1ebfbf3 --- /dev/null +++ b/dom/xhr/tests/file_XHRSendData_doc.xml^headers^ @@ -0,0 +1 @@ +Content-Type: application/xml; charset=ISO-8859-1 diff --git a/dom/xhr/tests/file_XHR_anon.sjs b/dom/xhr/tests/file_XHR_anon.sjs new file mode 100644 index 0000000000..8440e9f0c2 --- /dev/null +++ b/dom/xhr/tests/file_XHR_anon.sjs @@ -0,0 +1,24 @@ +function handleRequest(request, response) { + let invalidHeaders = ["Cookie"]; + let headers = {}; + + if (request.queryString == "expectAuth=true") { + if (request.hasHeader("Authorization")) { + headers.authorization = request.getHeader("Authorization"); + } else { + response.setStatusLine(null, 401, "Authentication required"); + response.setHeader("WWW-Authenticate", 'basic realm="testrealm"', true); + } + } else { + invalidHeaders.push("Authorization"); + } + + for (let header of invalidHeaders) { + if (request.hasHeader(header)) { + response.setStatusLine(null, 500, "Server Error"); + headers[header.toLowerCase()] = request.getHeader(header); + } + } + + response.write(JSON.stringify(headers)); +} diff --git a/dom/xhr/tests/file_XHR_binary1.bin b/dom/xhr/tests/file_XHR_binary1.bin new file mode 100644 index 0000000000..39e527bfc3 Binary files /dev/null and b/dom/xhr/tests/file_XHR_binary1.bin differ diff --git a/dom/xhr/tests/file_XHR_binary1.bin^headers^ b/dom/xhr/tests/file_XHR_binary1.bin^headers^ new file mode 100644 index 0000000000..8e8c8d859e --- /dev/null +++ b/dom/xhr/tests/file_XHR_binary1.bin^headers^ @@ -0,0 +1 @@ +Content-Type: application/binary diff --git a/dom/xhr/tests/file_XHR_binary2.bin b/dom/xhr/tests/file_XHR_binary2.bin new file mode 100644 index 0000000000..9f442b092d Binary files /dev/null and b/dom/xhr/tests/file_XHR_binary2.bin differ diff --git a/dom/xhr/tests/file_XHR_fail1.txt b/dom/xhr/tests/file_XHR_fail1.txt new file mode 100644 index 0000000000..462209d8da --- /dev/null +++ b/dom/xhr/tests/file_XHR_fail1.txt @@ -0,0 +1 @@ +redirect file diff --git a/dom/xhr/tests/file_XHR_fail1.txt^headers^ b/dom/xhr/tests/file_XHR_fail1.txt^headers^ new file mode 100644 index 0000000000..41c2359329 --- /dev/null +++ b/dom/xhr/tests/file_XHR_fail1.txt^headers^ @@ -0,0 +1,2 @@ +HTTP 301 Moved Permanently +Location: http://example.com/tests/dom/xhr/tests/file_XHR_pass2.txt diff --git a/dom/xhr/tests/file_XHR_fail1b.txt b/dom/xhr/tests/file_XHR_fail1b.txt new file mode 100644 index 0000000000..8944657af1 --- /dev/null +++ b/dom/xhr/tests/file_XHR_fail1b.txt @@ -0,0 +1 @@ +hello pass diff --git a/dom/xhr/tests/file_XHR_header.sjs b/dom/xhr/tests/file_XHR_header.sjs new file mode 100644 index 0000000000..d520d2befe --- /dev/null +++ b/dom/xhr/tests/file_XHR_header.sjs @@ -0,0 +1,8 @@ +// SJS file for getAllResponseRequests vs getResponseRequest +function handleRequest(request, response) { + // Header strings are interpreted by truncating the characters in them to + // bytes, so U+2026 HORIZONTAL ELLIPSIS here must be encoded manually: using + // "…" as the string would write a \x26 byte. + response.setHeader("X-Custom-Header-Bytes", "\xE2\x80\xA6", false); + response.write("42"); +} diff --git a/dom/xhr/tests/file_XHR_pass1.xml b/dom/xhr/tests/file_XHR_pass1.xml new file mode 100644 index 0000000000..06826d6c67 --- /dev/null +++ b/dom/xhr/tests/file_XHR_pass1.xml @@ -0,0 +1 @@ +hello diff --git a/dom/xhr/tests/file_XHR_pass2.txt b/dom/xhr/tests/file_XHR_pass2.txt new file mode 100644 index 0000000000..0d7f879f95 --- /dev/null +++ b/dom/xhr/tests/file_XHR_pass2.txt @@ -0,0 +1 @@ +hello pass diff --git a/dom/xhr/tests/file_XHR_pass3.txt b/dom/xhr/tests/file_XHR_pass3.txt new file mode 100644 index 0000000000..462209d8da --- /dev/null +++ b/dom/xhr/tests/file_XHR_pass3.txt @@ -0,0 +1 @@ +redirect file diff --git a/dom/xhr/tests/file_XHR_pass3.txt^headers^ b/dom/xhr/tests/file_XHR_pass3.txt^headers^ new file mode 100644 index 0000000000..fb5056c382 --- /dev/null +++ b/dom/xhr/tests/file_XHR_pass3.txt^headers^ @@ -0,0 +1,2 @@ +HTTP 301 Moved Permanently +Location: file_XHR_pass2.txt diff --git a/dom/xhr/tests/file_XHR_system_redirect.html b/dom/xhr/tests/file_XHR_system_redirect.html new file mode 100644 index 0000000000..eaca3f49fd --- /dev/null +++ b/dom/xhr/tests/file_XHR_system_redirect.html @@ -0,0 +1,5 @@ + + + + + diff --git a/dom/xhr/tests/file_XHR_system_redirect.html^headers^ b/dom/xhr/tests/file_XHR_system_redirect.html^headers^ new file mode 100644 index 0000000000..cefb165b02 --- /dev/null +++ b/dom/xhr/tests/file_XHR_system_redirect.html^headers^ @@ -0,0 +1,2 @@ +HTTP 302 Found +Location: file:///etc/passwd diff --git a/dom/xhr/tests/file_XHR_timeout.sjs b/dom/xhr/tests/file_XHR_timeout.sjs new file mode 100644 index 0000000000..5eb14e96bc --- /dev/null +++ b/dom/xhr/tests/file_XHR_timeout.sjs @@ -0,0 +1,16 @@ +var timer = null; + +function handleRequest(request, response) { + response.processAsync(); + timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.initWithCallback( + function () { + response.setStatusLine(null, 200, "OK"); + response.setHeader("Content-Type", "text/plain", false); + response.write("hello"); + response.finish(); + }, + 2500 /* milliseconds */, + Ci.nsITimer.TYPE_ONE_SHOT + ); +} diff --git a/dom/xhr/tests/file_html_in_xhr.html b/dom/xhr/tests/file_html_in_xhr.html new file mode 100644 index 0000000000..d77aeb4402 --- /dev/null +++ b/dom/xhr/tests/file_html_in_xhr.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/dom/xhr/tests/file_html_in_xhr.sjs b/dom/xhr/tests/file_html_in_xhr.sjs new file mode 100644 index 0000000000..6e7c57cae4 --- /dev/null +++ b/dom/xhr/tests/file_html_in_xhr.sjs @@ -0,0 +1,19 @@ +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/javascript", false); + if (request.queryString.includes("report")) { + if (getState("loaded") == "loaded") { + response.write( + "ok(false, 'This script was not supposed to get fetched.'); continueAfterReport();" + ); + } else { + response.write( + "ok(true, 'This script was not supposed to get fetched.'); continueAfterReport();" + ); + } + } else { + setState("loaded", "loaded"); + response.write( + 'document.documentElement.setAttribute("data-fail", "FAIL");' + ); + } +} diff --git a/dom/xhr/tests/file_html_in_xhr2.html b/dom/xhr/tests/file_html_in_xhr2.html new file mode 100644 index 0000000000..046052c753 --- /dev/null +++ b/dom/xhr/tests/file_html_in_xhr2.html @@ -0,0 +1 @@ +Þ diff --git a/dom/xhr/tests/file_html_in_xhr3.html b/dom/xhr/tests/file_html_in_xhr3.html new file mode 100644 index 0000000000..ff43ca4091 --- /dev/null +++ b/dom/xhr/tests/file_html_in_xhr3.html @@ -0,0 +1 @@ +SUCCESS diff --git a/dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html b/dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html new file mode 100644 index 0000000000..2135011d9c --- /dev/null +++ b/dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html @@ -0,0 +1,22 @@ + + + + diff --git a/dom/xhr/tests/file_sync_xhr_event_handling_helper.html b/dom/xhr/tests/file_sync_xhr_event_handling_helper.html new file mode 100644 index 0000000000..d1235328f6 --- /dev/null +++ b/dom/xhr/tests/file_sync_xhr_event_handling_helper.html @@ -0,0 +1,37 @@ + + + + + + + diff --git a/dom/xhr/tests/file_sync_xhr_nested_helper.html b/dom/xhr/tests/file_sync_xhr_nested_helper.html new file mode 100644 index 0000000000..9b25a4453b --- /dev/null +++ b/dom/xhr/tests/file_sync_xhr_nested_helper.html @@ -0,0 +1,30 @@ + + + + + + + diff --git a/dom/xhr/tests/iframe_sync_xhr_unload.html b/dom/xhr/tests/iframe_sync_xhr_unload.html new file mode 100644 index 0000000000..134fad76d0 --- /dev/null +++ b/dom/xhr/tests/iframe_sync_xhr_unload.html @@ -0,0 +1,17 @@ + + + + + + diff --git a/dom/xhr/tests/mochitest.toml b/dom/xhr/tests/mochitest.toml new file mode 100644 index 0000000000..4ed62dc06b --- /dev/null +++ b/dom/xhr/tests/mochitest.toml @@ -0,0 +1,242 @@ +[DEFAULT] +support-files = [ + "echo.sjs", + "temporaryFileBlob.sjs", + "file_html_in_xhr.html", + "file_html_in_xhr.sjs", + "file_html_in_xhr2.html", + "file_html_in_xhr3.html", + "file_XHRDocURI.text", + "file_XHRDocURI.text^headers^", + "file_XHRDocURI.xml", + "file_XHRDocURI.xml^headers^", + "file_XHRDocURI.html", + "file_XHRDocURI.html^headers^", + "file_XHRDocURI.sjs", + "file_XHRResponseURL.js", + "file_XHRResponseURL.sjs", + "file_XHRResponseURL.text", + "file_XHRResponseURL.text^headers^", + "file_XHRResponseURL_nocors.text", + "file_XHRSendData.sjs", + "file_XHRSendData_doc.xml", + "file_XHRSendData_doc.xml^headers^", + "file_XHR_anon.sjs", + "file_XHR_binary1.bin", + "file_XHR_binary1.bin^headers^", + "file_XHR_binary2.bin", + "file_XHR_fail1.txt", + "file_XHR_fail1.txt^headers^", + "file_XHR_header.sjs", + "file_XHR_pass1.xml", + "file_XHR_pass2.txt", + "file_XHR_pass3.txt", + "file_XHR_pass3.txt^headers^", + "file_XHR_system_redirect.html", + "file_XHR_system_redirect.html^headers^", + "file_XHR_timeout.sjs", + "progressserver.sjs", + "worker_terminateSyncXHR_frame.html", + "terminateSyncXHR_worker.js", + "worker_testXHR.txt", + "xhr_worker.js", + "xhr2_worker.js", + "xhrAbort_worker.js", + "test_XHR.js", + "test_worker_xhr_parameters.js", + "test_worker_xhr_system.js", + "worker_xhr_cors_redirect.js", + "worker_xhr_cors_redirect.sjs", + "worker_xhr_headers_server.sjs", + "worker_xhr_headers_worker.js", + "worker_file_getcookie.sjs", + "xhr_implicit_cancel_worker.js", + "relativeLoad_import.js", + "relativeLoad_worker.js", + "relativeLoad_worker2.js", + "responseIdentical.sjs", + "subdir/relativeLoad_sub_worker.js", + "subdir/relativeLoad_sub_worker2.js", + "subdir/relativeLoad_sub_import.js", + "common_temporaryFileBlob.js", + "worker_temporaryFileBlob.js", + "worker_bug1300552.js", + "sync_xhr_unload.sjs", + "iframe_sync_xhr_unload.html", + "empty.html", + "file_sync_xhr_document_write_with_iframe.html", + "slow.sjs", + "!/dom/events/test/event_leak_utils.js", + "worker_bug1697539.js", +] + +["test_XHR.html"] +skip-if = [ + "http2", + "http3", +] + +["test_XHRDocURI.html"] +skip-if = [ + "http2", + "http3", +] + +["test_XHRResponseURL.html"] +skip-if = [ + "http2", + "http3", +] + +["test_XHRSendData.html"] + +["test_XHR_anon.html"] +skip-if = [ + "http2", + "http3", +] + +["test_XHR_header.html"] +skip-if = [ + "http2", + "http3", +] + +["test_XHR_http2.html"] +run-if = [ + "http2", + "http3", +] + +["test_XHR_onuploadprogress.html"] + +["test_XHR_parameters.html"] + +["test_XHR_system.html"] +skip-if = [ + "http2", + "http3", +] + +["test_XHR_timeout.html"] +support-files = ["test_XHR_timeout.js"] + +["test_bug1070763.html"] +skip-if = [ + "http2", + "http3", +] + +["test_bug1300552.html"] +skip-if = [ + "http2", + "http3", +] + +["test_bug1697539.html"] +support-files = ["worker_bug1697539.js"] + +["test_bug1752863.html"] +support-files = ["test_bug1752863_worker.js"] +skip-if = ["os == 'linux' && bits == 64 && !debug"] # Bug 1755010 + +["test_bug1788125.html"] + +["test_event_listener_leaks.html"] + +["test_html_in_xhr.html"] + +["test_nestedSyncXHR.html"] + +["test_relativeLoad.html"] + +["test_sharedworker_xhr.html"] +support-files = ["xhr_sharedworker.js"] + +["test_sync_xhr_document_write_with_iframe.html"] +skip-if = ["os == 'android' && debug"] + +["test_sync_xhr_event_handling.html"] +support-files = ["file_sync_xhr_event_handling_helper.html"] + +["test_sync_xhr_nested.html"] +support-files = ["file_sync_xhr_nested_helper.html"] +skip-if = ["release_or_beta"] # Input event will be discarded during sync XHR, thus timeout + +["test_sync_xhr_timer.xhtml"] + +["test_sync_xhr_unload.html"] + +["test_temporaryFileBlob.html"] +skip-if = [ + "http2", + "http3", +] + +["test_worker_terminateSyncXHR.html"] + +["test_worker_xhr.html"] + +["test_worker_xhr2.html"] + +["test_worker_xhrAbort.html"] +skip-if = [ + "os == 'win'", + "os == 'mac'", +] + +["test_worker_xhr_3rdparty.html"] +support-files = ["window_worker_xhr_3rdparty.html"] +# Bug 1617611: Fix all the tests broken by "cookies SameSite=lax by default" +skip-if = ["xorigin"] + +["test_worker_xhr_cors_redirect.html"] +skip-if = [ + "http2", + "http3", +] + +["test_worker_xhr_doubleSend.html"] +support-files = ["xhr_worker_doubleSend.js"] + +["test_worker_xhr_headers.html"] +skip-if = [ + "http2", + "http3", +] + +["test_worker_xhr_implicit_cancel.html"] + +["test_worker_xhr_parameters.html"] + +["test_worker_xhr_responseURL.html"] +skip-if = [ + "http2", + "http3", +] + +["test_worker_xhr_system.html"] +skip-if = [ + "http2", + "http3", +] + +["test_worker_xhr_timeout.html"] + +["test_xhr_abort_after_load.html"] + +["test_xhr_forbidden_headers.html"] + +["test_xhr_overridemimetype_throws_on_invalid_state.html"] + +["test_xhr_progressevents.html"] +skip-if = [ + "http2", + "http3", +] + +["test_xhr_send.html"] + +["test_xhr_send_readystate.html"] + +["test_xhr_withCredentials.html"] diff --git a/dom/xhr/tests/progressserver.sjs b/dom/xhr/tests/progressserver.sjs new file mode 100644 index 0000000000..3aae7e91db --- /dev/null +++ b/dom/xhr/tests/progressserver.sjs @@ -0,0 +1,56 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function setReq(req) { + setObjectState("dom/xhr/tests/progressserver", req); +} + +function getReq() { + var req; + getObjectState("dom/xhr/tests/progressserver", function (v) { + req = v; + }); + return req; +} + +function handleRequest(request, response) { + var pairs = request.queryString.split("&"); + var command = pairs.shift(); + dump("received '" + command + "' command\n"); + + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var body = ""; + var bodyAvail; + while ((bodyAvail = bodyStream.available()) > 0) { + body += String.fromCharCode.apply( + null, + bodyStream.readByteArray(bodyAvail) + ); + } + + if (command == "open") { + response.processAsync(); + setReq(response); + + response.setHeader("Cache-Control", "no-cache", false); + pairs.forEach(function (val) { + var [name, value] = val.split("="); + response.setHeader(name, unescape(value), false); + }); + response.write(body); + return; + } + + if (command == "send") { + getReq().write(body); + } else if (command == "close") { + getReq().finish(); + setReq(null); + } + response.setHeader("Content-Type", "text/plain"); + response.write("ok"); +} diff --git a/dom/xhr/tests/relativeLoad_import.js b/dom/xhr/tests/relativeLoad_import.js new file mode 100644 index 0000000000..114d1883cd --- /dev/null +++ b/dom/xhr/tests/relativeLoad_import.js @@ -0,0 +1,5 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +const workerURL = "relativeLoad_worker.js"; diff --git a/dom/xhr/tests/relativeLoad_worker.js b/dom/xhr/tests/relativeLoad_worker.js new file mode 100644 index 0000000000..b600b592be --- /dev/null +++ b/dom/xhr/tests/relativeLoad_worker.js @@ -0,0 +1,31 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +/* eslint-env worker */ +/* global workerURL */ +const importURL = "relativeLoad_import.js"; + +onmessage = function (event) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "worker_testXHR.txt", false); + xhr.send(null); + if ( + xhr.status != 200 || + xhr.responseText != "A noisy noise annoys an oyster." + ) { + throw new Error("Couldn't get xhr text from where we wanted it!"); + } + + importScripts(importURL); + var worker = new Worker("relativeLoad_worker2.js"); + worker.onerror = function (e) { + throw e.message; + }; + worker.onmessage = function (e) { + if (e.data != workerURL) { + throw new Error("Bad data!"); + } + postMessage(workerURL); + }; +}; diff --git a/dom/xhr/tests/relativeLoad_worker2.js b/dom/xhr/tests/relativeLoad_worker2.js new file mode 100644 index 0000000000..680f80a76a --- /dev/null +++ b/dom/xhr/tests/relativeLoad_worker2.js @@ -0,0 +1,11 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +/* eslint-env worker */ +/* global workerURL */ +const importURL = "relativeLoad_import.js"; + +importScripts(importURL); + +postMessage(workerURL); diff --git a/dom/xhr/tests/responseIdentical.sjs b/dom/xhr/tests/responseIdentical.sjs new file mode 100644 index 0000000000..0e7b796e0f --- /dev/null +++ b/dom/xhr/tests/responseIdentical.sjs @@ -0,0 +1,19 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +// Simply sending back the same data that is received +function handleRequest(request, response) { + var body = ""; + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var avail = 0; + while ((avail = bodyStream.available()) > 0) { + body += String.fromCharCode.apply(String, bodyStream.readByteArray(avail)); + } + + response.setHeader("Content-Type", "application/octet-stream", false); + response.write(body); +} diff --git a/dom/xhr/tests/slow.sjs b/dom/xhr/tests/slow.sjs new file mode 100644 index 0000000000..0d0308f6e7 --- /dev/null +++ b/dom/xhr/tests/slow.sjs @@ -0,0 +1,13 @@ +function handleRequest(request, response) { + response.processAsync(); + + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.init( + function () { + response.write("Here the content. But slowly."); + response.finish(); + }, + 5000, + Ci.nsITimer.TYPE_ONE_SHOT + ); +} diff --git a/dom/xhr/tests/subdir/relativeLoad_sub_import.js b/dom/xhr/tests/subdir/relativeLoad_sub_import.js new file mode 100644 index 0000000000..cac2a6f041 --- /dev/null +++ b/dom/xhr/tests/subdir/relativeLoad_sub_import.js @@ -0,0 +1,5 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +const workerSubURL = "subdir/relativeLoad_sub_worker.js"; diff --git a/dom/xhr/tests/subdir/relativeLoad_sub_worker.js b/dom/xhr/tests/subdir/relativeLoad_sub_worker.js new file mode 100644 index 0000000000..5c1a4d59fb --- /dev/null +++ b/dom/xhr/tests/subdir/relativeLoad_sub_worker.js @@ -0,0 +1,28 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +/* eslint-env worker */ +/* global workerSubURL */ +const importSubURL = "relativeLoad_sub_import.js"; + +onmessage = function (_) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "testXHR.txt", false); + xhr.send(null); + if (xhr.status != 404) { + throw new Error("Loaded an xhr from the wrong location!"); + } + + importScripts(importSubURL); + var worker = new Worker("relativeLoad_sub_worker2.js"); + worker.onerror = function (event) { + throw event.data; + }; + worker.onmessage = function (event) { + if (event.data != workerSubURL) { + throw new Error("Bad data!"); + } + postMessage(workerSubURL); + }; +}; diff --git a/dom/xhr/tests/subdir/relativeLoad_sub_worker2.js b/dom/xhr/tests/subdir/relativeLoad_sub_worker2.js new file mode 100644 index 0000000000..b3e2c14d1a --- /dev/null +++ b/dom/xhr/tests/subdir/relativeLoad_sub_worker2.js @@ -0,0 +1,11 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +/* eslint-env worker */ +/* global workerSubURL */ +const importSubURL = "relativeLoad_sub_import.js"; + +importScripts(importSubURL); + +postMessage(workerSubURL); diff --git a/dom/xhr/tests/sync_xhr_unload.sjs b/dom/xhr/tests/sync_xhr_unload.sjs new file mode 100644 index 0000000000..f4f92649a8 --- /dev/null +++ b/dom/xhr/tests/sync_xhr_unload.sjs @@ -0,0 +1,16 @@ +var timer = null; + +function handleRequest(request, response) { + response.processAsync(); + timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.initWithCallback( + function () { + response.setStatusLine(null, 200, "OK"); + response.setHeader("Content-Type", "text/plain", false); + response.write("hello"); + response.finish(); + }, + 30000 /* milliseconds */, + Ci.nsITimer.TYPE_ONE_SHOT + ); +} diff --git a/dom/xhr/tests/temporaryFileBlob.sjs b/dom/xhr/tests/temporaryFileBlob.sjs new file mode 100644 index 0000000000..d952b325ce --- /dev/null +++ b/dom/xhr/tests/temporaryFileBlob.sjs @@ -0,0 +1,45 @@ +const CC = Components.Constructor; + +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); +const BinaryOutputStream = CC( + "@mozilla.org/binaryoutputstream;1", + "nsIBinaryOutputStream", + "setOutputStream" +); +const Timer = CC("@mozilla.org/timer;1", "nsITimer", "initWithCallback"); + +function handleRequest(request, response) { + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var bodyBytes = []; + let bodyAvail; + while ((bodyAvail = bodyStream.available()) > 0) { + Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail)); + } + + var bos = new BinaryOutputStream(response.bodyOutputStream); + + response.processAsync(); + + var part = bodyBytes.splice(0, 256); + bos.writeByteArray(part); + + response.timer1 = new Timer( + function (timer) { + bos.writeByteArray(bodyBytes); + }, + 1000, + Ci.nsITimer.TYPE_ONE_SHOT + ); + + response.timer2 = new Timer( + function (timer) { + response.finish(); + }, + 2000, + Ci.nsITimer.TYPE_ONE_SHOT + ); +} diff --git a/dom/xhr/tests/terminateSyncXHR_worker.js b/dom/xhr/tests/terminateSyncXHR_worker.js new file mode 100644 index 0000000000..7a2509af3d --- /dev/null +++ b/dom/xhr/tests/terminateSyncXHR_worker.js @@ -0,0 +1,20 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +onmessage = function (event) { + throw new Error("No messages should reach me!"); +}; + +var xhr = new XMLHttpRequest(); +xhr.open("GET", "worker_testXHR.txt", false); +xhr.addEventListener("loadstart", function () { + // Tell the parent to terminate us. + postMessage("TERMINATE"); + // And wait for it to do so. + while (1) { + true; + } +}); +xhr.send(null); diff --git a/dom/xhr/tests/test_XHR.html b/dom/xhr/tests/test_XHR.html new file mode 100644 index 0000000000..b8925750f6 --- /dev/null +++ b/dom/xhr/tests/test_XHR.html @@ -0,0 +1,17 @@ + + + + Test for XMLHttpRequest + + + + +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR.js b/dom/xhr/tests/test_XHR.js new file mode 100644 index 0000000000..12eb06e4f6 --- /dev/null +++ b/dom/xhr/tests/test_XHR.js @@ -0,0 +1,438 @@ +"use strict"; +SimpleTest.waitForExplicitFinish(); + +var gen = runTests(); +function continueTest() { + gen.next(); +} + +function* runTests() { + var expectHttp2Results = location.href.includes("http2"); + + var path = "/tests/dom/xhr/tests/"; + + var passFiles = [ + ["file_XHR_pass1.xml", "GET", 200, "OK", "text/xml"], + ["file_XHR_pass2.txt", "GET", 200, "OK", "text/plain"], + ["file_XHR_pass3.txt", "GET", 200, "OK", "text/plain"], + ["data:text/xml,%3Cres%3Ehello%3C/res%3E%0A", "GET", 200, "OK", "text/xml"], + ["data:text/plain,hello%20pass%0A", "GET", 200, "OK", "text/plain"], + ["data:,foo", "GET", 200, "OK", "text/plain;charset=US-ASCII", "foo"], + ["data:text/plain;base64,Zm9v", "GET", 200, "OK", "text/plain", "foo"], + ["data:text/plain,foo#bar", "GET", 200, "OK", "text/plain", "foo"], + ["data:text/plain,foo%23bar", "GET", 200, "OK", "text/plain", "foo#bar"], + ]; + + var blob = new Blob(["foo"], { type: "text/plain" }); + var blobURL = URL.createObjectURL(blob); + + passFiles.push([blobURL, "GET", 200, "OK", "text/plain", "foo"]); + + var failFiles = [ + ["//example.com" + path + "file_XHR_pass1.xml", "GET"], + ["ftp://localhost" + path + "file_XHR_pass1.xml", "GET"], + ["file_XHR_fail1.txt", "GET"], + ]; + + for (i = 0; i < passFiles.length; ++i) { + // Function to give our hacked is() a scope + (function (oldIs) { + function is(actual, expected, message) { + oldIs(actual, expected, message + " for " + passFiles[i][0]); + } + xhr = new XMLHttpRequest(); + is(xhr.getResponseHeader("Content-Type"), null, "should be null"); + is(xhr.getAllResponseHeaders(), "", "should be empty string"); + is(xhr.responseType, "", "wrong initial responseType"); + xhr.open(passFiles[i][1], passFiles[i][0], false); + xhr.send(null); + is(xhr.status, passFiles[i][2], "wrong status"); + + // over HTTP2, no status text is received for network requests (but + // data/blob URLs default to "200 OK" responses) + let expectedStatusText = passFiles[i][3]; + if ( + expectHttp2Results && + !passFiles[i][0].startsWith("data:") && + !passFiles[i][0].startsWith("blob:") + ) { + expectedStatusText = ""; + } + is(xhr.statusText, expectedStatusText, "wrong statusText"); + + is( + xhr.getResponseHeader("Content-Type"), + passFiles[i][4], + "wrong content type" + ); + var headers = xhr.getAllResponseHeaders(); + ok( + /(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) && + RegExp.$1 === passFiles[i][4], + "wrong response headers" + ); + if (xhr.responseXML) { + is( + new XMLSerializer().serializeToString( + xhr.responseXML.documentElement + ), + passFiles[i][5] || "hello", + "wrong responseXML" + ); + is( + xhr.response, + passFiles[i][5] || "hello\n", + "wrong response" + ); + } else { + is( + xhr.responseText, + passFiles[i][5] || "hello pass\n", + "wrong responseText" + ); + is(xhr.response, passFiles[i][5] || "hello pass\n", "wrong response"); + } + })(is); + } + + URL.revokeObjectURL(blobURL); + + for (i = 0; i < failFiles.length; ++i) { + xhr = new XMLHttpRequest(); + let didthrow = false; + try { + xhr.open(failFiles[i][1], failFiles[i][0], false); + xhr.send(null); + } catch (e) { + didthrow = true; + } + if (!didthrow) { + is(xhr.status, 301, "wrong status"); + is(xhr.responseText, "redirect file\n", "wrong response"); + } else { + ok(1, "should have thrown or given incorrect result"); + } + } + + function checkResponseTextAccessThrows(xhr) { + let didthrow = false; + try { + xhr.responseText; + } catch (e) { + didthrow = true; + } + ok(didthrow, "should have thrown when accessing responseText"); + } + function checkResponseXMLAccessThrows(xhr) { + let didthrow = false; + try { + xhr.responseXML; + } catch (e) { + didthrow = true; + } + ok(didthrow, "should have thrown when accessing responseXML"); + } + function checkSetResponseType(xhr, type) { + let didthrow = false; + try { + xhr.responseType = type; + } catch (e) { + didthrow = true; + } + is(xhr.responseType, type, "responseType should be " + type); + ok(!didthrow, "should not have thrown when setting responseType"); + } + function checkSetResponseTypeThrows(xhr, type) { + let didthrow = false; + try { + xhr.responseType = type; + } catch (e) { + didthrow = true; + } + ok(didthrow, "should have thrown when setting responseType"); + } + function checkOpenThrows(xhr, method, url, async) { + let didthrow = false; + try { + xhr.open(method, url, async); + } catch (e) { + didthrow = true; + } + ok(didthrow, "should have thrown when open is called"); + } + + // test if setting responseType before calling open() works + xhr = new XMLHttpRequest(); + checkSetResponseType(xhr, ""); + checkSetResponseType(xhr, "text"); + checkSetResponseType(xhr, "document"); + checkSetResponseType(xhr, "arraybuffer"); + checkSetResponseType(xhr, "blob"); + checkSetResponseType(xhr, "json"); + checkOpenThrows(xhr, "GET", "file_XHR_pass2.txt", false); + + // test response (sync, responseType is not changeable) + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_pass2.txt", false); + checkSetResponseTypeThrows(xhr, ""); + checkSetResponseTypeThrows(xhr, "text"); + checkSetResponseTypeThrows(xhr, "document"); + checkSetResponseTypeThrows(xhr, "arraybuffer"); + checkSetResponseTypeThrows(xhr, "blob"); + checkSetResponseTypeThrows(xhr, "json"); + xhr.send(null); + checkSetResponseTypeThrows(xhr, "document"); + is(xhr.status, 200, "wrong status"); + is(xhr.response, "hello pass\n", "wrong response"); + + // test response (responseType='document') + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_pass1.xml"); + xhr.responseType = "document"; + xhr.onloadend = continueTest; + xhr.send(null); + yield undefined; + checkSetResponseTypeThrows(xhr, "document"); + is(xhr.status, 200, "wrong status"); + checkResponseTextAccessThrows(xhr); + is( + new XMLSerializer().serializeToString(xhr.response.documentElement), + "hello", + "wrong response" + ); + + // test response (responseType='text') + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_pass2.txt"); + xhr.responseType = "text"; + xhr.onloadend = continueTest; + xhr.send(null); + yield undefined; + is(xhr.status, 200, "wrong status"); + checkResponseXMLAccessThrows(xhr); + is(xhr.response, "hello pass\n", "wrong response"); + + // test response (responseType='arraybuffer') + function arraybuffer_equals_to(ab, s) { + is(ab.byteLength, s.length, "wrong arraybuffer byteLength"); + + var u8v = new Uint8Array(ab); + is(String.fromCharCode.apply(String, u8v), s, "wrong values"); + } + + // with a simple text file + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_pass2.txt"); + xhr.responseType = "arraybuffer"; + xhr.onloadend = continueTest; + xhr.send(null); + yield undefined; + is(xhr.status, 200, "wrong status"); + checkResponseTextAccessThrows(xhr); + checkResponseXMLAccessThrows(xhr); + var ab = xhr.response; + ok(ab != null, "should have a non-null arraybuffer"); + arraybuffer_equals_to(ab, "hello pass\n"); + + // test reusing the same XHR (Bug 680816) + xhr.open("GET", "file_XHR_binary1.bin"); + xhr.responseType = "arraybuffer"; + xhr.onloadend = continueTest; + xhr.send(null); + yield undefined; + is(xhr.status, 200, "wrong status"); + var ab2 = xhr.response; + ok(ab2 != null, "should have a non-null arraybuffer"); + ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct"); + arraybuffer_equals_to(ab, "hello pass\n"); + arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); + + // with a binary file + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_binary1.bin"); + xhr.responseType = "arraybuffer"; + xhr.onloadend = continueTest; + xhr.send(null); + yield undefined; + is(xhr.status, 200, "wrong status"); + checkResponseTextAccessThrows(xhr); + checkResponseXMLAccessThrows(xhr); + ab = xhr.response; + ok(ab != null, "should have a non-null arraybuffer"); + arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); + is(xhr.response, xhr.response, "returns the same ArrayBuffer"); + + // test response (responseType='json') + var xhr = new XMLHttpRequest(); + xhr.open("POST", "responseIdentical.sjs"); + xhr.responseType = "json"; + var jsonObjStr = JSON.stringify({ title: "aBook", author: "john" }); + xhr.onloadend = continueTest; + xhr.send(jsonObjStr); + yield undefined; + is(xhr.status, 200, "wrong status"); + checkResponseTextAccessThrows(xhr); + checkResponseXMLAccessThrows(xhr); + is(JSON.stringify(xhr.response), jsonObjStr, "correct result"); + is(xhr.response, xhr.response, "returning the same object on each access"); + + // with invalid json + xhr = new XMLHttpRequest(); + xhr.open("POST", "responseIdentical.sjs"); + xhr.responseType = "json"; + xhr.onloadend = continueTest; + xhr.send("{"); + yield undefined; + is(xhr.status, 200, "wrong status"); + checkResponseTextAccessThrows(xhr); + checkResponseXMLAccessThrows(xhr); + is(xhr.response, null, "Bad JSON should result in null response."); + is( + xhr.response, + null, + "Bad JSON should result in null response even 2nd time." + ); + + // Test status/statusText in all readyStates + xhr = new XMLHttpRequest(); + function checkXHRStatus() { + if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) { + is(xhr.status, 0, "should be 0 before getting data"); + is(xhr.statusText, "", "should be empty before getting data"); + } else { + is(xhr.status, 200, "should be 200 when we have data"); + if (expectHttp2Results) { + is(xhr.statusText, "", "should be '' when over HTTP2"); + } else { + is(xhr.statusText, "OK", "should be OK when we have data"); + } + } + } + checkXHRStatus(); + xhr.open("GET", "file_XHR_binary1.bin"); + checkXHRStatus(); + xhr.responseType = "arraybuffer"; + xhr.send(null); + xhr.onreadystatechange = continueTest; + while (xhr.readyState != 4) { + checkXHRStatus(); + yield undefined; + } + checkXHRStatus(); + + // test response (responseType='blob') + // with a simple text file + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_pass2.txt"); + xhr.responseType = "blob"; + xhr.onloadend = continueTest; + xhr.send(null); + yield undefined; + is(xhr.status, 200, "wrong status"); + checkResponseTextAccessThrows(xhr); + checkResponseXMLAccessThrows(xhr); + var b = xhr.response; + ok(b, "should have a non-null blob"); + ok(b instanceof Blob, "should be a Blob"); + ok(!(b instanceof File), "should not be a File"); + is(b.size, "hello pass\n".length, "wrong blob size"); + + var fr = new FileReader(); + fr.onload = continueTest; + fr.readAsBinaryString(b); + yield undefined; + is(fr.result, "hello pass\n", "wrong values"); + + // with a binary file + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_binary1.bin", true); + xhr.send(null); + xhr.onreadystatechange = continueTest; + while (xhr.readyState != 2) { + yield undefined; + } + + is(xhr.status, 200, "wrong status"); + xhr.responseType = "blob"; + + while (xhr.readyState != 4) { + yield undefined; + } + + xhr.onreadystatechange = null; + + b = xhr.response; + ok(b != null, "should have a non-null blob"); + is(b.size, 12, "wrong blob size"); + + fr = new FileReader(); + fr.readAsBinaryString(b); + xhr = null; // kill the XHR object + b = null; + SpecialPowers.gc(); + fr.onload = continueTest; + yield undefined; + is( + fr.result, + "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", + "wrong values" + ); + + // with a larger binary file + xhr = new XMLHttpRequest(); + xhr.open("GET", "file_XHR_binary2.bin", true); + xhr.responseType = "blob"; + xhr.send(null); + xhr.onreadystatechange = continueTest; + + while (xhr.readyState != 4) { + yield undefined; + } + + xhr.onreadystatechange = null; + + b = xhr.response; + ok(b != null, "should have a non-null blob"); + is(b.size, 65536, "wrong blob size"); + + fr = new FileReader(); + fr.readAsArrayBuffer(b); + fr.onload = continueTest; + xhr = null; // kill the XHR object + b = null; + SpecialPowers.gc(); + yield undefined; + + var u8 = new Uint8Array(fr.result); + for (var i = 0; i < 65536; i++) { + if (u8[i] !== (i & 255)) { + break; + } + } + is(i, 65536, "wrong value at offset " + i); + + var client = new XMLHttpRequest(); + client.open("GET", "file_XHR_pass1.xml", true); + client.send(); + client.onreadystatechange = function () { + if (client.readyState == 4) { + try { + is(client.responseXML, null, "responseXML should be null."); + is(client.responseText, "", "responseText should be empty string."); + is(client.response, "", "response should be empty string."); + is(client.status, 0, "status should be 0."); + is(client.statusText, "", "statusText should be empty string."); + is( + client.getAllResponseHeaders(), + "", + "getAllResponseHeaders() should return empty string." + ); + } catch (ex) { + ok(false, "Shouldn't throw! [" + ex + "]"); + } + } + }; + client.abort(); + + SimpleTest.finish(); +} /* runTests */ diff --git a/dom/xhr/tests/test_XHRDocURI.html b/dom/xhr/tests/test_XHRDocURI.html new file mode 100644 index 0000000000..1062be13a6 --- /dev/null +++ b/dom/xhr/tests/test_XHRDocURI.html @@ -0,0 +1,487 @@ + + + + + XMLHttpRequest return document URIs + + + + + +Mozilla Bug 459470
+Mozilla Bug 859095 + +

+ +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHRResponseURL.html b/dom/xhr/tests/test_XHRResponseURL.html new file mode 100644 index 0000000000..f6bd3f3964 --- /dev/null +++ b/dom/xhr/tests/test_XHRResponseURL.html @@ -0,0 +1,69 @@ + + + + + + Test for Bug 998076 + + + + + + +Mozilla Bug 998076 +

+ +
+
+ + diff --git a/dom/xhr/tests/test_XHRSendData.html b/dom/xhr/tests/test_XHRSendData.html new file mode 100644 index 0000000000..260a4b83a6 --- /dev/null +++ b/dom/xhr/tests/test_XHRSendData.html @@ -0,0 +1,270 @@ + + + + + XMLHttpRequest send data and headers + + + + +Mozilla Bug 464848 +

+

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_anon.html b/dom/xhr/tests/test_XHR_anon.html new file mode 100644 index 0000000000..6747b6a918 --- /dev/null +++ b/dom/xhr/tests/test_XHR_anon.html @@ -0,0 +1,180 @@ + + + + + Test for XMLHttpRequest with system privileges + + + + +

+ +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_header.html b/dom/xhr/tests/test_XHR_header.html new file mode 100644 index 0000000000..0fd5829cac --- /dev/null +++ b/dom/xhr/tests/test_XHR_header.html @@ -0,0 +1,32 @@ + + + + Test for XMLHttpRequest.GetResponseHeader(foo) byte-inflates the output + + + + + +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_http2.html b/dom/xhr/tests/test_XHR_http2.html new file mode 100644 index 0000000000..b8925750f6 --- /dev/null +++ b/dom/xhr/tests/test_XHR_http2.html @@ -0,0 +1,17 @@ + + + + Test for XMLHttpRequest + + + + +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_onuploadprogress.html b/dom/xhr/tests/test_XHR_onuploadprogress.html new file mode 100644 index 0000000000..89426c034a --- /dev/null +++ b/dom/xhr/tests/test_XHR_onuploadprogress.html @@ -0,0 +1,40 @@ + + + + + + Test for Bug 743666 + + + + +Mozilla Bug 743666 +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_parameters.html b/dom/xhr/tests/test_XHR_parameters.html new file mode 100644 index 0000000000..4ba1c5562a --- /dev/null +++ b/dom/xhr/tests/test_XHR_parameters.html @@ -0,0 +1,97 @@ + + + + + + + Test for XMLHttpRequest with system privileges + + + + +

+

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_system.html b/dom/xhr/tests/test_XHR_system.html new file mode 100644 index 0000000000..917a034ada --- /dev/null +++ b/dom/xhr/tests/test_XHR_system.html @@ -0,0 +1,99 @@ + + + + + Test for XMLHttpRequest with system privileges + + + + +

+

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_timeout.html b/dom/xhr/tests/test_XHR_timeout.html new file mode 100644 index 0000000000..e66ef1d30b --- /dev/null +++ b/dom/xhr/tests/test_XHR_timeout.html @@ -0,0 +1,59 @@ + + + + + Test for Bug 525816 + + + + + + +Mozilla Bug 525816 (XMLHttpRequest timeout) +

+
+ This test takes over 1 minute to run, probably over 2 minutes. +
+
+
+
+
+ + diff --git a/dom/xhr/tests/test_XHR_timeout.js b/dom/xhr/tests/test_XHR_timeout.js new file mode 100644 index 0000000000..1e75c1c174 --- /dev/null +++ b/dom/xhr/tests/test_XHR_timeout.js @@ -0,0 +1,415 @@ +/* Notes: + - All times are expressed in milliseconds in this test suite. + - Test harness code is at the end of this file. + - We generate only one request at a time, to avoid overloading the HTTP + request handlers. + */ + +var inWorker = false; +try { + inWorker = !(self instanceof Window); +} catch (e) { + inWorker = true; +} + +function message(data) { + if (inWorker) { + self.postMessage(data); + } else { + self.postMessage(data, "*"); + } +} + +function is(got, expected, msg) { + var obj = {}; + obj.type = "is"; + obj.got = got; + obj.expected = expected; + obj.msg = msg; + + message(obj); +} + +function ok(bool, msg) { + var obj = {}; + obj.type = "ok"; + obj.bool = bool; + obj.msg = msg; + + message(obj); +} + +/** + * Generate and track results from a XMLHttpRequest with regards to timeouts. + * + * @param {String} id The test description. + * @param {Number} timeLimit The initial setting for the request timeout. + * @param {Number} resetAfter (Optional) The time after sending the request, to + * reset the timeout. + * @param {Number} resetTo (Optional) The delay to reset the timeout to. + * + * @note The actual testing takes place in handleEvent(event). + * The requests are generated in startXHR(). + * + * @note If resetAfter and resetTo are omitted, only the initial timeout setting + * applies. + * + * @constructor + * @implements DOMEventListener + */ +function RequestTracker(async, id, timeLimit /*[, resetAfter, resetTo]*/) { + this.async = async; + this.id = id; + this.timeLimit = timeLimit; + + if (arguments.length > 3) { + this.mustReset = true; + this.resetAfter = arguments[3]; + this.resetTo = arguments[4]; + } + + this.hasFired = false; +} +RequestTracker.prototype = { + /** + * Start the XMLHttpRequest! + */ + startXHR() { + var req = new XMLHttpRequest(); + this.request = req; + req.open("GET", "file_XHR_timeout.sjs", this.async); + var me = this; + function handleEvent(e) { + return me.handleEvent(e); + } + req.onerror = handleEvent; + req.onload = handleEvent; + req.onabort = handleEvent; + req.ontimeout = handleEvent; + + req.timeout = this.timeLimit; + + if (this.mustReset) { + var resetTo = this.resetTo; + self.setTimeout(function () { + req.timeout = resetTo; + }, this.resetAfter); + } + + var gotException; + var expectTimeoutException = + !this.async && inWorker && this.timeLimit > 0 && this.timeLimit < 3000; + + try { + req.send(null); + } catch (e) { + gotException = e; + if (expectTimeoutException) { + ok(e.name == "TimeoutError", "Should be a TimeoutError"); + } + } + + if (gotException && !expectTimeoutException) { + ok(false, `expected no exception, got ${gotException}`); + } else if (!gotException && expectTimeoutException) { + ok(false, "expected timeout exception"); + } + }, + + /** + * Get a message describing this test. + * + * @returns {String} The test description. + */ + getMessage() { + var rv = this.id + ", "; + if (this.mustReset) { + rv += "original timeout at " + this.timeLimit + ", "; + rv += "reset at " + this.resetAfter + " to " + this.resetTo; + } else { + rv += "timeout scheduled at " + this.timeLimit; + } + return rv; + }, + + /** + * Check the event received, and if it's the right (and only) one we get. + * + * @param {DOMProgressEvent} evt An event of type "load" or "timeout". + */ + handleEvent(evt) { + if (this.hasFired) { + ok(false, "Only one event should fire: " + this.getMessage()); + return; + } + this.hasFired = true; + + var type = evt.type, + expectedType; + // The XHR responds after 3000 milliseconds with a load event. + var timeLimit = + this.mustReset && this.resetAfter < Math.min(3000, this.timeLimit) + ? this.resetTo + : this.timeLimit; + if (timeLimit == 0 || timeLimit >= 3000) { + expectedType = "load"; + } else { + expectedType = "timeout"; + } + is(type, expectedType, this.getMessage()); + TestCounter.testComplete(); + }, +}; + +/** + * Generate and track XMLHttpRequests which will have abort() called on. + * + * @param shouldAbort {Boolean} True if we should call abort at all. + * @param abortDelay {Number} The time in ms to wait before calling abort(). + */ +function AbortedRequest(shouldAbort, abortDelay) { + this.shouldAbort = shouldAbort; + this.abortDelay = abortDelay; + this.hasFired = false; +} +AbortedRequest.prototype = { + /** + * Start the XMLHttpRequest! + */ + startXHR() { + var req = new XMLHttpRequest(); + this.request = req; + req.open("GET", "file_XHR_timeout.sjs"); + var me = this; + function handleEvent(e) { + return me.handleEvent(e); + } + req.onerror = handleEvent; + req.onload = handleEvent; + req.onabort = handleEvent; + req.ontimeout = handleEvent; + + req.timeout = 2000; + var _this = this; + + function abortReq() { + req.abort(); + } + + if (!this.shouldAbort) { + self.setTimeout(function () { + try { + _this.noEventsFired(); + } catch (e) { + ok(false, "Unexpected error: " + e); + TestCounter.testComplete(); + } + }, 5000); + } else { + // Abort events can only be triggered on sent requests. + req.send(); + if (this.abortDelay == -1) { + abortReq(); + } else { + self.setTimeout(abortReq, this.abortDelay); + } + } + }, + + /** + * Ensure that no events fired at all, especially not our timeout event. + */ + noEventsFired() { + ok( + !this.hasFired, + "No events should fire for an unsent, unaborted request" + ); + // We're done; if timeout hasn't fired by now, it never will. + TestCounter.testComplete(); + }, + + /** + * Get a message describing this test. + * + * @returns {String} The test description. + */ + getMessage() { + return "time to abort is " + this.abortDelay + ", timeout set at 2000"; + }, + + /** + * Check the event received, and if it's the right (and only) one we get. + * + * @param {DOMProgressEvent} evt An event of type "load" or "timeout". + */ + handleEvent(evt) { + if (this.hasFired) { + ok(false, "Only abort event should fire: " + this.getMessage()); + return; + } + this.hasFired = true; + + var expectedEvent = this.abortDelay >= 2000 ? "timeout" : "abort"; + is(evt.type, expectedEvent, this.getMessage()); + TestCounter.testComplete(); + }, +}; + +var SyncRequestSettingTimeoutAfterOpen = { + startXHR() { + var pass = false; + var req = new XMLHttpRequest(); + req.open("GET", "file_XHR_timeout.sjs", false); + try { + req.timeout = 1000; + } catch (e) { + pass = true; + } + ok(pass, "Synchronous XHR must not allow a timeout to be set"); + TestCounter.testComplete(); + }, +}; + +var SyncRequestSettingTimeoutBeforeOpen = { + startXHR() { + var pass = false; + var req = new XMLHttpRequest(); + req.timeout = 1000; + try { + req.open("GET", "file_XHR_timeout.sjs", false); + } catch (e) { + pass = true; + } + ok(pass, "Synchronous XHR must not allow a timeout to be set"); + TestCounter.testComplete(); + }, +}; + +var TestRequests = [ + // Simple timeouts. + new RequestTracker(true, "no time out scheduled, load fires normally", 0), + new RequestTracker(true, "load fires normally", 5000), + new RequestTracker(true, "timeout hit before load", 2000), + + // Timeouts reset after a certain delay. + new RequestTracker( + true, + "load fires normally with no timeout set, twice", + 0, + 2000, + 0 + ), + new RequestTracker( + true, + "load fires normally with same timeout set twice", + 5000, + 2000, + 5000 + ), + new RequestTracker( + true, + "timeout fires normally with same timeout set twice", + 2000, + 1000, + 2000 + ), + + new RequestTracker( + true, + "timeout disabled after initially set", + 5000, + 2000, + 0 + ), + new RequestTracker( + true, + "timeout overrides load after a delay", + 5000, + 1000, + 2000 + ), + new RequestTracker( + true, + "timeout enabled after initially disabled", + 0, + 2000, + 5000 + ), + + new RequestTracker( + true, + "timeout set to expiring value after load fires", + 5000, + 4000, + 1000 + ), + new RequestTracker( + true, + "timeout set to expired value before load fires", + 5000, + 2000, + 1000 + ), + new RequestTracker( + true, + "timeout set to non-expiring value after timeout fires", + 1000, + 2000, + 5000 + ), + + // Aborted requests. + new AbortedRequest(false), + new AbortedRequest(true, -1), + new AbortedRequest(true, 5000), +]; + +var MainThreadTestRequests = [ + new AbortedRequest(true, 0), + new AbortedRequest(true, 1000), + + // Synchronous requests. + SyncRequestSettingTimeoutAfterOpen, + SyncRequestSettingTimeoutBeforeOpen, +]; + +var WorkerThreadTestRequests = [ + // Simple timeouts. + new RequestTracker(false, "no time out scheduled, load fires normally", 0), + new RequestTracker(false, "load fires normally", 5000), + new RequestTracker(false, "timeout hit before load", 2000), + + // Reset timeouts don't make much sense with a sync request ... +]; + +if (inWorker) { + TestRequests = TestRequests.concat(WorkerThreadTestRequests); +} else { + TestRequests = TestRequests.concat(MainThreadTestRequests); +} + +// This code controls moving from one test to another. +var TestCounter = { + testComplete() { + // Allow for the possibility there are other events coming. + self.setTimeout(function () { + TestCounter.next(); + }, 5000); + }, + + next() { + var test = TestRequests.shift(); + + if (test) { + test.startXHR(); + } else { + message("done"); + } + }, +}; + +self.addEventListener("message", function (event) { + if (event.data == "start") { + TestCounter.next(); + } +}); diff --git a/dom/xhr/tests/test_bug1070763.html b/dom/xhr/tests/test_bug1070763.html new file mode 100644 index 0000000000..baf6ade4c1 --- /dev/null +++ b/dom/xhr/tests/test_bug1070763.html @@ -0,0 +1,58 @@ + + + + + XMLHttpRequest send data and headers + + + + +Mozilla Bug 1405571 +

+

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_bug1300552.html b/dom/xhr/tests/test_bug1300552.html new file mode 100644 index 0000000000..2374eb7c97 --- /dev/null +++ b/dom/xhr/tests/test_bug1300552.html @@ -0,0 +1,29 @@ + + + + + Test for Bug 1300552 + + + + + + + diff --git a/dom/xhr/tests/test_bug1697539.html b/dom/xhr/tests/test_bug1697539.html new file mode 100644 index 0000000000..c776bf9796 --- /dev/null +++ b/dom/xhr/tests/test_bug1697539.html @@ -0,0 +1,27 @@ + + + + + Test for Bug 1697539 + + + + + + + diff --git a/dom/xhr/tests/test_bug1752863.html b/dom/xhr/tests/test_bug1752863.html new file mode 100644 index 0000000000..567fdb017d --- /dev/null +++ b/dom/xhr/tests/test_bug1752863.html @@ -0,0 +1,32 @@ + + + + + Test for Bug 1752863 + + + + + diff --git a/dom/xhr/tests/test_bug1752863_worker.js b/dom/xhr/tests/test_bug1752863_worker.js new file mode 100644 index 0000000000..196b825c0c --- /dev/null +++ b/dom/xhr/tests/test_bug1752863_worker.js @@ -0,0 +1,34 @@ +var xhr; +var myself; + +async function handleLoadstart() { + try { + xhr.open("POST", "FOOBAR", false); + // This will potentially queue another "loadstart" event + // before we can catch (err). But the order should be + // guaranteed, that is the first postMessage arriving at + // our parent is from the first catch (err). + xhr.send(); + myself.postMessage("MissingError"); + } catch (err) { + if (err instanceof DOMException) { + // This is what we expect to happen on the first error + // and the parent will check for this to arrive. + myself.postMessage("DOMException"); + } else { + myself.postMessage("OtherError"); + } + // Let's ensure we still bail out from the processing. + xhr.removeEventListener("loadstart", handleLoadstart, true); + throw err; + } +} + +self.onmessage = async function (ev) { + xhr = new XMLHttpRequest({ mozAnon: false }); + myself = self; + xhr.addEventListener("loadstart", handleLoadstart, true); + xhr.open("POST", "FOOBAR", false); + xhr.send(); + postMessage("TERMINATE"); +}; diff --git a/dom/xhr/tests/test_bug1788125.html b/dom/xhr/tests/test_bug1788125.html new file mode 100644 index 0000000000..44cb79864c --- /dev/null +++ b/dom/xhr/tests/test_bug1788125.html @@ -0,0 +1,59 @@ + + + + + <!-- TODO: insert title here --> + + + + + + +
+

+ +

+
+
diff --git a/dom/xhr/tests/test_event_listener_leaks.html b/dom/xhr/tests/test_event_listener_leaks.html
new file mode 100644
index 0000000000..da0ca75323
--- /dev/null
+++ b/dom/xhr/tests/test_event_listener_leaks.html
@@ -0,0 +1,45 @@
+
+
+
+
+  Bug 1450271 - Test XHR event listener leak conditions
+  
+  
+  
+
+
+

+ + + + diff --git a/dom/xhr/tests/test_html_in_xhr.html b/dom/xhr/tests/test_html_in_xhr.html new file mode 100644 index 0000000000..e09b700295 --- /dev/null +++ b/dom/xhr/tests/test_html_in_xhr.html @@ -0,0 +1,97 @@ + + + + + Test for Bug 651072 + + + + + +Mozilla Bug 651072 +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_nestedSyncXHR.html b/dom/xhr/tests/test_nestedSyncXHR.html new file mode 100644 index 0000000000..a2e10ad9e5 --- /dev/null +++ b/dom/xhr/tests/test_nestedSyncXHR.html @@ -0,0 +1,101 @@ + + + + + Test for sync XHR into sync XHRs + + + + + + + diff --git a/dom/xhr/tests/test_relativeLoad.html b/dom/xhr/tests/test_relativeLoad.html new file mode 100644 index 0000000000..fdfe35ddd8 --- /dev/null +++ b/dom/xhr/tests/test_relativeLoad.html @@ -0,0 +1,51 @@ + + + + + + Test for DOM Worker Threads + + + + +
+
+
+ + diff --git a/dom/xhr/tests/test_sharedworker_xhr.html b/dom/xhr/tests/test_sharedworker_xhr.html new file mode 100644 index 0000000000..c0c43bcb26 --- /dev/null +++ b/dom/xhr/tests/test_sharedworker_xhr.html @@ -0,0 +1,23 @@ + + + + Test for SharedWorker Threads XHR + + + + + + + diff --git a/dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html b/dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html new file mode 100644 index 0000000000..eb03f7cf23 --- /dev/null +++ b/dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html @@ -0,0 +1,28 @@ + + + + Test for Bug + + + + +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_sync_xhr_event_handling.html b/dom/xhr/tests/test_sync_xhr_event_handling.html new file mode 100644 index 0000000000..eaaa1f608a --- /dev/null +++ b/dom/xhr/tests/test_sync_xhr_event_handling.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + diff --git a/dom/xhr/tests/test_sync_xhr_nested.html b/dom/xhr/tests/test_sync_xhr_nested.html new file mode 100644 index 0000000000..450c5f7e54 --- /dev/null +++ b/dom/xhr/tests/test_sync_xhr_nested.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + diff --git a/dom/xhr/tests/test_sync_xhr_timer.xhtml b/dom/xhr/tests/test_sync_xhr_timer.xhtml new file mode 100644 index 0000000000..823488889f --- /dev/null +++ b/dom/xhr/tests/test_sync_xhr_timer.xhtml @@ -0,0 +1,52 @@ + + + + + Test for Bug + + + + +Mozilla Bug +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_sync_xhr_unload.html b/dom/xhr/tests/test_sync_xhr_unload.html new file mode 100644 index 0000000000..069071461b --- /dev/null +++ b/dom/xhr/tests/test_sync_xhr_unload.html @@ -0,0 +1,36 @@ + + + + + Test for Bug 1307122 + + + + + + + + diff --git a/dom/xhr/tests/test_temporaryFileBlob.html b/dom/xhr/tests/test_temporaryFileBlob.html new file mode 100644 index 0000000000..ed0bca28e2 --- /dev/null +++ b/dom/xhr/tests/test_temporaryFileBlob.html @@ -0,0 +1,40 @@ + + + + + Test for Bug 1202006 + + + + + + + + diff --git a/dom/xhr/tests/test_worker_terminateSyncXHR.html b/dom/xhr/tests/test_worker_terminateSyncXHR.html new file mode 100644 index 0000000000..d952e3c6e7 --- /dev/null +++ b/dom/xhr/tests/test_worker_terminateSyncXHR.html @@ -0,0 +1,44 @@ + + + + + + Test for DOM Worker Threads XHR (Bug 450452 ) + + + + +DOM Worker Threads XHR (Bug 450452) +

+
+ +
+
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr.html b/dom/xhr/tests/test_worker_xhr.html new file mode 100644 index 0000000000..f95fbe8050 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr.html @@ -0,0 +1,76 @@ + + + + + + Test for DOM Worker Threads XHR (Bug 450452 ) + + + + +DOM Worker Threads XHR (Bug 450452) +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr2.html b/dom/xhr/tests/test_worker_xhr2.html new file mode 100644 index 0000000000..41a7b8ee85 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr2.html @@ -0,0 +1,37 @@ + + + + + + Test for DOM Worker Threads XHR (Bug 450452 ) + + + + +DOM Worker Threads XHR (Bug 450452) +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhrAbort.html b/dom/xhr/tests/test_worker_xhrAbort.html new file mode 100644 index 0000000000..35e77077c0 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhrAbort.html @@ -0,0 +1,44 @@ + + + + + + Test for DOM Worker Threads XHR (Bug 450452 ) + + + + +DOM Worker Threads XHR (Bug 450452) +

+ +
+
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr_3rdparty.html b/dom/xhr/tests/test_worker_xhr_3rdparty.html new file mode 100644 index 0000000000..ab29b09615 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_3rdparty.html @@ -0,0 +1,51 @@ + + + + + + Test for DOM Worker Threads XHR (Bug 450452 ) + + + + +DOM Worker Threads XHR (Bug 450452) + + +
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr_cors_redirect.html b/dom/xhr/tests/test_worker_xhr_cors_redirect.html new file mode 100644 index 0000000000..777c31b1c2 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_cors_redirect.html @@ -0,0 +1,35 @@ + + + + + Test for Bug 1206121 + + + + + + + diff --git a/dom/xhr/tests/test_worker_xhr_doubleSend.html b/dom/xhr/tests/test_worker_xhr_doubleSend.html new file mode 100644 index 0000000000..d5a052bcf9 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_doubleSend.html @@ -0,0 +1,30 @@ + + + + + Test for DOM Worker Threads XHR - double send + + + + + + + + diff --git a/dom/xhr/tests/test_worker_xhr_headers.html b/dom/xhr/tests/test_worker_xhr_headers.html new file mode 100644 index 0000000000..1416ababd7 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_headers.html @@ -0,0 +1,86 @@ + + + + + Test for XHR Headers + + + + +

+ +
+      
+    
+ + diff --git a/dom/xhr/tests/test_worker_xhr_implicit_cancel.html b/dom/xhr/tests/test_worker_xhr_implicit_cancel.html new file mode 100644 index 0000000000..d749b0696f --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_implicit_cancel.html @@ -0,0 +1,43 @@ + + + + + + Test for DOM Worker Threads XHR (Bug 450452 ) + + + + +DOM Worker Threads XHR (Bug 450452) +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr_parameters.html b/dom/xhr/tests/test_worker_xhr_parameters.html new file mode 100644 index 0000000000..dde0c32ed7 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_parameters.html @@ -0,0 +1,66 @@ + + + + + Test for XMLHttpRequest with system privileges + + + + +

+

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr_parameters.js b/dom/xhr/tests/test_worker_xhr_parameters.js new file mode 100644 index 0000000000..688457db96 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_parameters.js @@ -0,0 +1,84 @@ +function ok(what, msg) { + postMessage({ event: msg, test: "ok", a: what }); +} + +function is(a, b, msg) { + postMessage({ event: msg, test: "is", a, b }); +} + +// This is a copy of dom/xhr/tests/test_XHR_parameters.js +var validParameters = [ + undefined, + null, + {}, + { mozSystem: "" }, + { mozSystem: 0 }, + { mozAnon: 1 }, + { mozAnon: [] }, + { + get mozAnon() { + return true; + }, + }, + 0, + 7, + Math.PI, + "string", + true, + false, +]; + +var invalidParameters = [ + { + get mozSystem() { + throw new Error("Bla"); + }, + }, +]; + +function testParameters(havePrivileges) { + function testValidParameter(value) { + var xhr; + try { + xhr = new XMLHttpRequest(value); + } catch (ex) { + ok(false, "Got unexpected exception: " + ex); + return; + } + ok(!!xhr, "passed " + JSON.stringify(value)); + + // If the page doesnt have privileges to create a system or anon XHR, + // these flags will always be false no matter what is passed. + var expectedAnon = false; + var expectedSystem = false; + if (havePrivileges) { + expectedAnon = Boolean(value && value.mozAnon); + expectedSystem = Boolean(value && value.mozSystem); + } + is(xhr.mozAnon, expectedAnon, "testing mozAnon"); + is(xhr.mozSystem, expectedSystem, "testing mozSystem"); + } + + function testInvalidParameter(value) { + try { + new XMLHttpRequest(value); + ok( + false, + "invalid parameter did not cause exception: " + JSON.stringify(value) + ); + } catch (ex) { + ok( + true, + "invalid parameter raised exception as expected: " + JSON.stringify(ex) + ); + } + } + + validParameters.forEach(testValidParameter); + invalidParameters.forEach(testInvalidParameter); +} + +self.onmessage = function onmessage(event) { + testParameters(event.data); + postMessage({ test: "finish" }); +}; diff --git a/dom/xhr/tests/test_worker_xhr_responseURL.html b/dom/xhr/tests/test_worker_xhr_responseURL.html new file mode 100644 index 0000000000..89924e9815 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_responseURL.html @@ -0,0 +1,76 @@ + + + + + + Test for Bug 998076 + + + + + +Mozilla Bug 998076 +

+ +
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr_system.html b/dom/xhr/tests/test_worker_xhr_system.html new file mode 100644 index 0000000000..6d86d110e5 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_system.html @@ -0,0 +1,54 @@ + + + + + Test for XMLHttpRequest with system privileges + + + + +

+

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_worker_xhr_system.js b/dom/xhr/tests/test_worker_xhr_system.js new file mode 100644 index 0000000000..23137801a0 --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_system.js @@ -0,0 +1,30 @@ +function ok(what, msg) { + postMessage({ event: msg, test: "ok", a: what }); +} + +function is(a, b, msg) { + postMessage({ event: msg, test: "is", a, b }); +} + +self.onmessage = function onmessage(event) { + // An XHR with system privileges will be able to do cross-site calls. + + const TEST_URL = + "http://example.com/tests/dom/xhr/tests/test_XHR_system.html"; + is(location.hostname, "mochi.test", "hostname should be mochi.test"); + + var xhr = new XMLHttpRequest({ mozSystem: true }); + is(xhr.mozSystem, true, ".mozSystem == true"); + xhr.open("GET", TEST_URL); + xhr.onload = function onload() { + is(xhr.status, 200); + ok(xhr.responseText != null); + ok(xhr.responseText.length); + postMessage({ test: "finish" }); + }; + xhr.onerror = function onerror() { + ok(false, "Got an error event!"); + postMessage({ test: "finish" }); + }; + xhr.send(); +}; diff --git a/dom/xhr/tests/test_worker_xhr_timeout.html b/dom/xhr/tests/test_worker_xhr_timeout.html new file mode 100644 index 0000000000..3cbfcefb5e --- /dev/null +++ b/dom/xhr/tests/test_worker_xhr_timeout.html @@ -0,0 +1,57 @@ + + + + + Test for Bug 498998 + + + + + + +Mozilla Bug 498998 (Worker XMLHttpRequest timeout) +

+
+ This test takes over 1 minute to run, probably over 2 minutes. +
+
+
+
+ + diff --git a/dom/xhr/tests/test_xhr_abort_after_load.html b/dom/xhr/tests/test_xhr_abort_after_load.html new file mode 100644 index 0000000000..f3d6f4d2f2 --- /dev/null +++ b/dom/xhr/tests/test_xhr_abort_after_load.html @@ -0,0 +1,96 @@ + + + + Test bug 482935 + + + + + + + diff --git a/dom/xhr/tests/test_xhr_forbidden_headers.html b/dom/xhr/tests/test_xhr_forbidden_headers.html new file mode 100644 index 0000000000..d393544b79 --- /dev/null +++ b/dom/xhr/tests/test_xhr_forbidden_headers.html @@ -0,0 +1,96 @@ + + + + + Test for Bug 308484 + + + + +Mozilla Bug 308484 +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html b/dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html new file mode 100644 index 0000000000..99e6bde004 --- /dev/null +++ b/dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html @@ -0,0 +1,62 @@ + + + + Test bug 482935 + + + + + + + diff --git a/dom/xhr/tests/test_xhr_progressevents.html b/dom/xhr/tests/test_xhr_progressevents.html new file mode 100644 index 0000000000..ebfc06fd5b --- /dev/null +++ b/dom/xhr/tests/test_xhr_progressevents.html @@ -0,0 +1,307 @@ + + + + Test for XMLHttpRequest Progress Events + + + + +

+
+
+
+
diff --git a/dom/xhr/tests/test_xhr_send.html b/dom/xhr/tests/test_xhr_send.html
new file mode 100644
index 0000000000..cec347a88b
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_send.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  Test for Bug 1096263
+  
+  
+  
+
+
+Mozilla Bug 1096263
+

+
+ +
+
+
+ + diff --git a/dom/xhr/tests/test_xhr_send_readystate.html b/dom/xhr/tests/test_xhr_send_readystate.html new file mode 100644 index 0000000000..a810055a64 --- /dev/null +++ b/dom/xhr/tests/test_xhr_send_readystate.html @@ -0,0 +1,39 @@ + + + + + + Test for Bug 814064 + + + + +Mozilla Bug 814064 +

+ +
+
+
+ + diff --git a/dom/xhr/tests/test_xhr_withCredentials.html b/dom/xhr/tests/test_xhr_withCredentials.html new file mode 100644 index 0000000000..320e303e68 --- /dev/null +++ b/dom/xhr/tests/test_xhr_withCredentials.html @@ -0,0 +1,35 @@ + + + + + + Test for Bug 814050 + + + + +Mozilla Bug 814050 +

+ +
+
+
+ + diff --git a/dom/xhr/tests/window_worker_xhr_3rdparty.html b/dom/xhr/tests/window_worker_xhr_3rdparty.html new file mode 100644 index 0000000000..1c22a3aad0 --- /dev/null +++ b/dom/xhr/tests/window_worker_xhr_3rdparty.html @@ -0,0 +1,75 @@ + + + + + + + + + diff --git a/dom/xhr/tests/worker_bug1300552.js b/dom/xhr/tests/worker_bug1300552.js new file mode 100644 index 0000000000..d874f32c8d --- /dev/null +++ b/dom/xhr/tests/worker_bug1300552.js @@ -0,0 +1,37 @@ +function info(msg) { + postMessage({ type: "info", msg }); +} + +function ok(a, msg) { + postMessage({ type: "check", what: !!a, msg }); +} + +function finish() { + postMessage({ type: "finish" }); +} + +info("Creating XHR..."); +var xhr = new XMLHttpRequest(); +xhr.open("POST", "echo.sjs"); +xhr.responseType = "arraybuffer"; + +info("Sending some data..."); +var data = new Array(256).join("1234567890ABCDEF"); +xhr.send({ + toString() { + return data; + }, +}); + +var aborted = false; + +xhr.onprogress = function () { + info("Onprogress, we abort!"); + aborted = true; + xhr.abort(); +}; + +xhr.onloadend = function () { + ok(aborted, "We are still alive after an abort()!"); + finish(); +}; diff --git a/dom/xhr/tests/worker_bug1697539.js b/dom/xhr/tests/worker_bug1697539.js new file mode 100644 index 0000000000..faef1f1614 --- /dev/null +++ b/dom/xhr/tests/worker_bug1697539.js @@ -0,0 +1,19 @@ +onmessage = function (e) { + let xhr = new XMLHttpRequest(); + let already_sent = false; + xhr.addEventListener("readystatechange", event => { + try { + event.originalTarget.send("test"); + } catch (error) { + if (error.name == "InvalidStateError") { + if (!already_sent) { + postMessage(error.name); + already_sent = true; + } + } + } + }); + + xhr.open("POST", e.data, false); + xhr.send(); +}; diff --git a/dom/xhr/tests/worker_file_getcookie.sjs b/dom/xhr/tests/worker_file_getcookie.sjs new file mode 100644 index 0000000000..b5204bdd71 --- /dev/null +++ b/dom/xhr/tests/worker_file_getcookie.sjs @@ -0,0 +1,15 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +function handleRequest(request, response) { + try { + var cookie = request.getHeader("Cookie"); + } catch (e) { + cookie = "EMPTY_COOKIE"; + } + + // avoid confusing cache behaviors. + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-type", "text/plain", false); + response.setStatusLine(request.httpVersion, "200", "OK"); + response.write(cookie); +} diff --git a/dom/xhr/tests/worker_temporaryFileBlob.js b/dom/xhr/tests/worker_temporaryFileBlob.js new file mode 100644 index 0000000000..50f071bab7 --- /dev/null +++ b/dom/xhr/tests/worker_temporaryFileBlob.js @@ -0,0 +1,30 @@ +/* eslint-env worker */ +importScripts("common_temporaryFileBlob.js"); + +function info(msg) { + postMessage({ type: "info", msg }); +} + +function ok(a, msg) { + postMessage({ type: "check", what: !!a, msg }); +} + +function is(a, b, msg) { + ok(a === b, msg); +} + +function next() { + postMessage({ type: "finish" }); +} + +onmessage = function (e) { + if (e.data == "simple") { + test_simple(); + } else if (e.data == "abort") { + test_abort(); + } else if (e.data == "reuse") { + test_reuse(); + } else { + ok(false, "Something wrong happened"); + } +}; diff --git a/dom/xhr/tests/worker_terminateSyncXHR_frame.html b/dom/xhr/tests/worker_terminateSyncXHR_frame.html new file mode 100644 index 0000000000..04bd53ff1d --- /dev/null +++ b/dom/xhr/tests/worker_terminateSyncXHR_frame.html @@ -0,0 +1,25 @@ + + + + + Test for SharedWorker + + + + + diff --git a/dom/xhr/tests/worker_testXHR.txt b/dom/xhr/tests/worker_testXHR.txt new file mode 100644 index 0000000000..2beab22c66 --- /dev/null +++ b/dom/xhr/tests/worker_testXHR.txt @@ -0,0 +1 @@ +A noisy noise annoys an oyster. \ No newline at end of file diff --git a/dom/xhr/tests/worker_xhr_cors_redirect.js b/dom/xhr/tests/worker_xhr_cors_redirect.js new file mode 100644 index 0000000000..0d86e75eaa --- /dev/null +++ b/dom/xhr/tests/worker_xhr_cors_redirect.js @@ -0,0 +1,10 @@ +onmessage = function (e) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", e.data, true); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + postMessage(xhr.status); + } + }; + xhr.send(); +}; diff --git a/dom/xhr/tests/worker_xhr_cors_redirect.sjs b/dom/xhr/tests/worker_xhr_cors_redirect.sjs new file mode 100644 index 0000000000..aac9c8ffe6 --- /dev/null +++ b/dom/xhr/tests/worker_xhr_cors_redirect.sjs @@ -0,0 +1,10 @@ +function handleRequest(request, response) { + response.setHeader("Access-Control-Allow-Origin", "*"); + + if (request.queryString == "redirect") { + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", "worker_xhr_cors_redirect.sjs"); + } else { + response.write("'hello world'"); + } +} diff --git a/dom/xhr/tests/worker_xhr_headers_server.sjs b/dom/xhr/tests/worker_xhr_headers_server.sjs new file mode 100644 index 0000000000..c2a944f6ef --- /dev/null +++ b/dom/xhr/tests/worker_xhr_headers_server.sjs @@ -0,0 +1,69 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +"use strict"; + +function handleRequest(request, response) { + switch (request.method) { + case "POST": + try { + var optionsHost = request.getHeader("options-host"); + } catch (e) {} + + var headerFound = false; + if (optionsHost) { + setState("postHost", request.host); + setState("optionsHost", optionsHost); + headerFound = true; + } + + try { + var emptyHeader = "nada" + request.getHeader("empty"); + } catch (e) {} + + if (emptyHeader && emptyHeader == "nada") { + setState("emptyHeader", "nada"); + headerFound = true; + } + if (headerFound) { + return; + } + break; + + case "OPTIONS": + if (getState("optionsHost") == request.host) { + try { + var optionsHeader = request.getHeader( + "Access-Control-Request-Headers" + ); + } catch (e) {} + setState("optionsHeader", "'" + optionsHeader + "'"); + } + break; + + case "GET": + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + + if ( + getState("postHost") == request.host && + getState("emptyHeader") == "nada" + ) { + var result = getState("optionsHeader"); + if (result) { + response.write( + "Success: expected OPTIONS request with " + result + " header" + ); + } else if (getState("badGet") == 1) { + response.write("Error: unexpected GET request"); + } + } else { + setState("badGet", "1"); + response.write("Error: this response should never be seen"); + } + return; + } + + response.setStatusLine(request.httpVersion, 501, "Not Implemented"); +} diff --git a/dom/xhr/tests/worker_xhr_headers_worker.js b/dom/xhr/tests/worker_xhr_headers_worker.js new file mode 100644 index 0000000000..e4f4341cef --- /dev/null +++ b/dom/xhr/tests/worker_xhr_headers_worker.js @@ -0,0 +1,16 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +"use strict"; + +var customHeader = "custom-key"; +var customHeaderValue = "custom-key-value"; + +self.onmessage = function (event) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", event.data, false); + xhr.setRequestHeader(customHeader, customHeaderValue); + xhr.send(); + postMessage({ response: xhr.responseText, header: customHeader }); +}; diff --git a/dom/xhr/tests/xhr2_worker.js b/dom/xhr/tests/xhr2_worker.js new file mode 100644 index 0000000000..f9bfc88ed9 --- /dev/null +++ b/dom/xhr/tests/xhr2_worker.js @@ -0,0 +1,102 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +/* eslint-env worker */ +onmessage = function (event) { + const url = event.data; + + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + xhr.send(); + + const refText = xhr.responseText; + + function getResponse(type) { + xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + if (type !== undefined) { + xhr.responseType = type; + } + xhr.send(); + return xhr.response; + } + + if (getResponse() != refText) { + throw new Error("unset responseType failed"); + } + + if (getResponse("") != refText) { + throw new Error("'' responseType failed"); + } + + if (getResponse("text") != refText) { + throw new Error("'text' responseType failed"); + } + + var array = new Uint8Array(getResponse("arraybuffer")); + if (String.fromCharCode.apply(String, array) != refText) { + throw new Error("'arraybuffer' responseType failed"); + } + + var blob = getResponse("blob"); + if (new FileReaderSync().readAsText(blob) != refText) { + throw new Error("'blob' responseType failed"); + } + + // Make sure that we get invalid state exceptions when getting the wrong + // property. + + function testResponseTextException(type) { + xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + xhr.responseType = type; + xhr.send(); + + var exception; + + try { + xhr.responseText; + } catch (e) { + exception = e; + } + + if (!exception) { + throw new Error( + "Failed to throw when getting responseText on '" + type + "' type" + ); + } + + if (exception.name != "InvalidStateError") { + throw new Error( + "Unexpected error when getting responseText on '" + type + "' type" + ); + } + + if (exception.code != DOMException.INVALID_STATE_ERR) { + throw new Error( + "Unexpected error code when getting responseText on '" + type + "' type" + ); + } + } + + testResponseTextException("arraybuffer"); + testResponseTextException("blob"); + + // Make sure "document" works, but returns text. + xhr = new XMLHttpRequest(); + + if (xhr.responseType != "") { + throw new Error("Default value for responseType is wrong!"); + } + + xhr.open("GET", url, false); + xhr.responseType = "document"; + xhr.send(); + + if (xhr.responseText != refText) { + throw new Error("'document' type not working correctly"); + } + + postMessage("done"); +}; diff --git a/dom/xhr/tests/xhrAbort_worker.js b/dom/xhr/tests/xhrAbort_worker.js new file mode 100644 index 0000000000..6b82241d68 --- /dev/null +++ b/dom/xhr/tests/xhrAbort_worker.js @@ -0,0 +1,101 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +/* eslint-env worker */ +/* global WorkerProgressEvent */ +function runTest() { + var xhr = new XMLHttpRequest(); + + var events = []; + function pushEvent(event) { + var readyState, responseText, status, statusText; + + try { + readyState = xhr.readyState; + } catch (e) { + readyState = "[exception]"; + } + + try { + responseText = xhr.responseText; + } catch (e) { + responseText = "[exception]"; + } + + try { + status = xhr.status; + } catch (e) { + status = "[exception]"; + } + + try { + statusText = xhr.statusText; + } catch (e) { + statusText = "[exception]"; + } + + var str = + event.type + + "(" + + readyState + + ", '" + + responseText + + "', " + + status + + ", '" + + statusText + + "'"; + if ( + ("ProgressEvent" in this && event instanceof ProgressEvent) || + ("WorkerProgressEvent" in this && event instanceof WorkerProgressEvent) + ) { + str += ", progressEvent"; + } + str += ")"; + + events.push(str); + } + + xhr.onerror = function (event) { + throw new Error("Error: " + xhr.statusText); + }; + + xhr.onload = function (event) { + throw new Error("Shouldn't have gotten load event!"); + }; + + var seenAbort; + xhr.onabort = function (event) { + if (seenAbort) { + throw new Error("Already seen the abort event!"); + } + seenAbort = true; + + pushEvent(event); + postMessage(events); + }; + + xhr.onreadystatechange = function (event) { + pushEvent(event); + if (xhr.readyState == xhr.HEADERS_RECEIVED) { + xhr.abort(); + } + }; + + xhr.open("GET", "worker_testXHR.txt"); + xhr.overrideMimeType("text/plain"); + xhr.send(null); +} + +function messageListener(event) { + switch (event.data) { + case "start": + runTest(); + break; + default: + throw new Error("Bad message!"); + } +} + +addEventListener("message", messageListener, false); diff --git a/dom/xhr/tests/xhr_implicit_cancel_worker.js b/dom/xhr/tests/xhr_implicit_cancel_worker.js new file mode 100644 index 0000000000..2045452caa --- /dev/null +++ b/dom/xhr/tests/xhr_implicit_cancel_worker.js @@ -0,0 +1,10 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +var xhr = new XMLHttpRequest(); +xhr.open("GET", "worker_testXHR.txt"); +xhr.send(null); +xhr.open("GET", "worker_testXHR.txt"); +xhr.send(null); +postMessage("done"); diff --git a/dom/xhr/tests/xhr_sharedworker.js b/dom/xhr/tests/xhr_sharedworker.js new file mode 100644 index 0000000000..c8e1c10094 --- /dev/null +++ b/dom/xhr/tests/xhr_sharedworker.js @@ -0,0 +1,105 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* eslint-env worker */ +onconnect = e => { + e.ports[0].onmessage = event => { + const url = event.data; + + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + xhr.send(); + + const refText = xhr.responseText; + + function getResponse(type) { + xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + if (type !== undefined) { + xhr.responseType = type; + } + xhr.send(); + return xhr.response; + } + + if (getResponse() != refText) { + throw new Error("unset responseType failed"); + } + + if (getResponse("") != refText) { + throw new Error("'' responseType failed"); + } + + if (getResponse("text") != refText) { + throw new Error("'text' responseType failed"); + } + + var array = new Uint8Array(getResponse("arraybuffer")); + if (String.fromCharCode.apply(String, array) != refText) { + throw new Error("'arraybuffer' responseType failed"); + } + + var blob = getResponse("blob"); + if (new FileReaderSync().readAsText(blob) != refText) { + throw new Error("'blob' responseType failed"); + } + + // Make sure that we get invalid state exceptions when getting the wrong + // property. + + function testResponseTextException(type) { + xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + xhr.responseType = type; + xhr.send(); + + var exception; + + try { + xhr.responseText; + } catch (ex) { + exception = ex; + } + + if (!exception) { + throw new Error( + `Failed to throw when getting responseText on ${type} type` + ); + } + + if (exception.name != "InvalidStateError") { + throw new Error( + `Unexpected error when getting responseText on ${type} type` + ); + } + + if (exception.code != DOMException.INVALID_STATE_ERR) { + throw new Error( + `Unexpected error code when getting responseText on ${type} type` + ); + } + } + + testResponseTextException("arraybuffer"); + testResponseTextException("blob"); + + // Make sure "document" works, but returns text. + xhr = new XMLHttpRequest(); + + if (xhr.responseType != "") { + throw new Error("Default value for responseType is wrong!"); + } + + xhr.open("GET", url, false); + xhr.responseType = "document"; + xhr.send(); + + if (xhr.responseText != refText) { + throw new Error("'document' type not working correctly"); + } + + e.ports[0].postMessage("done"); + }; +}; diff --git a/dom/xhr/tests/xhr_worker.js b/dom/xhr/tests/xhr_worker.js new file mode 100644 index 0000000000..46edd700db --- /dev/null +++ b/dom/xhr/tests/xhr_worker.js @@ -0,0 +1,84 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +var xhr = new XMLHttpRequest(); + +function onload(event) { + if (event.target != xhr) { + throw new Error("onload event.target != xhr"); + } + + if (event.target.status != 200) { + const message = { type: "error", error: event.target.status }; + postMessage(message); + } + + const message = { type: "load", data: xhr.responseText }; + postMessage(message); +} + +xhr.onload = onload; +xhr.addEventListener("load", onload); +xhr.removeEventListener("load", onload); +if (!xhr.onload) { + const message = { type: "error", error: "Lost message listener!" }; + postMessage(message); +} + +xhr.onerror = function (event) { + if (event.target != xhr) { + throw new Error("onerror event.target != xhr"); + } + var message = { type: "error", error: event.target.status }; + postMessage(message); +}; +// eslint-disable-next-line no-self-assign +xhr.onerror = xhr.onerror; +// eslint-disable-next-line no-self-compare +if (!xhr.onerror || xhr.onerror != xhr.onerror) { + throw new Error("onerror wasn't set properly"); +} + +function onprogress(event) { + if (event.target != xhr) { + throw new Error("onprogress event.target != xhr"); + } + const message = { + type: "progress", + current: event.loaded, + total: event.total, + }; + postMessage(message); +} +xhr.addEventListener("progress", onprogress); + +xhr.addEventListener("foopety", function (event) {}); +xhr.removeEventListener("doopety", function (event) {}); + +xhr.onloadend = function (event) { + const message = { type: "loadend" }; + postMessage(message); +}; + +var upload = xhr.upload; +upload.onprogress = function (event) {}; +upload.addEventListener("foo", function (event) {}); +upload.removeEventListener("foo", function (event) {}); +upload.addEventListener("load", function (event) {}); +upload.removeEventListener("foo", function (event) {}); +upload.onload = function (event) { + const message = { type: "upload.load" }; + postMessage(message); +}; + +onmessage = function (event) { + if (xhr.DONE != 4 || XMLHttpRequest.DONE != 4) { + throw new Error("xhr constants not correct!"); + } + if (xhr.readystate > xhr.UNSENT) { + throw new Error("XHR already running!"); + } + xhr.open("POST", event.data); + xhr.send("Data to send"); +}; diff --git a/dom/xhr/tests/xhr_worker_doubleSend.js b/dom/xhr/tests/xhr_worker_doubleSend.js new file mode 100644 index 0000000000..1ecf28e57c --- /dev/null +++ b/dom/xhr/tests/xhr_worker_doubleSend.js @@ -0,0 +1,11 @@ +var xhr = new XMLHttpRequest(); +xhr.open("POST", "worker_testXHR.txt"); +xhr.send(); +try { + xhr.send(); + postMessage("KO double send should fail"); +} catch (e) { + postMessage( + e.name === "InvalidStateError" ? "OK" : "KO InvalidStateError expected" + ); +} -- cgit v1.2.3