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 --- netwerk/test/browser/103_preload.html | 6 + netwerk/test/browser/103_preload.html^headers^ | 1 + .../103_preload.html^informationalResponse^ | 2 + netwerk/test/browser/103_preload_anchor.html | 6 + .../test/browser/103_preload_anchor.html^headers^ | 1 + .../103_preload_anchor.html^informationalResponse^ | 2 + netwerk/test/browser/103_preload_and_404.html | 6 + .../test/browser/103_preload_and_404.html^headers^ | 1 + ...103_preload_and_404.html^informationalResponse^ | 2 + .../test/browser/103_preload_csp_imgsrc_none.html | 6 + .../103_preload_csp_imgsrc_none.html^headers^ | 2 + ...oad_csp_imgsrc_none.html^informationalResponse^ | 2 + netwerk/test/browser/103_preload_iframe.html | 6 + .../test/browser/103_preload_iframe.html^headers^ | 1 + netwerk/test/browser/auth_post.sjs | 37 +++ netwerk/test/browser/browser.toml | 188 ++++++++++++ netwerk/test/browser/browser_103_assets.js | 169 +++++++++++ .../test/browser/browser_103_assets_extension.js | 78 +++++ netwerk/test/browser/browser_103_cleanup.js | 47 +++ netwerk/test/browser/browser_103_csp.js | 86 ++++++ netwerk/test/browser/browser_103_csp_images.js | 170 +++++++++++ netwerk/test/browser/browser_103_csp_styles.js | 86 ++++++ netwerk/test/browser/browser_103_error.js | 121 ++++++++ .../test/browser/browser_103_no_cancel_on_error.js | 67 +++++ netwerk/test/browser/browser_103_preconnect.js | 71 +++++ netwerk/test/browser/browser_103_preload.js | 138 +++++++++ netwerk/test/browser/browser_103_preload_2.js | 180 ++++++++++++ netwerk/test/browser/browser_103_private_window.js | 70 +++++ netwerk/test/browser/browser_103_redirect.js | 52 ++++ .../browser/browser_103_redirect_from_server.js | 321 +++++++++++++++++++++ .../test/browser/browser_103_referrer_policy.js | 167 +++++++++++ netwerk/test/browser/browser_103_telemetry.js | 107 +++++++ netwerk/test/browser/browser_103_user_load.js | 85 ++++++ netwerk/test/browser/browser_NetUtil.js | 111 +++++++ netwerk/test/browser/browser_about_cache.js | 136 +++++++++ .../browser_backgroundtask_purgeHTTPCache.js | 40 +++ netwerk/test/browser/browser_bug1535877.js | 15 + netwerk/test/browser/browser_bug1629307.js | 81 ++++++ netwerk/test/browser/browser_child_resource.js | 246 ++++++++++++++++ .../test/browser/browser_cookie_filtering_basic.js | 184 ++++++++++++ .../browser_cookie_filtering_cross_origin.js | 146 ++++++++++ .../browser/browser_cookie_filtering_insecure.js | 106 +++++++ .../test/browser/browser_cookie_filtering_oa.js | 190 ++++++++++++ .../browser/browser_cookie_filtering_subdomain.js | 175 +++++++++++ .../browser/browser_cookie_sync_across_tabs.js | 79 +++++ netwerk/test/browser/browser_fetch_lnk.js | 23 ++ netwerk/test/browser/browser_http_index_format.js | 48 +++ .../browser/browser_nsIFormPOSTActionChannel.js | 273 ++++++++++++++++++ netwerk/test/browser/browser_post_auth.js | 65 +++++ netwerk/test/browser/browser_post_file.js | 71 +++++ .../test/browser/browser_purgeCache_idle_daily.js | 86 ++++++ .../test/browser/browser_resource_navigation.js | 76 +++++ .../browser_speculative_connection_link_header.js | 57 ++++ .../browser/browser_test_data_channel_observer.js | 35 +++ netwerk/test/browser/browser_test_favicon.js | 26 ++ netwerk/test/browser/browser_test_io_activity.js | 50 ++++ netwerk/test/browser/browser_test_offline_tab.js | 36 +++ .../test/browser/cookie_filtering_helper.sys.mjs | 166 +++++++++++ netwerk/test/browser/cookie_filtering_resource.sjs | 35 +++ .../cookie_filtering_secure_resource_com.html | 6 + ...kie_filtering_secure_resource_com.html^headers^ | 2 + .../cookie_filtering_secure_resource_org.html | 6 + ...kie_filtering_secure_resource_org.html^headers^ | 2 + netwerk/test/browser/cookie_filtering_square.png | 0 .../browser/cookie_filtering_square.png^headers^ | 2 + netwerk/test/browser/damonbowling.jpg | Bin 0 -> 44008 bytes netwerk/test/browser/damonbowling.jpg^headers^ | 2 + netwerk/test/browser/dummy.html | 11 + netwerk/test/browser/early_hint_asset.sjs | 50 ++++ netwerk/test/browser/early_hint_asset_html.sjs | 135 +++++++++ .../test/browser/early_hint_csp_options_html.sjs | 120 ++++++++ netwerk/test/browser/early_hint_error.sjs | 35 +++ netwerk/test/browser/early_hint_main_html.sjs | 62 ++++ netwerk/test/browser/early_hint_main_redirect.sjs | 67 +++++ netwerk/test/browser/early_hint_pixel.sjs | 37 +++ netwerk/test/browser/early_hint_pixel_count.sjs | 9 + .../test/browser/early_hint_preconnect_html.sjs | 32 ++ .../browser/early_hint_preload_test_helper.sys.mjs | 159 ++++++++++ netwerk/test/browser/early_hint_redirect.sjs | 21 ++ netwerk/test/browser/early_hint_redirect_html.sjs | 24 ++ .../browser/early_hint_referrer_policy_html.sjs | 132 +++++++++ netwerk/test/browser/file_favicon.html | 7 + netwerk/test/browser/file_link_header.sjs | 24 ++ netwerk/test/browser/file_lnk.lnk | Bin 0 -> 1531 bytes netwerk/test/browser/ioactivity.html | 11 + netwerk/test/browser/no_103_preload.html | 6 + netwerk/test/browser/no_103_preload.html^headers^ | 1 + netwerk/test/browser/post.html | 14 + netwerk/test/browser/redirect.sjs | 6 + netwerk/test/browser/res.css | 4 + netwerk/test/browser/res.css^headers^ | 1 + netwerk/test/browser/res.csv | 1 + netwerk/test/browser/res.csv^headers^ | 1 + netwerk/test/browser/res.mp3 | Bin 0 -> 3530 bytes netwerk/test/browser/res.unknown | 1 + netwerk/test/browser/res_206.html | 11 + netwerk/test/browser/res_206.html^headers^ | 2 + netwerk/test/browser/res_206.mp3 | Bin 0 -> 3530 bytes netwerk/test/browser/res_206.mp3^headers^ | 1 + netwerk/test/browser/res_empty.zip | Bin 0 -> 166 bytes netwerk/test/browser/res_http_index_format | 1 + .../test/browser/res_http_index_format^headers^ | 1 + netwerk/test/browser/res_img.png | Bin 0 -> 129497 bytes netwerk/test/browser/res_img_for_unknown_decoder | Bin 0 -> 4421 bytes .../browser/res_img_for_unknown_decoder^headers^ | 2 + netwerk/test/browser/res_img_unknown.png | 11 + netwerk/test/browser/res_invalid_partial.mp3 | Bin 0 -> 3530 bytes .../test/browser/res_invalid_partial.mp3^headers^ | 2 + netwerk/test/browser/res_nosniff.html | 11 + netwerk/test/browser/res_nosniff.html^headers^ | 2 + netwerk/test/browser/res_nosniff2.html | 11 + netwerk/test/browser/res_nosniff2.html^headers^ | 2 + netwerk/test/browser/res_not_200or206.mp3 | Bin 0 -> 3530 bytes netwerk/test/browser/res_not_200or206.mp3^headers^ | 1 + netwerk/test/browser/res_not_ok.html | 11 + netwerk/test/browser/res_not_ok.html^headers^ | 1 + netwerk/test/browser/res_object.html | 18 ++ netwerk/test/browser/res_sub_document.html | 11 + netwerk/test/browser/square.png | 0 netwerk/test/browser/test_1629307.html | 9 + netwerk/test/browser/x_frame_options.html | 0 netwerk/test/browser/x_frame_options.html^headers^ | 3 + 122 files changed, 5942 insertions(+) create mode 100644 netwerk/test/browser/103_preload.html create mode 100644 netwerk/test/browser/103_preload.html^headers^ create mode 100644 netwerk/test/browser/103_preload.html^informationalResponse^ create mode 100644 netwerk/test/browser/103_preload_anchor.html create mode 100644 netwerk/test/browser/103_preload_anchor.html^headers^ create mode 100644 netwerk/test/browser/103_preload_anchor.html^informationalResponse^ create mode 100644 netwerk/test/browser/103_preload_and_404.html create mode 100644 netwerk/test/browser/103_preload_and_404.html^headers^ create mode 100644 netwerk/test/browser/103_preload_and_404.html^informationalResponse^ create mode 100644 netwerk/test/browser/103_preload_csp_imgsrc_none.html create mode 100644 netwerk/test/browser/103_preload_csp_imgsrc_none.html^headers^ create mode 100644 netwerk/test/browser/103_preload_csp_imgsrc_none.html^informationalResponse^ create mode 100644 netwerk/test/browser/103_preload_iframe.html create mode 100644 netwerk/test/browser/103_preload_iframe.html^headers^ create mode 100644 netwerk/test/browser/auth_post.sjs create mode 100644 netwerk/test/browser/browser.toml create mode 100644 netwerk/test/browser/browser_103_assets.js create mode 100644 netwerk/test/browser/browser_103_assets_extension.js create mode 100644 netwerk/test/browser/browser_103_cleanup.js create mode 100644 netwerk/test/browser/browser_103_csp.js create mode 100644 netwerk/test/browser/browser_103_csp_images.js create mode 100644 netwerk/test/browser/browser_103_csp_styles.js create mode 100644 netwerk/test/browser/browser_103_error.js create mode 100644 netwerk/test/browser/browser_103_no_cancel_on_error.js create mode 100644 netwerk/test/browser/browser_103_preconnect.js create mode 100644 netwerk/test/browser/browser_103_preload.js create mode 100644 netwerk/test/browser/browser_103_preload_2.js create mode 100644 netwerk/test/browser/browser_103_private_window.js create mode 100644 netwerk/test/browser/browser_103_redirect.js create mode 100644 netwerk/test/browser/browser_103_redirect_from_server.js create mode 100644 netwerk/test/browser/browser_103_referrer_policy.js create mode 100644 netwerk/test/browser/browser_103_telemetry.js create mode 100644 netwerk/test/browser/browser_103_user_load.js create mode 100644 netwerk/test/browser/browser_NetUtil.js create mode 100644 netwerk/test/browser/browser_about_cache.js create mode 100644 netwerk/test/browser/browser_backgroundtask_purgeHTTPCache.js create mode 100644 netwerk/test/browser/browser_bug1535877.js create mode 100644 netwerk/test/browser/browser_bug1629307.js create mode 100644 netwerk/test/browser/browser_child_resource.js create mode 100644 netwerk/test/browser/browser_cookie_filtering_basic.js create mode 100644 netwerk/test/browser/browser_cookie_filtering_cross_origin.js create mode 100644 netwerk/test/browser/browser_cookie_filtering_insecure.js create mode 100644 netwerk/test/browser/browser_cookie_filtering_oa.js create mode 100644 netwerk/test/browser/browser_cookie_filtering_subdomain.js create mode 100644 netwerk/test/browser/browser_cookie_sync_across_tabs.js create mode 100644 netwerk/test/browser/browser_fetch_lnk.js create mode 100644 netwerk/test/browser/browser_http_index_format.js create mode 100644 netwerk/test/browser/browser_nsIFormPOSTActionChannel.js create mode 100644 netwerk/test/browser/browser_post_auth.js create mode 100644 netwerk/test/browser/browser_post_file.js create mode 100644 netwerk/test/browser/browser_purgeCache_idle_daily.js create mode 100644 netwerk/test/browser/browser_resource_navigation.js create mode 100644 netwerk/test/browser/browser_speculative_connection_link_header.js create mode 100644 netwerk/test/browser/browser_test_data_channel_observer.js create mode 100644 netwerk/test/browser/browser_test_favicon.js create mode 100644 netwerk/test/browser/browser_test_io_activity.js create mode 100644 netwerk/test/browser/browser_test_offline_tab.js create mode 100644 netwerk/test/browser/cookie_filtering_helper.sys.mjs create mode 100644 netwerk/test/browser/cookie_filtering_resource.sjs create mode 100644 netwerk/test/browser/cookie_filtering_secure_resource_com.html create mode 100644 netwerk/test/browser/cookie_filtering_secure_resource_com.html^headers^ create mode 100644 netwerk/test/browser/cookie_filtering_secure_resource_org.html create mode 100644 netwerk/test/browser/cookie_filtering_secure_resource_org.html^headers^ create mode 100644 netwerk/test/browser/cookie_filtering_square.png create mode 100644 netwerk/test/browser/cookie_filtering_square.png^headers^ create mode 100644 netwerk/test/browser/damonbowling.jpg create mode 100644 netwerk/test/browser/damonbowling.jpg^headers^ create mode 100644 netwerk/test/browser/dummy.html create mode 100644 netwerk/test/browser/early_hint_asset.sjs create mode 100644 netwerk/test/browser/early_hint_asset_html.sjs create mode 100644 netwerk/test/browser/early_hint_csp_options_html.sjs create mode 100644 netwerk/test/browser/early_hint_error.sjs create mode 100644 netwerk/test/browser/early_hint_main_html.sjs create mode 100644 netwerk/test/browser/early_hint_main_redirect.sjs create mode 100644 netwerk/test/browser/early_hint_pixel.sjs create mode 100644 netwerk/test/browser/early_hint_pixel_count.sjs create mode 100644 netwerk/test/browser/early_hint_preconnect_html.sjs create mode 100644 netwerk/test/browser/early_hint_preload_test_helper.sys.mjs create mode 100644 netwerk/test/browser/early_hint_redirect.sjs create mode 100644 netwerk/test/browser/early_hint_redirect_html.sjs create mode 100644 netwerk/test/browser/early_hint_referrer_policy_html.sjs create mode 100644 netwerk/test/browser/file_favicon.html create mode 100644 netwerk/test/browser/file_link_header.sjs create mode 100644 netwerk/test/browser/file_lnk.lnk create mode 100644 netwerk/test/browser/ioactivity.html create mode 100644 netwerk/test/browser/no_103_preload.html create mode 100644 netwerk/test/browser/no_103_preload.html^headers^ create mode 100644 netwerk/test/browser/post.html create mode 100644 netwerk/test/browser/redirect.sjs create mode 100644 netwerk/test/browser/res.css create mode 100644 netwerk/test/browser/res.css^headers^ create mode 100644 netwerk/test/browser/res.csv create mode 100644 netwerk/test/browser/res.csv^headers^ create mode 100644 netwerk/test/browser/res.mp3 create mode 100644 netwerk/test/browser/res.unknown create mode 100644 netwerk/test/browser/res_206.html create mode 100644 netwerk/test/browser/res_206.html^headers^ create mode 100644 netwerk/test/browser/res_206.mp3 create mode 100644 netwerk/test/browser/res_206.mp3^headers^ create mode 100644 netwerk/test/browser/res_empty.zip create mode 100644 netwerk/test/browser/res_http_index_format create mode 100644 netwerk/test/browser/res_http_index_format^headers^ create mode 100644 netwerk/test/browser/res_img.png create mode 100644 netwerk/test/browser/res_img_for_unknown_decoder create mode 100644 netwerk/test/browser/res_img_for_unknown_decoder^headers^ create mode 100644 netwerk/test/browser/res_img_unknown.png create mode 100644 netwerk/test/browser/res_invalid_partial.mp3 create mode 100644 netwerk/test/browser/res_invalid_partial.mp3^headers^ create mode 100644 netwerk/test/browser/res_nosniff.html create mode 100644 netwerk/test/browser/res_nosniff.html^headers^ create mode 100644 netwerk/test/browser/res_nosniff2.html create mode 100644 netwerk/test/browser/res_nosniff2.html^headers^ create mode 100644 netwerk/test/browser/res_not_200or206.mp3 create mode 100644 netwerk/test/browser/res_not_200or206.mp3^headers^ create mode 100644 netwerk/test/browser/res_not_ok.html create mode 100644 netwerk/test/browser/res_not_ok.html^headers^ create mode 100644 netwerk/test/browser/res_object.html create mode 100644 netwerk/test/browser/res_sub_document.html create mode 100644 netwerk/test/browser/square.png create mode 100644 netwerk/test/browser/test_1629307.html create mode 100644 netwerk/test/browser/x_frame_options.html create mode 100644 netwerk/test/browser/x_frame_options.html^headers^ (limited to 'netwerk/test/browser') diff --git a/netwerk/test/browser/103_preload.html b/netwerk/test/browser/103_preload.html new file mode 100644 index 0000000000..9583815cfb --- /dev/null +++ b/netwerk/test/browser/103_preload.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/netwerk/test/browser/103_preload.html^headers^ b/netwerk/test/browser/103_preload.html^headers^ new file mode 100644 index 0000000000..9e23c73b7f --- /dev/null +++ b/netwerk/test/browser/103_preload.html^headers^ @@ -0,0 +1 @@ +Cache-Control: no-cache diff --git a/netwerk/test/browser/103_preload.html^informationalResponse^ b/netwerk/test/browser/103_preload.html^informationalResponse^ new file mode 100644 index 0000000000..b95a96e74b --- /dev/null +++ b/netwerk/test/browser/103_preload.html^informationalResponse^ @@ -0,0 +1,2 @@ +HTTP 103 Too Early +Link: ; rel=preload; as=image diff --git a/netwerk/test/browser/103_preload_anchor.html b/netwerk/test/browser/103_preload_anchor.html new file mode 100644 index 0000000000..c12fe92072 --- /dev/null +++ b/netwerk/test/browser/103_preload_anchor.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/netwerk/test/browser/103_preload_anchor.html^headers^ b/netwerk/test/browser/103_preload_anchor.html^headers^ new file mode 100644 index 0000000000..9e23c73b7f --- /dev/null +++ b/netwerk/test/browser/103_preload_anchor.html^headers^ @@ -0,0 +1 @@ +Cache-Control: no-cache diff --git a/netwerk/test/browser/103_preload_anchor.html^informationalResponse^ b/netwerk/test/browser/103_preload_anchor.html^informationalResponse^ new file mode 100644 index 0000000000..1099062e15 --- /dev/null +++ b/netwerk/test/browser/103_preload_anchor.html^informationalResponse^ @@ -0,0 +1,2 @@ +HTTP 103 Early Hints +Link: ; rel=preload; as=image; anchor="/browser/" diff --git a/netwerk/test/browser/103_preload_and_404.html b/netwerk/test/browser/103_preload_and_404.html new file mode 100644 index 0000000000..f09f5cb085 --- /dev/null +++ b/netwerk/test/browser/103_preload_and_404.html @@ -0,0 +1,6 @@ + + 404 Not Found + +

