feat: add custom search engines

This commit is contained in:
Alex Kontos
2022-07-14 14:25:53 +01:00
parent 78658ddea6
commit ecc220a050
16 changed files with 497 additions and 51 deletions

View File

@@ -11,6 +11,6 @@ browser.jar:
content/browser/contentSearchUI.js (content/contentSearchUI.js)
content/browser/contentSearchHandoffUI.js (content/contentSearchHandoffUI.js)
content/browser/contentSearchUI.css (content/contentSearchUI.css)
search-extensions/ (extensions/**)
# search-extensions/ (extensions/**)
% resource search-extensions %search-extensions/ contentaccessible=yes

View File

@@ -115,11 +115,13 @@ class IconHandler {
if (!this.#iconMap) {
await this.#buildIconMap();
}
let iconList = this.#iconMap.get(this.getKey(engineIdentifier)) || [];
return iconList.filter(r =>
this.#identifierMatches(engineIdentifier, r.engineIdentifiers)
);
// If #buildIconMap could have resulted in #iconMap being null
if (!this.#iconMap) {
console.warn("Icon map is not available.");
return [];
}
// Get the array of icon objects for the engine, or an empty array if not found.
return this.#iconMap.get(engineIdentifier) || [];
}
/**
@@ -240,25 +242,20 @@ class IconHandler {
async #buildIconMap() {
let iconList = [];
try {
iconList = await this.#iconCollection.get();
this.#iconMap = new Map(
await (
await fetch(
"chrome://browser/content/search/BrowserSearchEngineIcons.json"
)
).json()
);
} catch (ex) {
console.error(ex);
this.#iconMap = null;
}
if (!iconList.length) {
if (!this.#iconMap) {
console.error("Failed to obtain search engine icon list records");
}
this.#iconMap = new Map();
for (let record of iconList) {
let keys = new Set(record.engineIdentifiers.map(this.getKey));
for (let key of keys) {
if (this.#iconMap.has(key)) {
this.#iconMap.get(key).push(record);
} else {
this.#iconMap.set(key, [record]);
}
}
}
}
/**
@@ -561,27 +558,29 @@ export class AppProvidedSearchEngine extends SearchEngine {
* A promise that resolves to the URL of the icon.
*/
async getIconURL(preferredWidth) {
// XPCOM interfaces pass optional number parameters as 0.
preferredWidth ||= 16;
let availableRecords =
// This call should return a string (the icon URL) if the engineId is in your JSON,
// or undefined if not found or if #iconMap failed to build.
const iconURLString =
await AppProvidedSearchEngine.iconHandler.getAvailableRecords(this.id);
if (!availableRecords.length) {
console.warn("No icon found for", this.id);
if (typeof iconURLString === "string") {
// We have a direct URL string.
// The #blobURLPromises cache was keyed by actual image width.
// Since we only get one URL directly, we can use preferredWidth as the cache key.
if (this.#blobURLPromises.has(preferredWidth)) {
return this.#blobURLPromises.get(preferredWidth);
}
// Store and return the promise for this direct URL.
const promise = Promise.resolve(iconURLString);
this.#blobURLPromises.set(preferredWidth, promise);
return promise;
} else {
// No specific icon URL found from the JSON-backed map for this engine.
console.warn(`No icon URL string found for engine ${this.id} via IconHandler.getAvailableRecords.`);
return null;
}
let availableSizes = availableRecords.map(r => r.imageSize);
let width = lazy.SearchUtils.chooseIconSize(preferredWidth, availableSizes);
if (this.#blobURLPromises.has(width)) {
return this.#blobURLPromises.get(width);
}
let record = availableRecords.find(r => r.imageSize == width);
let promise = AppProvidedSearchEngine.iconHandler.createIconURL(record);
this.#blobURLPromises.set(width, promise);
return promise;
}
/**

View File

@@ -2631,21 +2631,11 @@ export class SearchService {
// This is prefixed with _ rather than # because it is
// called in test_remove_engine_notification_box.js
async _fetchEngineSelectorEngines() {
let searchEngineSelectorProperties = {
locale: Services.locale.appLocaleAsBCP47,
region: lazy.Region.home || "unknown",
channel: lazy.SearchUtils.MODIFIED_APP_CHANNEL,
experiment: this._experimentPrefValue,
distroID: lazy.SearchUtils.distroID ?? "",
};
for (let [key, value] of Object.entries(searchEngineSelectorProperties)) {
this._settings.setMetaDataAttribute(key, value);
}
return this.#engineSelector.fetchEngineConfiguration(
searchEngineSelectorProperties
);
const engines = await (
await fetch("chrome://browser/content/search/BrowserSearchEngines.json")
).json();
// MODIFICATION: Use the correct property names appDefaultEngineId and appPrivateDefaultEngineId.
return { engines, appDefaultEngineId: "ecosia", appPrivateDefaultEngineId: "ecosia" };
}
#setDefaultFromSelector(refinedConfig) {

View File

@@ -11,6 +11,7 @@ DIRS += [
"addonstores",
"preferences",
"privatetab",
"search",
"statusbar",
"tabfeatures",
"uicustomizations",

View File

@@ -0,0 +1,10 @@
[
["bing", "chrome://browser/content/search/bing/favicon.ico"],
["ddg", "chrome://browser/content/search/ddg/favicon.ico"],
["ecosia", "chrome://browser/content/search/ecosia/favicon.ico"],
["google", "chrome://browser/content/search/google/favicon.ico"],
["mojeek", "chrome://browser/content/search/mojeek/favicon.ico"],
["qwant", "chrome://browser/content/search/qwant/favicon.ico"],
["startpage", "chrome://browser/content/search/startpage/favicon.ico"],
["wps", "chrome://browser/content/search/wps/favicon.svg"]
]

View File

@@ -0,0 +1,402 @@
[
{
"aliases": [
"bing",
"b"
],
"name": "Bing",
"urls": {
"search": {
"base": "https://www.bing.com/search",
"params": [
{
"name": "PC",
"value": "IS45"
},
{
"name": "PTAG",
"value": "SYS1000000"
}
],
"searchTermParamName": "q"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "2b86db12-a65d-4cdc-84f8-cdcf705ad5ca",
"identifier": "bing",
"recordType": "engine",
"variants": []
},
{
"aliases": [
"duckduckgo",
"ddg"
],
"name": "DuckDuckGo",
"urls": {
"search": {
"base": "https://duckduckgo.com/",
"params": [
{
"name": "t",
"value": "waterfox"
}
],
"searchTermParamName": "q"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "c8ef2865-c592-4eea-8e13-abdefc4e586d",
"identifier": "ddg",
"recordType": "engine",
"variants": []
},
{
"aliases": [
"ecosia",
"e"
],
"name": "Ecosia",
"urls": {
"search": {
"base": "https://www.ecosia.org/search",
"params": [
{
"name": "tt",
"value": "57226k1p"
}
],
"searchTermParamName": "q"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "6e24cbe0-e421-4462-ad7d-197db4cde98f",
"identifier": "ecosia",
"recordType": "engine",
"variants": []
},
{
"aliases": [
"google",
"g"
],
"name": "Google",
"urls": {
"search": {
"base": "https://www.google.com/search",
"params": [],
"searchTermParamName": "q"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "cc42ee69-382f-44b9-9222-980755a6849f",
"identifier": "google",
"recordType": "engine",
"variants": []
},
{
"aliases": [
"mojeek",
"m"
],
"name": "Mojeek",
"urls": {
"search": {
"base": "https://www.mojeek.com/search",
"searchTermParamName": "q"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "db59d254-ecf4-42a1-b15c-63563debb60a",
"identifier": "mojeek",
"recordType": "engine",
"variants": []
},
{
"aliases": [
"qwant",
"q"
],
"name": "Qwant",
"urls": {
"search": {
"base": "https://www.qwant.com/",
"params": [],
"searchTermParamName": "q"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "d7e41317-0461-4801-9ebc-fa4de57dcd57",
"identifier": "qwant",
"recordType": "engine",
"variants": []
},
{
"aliases": [
"startpage",
"sp"
],
"name": "Startpage",
"urls": {
"search": {
"base": "https://www.startpage.com/sp/search",
"method": "POST",
"params": [
{
"name": "segment",
"value": "startpage.waterfox.1"
}
],
"searchTermParamName": "query"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "7debf7f1-bac9-4585-b94e-cce2a4eecacc",
"identifier": "startpage",
"recordType": "engine",
"variants": []
},
{
"aliases": [
"wps",
"w"
],
"name": "Waterfox Private Search",
"urls": {
"search": {
"base": "https://search.waterfox.net/search",
"params": [],
"searchTermParamName": "q"
},
"suggestions": {
"base": "https://www.google.com/complete/search",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"experimentConfig": "search_rich_suggestions",
"name": "channel"
}
],
"searchTermParamName": "q"
},
"trending": {
"base": "https://www.google.com/complete/search",
"method": "GET",
"params": [
{
"name": "client",
"value": "firefox"
},
{
"name": "channel",
"value": "ftr"
}
],
"searchTermParamName": "q"
}
},
"id": "9b2df7d1-77d2-43e8-b20c-6b6ae4b6844b",
"identifier": "wps",
"recordType": "engine",
"variants": []
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

View File

@@ -0,0 +1,29 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 -5.5 36 36" fill="none">
<path fill="url(#a)" d="M7.05391 17.5532c1.13727 0 1.70832-.649 2.29389-1.9641l2.2044-4.9161-3.67316-8.22905C6.95229.363673 4.51806-.568696 2.43952.35883.363413 1.28636-.568176 3.72505.358573 5.8029L5.21009 16.6814c.39684.5739 1.09129.8718 1.8414.8718h.00242Z"/>
<path fill="url(#b)" d="M28.3765 17.5532c-1.1373 0-1.7083-.6491-2.2939-1.9641l-2.2044-4.9161 3.6707-8.22907c.9268-2.077848 3.361-3.010217 5.4395-2.082691 2.0762.927531 3.0077 3.363791 2.081 5.444071L30.2179 16.6838c-.3969.5739-1.0913.8718-1.8414.8718v-.0024Z"/>
<path fill="url(#c)" d="M28.3758 17.5556c-1.1373 0-1.7084-.6491-2.2939-1.9641L21.4917 5.35485c-.6848-1.5378-2.1971-2.44838-3.7796-2.44111-1.5801-.00727-3.0924.90331-3.7796 2.44111L9.34232 15.5915c-.58557 1.315-1.15662 1.9641-2.29389 1.9641-.75011 0-1.44457-.2955-1.8414-.8718.32666.7967 1.20018 3.0659 2.14628 5.0856.0363.0775.0726.1526.10889.2252v-.0024c.40409.5522 1.15178.8694 1.88496.8694 1.13724 0 1.70834-.649 2.29384-1.964 0 0 2.9206-6.5242 3.8934-8.7013.2637-.5909.8662-2.0125 2.1753-2.0125 1.309 0 1.8849 1.3634 2.1753 2.0125.9727 2.1747 3.8933 8.7013 3.8933 8.7013.5856 1.315 1.1566 1.964 2.2939 1.964.7332 0 1.4809-.3172 1.885-.8694v.0024c.0363-.0726.0725-.1477.1088-.2252.9461-2.0197 1.8197-4.2889 2.1463-5.0856-.3968.5739-1.0913.8718-1.8414.8718h.0049Z"/>
<path fill="url(#d)" d="M27.9621 21.997c-.438.8791-.9122 1.5112-1.3986 1.9616-.7259.6394-1.6115 1.0027-2.6859 1.0414h-.0338c-1.1736-.0242-2.3351-.5376-3.1215-1.4409-.2492-.3028-.467-.6466-.6485-1.0244 0 0-1.2485-2.8407-2.3568-5.3448v.0048-.0048c-1.1106 2.5041-2.3568 5.3448-2.3568 5.3448-.1814.3778-.3968.7216-.6484 1.0244-.7864.9033-1.9503 1.4167-3.1215 1.4409h-.0338c-1.0744-.0387-1.96001-.4044-2.68592-1.0414-.48636-.4504-.96063-1.0825-1.3986-1.9616.4041.5498 1.15179.867 1.88496.867 1.13726 0 1.70836-.649 2.29386-1.964 0 0 2.9206-6.5242 3.8933-8.7013.2904-.649.8687-2.0125 2.1754-2.0125 1.3066 0 1.8849 1.3635 2.1753 2.0125.9727 2.1747 3.8933 8.7013 3.8933 8.7013.5856 1.315 1.1566 1.964 2.2939 1.964.7332 0 1.4809-.3172 1.8849-.867h-.0048Z"/>
<defs>
<radialGradient id="a" cx="0" cy="0" r="1" gradientTransform="matrix(9.99099 0 0 9.99936 1.71119 1.00786)" gradientUnits="userSpaceOnUse">
<stop offset=".1" stop-color="#00BAE6"/>
<stop offset=".78" stop-color="#0084E7"/>
</radialGradient>
<radialGradient id="b" cx="0" cy="0" r="1" gradientTransform="matrix(-9.99099 0 0 -9.99936 33.7216 1.00784)" gradientUnits="userSpaceOnUse">
<stop offset=".14" stop-color="#788CF3"/>
<stop offset=".46" stop-color="#587EEF"/>
<stop offset="1" stop-color="#1A65E8"/>
</radialGradient>
<linearGradient id="c" x1="5.20945" x2="30.2196" y1="12.8889" y2="12.8889" gradientUnits="userSpaceOnUse">
<stop stop-color="#788CF3"/>
<stop offset=".25" stop-color="#57ABF6"/>
<stop offset=".51" stop-color="#39CAFA"/>
<stop offset=".86" stop-color="#39CAFA"/>
</linearGradient>
<linearGradient id="d" x1="7.46715" x2="27.9621" y1="17.5943" y2="17.5943" gradientUnits="userSpaceOnUse">
<stop stop-color="#679BF5"/>
<stop offset=".19" stop-color="#529DF4"/>
<stop offset=".51" stop-color="#34A2F3"/>
<stop offset=".86" stop-color="#4DAFF7"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,8 @@
# 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/.
browser.jar:
content/browser/search/BrowserSearchEngineIcons.json (content/BrowserSearchEngineIcons.json)
content/browser/search/BrowserSearchEngines.json (content/BrowserSearchEngines.json)
content/browser/search/ (extensions/**)

View File

@@ -0,0 +1,7 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
JAR_MANIFESTS += ["jar.mn"]