commit 6225c88e92cc2f2d71265600329aa1191aa76290
parent 2f7bfd630e4eb2ce47db838f6c9fc2b166db4231
Author: Mike Conley <mconley@mozilla.com>
Date: Wed, 10 Dec 2025 19:43:49 +0000
Bug 2005277 - Convert Headers object into a JS key-value object when calling into ObliviousHTTP from DiscoveryStreamFeed. r=home-newtab-reviewers,nbarrett
Differential Revision: https://phabricator.services.mozilla.com/D275832
Diffstat:
2 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/browser/extensions/newtab/lib/DiscoveryStreamFeed.sys.mjs b/browser/extensions/newtab/lib/DiscoveryStreamFeed.sys.mjs
@@ -452,6 +452,17 @@ export class DiscoveryStreamFeed {
);
return null;
}
+
+ // ObliviousHTTP.ohttpRequest only accepts a key/value object, and not
+ // a Headers instance. We normalize any headers to a key/value object.
+ //
+ // We use instanceof here since isInstance isn't available for node
+ // tests like DiscoveryStreamFeed.test.js.
+ // eslint-disable-next-line mozilla/use-isInstance
+ if (options.headers && options.headers instanceof Headers) {
+ options.headers = Object.fromEntries(options.headers);
+ }
+
fetchPromise = lazy.ObliviousHTTP.ohttpRequest(
ohttpRelayURL,
config,
diff --git a/browser/extensions/newtab/test/unit/lib/DiscoveryStreamFeed.test.js b/browser/extensions/newtab/test/unit/lib/DiscoveryStreamFeed.test.js
@@ -300,6 +300,60 @@ describe("DiscoveryStreamFeed", () => {
DUMMY_ENDPOINT
);
});
+
+ it("should cast headers from a Headers object to JS object when using OHTTP", async () => {
+ sandbox
+ .stub(global.Services.prefs, "getStringPref")
+ .withArgs(
+ "browser.newtabpage.activity-stream.discoverystream.ohttp.relayURL"
+ )
+ .returns("https://relay.url")
+ .withArgs(
+ "browser.newtabpage.activity-stream.discoverystream.ohttp.configURL"
+ )
+ .returns("https://config.url");
+
+ const fakeOhttpConfig = { config: "config" };
+ sandbox
+ .stub(global.ObliviousHTTP, "getOHTTPConfig")
+ .resolves(fakeOhttpConfig);
+
+ const ohttpResponse = {
+ json: () => Promise.resolve("ohttp response"),
+ ok: true,
+ };
+ const ohttpRequestStub = sandbox
+ .stub(global.ObliviousHTTP, "ohttpRequest")
+ .resolves(ohttpResponse);
+
+ // Allow the endpoint
+ feed.store.getState = () => ({
+ Prefs: {
+ values: {
+ [ENDPOINTS_PREF_NAME]: DUMMY_ENDPOINT,
+ },
+ },
+ });
+
+ const headers = new Headers();
+ headers.set("headername", "headervalue");
+
+ const result = await feed.fetchFromEndpoint(
+ DUMMY_ENDPOINT,
+ { headers },
+ true
+ );
+
+ assert.equal(result, "ohttp response");
+ assert.calledOnce(ohttpRequestStub);
+ assert.calledWithMatch(
+ ohttpRequestStub,
+ "https://relay.url",
+ fakeOhttpConfig,
+ DUMMY_ENDPOINT,
+ { headers: Object.fromEntries(headers), credentials: "omit" }
+ );
+ });
});
describe("#getOrCreateImpressionId", () => {