404 Not Found

+ + diff --git a/netwerk/test/browser/103_preload_and_404.html^headers^ b/netwerk/test/browser/103_preload_and_404.html^headers^ new file mode 100644 index 0000000000..937e38c6c4 --- /dev/null +++ b/netwerk/test/browser/103_preload_and_404.html^headers^ @@ -0,0 +1 @@ +HTTP 404 Not Found diff --git a/netwerk/test/browser/103_preload_and_404.html^informationalResponse^ b/netwerk/test/browser/103_preload_and_404.html^informationalResponse^ new file mode 100644 index 0000000000..78cb7efea4 --- /dev/null +++ b/netwerk/test/browser/103_preload_and_404.html^informationalResponse^ @@ -0,0 +1,2 @@ +HTTP 103 Early Hints +Link: ; rel=preload; as=image diff --git a/netwerk/test/browser/103_preload_csp_imgsrc_none.html b/netwerk/test/browser/103_preload_csp_imgsrc_none.html new file mode 100644 index 0000000000..367e80a6b3 --- /dev/null +++ b/netwerk/test/browser/103_preload_csp_imgsrc_none.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/netwerk/test/browser/103_preload_csp_imgsrc_none.html^headers^ b/netwerk/test/browser/103_preload_csp_imgsrc_none.html^headers^ new file mode 100644 index 0000000000..b4dedd0812 --- /dev/null +++ b/netwerk/test/browser/103_preload_csp_imgsrc_none.html^headers^ @@ -0,0 +1,2 @@ +Cache-Control: no-cache +Content-Security-Policy: img-src 'none' diff --git a/netwerk/test/browser/103_preload_csp_imgsrc_none.html^informationalResponse^ b/netwerk/test/browser/103_preload_csp_imgsrc_none.html^informationalResponse^ new file mode 100644 index 0000000000..d82224fd07 --- /dev/null +++ b/netwerk/test/browser/103_preload_csp_imgsrc_none.html^informationalResponse^ @@ -0,0 +1,2 @@ +HTTP 103 Too Early +Link: ; rel=preload; as=image diff --git a/netwerk/test/browser/103_preload_iframe.html b/netwerk/test/browser/103_preload_iframe.html new file mode 100644 index 0000000000..815a14220f --- /dev/null +++ b/netwerk/test/browser/103_preload_iframe.html @@ -0,0 +1,6 @@ + + + + + + +`; + } else if (this.uri.spec.startsWith(ACTION_BASE)) { + var postData = ""; + var headers = {}; + if (this._uploadStream) { + var bstream = Cc["@mozilla.org/binaryinputstream;1"].createInstance( + Ci.nsIBinaryInputStream + ); + bstream.setInputStream(this._uploadStream); + postData = bstream.readBytes(bstream.available()); + + if (this._uploadStream instanceof Ci.nsIMIMEInputStream) { + this._uploadStream.visitHeaders((name, value) => { + headers[name] = value; + }); + } + } + data += ` + + + +`; + } + + data += ` + + +`; + + var stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( + Ci.nsIStringInputStream + ); + stream.setData(data, data.length); + + var runnable = { + run: () => { + try { + aListener.onStartRequest(this, null); + } catch (e) {} + try { + aListener.onDataAvailable(this, stream, 0, stream.available()); + } catch (e) {} + try { + aListener.onStopRequest(this, null, Cr.NS_OK); + } catch (e) {} + }, + }; + Services.tm.dispatchToMainThread(runnable); + }, + + /** nsIRequest */ + get name() { + return this.uri.spec; + }, + isPending() { + return false; + }, + get status() { + return Cr.NS_OK; + }, + cancel(status) {}, + loadGroup: null, + loadFlags: + Ci.nsIRequest.LOAD_NORMAL | + Ci.nsIRequest.INHIBIT_CACHING | + Ci.nsIRequest.LOAD_BYPASS_CACHE, +}; + +function frameScript() { + /* eslint-env mozilla/frame-script */ + /* eslint-disable mozilla/no-arbitrary-setTimeout */ + addMessageListener("Test:WaitForIFrame", function () { + var check = function () { + if (content) { + var frame = content.document.getElementById("frame"); + if (frame) { + var upload_stream = + frame.contentDocument.getElementById("upload_stream"); + var post_data = frame.contentDocument.getElementById("post_data"); + var headers = frame.contentDocument.getElementById("upload_headers"); + if (upload_stream && post_data && headers) { + sendAsyncMessage("Test:IFrameLoaded", [ + upload_stream.value, + post_data.value, + headers.value, + ]); + return; + } + } + } + + setTimeout(check, 100); + }; + + check(); + }); + /* eslint-enable mozilla/no-arbitrary-setTimeout */ +} + +function loadTestTab(uri) { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, uri); + var browser = gBrowser.selectedBrowser; + + let manager = browser.messageManager; + browser.messageManager.loadFrameScript( + "data:,(" + frameScript.toString() + ")();", + true + ); + + return new Promise(resolve => { + function listener({ data: [hasUploadStream, postData, headers] }) { + manager.removeMessageListener("Test:IFrameLoaded", listener); + resolve([hasUploadStream, atob(postData), JSON.parse(headers)]); + } + + manager.addMessageListener("Test:IFrameLoaded", listener); + manager.sendAsyncMessage("Test:WaitForIFrame"); + }); +} + +add_task(async function () { + var handler = new CustomProtocolHandler(); + Services.io.registerProtocolHandler( + SCHEME, + handler, + Ci.nsIProtocolHandler.URI_NORELATIVE | + Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE, + -1 + ); + registerCleanupFunction(function () { + Services.io.unregisterProtocolHandler(SCHEME); + }); +}); + +add_task(async function () { + var [hasUploadStream] = await loadTestTab(NORMAL_FORM_URI); + is(hasUploadStream, "no", "normal action should not have uploadStream"); + + gBrowser.removeCurrentTab(); +}); + +add_task(async function () { + var [hasUploadStream] = await loadTestTab(UPLOAD_FORM_URI); + is(hasUploadStream, "no", "upload action should not have uploadStream"); + + gBrowser.removeCurrentTab(); +}); + +add_task(async function () { + var [hasUploadStream, postData, headers] = await loadTestTab(POST_FORM_URI); + + is(hasUploadStream, "yes", "post action should have uploadStream"); + is(postData, "foo=bar\r\n", "POST data is received correctly"); + + is(headers["Content-Type"], "text/plain", "Content-Type header is correct"); + is(headers["Content-Length"], undefined, "Content-Length header is correct"); + + gBrowser.removeCurrentTab(); +}); diff --git a/netwerk/test/browser/browser_post_auth.js b/netwerk/test/browser/browser_post_auth.js new file mode 100644 index 0000000000..24104f96d6 --- /dev/null +++ b/netwerk/test/browser/browser_post_auth.js @@ -0,0 +1,65 @@ +"use strict"; + +const { PromptTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PromptTestUtils.sys.mjs" +); + +const FOLDER = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "http://mochi.test:8888/" +); + +add_task(async function () { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:blank" + ); + let browserLoadedPromise = BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + true, + `${FOLDER}post.html` + ); + BrowserTestUtils.startLoadingURIString( + tab.linkedBrowser, + `${FOLDER}post.html` + ); + await browserLoadedPromise; + + let finalLoadPromise = BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + true, + `${FOLDER}auth_post.sjs` + ); + + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + let file = new content.File( + [new content.Blob(["1234".repeat(1024 * 500)], { type: "text/plain" })], + "test-name" + ); + content.document.getElementById("input_file").mozSetFileArray([file]); + content.document.getElementById("form").submit(); + }); + + let promptPromise = PromptTestUtils.handleNextPrompt( + tab.linkedBrowser, + { + modalType: Services.prefs.getIntPref("prompts.modalType.httpAuth"), + promptType: "promptUserAndPass", + }, + { buttonNumClick: 0, loginInput: "user", passwordInput: "pass" } + ); + + await promptPromise; + + await finalLoadPromise; + + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + Assert.ok(content.location.href.includes("auth_post.sjs")); + Assert.ok(content.document.body.innerHTML.includes("1234")); + }); + + BrowserTestUtils.removeTab(tab); + + // Clean up any active logins we added during the test. + Services.obs.notifyObservers(null, "net:clear-active-logins"); +}); diff --git a/netwerk/test/browser/browser_post_file.js b/netwerk/test/browser/browser_post_file.js new file mode 100644 index 0000000000..8b156dff9e --- /dev/null +++ b/netwerk/test/browser/browser_post_file.js @@ -0,0 +1,71 @@ +/* + * Tests for bug 1241100: Post to local file should not overwrite the file. + */ +"use strict"; + +async function createTestFile(filename, content) { + let path = PathUtils.join(PathUtils.tempDir, filename); + await IOUtils.writeUTF8(path, content); + return path; +} + +add_task(async function () { + var postFilename = "post_file.html"; + var actionFilename = "action_file.html"; + + var postFileContent = ` + + + + +post file + + +
+ + +
+ + + +`; + + var actionFileContent = ` + + + + +action file + + +
ok
+ + +`; + + var postPath = await createTestFile(postFilename, postFileContent); + var actionPath = await createTestFile(actionFilename, actionFileContent); + + var postURI = PathUtils.toFileURI(postPath); + var actionURI = PathUtils.toFileURI(actionPath); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:blank" + ); + let browserLoadedPromise = BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + true, + actionURI + ); + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, postURI); + await browserLoadedPromise; + + var actionFileContentAfter = await IOUtils.readUTF8(actionPath); + is(actionFileContentAfter, actionFileContent, "action file is not modified"); + + await IOUtils.remove(postPath); + await IOUtils.remove(actionPath); + + gBrowser.removeCurrentTab(); +}); diff --git a/netwerk/test/browser/browser_purgeCache_idle_daily.js b/netwerk/test/browser/browser_purgeCache_idle_daily.js new file mode 100644 index 0000000000..21ba46af1d --- /dev/null +++ b/netwerk/test/browser/browser_purgeCache_idle_daily.js @@ -0,0 +1,86 @@ +/* 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/. */ + +"use strict"; + +add_task(async function test_idle_cleanup() { + Services.fog.testResetFOG(); + Services.prefs.setBoolPref( + "network.cache.shutdown_purge_in_background_task", + true + ); + Services.prefs.setBoolPref("privacy.clearOnShutdown.cache", true); + Services.prefs.setBoolPref("privacy.sanitize.sanitizeOnShutdown", true); + let dir = Services.dirsvc.get("ProfD", Ci.nsIFile); + dir.append("cache2.2021-11-25-08-47-04.purge.bg_rm"); + Assert.equal(dir.exists(), false, `Folder ${dir.path} should not exist`); + dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o744); + Assert.equal( + dir.exists(), + true, + `Folder ${dir.path} should have been created` + ); + + Services.obs.notifyObservers(null, "idle-daily"); + + await TestUtils.waitForCondition(() => { + return !dir.exists(); + }); + + Assert.equal( + dir.exists(), + false, + `Folder ${dir.path} should have been purged by background task` + ); + Assert.equal( + await Glean.networking.residualCacheFolderCount.testGetValue(), + 1 + ); + Assert.equal( + await Glean.networking.residualCacheFolderRemoval.success.testGetValue(), + 1 + ); + Assert.equal( + await Glean.networking.residualCacheFolderRemoval.failure.testGetValue(), + null + ); + + // Check that telemetry properly detects folders failing to be deleted when readonly + // Making folders readonly only works on windows + if (AppConstants.platform == "win") { + dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o744); + dir.QueryInterface(Ci.nsILocalFileWin).readOnly = true; + + Services.obs.notifyObservers(null, "idle-daily"); + + await BrowserTestUtils.waitForCondition(async () => { + return ( + (await Glean.networking.residualCacheFolderRemoval.failure.testGetValue()) == + 1 + ); + }); + + Assert.equal( + await Glean.networking.residualCacheFolderCount.testGetValue(), + 2 + ); + Assert.equal( + await Glean.networking.residualCacheFolderRemoval.success.testGetValue(), + 1 + ); + Assert.equal( + await Glean.networking.residualCacheFolderRemoval.failure.testGetValue(), + 1 + ); + + dir.QueryInterface(Ci.nsILocalFileWin).readOnly = false; + dir.remove(true); + } + + Services.prefs.clearUserPref( + "network.cache.shutdown_purge_in_background_task" + ); + Services.prefs.clearUserPref("privacy.clearOnShutdown.cache"); + Services.prefs.clearUserPref("privacy.sanitize.sanitizeOnShutdown"); +}); diff --git a/netwerk/test/browser/browser_resource_navigation.js b/netwerk/test/browser/browser_resource_navigation.js new file mode 100644 index 0000000000..56ec280b83 --- /dev/null +++ b/netwerk/test/browser/browser_resource_navigation.js @@ -0,0 +1,76 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +"use strict"; + +add_task(async function () { + info("Make sure navigation through links in resource:// pages work"); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "resource://gre/" }, + async function (browser) { + // Following a directory link shall properly open the directory (bug 1224046) + await SpecialPowers.spawn(browser, [], function () { + let link = Array.prototype.filter.call( + content.document.getElementsByClassName("dir"), + function (element) { + let name = element.textContent; + // Depending whether resource:// is backed by jar: or file://, + // directories either have a trailing slash or they don't. + if (name.endsWith("/")) { + name = name.slice(0, -1); + } + return name == "components"; + } + )[0]; + // First ensure the link is in the viewport + link.scrollIntoView(); + // Then click on it. + link.click(); + }); + + await BrowserTestUtils.browserLoaded( + browser, + undefined, + "resource://gre/components/" + ); + + // Following the parent link shall properly open the parent (bug 1366180) + await SpecialPowers.spawn(browser, [], function () { + let link = content.document + .getElementById("UI_goUp") + .getElementsByTagName("a")[0]; + // The link should always be high enough in the page to be in the viewport. + link.click(); + }); + + await BrowserTestUtils.browserLoaded( + browser, + undefined, + "resource://gre/" + ); + + // Following a link to a given file shall properly open the file. + await SpecialPowers.spawn(browser, [], function () { + let link = Array.prototype.filter.call( + content.document.getElementsByClassName("file"), + function (element) { + return element.textContent == "greprefs.js"; + } + )[0]; + link.scrollIntoView(); + link.click(); + }); + + await BrowserTestUtils.browserLoaded( + browser, + undefined, + "resource://gre/greprefs.js" + ); + + ok(true, "Got to the end of the test!"); + } + ); +}); diff --git a/netwerk/test/browser/browser_speculative_connection_link_header.js b/netwerk/test/browser/browser_speculative_connection_link_header.js new file mode 100644 index 0000000000..24549d30b0 --- /dev/null +++ b/netwerk/test/browser/browser_speculative_connection_link_header.js @@ -0,0 +1,57 @@ +/* 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/. */ + +Services.prefs.setBoolPref("network.http.debug-observations", true); + +registerCleanupFunction(function () { + Services.prefs.clearUserPref("network.http.debug-observations"); +}); + +// Test steps: +// 1. Load file_link_header.sjs +// 2.`` is in +// file_link_header.sjs, so we will create a speculative connection. +// 3. We use "speculative-connect-request" topic to observe whether the +// speculative connection is attempted. +// 4. Finally, we check if the observed host and partition key are the same and +// as the expected. +add_task(async function test_link_preconnect() { + let requestUrl = `https://example.com/browser/netwerk/test/browser/file_link_header.sjs`; + + let observed = ""; + let observer = { + QueryInterface: ChromeUtils.generateQI(["nsIObserver"]), + observe(aSubject, aTopic, aData) { + if (aTopic == "speculative-connect-request") { + Services.obs.removeObserver(observer, "speculative-connect-request"); + observed = aData; + } + }, + }; + Services.obs.addObserver(observer, "speculative-connect-request"); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: requestUrl, + waitForLoad: true, + }, + async function () {} + ); + + // The hash key should be like: + // ".S........[tlsflags0x00000000]localhost:443^partitionKey=%28https%2Cexample.com%29" + + // Extracting "localhost:443" + let hostPortRegex = /\[.*\](.*?)\^/; + let hostPortMatch = hostPortRegex.exec(observed); + let hostPort = hostPortMatch ? hostPortMatch[1] : ""; + // Extracting "%28https%2Cexample.com%29" + let partitionKeyRegex = /\^partitionKey=(.*)$/; + let partitionKeyMatch = partitionKeyRegex.exec(observed); + let partitionKey = partitionKeyMatch ? partitionKeyMatch[1] : ""; + + Assert.equal(hostPort, "localhost:443"); + Assert.equal(partitionKey, "%28https%2Cexample.com%29"); +}); diff --git a/netwerk/test/browser/browser_test_data_channel_observer.js b/netwerk/test/browser/browser_test_data_channel_observer.js new file mode 100644 index 0000000000..e03bbc72e6 --- /dev/null +++ b/netwerk/test/browser/browser_test_data_channel_observer.js @@ -0,0 +1,35 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_URI = "data:text/html;charset=utf-8,

