1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 var { setTimeout
} = ChromeUtils
.importESModule(
8 "resource://gre/modules/Timer.sys.mjs"
10 const { TestUtils
} = ChromeUtils
.importESModule(
11 "resource://testing-common/TestUtils.sys.mjs"
17 const certOverrideService
= Cc
[
18 "@mozilla.org/security/certoverride;1"
19 ].getService(Ci
.nsICertOverrideService
);
22 Services
.prefs
.setIntPref("network.max_socket_process_failed_count", 2);
25 h2Port
= Services
.env
.get("MOZHTTP2_PORT");
26 Assert
.notEqual(h2Port
, null);
27 Assert
.notEqual(h2Port
, "");
29 Assert
.ok(mozinfo
.socketprocess_networking
);
33 registerCleanupFunction(async () => {
34 Services
.prefs
.clearUserPref("network.max_socket_process_failed_count");
37 await trrServer
.stop();
41 function makeChan(url
) {
42 let chan
= NetUtil
.newChannel({
44 loadUsingSystemPrincipal
: true,
45 contentPolicyType
: Ci
.nsIContentPolicy
.TYPE_DOCUMENT
,
46 }).QueryInterface(Ci
.nsIHttpChannel
);
50 function channelOpenPromise(chan
, flags
) {
51 return new Promise(resolve
=> {
52 function finish(req
, buffer
) {
53 resolve([req
, buffer
]);
54 certOverrideService
.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
58 certOverrideService
.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
61 chan
.asyncOpen(new ChannelListener(finish
, null, flags
));
65 add_task(async
function setupTRRServer() {
66 trrServer
= new TRRServer();
67 await trrServer
.start();
69 Services
.prefs
.setIntPref("network.trr.mode", 3);
70 Services
.prefs
.setCharPref(
72 `https://foo.example.com:${trrServer.port()}/dns-query`
75 // Only the last record is valid to use.
76 await trrServer
.registerDoHAnswers("test.example.com", "HTTPS", {
79 name
: "test.example.com",
85 name
: "test.example.com",
87 { key
: "alpn", value
: ["h2"] },
88 { key
: "port", value
: h2Port
},
95 await trrServer
.registerDoHAnswers("test.example.com", "A", {
98 name
: "test.example.com",
108 async
function doTestSimpleRequest(fromSocketProcess
) {
109 let { inRecord
} = await
new TRRDNSListener("test.example.com", "127.0.0.1");
110 inRecord
.QueryInterface(Ci
.nsIDNSAddrRecord
);
111 Assert
.equal(inRecord
.resolvedInSocketProcess(), fromSocketProcess
);
113 let chan
= makeChan(`https://test.example.com/server-timing`);
114 let [req
] = await
channelOpenPromise(chan
);
115 // Test if this request is done by h2.
116 Assert
.equal(req
.getResponseHeader("x-connection-http2"), "yes");
118 let internal = chan
.QueryInterface(Ci
.nsIHttpChannelInternal
);
119 Assert
.equal(internal.isLoadedBySocketProcess
, fromSocketProcess
);
122 // Test if the data is loaded from socket process.
123 add_task(async
function testSimpleRequest() {
124 await
doTestSimpleRequest(true);
127 function killSocketProcess(pid
) {
128 const ProcessTools
= Cc
["@mozilla.org/processtools-service;1"].getService(
129 Ci
.nsIProcessToolsService
131 ProcessTools
.kill(pid
);
134 // Test if socket process is restarted.
135 add_task(async
function testSimpleRequestAfterCrash() {
136 let socketProcessId
= Services
.io
.socketProcessId
;
137 info(`socket process pid is ${socketProcessId}`);
138 Assert
.ok(socketProcessId
!= 0);
140 killSocketProcess(socketProcessId
);
142 info("wait socket process restart...");
143 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
144 await
new Promise(resolve
=> setTimeout(resolve
, 1000));
145 Services
.dns
; // Needed to trigger socket process.
146 await TestUtils
.waitForCondition(() => Services
.io
.socketProcessLaunched
);
148 await
doTestSimpleRequest(true);
151 // Test if data is loaded from parent process.
152 add_task(async
function testTooManyCrashes() {
153 let socketProcessId
= Services
.io
.socketProcessId
;
154 info(`socket process pid is ${socketProcessId}`);
155 Assert
.ok(socketProcessId
!= 0);
157 let socketProcessCrashed
= false;
158 Services
.obs
.addObserver(function observe(subject
, topic
) {
159 Services
.obs
.removeObserver(observe
, topic
);
160 socketProcessCrashed
= true;
161 }, "network:socket-process-crashed");
163 killSocketProcess(socketProcessId
);
164 await TestUtils
.waitForCondition(() => socketProcessCrashed
);
165 await
doTestSimpleRequest(false);