commit c8b225050fb48f59c99470518e612ff1e78825c3
parent d37080e197da0eaff6b4e08d5b2c44701713039f
Author: Pier Angelo Vendrame <pierov@torproject.org>
Date: Mon, 6 Oct 2025 16:41:41 +0000
Bug 1987600 - Add origin attributes to OpenSearch. r=search-reviewers,Standard8
Differential Revision: https://phabricator.services.mozilla.com/D265878
Diffstat:
6 files changed, 50 insertions(+), 14 deletions(-)
diff --git a/browser/components/search/SearchUIUtils.sys.mjs b/browser/components/search/SearchUIUtils.sys.mjs
@@ -195,7 +195,11 @@ export var SearchUIUtils = {
*/
async addOpenSearchEngine(locationURL, image, browsingContext) {
try {
- await Services.search.addOpenSearchEngine(locationURL, image);
+ await Services.search.addOpenSearchEngine(
+ locationURL,
+ image,
+ browsingContext?.embedderElement?.contentPrincipal?.originAttributes
+ );
} catch (ex) {
let titleMsgName;
let descMsgName;
diff --git a/toolkit/components/search/OpenSearchLoader.sys.mjs b/toolkit/components/search/OpenSearchLoader.sys.mjs
@@ -95,10 +95,18 @@ const MOZSEARCH_LOCALNAME = "SearchPlugin";
* The uri from which to load the OpenSearch engine data.
* @param {string} [lastModified]
* The UTC date when the engine was last updated, if any.
+ * @param {object} [originAttributes]
+ * The origin attributes of the site loading the manifest. If none are
+ * specified, the origin attributes will be formed of the first party domain
+ * based on the domain of the manifest.
* @returns {Promise<OpenSearchProperties>}
* The properties of the loaded OpenSearch engine.
*/
-export async function loadAndParseOpenSearchEngine(sourceURI, lastModified) {
+export async function loadAndParseOpenSearchEngine(
+ sourceURI,
+ lastModified,
+ originAttributes
+) {
if (!sourceURI) {
throw Components.Exception(
"Must have URI when calling _install!",
@@ -114,7 +122,7 @@ export async function loadAndParseOpenSearchEngine(sourceURI, lastModified) {
lazy.logConsole.debug("Downloading OpenSearch engine from:", sourceURI.spec);
- let xmlData = await loadEngineXML(sourceURI, lastModified);
+ let xmlData = await loadEngineXML(sourceURI, lastModified, originAttributes);
let xmlDocument = await parseXML(xmlData);
lazy.logConsole.debug("Loading search plugin");
@@ -145,16 +153,19 @@ export async function loadAndParseOpenSearchEngine(sourceURI, lastModified) {
* The uri from which to load the OpenSearch engine data.
* @param {string} [lastModified]
* The UTC date when the engine was last updated, if any.
+ * @param {object} [originAttributes]
+ * The origin attributes to use to load the manifest.
* @returns {Promise}
* A promise that is resolved with the data if the engine is successfully loaded
* and rejected otherwise.
*/
-function loadEngineXML(sourceURI, lastModified) {
+function loadEngineXML(sourceURI, lastModified, originAttributes = null) {
var chan = lazy.SearchUtils.makeChannel(
sourceURI,
// OpenSearchEngine is loading a definition file for a search engine,
// TYPE_DOCUMENT captures that load best.
- Ci.nsIContentPolicy.TYPE_DOCUMENT
+ Ci.nsIContentPolicy.TYPE_DOCUMENT,
+ originAttributes
);
// we collect https telemetry for all top-level (document) loads.
diff --git a/toolkit/components/search/SearchService.sys.mjs b/toolkit/components/search/SearchService.sys.mjs
@@ -750,13 +750,15 @@ export class SearchService {
});
}
- async addOpenSearchEngine(engineURL, iconURL) {
+ async addOpenSearchEngine(engineURL, iconURL, originAttributes) {
lazy.logConsole.debug("addOpenSearchEngine: Adding", engineURL);
await this.init();
let engine;
try {
let engineData = await lazy.loadAndParseOpenSearchEngine(
- Services.io.newURI(engineURL)
+ Services.io.newURI(engineURL),
+ null,
+ originAttributes
);
engine = new lazy.OpenSearchEngine({ engineData, faviconURL: iconURL });
} catch (ex) {
diff --git a/toolkit/components/search/SearchUtils.sys.mjs b/toolkit/components/search/SearchUtils.sys.mjs
@@ -244,19 +244,34 @@ export var SearchUtils = {
* The URL string from which to create an nsIChannel.
* @param {nsContentPolicyType} contentPolicyType
* The type of document being loaded.
+ * @param {object} [originAttributes]
+ * The origin attributes to associate to this channel.
* @returns {nsIChannel}
* an nsIChannel object, or null if the url is invalid.
*/
- makeChannel(url, contentPolicyType) {
+ makeChannel(url, contentPolicyType, originAttributes = null) {
if (!contentPolicyType) {
throw new Error("makeChannel called with invalid content policy type");
}
try {
let uri = typeof url == "string" ? Services.io.newURI(url) : url;
- let principal =
- uri.scheme == "moz-extension"
- ? Services.scriptSecurityManager.createContentPrincipal(uri, {})
- : Services.scriptSecurityManager.createNullPrincipal({});
+ let principal;
+ if (uri.scheme == "moz-extension") {
+ principal = Services.scriptSecurityManager.createContentPrincipal(
+ uri,
+ {}
+ );
+ } else {
+ if (!originAttributes) {
+ originAttributes = {};
+ try {
+ originAttributes.firstPartyDomain =
+ Services.eTLD.getSchemelessSite(uri);
+ } catch {}
+ }
+ principal =
+ Services.scriptSecurityManager.createNullPrincipal(originAttributes);
+ }
return Services.io.newChannelFromURI(
uri,
diff --git a/toolkit/components/search/nsISearchService.idl b/toolkit/components/search/nsISearchService.idl
@@ -345,10 +345,14 @@ interface nsISearchService : nsISupports
* icon. This value may be overridden by an icon specified in the
* engine description file.
*
+ * @param originAttributes [optional]
+ The origin attributes to use to load this manifest.
+ *
* @throws NS_ERROR_FAILURE if the description file cannot be successfully
* loaded.
*/
- Promise addOpenSearchEngine(in AString engineURL, in AString iconURL);
+ Promise addOpenSearchEngine(in AString engineURL, in AString iconURL,
+ [optional] in jsval originAttributes);
/**
* Adds a new search engine defined by the user.
diff --git a/tools/@types/generated/lib.gecko.xpcom.d.ts b/tools/@types/generated/lib.gecko.xpcom.d.ts
@@ -11625,7 +11625,7 @@ interface nsISearchService extends nsISupports, Enums<typeof nsISearchService_Op
readonly hasSuccessfullyInitialized: boolean;
runBackgroundChecks(): Promise<any>;
resetToAppDefaultEngine(): void;
- addOpenSearchEngine(engineURL: string, iconURL: string): Promise<any>;
+ addOpenSearchEngine(engineURL: string, iconURL: string, originAttributes?: any): Promise<any>;
addUserEngine(formInfo: any): Promise<any>;
addEnginesFromExtension(extension: any): Promise<any>;
restoreDefaultEngines(): void;