Test"; + +let created = false; + +add_task(async function test_data_channel_observer() { + setupObserver(); + let tab = await BrowserTestUtils.addTab(gBrowser, TEST_URI); + await BrowserTestUtils.waitForCondition(() => created); + ok(created, "We received observer notification"); + await BrowserTestUtils.removeTab(tab); +}); + +function setupObserver() { + const observer = { + QueryInterface: ChromeUtils.generateQI(["nsIObserver"]), + + observe: function observe(subject, topic) { + switch (topic) { + case "data-channel-opened": + let channelURI = subject.QueryInterface(Ci.nsIChannel).URI.spec; + if (channelURI === TEST_URI) { + Services.obs.removeObserver(observer, "data-channel-opened"); + created = true; + } + break; + } + }, + }; + Services.obs.addObserver(observer, "data-channel-opened"); +} diff --git a/netwerk/test/browser/browser_test_favicon.js b/netwerk/test/browser/browser_test_favicon.js new file mode 100644 index 0000000000..99cc6b0922 --- /dev/null +++ b/netwerk/test/browser/browser_test_favicon.js @@ -0,0 +1,26 @@ +// Tests third party cookie blocking using a favicon loaded from a different +// domain. The cookie should be considered third party. +"use strict"; +add_task(async function () { + const iconUrl = + "http://example.org/browser/netwerk/test/browser/damonbowling.jpg"; + const pageUrl = + "http://example.com/browser/netwerk/test/browser/file_favicon.html"; + await SpecialPowers.pushPrefEnv({ + set: [["network.cookie.cookieBehavior", 1]], + }); + + let promise = TestUtils.topicObserved("cookie-rejected", subject => { + let uri = subject.QueryInterface(Ci.nsIURI); + return uri.spec == iconUrl; + }); + + // Kick off a page load that will load the favicon. + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl); + registerCleanupFunction(async function () { + BrowserTestUtils.removeTab(tab); + }); + + await promise; + ok(true, "foreign favicon cookie was blocked"); +}); diff --git a/netwerk/test/browser/browser_test_io_activity.js b/netwerk/test/browser/browser_test_io_activity.js new file mode 100644 index 0000000000..1e9cb29b6d --- /dev/null +++ b/netwerk/test/browser/browser_test_io_activity.js @@ -0,0 +1,50 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; +const ROOT_URL = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "https://example.com/" +); +const TEST_URL = "about:license"; +const TEST_URL2 = ROOT_URL + "ioactivity.html"; + +var gotSocket = false; +var gotFile = false; +var gotSqlite = false; +var gotEmptyData = false; + +function processResults(results) { + for (let data of results) { + console.log(data.location); + gotEmptyData = data.rx == 0 && data.tx == 0 && !gotEmptyData; + gotSocket = data.location.startsWith("socket://127.0.0.1:") || gotSocket; + gotFile = data.location.endsWith("aboutLicense.css") || gotFile; + gotSqlite = data.location.endsWith("places.sqlite") || gotSqlite; + // check for the write-ahead file as well + gotSqlite = data.location.endsWith("places.sqlite-wal") || gotSqlite; + } +} + +add_task(async function testRequestIOActivity() { + await SpecialPowers.pushPrefEnv({ + set: [["io.activity.enabled", true]], + }); + waitForExplicitFinish(); + Services.obs.notifyObservers(null, "profile-initial-state"); + + await BrowserTestUtils.withNewTab(TEST_URL, async function (browser) { + await BrowserTestUtils.withNewTab(TEST_URL2, async function (browser) { + let results = await ChromeUtils.requestIOActivity(); + processResults(results); + + ok(gotSocket, "A socket was used"); + // test deactivated for now + // ok(gotFile, "A file was used"); + ok(gotSqlite, "A sqlite DB was used"); + ok(!gotEmptyData, "Every I/O event had data"); + }); + }); +}); diff --git a/netwerk/test/browser/browser_test_offline_tab.js b/netwerk/test/browser/browser_test_offline_tab.js new file mode 100644 index 0000000000..bf60b4f462 --- /dev/null +++ b/netwerk/test/browser/browser_test_offline_tab.js @@ -0,0 +1,36 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function test_set_tab_offline() { + await BrowserTestUtils.withNewTab("https://example.com", async browser => { + // Set the tab to offline + gBrowser.selectedBrowser.browsingContext.forceOffline = true; + + await SpecialPowers.spawn(browser, [], async () => { + try { + await content.fetch("https://example.com/empty.html"); + ok(false, "Should not load since tab is offline"); + } catch (err) { + is(err.name, "TypeError", "Should fail since tab is offline"); + } + }); + }); +}); + +add_task(async function test_set_tab_online() { + await BrowserTestUtils.withNewTab("https://example.com", async browser => { + // Set the tab to online + gBrowser.selectedBrowser.browsingContext.forceOffline = false; + + await SpecialPowers.spawn(browser, [], async () => { + try { + await content.fetch("https://example.com/empty.html"); + ok(true, "Should load since tab is online"); + } catch (err) { + ok(false, "Should not fail since tab is online"); + } + }); + }); +}); diff --git a/netwerk/test/browser/cookie_filtering_helper.sys.mjs b/netwerk/test/browser/cookie_filtering_helper.sys.mjs new file mode 100644 index 0000000000..ab9d721359 --- /dev/null +++ b/netwerk/test/browser/cookie_filtering_helper.sys.mjs @@ -0,0 +1,166 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// The functions in this file will run in the content process in a test +// scope. +/* eslint-env mozilla/simpletest */ +/* global ContentTaskUtils, content */ + +import { NetUtil } from "resource://gre/modules/NetUtil.sys.mjs"; + +const info = console.log; + +export var HTTPS_EXAMPLE_ORG = "https://example.org"; +export var HTTPS_EXAMPLE_COM = "https://example.com"; +export var HTTP_EXAMPLE_COM = "http://example.com"; + +export function browserTestPath(uri) { + return uri + "/browser/netwerk/test/browser/"; +} + +export function waitForAllExpectedTests() { + return ContentTaskUtils.waitForCondition(() => { + return content.testDone === true; + }); +} + +export function cleanupObservers() { + Services.obs.notifyObservers(null, "cookie-content-filter-cleanup"); +} + +export async function preclean_test() { + // enable all cookies for the set-cookie trigger via setCookieStringFromHttp + Services.prefs.setIntPref("network.cookie.cookieBehavior", 0); + Services.prefs.setBoolPref( + "network.cookieJarSettings.unblocked_for_testing", + true + ); + + Services.prefs.setBoolPref("network.cookie.sameSite.laxByDefault", false); + Services.prefs.setBoolPref( + "network.cookie.sameSite.noneRequiresSecure", + false + ); + Services.prefs.setBoolPref("network.cookie.sameSite.schemeful", false); + + Services.cookies.removeAll(); +} + +export async function cleanup_test() { + Services.prefs.clearUserPref("network.cookie.cookieBehavior"); + Services.prefs.clearUserPref( + "network.cookieJarSettings.unblocked_for_testing" + ); + + Services.prefs.clearUserPref("network.cookie.sameSite.laxByDefault"); + Services.prefs.clearUserPref("network.cookie.sameSite.noneRequiresSecure"); + Services.prefs.clearUserPref("network.cookie.sameSite.schemeful"); + + Services.cookies.removeAll(); +} + +export async function fetchHelper(url, cookie, secure, domain = "") { + let headers = new Headers(); + + headers.append("return-set-cookie", cookie); + + if (!secure) { + headers.append("return-insecure-cookie", cookie); + } + + if (domain != "") { + headers.append("return-cookie-domain", domain); + } + + info("fetching " + url); + await fetch(url, { headers }); +} + +// cookie header strings with multiple name=value pairs delimited by \n +// will trigger multiple "cookie-changed" signals +export function triggerSetCookieFromHttp(uri, cookie, fpd = "", ucd = 0) { + info("about to trigger set-cookie: " + uri + " " + cookie); + let channel = NetUtil.newChannel({ + uri, + loadUsingSystemPrincipal: true, + contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, + }); + + if (fpd != "") { + channel.loadInfo.originAttributes = { firstPartyDomain: fpd }; + } + + if (ucd != 0) { + channel.loadInfo.originAttributes = { userContextId: ucd }; + } + Services.cookies.setCookieStringFromHttp(uri, cookie, channel); +} + +export async function triggerSetCookieFromHttpPrivate(uri, cookie) { + info("about to trigger set-cookie: " + uri + " " + cookie); + let channel = NetUtil.newChannel({ + uri, + loadUsingSystemPrincipal: true, + contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, + }).QueryInterface(Ci.nsIPrivateBrowsingChannel); + channel.loadInfo.originAttributes = { privateBrowsingId: 1 }; + channel.setPrivate(true); + Services.cookies.setCookieStringFromHttp(uri, cookie, channel); +} + +// observer/listener function that will be run on the content processes +// listens and checks for the expected cookies +export function checkExpectedCookies(expected, browserName) { + const COOKIE_FILTER_TEST_MESSAGE = "content-added-cookie"; + const COOKIE_FILTER_TEST_CLEANUP = "cookie-content-filter-cleanup"; + + // Counting the expected number of tests is vital to the integrity of these + // tests due to the fact that this test suite relies on triggering tests + // to occur on multiple content processes. + // As such, test modifications/bugs often lead to silent failures. + // Hence, we count to ensure we didn't break anything + // To reduce risk here, we modularize each test as much as possible to + // increase liklihood that a silent failure will trigger a no-test + // error/warning + content.testDone = false; + let testNumber = 0; + + // setup observer that continues listening/testing + function obs(subject, topic) { + // cleanup trigger recieved -> tear down the observer + if (topic == COOKIE_FILTER_TEST_CLEANUP) { + info("cleaning up: " + browserName); + Services.obs.removeObserver(obs, COOKIE_FILTER_TEST_MESSAGE); + Services.obs.removeObserver(obs, COOKIE_FILTER_TEST_CLEANUP); + return; + } + + // test trigger recv'd -> perform test on cookie contents + if (topic == COOKIE_FILTER_TEST_MESSAGE) { + info("Checking if cookie visible: " + browserName); + let result = content.document.cookie; + let resultStr = + "Result " + + result + + " == expected: " + + expected[testNumber] + + " in " + + browserName; + ok(result == expected[testNumber], resultStr); + testNumber++; + if (testNumber >= expected.length) { + info("finishing browser tests: " + browserName); + content.testDone = true; + } + return; + } + + ok(false, "Didn't handle cookie message properly"); // + } + + info("setting up observers: " + browserName); + Services.obs.addObserver(obs, COOKIE_FILTER_TEST_MESSAGE); + Services.obs.addObserver(obs, COOKIE_FILTER_TEST_CLEANUP); +} diff --git a/netwerk/test/browser/cookie_filtering_resource.sjs b/netwerk/test/browser/cookie_filtering_resource.sjs new file mode 100644 index 0000000000..979d56dc9c --- /dev/null +++ b/netwerk/test/browser/cookie_filtering_resource.sjs @@ -0,0 +1,35 @@ +/* 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/. */ + +"use strict"; + +function handleRequest(request, response) { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + + // configure set-cookie domain + let domain = ""; + if (request.hasHeader("return-cookie-domain")) { + domain = "; Domain=" + request.getHeader("return-cookie-domain"); + } + + // configure set-cookie sameSite + let authStr = "; Secure"; + if (request.hasHeader("return-insecure-cookie")) { + authStr = ""; + } + + // use headers to decide if we have them + if (request.hasHeader("return-set-cookie")) { + response.setHeader( + "Set-Cookie", + request.getHeader("return-set-cookie") + authStr + domain, + false + ); + } + + let body = " true "; + response.write(body); +} diff --git a/netwerk/test/browser/cookie_filtering_secure_resource_com.html b/netwerk/test/browser/cookie_filtering_secure_resource_com.html new file mode 100644 index 0000000000..e25a719644 --- /dev/null +++ b/netwerk/test/browser/cookie_filtering_secure_resource_com.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/netwerk/test/browser/cookie_filtering_secure_resource_com.html^headers^ b/netwerk/test/browser/cookie_filtering_secure_resource_com.html^headers^ new file mode 100644 index 0000000000..2bdf118064 --- /dev/null +++ b/netwerk/test/browser/cookie_filtering_secure_resource_com.html^headers^ @@ -0,0 +1,2 @@ +Cache-Control: no-store +Set-Cookie: test-cookie=comhtml diff --git a/netwerk/test/browser/cookie_filtering_secure_resource_org.html b/netwerk/test/browser/cookie_filtering_secure_resource_org.html new file mode 100644 index 0000000000..7221dc370d --- /dev/null +++ b/netwerk/test/browser/cookie_filtering_secure_resource_org.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/netwerk/test/browser/cookie_filtering_secure_resource_org.html^headers^ b/netwerk/test/browser/cookie_filtering_secure_resource_org.html^headers^ new file mode 100644 index 0000000000..924c150ccc --- /dev/null +++ b/netwerk/test/browser/cookie_filtering_secure_resource_org.html^headers^ @@ -0,0 +1,2 @@ +Cache-Control: no-store +Set-Cookie: test-cookie=orghtml diff --git a/netwerk/test/browser/cookie_filtering_square.png b/netwerk/test/browser/cookie_filtering_square.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/netwerk/test/browser/cookie_filtering_square.png^headers^ b/netwerk/test/browser/cookie_filtering_square.png^headers^ new file mode 100644 index 0000000000..912856ae4a --- /dev/null +++ b/netwerk/test/browser/cookie_filtering_square.png^headers^ @@ -0,0 +1,2 @@ +Cache-Control: no-cache +Set-Cookie: test-cookie=png diff --git a/netwerk/test/browser/damonbowling.jpg b/netwerk/test/browser/damonbowling.jpg new file mode 100644 index 0000000000..8bdb2b6042 Binary files /dev/null and b/netwerk/test/browser/damonbowling.jpg differ diff --git a/netwerk/test/browser/damonbowling.jpg^headers^ b/netwerk/test/browser/damonbowling.jpg^headers^ new file mode 100644 index 0000000000..77f4f49089 --- /dev/null +++ b/netwerk/test/browser/damonbowling.jpg^headers^ @@ -0,0 +1,2 @@ +Cache-Control: no-store +Set-Cookie: damon=bowling diff --git a/netwerk/test/browser/dummy.html b/netwerk/test/browser/dummy.html new file mode 100644 index 0000000000..8025fcdb20 --- /dev/null +++ b/netwerk/test/browser/dummy.html @@ -0,0 +1,11 @@ + + + + + + + + +

Dummy Page

+ + diff --git a/netwerk/test/browser/early_hint_asset.sjs b/netwerk/test/browser/early_hint_asset.sjs new file mode 100644 index 0000000000..ba52e757ff --- /dev/null +++ b/netwerk/test/browser/early_hint_asset.sjs @@ -0,0 +1,50 @@ +"use strict"; + +function handleRequest(request, response) { + let hinted = + request.hasHeader("X-Moz") && request.getHeader("X-Moz") === "early hint"; + let count = JSON.parse(getSharedState("earlyHintCount")); + if (hinted) { + count.hinted += 1; + } else { + count.normal += 1; + } + setSharedState("earlyHintCount", JSON.stringify(count)); + + let content = ""; + let qs = new URLSearchParams(request.queryString); + let asset = qs.get("as"); + + if (qs.get("cached") === "1") { + response.setHeader("Cache-Control", "max-age=604800", false); + } else { + response.setHeader("Cache-Control", "no-cache", false); + } + + if (asset === "image") { + response.setHeader("Content-Type", "image/png", false); + // set to green/black horizontal stripes (71 bytes) + content = atob( + hinted + ? "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAADklEQVQIW2OU+i/FAAcADoABNV8XGBMAAAAASUVORK5CYII=" + : "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAE0lEQVQIW2P4//+/N8MkBiAGsgA1bAe1SzDY8gAAAABJRU5ErkJggg==" + ); + } else if (asset === "style") { + response.setHeader("Content-Type", "text/css", false); + // green background on hint response, purple response otherwise + content = `#square { background: ${hinted ? "#1aff1a" : "#4b0092"}`; + } else if (asset === "script") { + response.setHeader("Content-Type", "application/javascript", false); + // green background on hint response, purple response otherwise + content = `window.onload = function() { + document.getElementById('square').style.background = "${ + hinted ? "#1aff1a" : "#4b0092" + }"; + }`; + } else if (asset === "fetch") { + response.setHeader("Content-Type", "text/plain", false); + content = hinted ? "hinted" : "normal"; + } + + response.write(content); +} diff --git a/netwerk/test/browser/early_hint_asset_html.sjs b/netwerk/test/browser/early_hint_asset_html.sjs new file mode 100644 index 0000000000..eb5156d4f8 --- /dev/null +++ b/netwerk/test/browser/early_hint_asset_html.sjs @@ -0,0 +1,135 @@ +"use strict"; + +function handleRequest(request, response) { + let qs = new URLSearchParams(request.queryString); + let asset = qs.get("as"); + let hinted = qs.get("hinted") === "1"; + let httpCode = qs.get("code"); + let uuid = qs.get("uuid"); + let cached = qs.get("cached") === "1"; + + let url = `early_hint_asset.sjs?as=${asset}${uuid ? `&uuid=${uuid}` : ""}${ + cached ? "&cached=1" : "" + }`; + + // write to raw socket + response.seizePower(); + let link = ""; + if (hinted) { + response.write("HTTP/1.1 103 Early Hint\r\n"); + if (asset === "fetch" || asset === "font") { + // fetch and font has to specify the crossorigin attribute + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-as + link = `Link: <${url}>; rel=preload; as=${asset}; crossorigin=anonymous\r\n`; + response.write(link); + } else if (asset === "module") { + // module preloads are handled differently + link = `Link: <${url}>; rel=modulepreload\r\n`; + response.write(link); + } else { + link = `Link: <${url}>; rel=preload; as=${asset}\r\n`; + response.write(link); + } + response.write("\r\n"); + } + + let body = ""; + if (asset === "image") { + body = ` + + + + + `; + } else if (asset === "style") { + body = ` + + + + + +

Test preload css

+
+ + + `; + } else if (asset === "script") { + body = ` + + + + + +

Test preload javascript

+
+ + + `; + } else if (asset === "module") { + // this code assumes that the .sjs for the module is in the same directory + var file_name = url.split("/"); + file_name = file_name[file_name.length - 1]; + body = ` + + + + +

Test preload module

+
+ + + + `; + } else if (asset === "fetch") { + body = ` + + + +

Test preload fetch

+

Fetching...

+ + + `; + } else if (asset === "font") { + body = ` + + + + + +

Test preload font

+ + + `; + } + + if (!httpCode) { + response.write(`HTTP/1.1 200 OK\r\n`); + } else { + response.write(`HTTP/1.1 ${httpCode} Error\r\n`); + } + response.write(link); + response.write("Content-Type: text/html;charset=utf-8\r\n"); + response.write("Cache-Control: no-cache\r\n"); + response.write(`Content-Length: ${body.length}\r\n`); + response.write("\r\n"); + response.write(body); + response.finish(); +} diff --git a/netwerk/test/browser/early_hint_csp_options_html.sjs b/netwerk/test/browser/early_hint_csp_options_html.sjs new file mode 100644 index 0000000000..73a6a539d8 --- /dev/null +++ b/netwerk/test/browser/early_hint_csp_options_html.sjs @@ -0,0 +1,120 @@ +"use strict"; + +function handleRequest(request, response) { + let qs = new URLSearchParams(request.queryString); + let asset = qs.get("as"); + let hinted = qs.get("hinted") !== "0"; + let httpCode = qs.get("code"); + let csp = qs.get("csp"); + let csp_in_early_hint = qs.get("csp_in_early_hint"); + let host = qs.get("host"); + + // eslint-disable-next-line mozilla/use-services + let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService( + Ci.nsIUUIDGenerator + ); + let uuid = uuidGenerator.generateUUID().toString(); + let url = `early_hint_pixel.sjs?as=${asset}&uuid=${uuid}`; + if (host) { + url = host + url; + } + + // write to raw socket + response.seizePower(); + + if (hinted) { + response.write("HTTP/1.1 103 Early Hint\r\n"); + if (csp_in_early_hint) { + response.write( + `Content-Security-Policy: ${csp_in_early_hint.replaceAll('"', "")}\r\n` + ); + } + response.write(`Link: <${url}>; rel=preload; as=${asset}\r\n`); + response.write("\r\n"); + } + + let body = ""; + if (asset === "image") { + body = ` + + + + + `; + } else if (asset === "style") { + body = ` + + + + + +

Test preload css

+
+ + + `; + } else if (asset === "script") { + body = ` + + + + + +

Test preload javascript

+
+ + + `; + } else if (asset === "fetch") { + body = ` + + + +

Test preload fetch

+

Fetching...

+ + + `; + } else if (asset === "font") { + body = ` + + + + + +

Test preload font

+ + + `; + } + + if (!httpCode) { + response.write(`HTTP/1.1 200 OK\r\n`); + } else { + response.write(`HTTP/1.1 ${httpCode} Error\r\n`); + } + response.write("Content-Type: text/html;charset=utf-8\r\n"); + response.write("Cache-Control: no-cache\r\n"); + response.write(`Content-Length: ${body.length}\r\n`); + if (csp) { + response.write(`Content-Security-Policy: ${csp.replaceAll('"', "")}\r\n`); + } + response.write("\r\n"); + response.write(body); + + response.finish(); +} diff --git a/netwerk/test/browser/early_hint_error.sjs b/netwerk/test/browser/early_hint_error.sjs new file mode 100644 index 0000000000..d3d0da4bd5 --- /dev/null +++ b/netwerk/test/browser/early_hint_error.sjs @@ -0,0 +1,35 @@ +"use strict"; + +function handleRequest(request, response) { + response.setStatusLine( + request.httpVersion, + parseInt(request.queryString), + "Dynamic error" + ); + response.setHeader("Content-Type", "image/png", false); + response.setHeader("Cache-Control", "max-age=604800", false); + + // count requests + let image; + let count = JSON.parse(getSharedState("earlyHintCount")); + if ( + request.hasHeader("X-Moz") && + request.getHeader("X-Moz") === "early hint" + ) { + count.hinted += 1; + // set to green/black horizontal stripes (71 bytes) + image = atob( + "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAADklEQVQIW2OU+i/FAAcADoABNV8X" + + "GBMAAAAASUVORK5CYII=" + ); + } else { + count.normal += 1; + // set to purple/white checkered pattern (76 bytes) + image = atob( + "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAE0lEQVQIW2P4//+/N8MkBiAGsgA1" + + "bAe1SzDY8gAAAABJRU5ErkJggg==" + ); + } + setSharedState("earlyHintCount", JSON.stringify(count)); + response.write(image); +} diff --git a/netwerk/test/browser/early_hint_main_html.sjs b/netwerk/test/browser/early_hint_main_html.sjs new file mode 100644 index 0000000000..dc95273c9d --- /dev/null +++ b/netwerk/test/browser/early_hint_main_html.sjs @@ -0,0 +1,62 @@ +"use strict"; + +function handleRequest(request, response) { + // write to raw socket + response.seizePower(); + + let qs = new URLSearchParams(request.queryString); + let imgs = []; + let new_hint = true; + let new_header = true; + for (const [imgUrl, uuid] of qs.entries()) { + if (new_hint) { + // we need to write a new header + new_hint = false; + response.write("HTTP/1.1 103 Early Hint\r\n"); + } + if (!imgUrl.length) { + // next hint in new early hint response when empty string is passed + new_header = true; + if (uuid === "new_response") { + new_hint = true; + response.write("\r\n"); + } else if (uuid === "non_link_header") { + response.write("Content-Length: 25\r\n"); + } + response.write("\r\n"); + } else { + // either append link in new header or in same header + if (new_header) { + new_header = false; + response.write("Link: "); + } else { + response.write(", "); + } + // add query string to make request unique this has the drawback that + // the preloaded image can't accept query strings on it's own / or has + // to strip the appended "?uuid" from the query string before parsing + imgs.push(``); + response.write(`<${imgUrl}?${uuid}>; rel=preload; as=image`); + } + } + if (!new_hint) { + // add separator to main document + response.write("\r\n\r\n"); + } + + let body = ` + + +${imgs.join("\n")} + +`; + + // main document response + response.write("HTTP/1.1 200 OK\r\n"); + response.write("Content-Type: text/html;charset=utf-8\r\n"); + response.write("Cache-Control: no-cache\r\n"); + response.write(`Content-Length: ${body.length}\r\n`); + response.write("\r\n"); + response.write(body); + response.finish(); +} diff --git a/netwerk/test/browser/early_hint_main_redirect.sjs b/netwerk/test/browser/early_hint_main_redirect.sjs new file mode 100644 index 0000000000..0da69d5cee --- /dev/null +++ b/netwerk/test/browser/early_hint_main_redirect.sjs @@ -0,0 +1,67 @@ +"use strict"; + +// In an SJS file we need to get the setTimeout bits ourselves, despite +// what eslint might think applies for browser tests. +// eslint-disable-next-line mozilla/no-redeclare-with-import-autofix +let { setTimeout } = ChromeUtils.importESModule( + "resource://gre/modules/Timer.sys.mjs" +); + +async function handleRequest(request, response) { + let hinted = + request.hasHeader("X-Moz") && request.getHeader("X-Moz") === "early hint"; + let count = JSON.parse(getSharedState("earlyHintCount")); + if (hinted) { + count.hinted += 1; + } else { + count.normal += 1; + } + setSharedState("earlyHintCount", JSON.stringify(count)); + response.setHeader("Cache-Control", "max-age=604800", false); + + let content = ""; + let qs = new URLSearchParams(request.queryString); + let asset = qs.get("as"); + + if (asset === "image") { + response.setHeader("Content-Type", "image/png", false); + // set to green/black horizontal stripes (71 bytes) + content = atob( + hinted + ? "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAADklEQVQIW2OU+i/FAAcADoABNV8XGBMAAAAASUVORK5CYII=" + : "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAE0lEQVQIW2P4//+/N8MkBiAGsgA1bAe1SzDY8gAAAABJRU5ErkJggg==" + ); + } else if (asset === "style") { + response.setHeader("Content-Type", "text/css", false); + // green background on hint response, purple response otherwise + content = `#square { background: ${hinted ? "#1aff1a" : "#4b0092"}`; + } else if (asset === "script") { + response.setHeader("Content-Type", "application/javascript", false); + // green background on hint response, purple response otherwise + content = `window.onload = function() { + document.getElementById('square').style.background = "${ + hinted ? "#1aff1a" : "#4b0092" + }"; + }`; + } else if (asset === "module") { + response.setHeader("Content-Type", "application/javascript", false); + // green background on hint response, purple response otherwise + content = `export function draw() { + document.getElementById('square').style.background = "${ + hinted ? "#1aff1a" : "#4b0092" + }"; + }`; + } else if (asset === "fetch") { + response.setHeader("Content-Type", "text/plain", false); + content = hinted ? "hinted" : "normal"; + } else if (asset === "font") { + response.setHeader("Content-Type", "font/svg+xml", false); + content = ''; + } + response.processAsync(); + setTimeout(() => { + response.write(content); + response.finish(); + }, 0); + //response.write(content); +} diff --git a/netwerk/test/browser/early_hint_pixel.sjs b/netwerk/test/browser/early_hint_pixel.sjs new file mode 100644 index 0000000000..56a64e9af2 --- /dev/null +++ b/netwerk/test/browser/early_hint_pixel.sjs @@ -0,0 +1,37 @@ +"use strict"; + +function handleRequest(request, response) { + response.setHeader("Content-Type", "image/png", false); + response.setHeader("Cache-Control", "max-age=604800", false); + + // the typo in "Referer" is part of the http spec + if (request.hasHeader("Referer")) { + setSharedState("requestReferrer", request.getHeader("Referer")); + } else { + setSharedState("requestReferrer", ""); + } + + let count = JSON.parse(getSharedState("earlyHintCount")); + let image; + // send different sized images depending whether this is an early hint request + if ( + request.hasHeader("X-Moz") && + request.getHeader("X-Moz") === "early hint" + ) { + count.hinted += 1; + // set to green/black horizontal stripes (71 bytes) + image = atob( + "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAADklEQVQIW2OU+i/FAAcADoABNV8X" + + "GBMAAAAASUVORK5CYII=" + ); + } else { + count.normal += 1; + // set to purple/white checkered pattern (76 bytes) + image = atob( + "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAE0lEQVQIW2P4//+/N8MkBiAGsgA1" + + "bAe1SzDY8gAAAABJRU5ErkJggg==" + ); + } + setSharedState("earlyHintCount", JSON.stringify(count)); + response.write(image); +} diff --git a/netwerk/test/browser/early_hint_pixel_count.sjs b/netwerk/test/browser/early_hint_pixel_count.sjs new file mode 100644 index 0000000000..b59dd035de --- /dev/null +++ b/netwerk/test/browser/early_hint_pixel_count.sjs @@ -0,0 +1,9 @@ +"use strict"; + +function handleRequest(request, response) { + if (request.hasHeader("X-Early-Hint-Count-Start")) { + setSharedState("earlyHintCount", JSON.stringify({ hinted: 0, normal: 0 })); + } + response.setHeader("Content-Type", "application/json", false); + response.write(getSharedState("earlyHintCount")); +} diff --git a/netwerk/test/browser/early_hint_preconnect_html.sjs b/netwerk/test/browser/early_hint_preconnect_html.sjs new file mode 100644 index 0000000000..044c842142 --- /dev/null +++ b/netwerk/test/browser/early_hint_preconnect_html.sjs @@ -0,0 +1,32 @@ +"use strict"; + +function handleRequest(request, response) { + let qs = new URLSearchParams(request.queryString); + let href = qs.get("href"); + let crossOrigin = qs.get("crossOrigin"); + + // write to raw socket + response.seizePower(); + + response.write("HTTP/1.1 103 Early Hint\r\n"); + response.write( + `Link: <${href}>; rel=preconnect; crossOrigin=${crossOrigin}\r\n` + ); + response.write("\r\n"); + + let body = ` + + +

Test rel=preconnect

+ + `; + + response.write("HTTP/1.1 200 OK\r\n"); + response.write("Content-Type: text/html;charset=utf-8\r\n"); + response.write("Cache-Control: no-cache\r\n"); + response.write(`Content-Length: ${body.length}\r\n`); + response.write("\r\n"); + response.write(body); + + response.finish(); +} diff --git a/netwerk/test/browser/early_hint_preload_test_helper.sys.mjs b/netwerk/test/browser/early_hint_preload_test_helper.sys.mjs new file mode 100644 index 0000000000..afe6a6bb70 --- /dev/null +++ b/netwerk/test/browser/early_hint_preload_test_helper.sys.mjs @@ -0,0 +1,159 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { Assert } from "resource://testing-common/Assert.sys.mjs"; +import { BrowserTestUtils } from "resource://testing-common/BrowserTestUtils.sys.mjs"; + +const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser"); + +export async function request_count_checking(testName, got, expected) { + // stringify to pretty print assert output + let g = JSON.stringify(got); + let e = JSON.stringify(expected); + // each early hint request can starts one hinted request, but doesn't yet + // complete the early hint request during the test case + Assert.ok( + got.hinted == expected.hinted, + `${testName}: unexpected amount of hinted request made expected ${expected.hinted} (${e}), got ${got.hinted} (${g})` + ); + // when the early hint request doesn't complete fast enough, another request + // is currently sent from the main document + let expected_normal = expected.normal; + Assert.ok( + got.normal == expected_normal, + `${testName}: unexpected amount of normal request made expected ${expected_normal} (${e}), got ${got.normal} (${g})` + ); +} + +export async function test_hint_preload( + testName, + requestFrom, + imgUrl, + expectedRequestCount, + uuid = undefined +) { + // generate a uuid if none were passed + if (uuid == undefined) { + uuid = Services.uuid.generateUUID(); + } + await test_hint_preload_internal( + testName, + requestFrom, + [[imgUrl, uuid.toString()]], + expectedRequestCount + ); +} + +// - testName is just there to be printed during Asserts when failing +// - the baseUrl can't have query strings, because they are currently used to pass +// the early hint the server responds with +// - urls are in the form [[url1, uuid1], ...]. The uuids are there to make each preload +// unique and not available in the cache from other test cases +// - expectedRequestCount is the sum of all requested objects { normal: count, hinted: count } +export async function test_hint_preload_internal( + testName, + requestFrom, + imgUrls, + expectedRequestCount +) { + // reset the count + let headers = new Headers(); + headers.append("X-Early-Hint-Count-Start", ""); + await fetch( + "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs", + { headers } + ); + + let requestUrl = + requestFrom + + "/browser/netwerk/test/browser/early_hint_main_html.sjs?" + + new URLSearchParams(imgUrls).toString(); // encode the hinted images as query string + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: requestUrl, + waitForLoad: true, + }, + async function () {} + ); + + let gotRequestCount = await fetch( + "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs" + ).then(response => response.json()); + + await request_count_checking(testName, gotRequestCount, expectedRequestCount); +} + +// Verify that CSP policies in both the 103 response as well as the main response are respected. +// e.g. +// 103 Early Hint +// Content-Security-Policy: style-src: self; +// Link: ; rel=preload; as=style +// 200 OK +// Content-Security-Policy: style-src: none; +// Link: ; rel=preload; as=font + +// Server-side we verify that: +// - the hinted preload request was made as expected +// - the load request request was made as expected +// Client-side, we verify that the image was loaded or not loaded, depending on the scenario + +// This verifies preload hints and requests +export async function test_preload_hint_and_request(input, expected_results) { + // reset the count + let headers = new Headers(); + headers.append("X-Early-Hint-Count-Start", ""); + await fetch( + "https://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs", + { headers } + ); + + let requestUrl = `https://example.com/browser/netwerk/test/browser/early_hint_csp_options_html.sjs?as=${ + input.resource_type + }&hinted=${input.hinted ? "1" : "0"}${input.csp ? "&csp=" + input.csp : ""}${ + input.csp_in_early_hint + ? "&csp_in_early_hint=" + input.csp_in_early_hint + : "" + }${input.host ? "&host=" + input.host : ""}`; + + await BrowserTestUtils.openNewForegroundTab(gBrowser, requestUrl, true); + + let gotRequestCount = await fetch( + "https://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs" + ).then(response => response.json()); + + await Assert.deepEqual(gotRequestCount, expected_results, input.test_name); + + gBrowser.removeCurrentTab(); + Services.cache2.clear(); +} + +// simple loading of one url and then checking the request count against the +// passed expected count +export async function test_preload_url(testName, url, expectedRequestCount) { + // reset the count + let headers = new Headers(); + headers.append("X-Early-Hint-Count-Start", ""); + await fetch( + "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs", + { headers } + ); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + waitForLoad: true, + }, + async function () {} + ); + + let gotRequestCount = await fetch( + "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs" + ).then(response => response.json()); + + await request_count_checking(testName, gotRequestCount, expectedRequestCount); + Services.cache2.clear(); +} diff --git a/netwerk/test/browser/early_hint_redirect.sjs b/netwerk/test/browser/early_hint_redirect.sjs new file mode 100644 index 0000000000..6bcb6bdc86 --- /dev/null +++ b/netwerk/test/browser/early_hint_redirect.sjs @@ -0,0 +1,21 @@ +"use strict"; + +function handleRequest(request, response) { + // increase count + let count = JSON.parse(getSharedState("earlyHintCount")); + if ( + request.hasHeader("X-Moz") && + request.getHeader("X-Moz") === "early hint" + ) { + count.hinted += 1; + } else { + count.normal += 1; + } + setSharedState("earlyHintCount", JSON.stringify(count)); + + // respond with redirect + response.setStatusLine(request.httpVersion, 301, "Moved Permanently"); + let location = request.queryString; + response.setHeader("Location", location, false); + response.write("Hello world!"); +} diff --git a/netwerk/test/browser/early_hint_redirect_html.sjs b/netwerk/test/browser/early_hint_redirect_html.sjs new file mode 100644 index 0000000000..c111af0978 --- /dev/null +++ b/netwerk/test/browser/early_hint_redirect_html.sjs @@ -0,0 +1,24 @@ +"use strict"; + +// usage via url parameters: +// - link: if set sends a link header with the given link value as an early hint repsonse +// - location: sets destination of 301 response + +function handleRequest(request, response) { + let qs = new URLSearchParams(request.queryString); + let link = qs.get("link"); + let location = qs.get("location"); + + // write to raw socket + response.seizePower(); + if (link != undefined) { + response.write("HTTP/1.1 103 Early Hint\r\n"); + response.write(`Link: ${link}\r\n`); + response.write("\r\n"); + } + + response.write("HTTP/1.1 307 Temporary Redirect\r\n"); + response.write(`Location: ${location}\r\n`); + response.write("\r\n"); + response.finish(); +} diff --git a/netwerk/test/browser/early_hint_referrer_policy_html.sjs b/netwerk/test/browser/early_hint_referrer_policy_html.sjs new file mode 100644 index 0000000000..3c8a626de1 --- /dev/null +++ b/netwerk/test/browser/early_hint_referrer_policy_html.sjs @@ -0,0 +1,132 @@ +"use strict"; + +function handleRequest(request, response) { + let qs = new URLSearchParams(request.queryString); + let asset = qs.get("as"); + var action = qs.get("action"); + let hinted = qs.get("hinted") !== "0"; + let httpCode = qs.get("code"); + let header_referrer_policy = qs.get("header_referrer_policy"); + let link_referrer_policy = qs.get("link_referrer_policy"); + + // eslint-disable-next-line mozilla/use-services + let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService( + Ci.nsIUUIDGenerator + ); + let uuid = uuidGenerator.generateUUID().toString(); + let url = `early_hint_pixel.sjs?as=${asset}&uuid=${uuid}`; + + if (action === "get_request_referrer_results") { + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write(getSharedState("requestReferrer")); + return; + } else if (action === "reset_referrer_results") { + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write(setSharedState("requestReferrer", "not set")); + return; + } + + // write to raw socket + response.seizePower(); + + if (hinted) { + response.write("HTTP/1.1 103 Early Hint\r\n"); + + if (header_referrer_policy) { + response.write( + `Referrer-Policy: ${header_referrer_policy.replaceAll('"', "")}\r\n` + ); + } + + response.write( + `Link: <${url}>; rel=preload; as=${asset}; ${ + link_referrer_policy ? "referrerpolicy=" + link_referrer_policy : "" + } \r\n` + ); + response.write("\r\n"); + } + + let body = ""; + if (asset === "image") { + body = ` + + + + + `; + } else if (asset === "style") { + body = ` + + + + + +

Test preload css

+
+ + + `; + } else if (asset === "script") { + body = ` + + + + + +

Test preload javascript

+
+ + + `; + } else if (asset === "fetch") { + body = ` + + + +

Test preload fetch

+

Fetching...

+ + + `; + } else if (asset === "font") { + body = ` + + + + + +

Test preload font

+ + + `; + } + + if (!httpCode) { + response.write(`HTTP/1.1 200 OK\r\n`); + } else { + response.write(`HTTP/1.1 ${httpCode} Error\r\n`); + } + response.write("Content-Type: text/html;charset=utf-8\r\n"); + response.write("Cache-Control: no-cache\r\n"); + response.write(`Content-Length: ${body.length}\r\n`); + response.write("\r\n"); + response.write(body); + + response.finish(); +} diff --git a/netwerk/test/browser/file_favicon.html b/netwerk/test/browser/file_favicon.html new file mode 100644 index 0000000000..77532a3a53 --- /dev/null +++ b/netwerk/test/browser/file_favicon.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/netwerk/test/browser/file_link_header.sjs b/netwerk/test/browser/file_link_header.sjs new file mode 100644 index 0000000000..6bab515d19 --- /dev/null +++ b/netwerk/test/browser/file_link_header.sjs @@ -0,0 +1,24 @@ +"use strict"; + +function handleRequest(request, response) { + // write to raw socket + response.seizePower(); + let body = ` + + + + + +

Test rel=preconnect

+ + `; + + response.write("HTTP/1.1 200 OK\r\n"); + response.write("Content-Type: text/html;charset=utf-8\r\n"); + response.write("Cache-Control: no-cache\r\n"); + response.write(`Content-Length: ${body.length}\r\n`); + response.write("\r\n"); + response.write(body); + + response.finish(); +} diff --git a/netwerk/test/browser/file_lnk.lnk b/netwerk/test/browser/file_lnk.lnk new file mode 100644 index 0000000000..abce7587d2 Binary files /dev/null and b/netwerk/test/browser/file_lnk.lnk differ diff --git a/netwerk/test/browser/ioactivity.html b/netwerk/test/browser/ioactivity.html new file mode 100644 index 0000000000..5e23f6f117 --- /dev/null +++ b/netwerk/test/browser/ioactivity.html @@ -0,0 +1,11 @@ + + + + + + + + +

IOActivity Test Page

+ + diff --git a/netwerk/test/browser/no_103_preload.html b/netwerk/test/browser/no_103_preload.html new file mode 100644 index 0000000000..64f5e79259 --- /dev/null +++ b/netwerk/test/browser/no_103_preload.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/netwerk/test/browser/no_103_preload.html^headers^ b/netwerk/test/browser/no_103_preload.html^headers^ new file mode 100644 index 0000000000..9e23c73b7f --- /dev/null +++ b/netwerk/test/browser/no_103_preload.html^headers^ @@ -0,0 +1 @@ +Cache-Control: no-cache diff --git a/netwerk/test/browser/post.html b/netwerk/test/browser/post.html new file mode 100644 index 0000000000..9d238c2b97 --- /dev/null +++ b/netwerk/test/browser/post.html @@ -0,0 +1,14 @@ + + + + +post file + + +
+ + + +
+ + diff --git a/netwerk/test/browser/redirect.sjs b/netwerk/test/browser/redirect.sjs new file mode 100644 index 0000000000..09e7d9b1e4 --- /dev/null +++ b/netwerk/test/browser/redirect.sjs @@ -0,0 +1,6 @@ +function handleRequest(request, response) { + response.setStatusLine(request.httpVersion, 301, "Moved Permanently"); + let location = request.queryString; + response.setHeader("Location", location, false); + response.write("Hello world!"); +} diff --git a/netwerk/test/browser/res.css b/netwerk/test/browser/res.css new file mode 100644 index 0000000000..eab83656ed --- /dev/null +++ b/netwerk/test/browser/res.css @@ -0,0 +1,4 @@ +/* François was here. */ +#purple-text { + color: purple; +} diff --git a/netwerk/test/browser/res.css^headers^ b/netwerk/test/browser/res.css^headers^ new file mode 100644 index 0000000000..e13897f157 --- /dev/null +++ b/netwerk/test/browser/res.css^headers^ @@ -0,0 +1 @@ +Content-Type: text/css; charset=utf-8 diff --git a/netwerk/test/browser/res.csv b/netwerk/test/browser/res.csv new file mode 100644 index 0000000000..b0246d5964 --- /dev/null +++ b/netwerk/test/browser/res.csv @@ -0,0 +1 @@ +1,2,3 diff --git a/netwerk/test/browser/res.csv^headers^ b/netwerk/test/browser/res.csv^headers^ new file mode 100644 index 0000000000..8d30131059 --- /dev/null +++ b/netwerk/test/browser/res.csv^headers^ @@ -0,0 +1 @@ +Content-Type: text/csv; diff --git a/netwerk/test/browser/res.mp3 b/netwerk/test/browser/res.mp3 new file mode 100644 index 0000000000..bad506cf18 Binary files /dev/null and b/netwerk/test/browser/res.mp3 differ diff --git a/netwerk/test/browser/res.unknown b/netwerk/test/browser/res.unknown new file mode 100644 index 0000000000..3546645658 --- /dev/null +++ b/netwerk/test/browser/res.unknown @@ -0,0 +1 @@ +unknown diff --git a/netwerk/test/browser/res_206.html b/netwerk/test/browser/res_206.html new file mode 100644 index 0000000000..8025fcdb20 --- /dev/null +++ b/netwerk/test/browser/res_206.html @@ -0,0 +1,11 @@ + + + + + + + + +

Dummy Page

+ + diff --git a/netwerk/test/browser/res_206.html^headers^ b/netwerk/test/browser/res_206.html^headers^ new file mode 100644 index 0000000000..5a3e3a24c8 --- /dev/null +++ b/netwerk/test/browser/res_206.html^headers^ @@ -0,0 +1,2 @@ +HTTP 206 +Content-Type: text/html; diff --git a/netwerk/test/browser/res_206.mp3 b/netwerk/test/browser/res_206.mp3 new file mode 100644 index 0000000000..bad506cf18 Binary files /dev/null and b/netwerk/test/browser/res_206.mp3 differ diff --git a/netwerk/test/browser/res_206.mp3^headers^ b/netwerk/test/browser/res_206.mp3^headers^ new file mode 100644 index 0000000000..6e7e4d23ba --- /dev/null +++ b/netwerk/test/browser/res_206.mp3^headers^ @@ -0,0 +1 @@ +HTTP 206 diff --git a/netwerk/test/browser/res_empty.zip b/netwerk/test/browser/res_empty.zip new file mode 100644 index 0000000000..b613b60c02 Binary files /dev/null and b/netwerk/test/browser/res_empty.zip differ diff --git a/netwerk/test/browser/res_http_index_format b/netwerk/test/browser/res_http_index_format new file mode 100644 index 0000000000..e42645a762 --- /dev/null +++ b/netwerk/test/browser/res_http_index_format @@ -0,0 +1 @@ +100: This is a sample application/http-index-format directory index listing. diff --git a/netwerk/test/browser/res_http_index_format^headers^ b/netwerk/test/browser/res_http_index_format^headers^ new file mode 100644 index 0000000000..f076e27a72 --- /dev/null +++ b/netwerk/test/browser/res_http_index_format^headers^ @@ -0,0 +1 @@ +Content-Type: application/http-index-format diff --git a/netwerk/test/browser/res_img.png b/netwerk/test/browser/res_img.png new file mode 100644 index 0000000000..94e7eb6db2 Binary files /dev/null and b/netwerk/test/browser/res_img.png differ diff --git a/netwerk/test/browser/res_img_for_unknown_decoder b/netwerk/test/browser/res_img_for_unknown_decoder new file mode 100644 index 0000000000..74d74fde5a Binary files /dev/null and b/netwerk/test/browser/res_img_for_unknown_decoder differ diff --git a/netwerk/test/browser/res_img_for_unknown_decoder^headers^ b/netwerk/test/browser/res_img_for_unknown_decoder^headers^ new file mode 100644 index 0000000000..defde38020 --- /dev/null +++ b/netwerk/test/browser/res_img_for_unknown_decoder^headers^ @@ -0,0 +1,2 @@ +Content-Type: +Content-Encoding: gzip diff --git a/netwerk/test/browser/res_img_unknown.png b/netwerk/test/browser/res_img_unknown.png new file mode 100644 index 0000000000..8025fcdb20 --- /dev/null +++ b/netwerk/test/browser/res_img_unknown.png @@ -0,0 +1,11 @@ + + + + + + + + +

Dummy Page

+ + diff --git a/netwerk/test/browser/res_invalid_partial.mp3 b/netwerk/test/browser/res_invalid_partial.mp3 new file mode 100644 index 0000000000..bad506cf18 Binary files /dev/null and b/netwerk/test/browser/res_invalid_partial.mp3 differ diff --git a/netwerk/test/browser/res_invalid_partial.mp3^headers^ b/netwerk/test/browser/res_invalid_partial.mp3^headers^ new file mode 100644 index 0000000000..0213f38e4e --- /dev/null +++ b/netwerk/test/browser/res_invalid_partial.mp3^headers^ @@ -0,0 +1,2 @@ +HTTP 206 +Content-Range: bytes 100-1024/* diff --git a/netwerk/test/browser/res_nosniff.html b/netwerk/test/browser/res_nosniff.html new file mode 100644 index 0000000000..8025fcdb20 --- /dev/null +++ b/netwerk/test/browser/res_nosniff.html @@ -0,0 +1,11 @@ + + + + + + + + +

Dummy Page

+ + diff --git a/netwerk/test/browser/res_nosniff.html^headers^ b/netwerk/test/browser/res_nosniff.html^headers^ new file mode 100644 index 0000000000..024cdcf5ab --- /dev/null +++ b/netwerk/test/browser/res_nosniff.html^headers^ @@ -0,0 +1,2 @@ +X-Content-Type-Options: nosniff +Content-Type: text/html; diff --git a/netwerk/test/browser/res_nosniff2.html b/netwerk/test/browser/res_nosniff2.html new file mode 100644 index 0000000000..8025fcdb20 --- /dev/null +++ b/netwerk/test/browser/res_nosniff2.html @@ -0,0 +1,11 @@ + + + + + + + + +

Dummy Page

+ + diff --git a/netwerk/test/browser/res_nosniff2.html^headers^ b/netwerk/test/browser/res_nosniff2.html^headers^ new file mode 100644 index 0000000000..e46db01e23 --- /dev/null +++ b/netwerk/test/browser/res_nosniff2.html^headers^ @@ -0,0 +1,2 @@ +X-Content-Type-Options: nosniff +Content-Type: text/test diff --git a/netwerk/test/browser/res_not_200or206.mp3 b/netwerk/test/browser/res_not_200or206.mp3 new file mode 100644 index 0000000000..bad506cf18 Binary files /dev/null and b/netwerk/test/browser/res_not_200or206.mp3 differ diff --git a/netwerk/test/browser/res_not_200or206.mp3^headers^ b/netwerk/test/browser/res_not_200or206.mp3^headers^ new file mode 100644 index 0000000000..dd0b48aaa0 --- /dev/null +++ b/netwerk/test/browser/res_not_200or206.mp3^headers^ @@ -0,0 +1 @@ +HTTP 226 diff --git a/netwerk/test/browser/res_not_ok.html b/netwerk/test/browser/res_not_ok.html new file mode 100644 index 0000000000..8025fcdb20 --- /dev/null +++ b/netwerk/test/browser/res_not_ok.html @@ -0,0 +1,11 @@ + + + + + + + + +

Dummy Page

+ + diff --git a/netwerk/test/browser/res_not_ok.html^headers^ b/netwerk/test/browser/res_not_ok.html^headers^ new file mode 100644 index 0000000000..5d15d79e46 --- /dev/null +++ b/netwerk/test/browser/res_not_ok.html^headers^ @@ -0,0 +1 @@ +HTTP 302 Found diff --git a/netwerk/test/browser/res_object.html b/netwerk/test/browser/res_object.html new file mode 100644 index 0000000000..8097415d17 --- /dev/null +++ b/netwerk/test/browser/res_object.html @@ -0,0 +1,18 @@ + + + + + + + + +

Dummy Page

+ + + diff --git a/netwerk/test/browser/res_sub_document.html b/netwerk/test/browser/res_sub_document.html new file mode 100644 index 0000000000..8025fcdb20 --- /dev/null +++ b/netwerk/test/browser/res_sub_document.html @@ -0,0 +1,11 @@ + + + + + + + + +

Dummy Page

+ + diff --git a/netwerk/test/browser/square.png b/netwerk/test/browser/square.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/netwerk/test/browser/test_1629307.html b/netwerk/test/browser/test_1629307.html new file mode 100644 index 0000000000..01f2a0439e --- /dev/null +++ b/netwerk/test/browser/test_1629307.html @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/netwerk/test/browser/x_frame_options.html b/netwerk/test/browser/x_frame_options.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/netwerk/test/browser/x_frame_options.html^headers^ b/netwerk/test/browser/x_frame_options.html^headers^ new file mode 100644 index 0000000000..dc4bb949f5 --- /dev/null +++ b/netwerk/test/browser/x_frame_options.html^headers^ @@ -0,0 +1,3 @@ +HTTP 401 UNAUTHORIZED +X-Frame-Options: SAMEORIGIN +WWW-Authenticate: basic realm="login required" -- cgit v1.2.3