Я давно пользуюсь FVD Speed Dial как основной экспресс‑панелью. Однажды после перенастройки сети (VPN, прокси, DNS) заметил неприятный эффект: любое слово, набранное в строке поиска новой вкладки, всегда улетало в Yahoo. Никаких настроек выбора поисковика в интерфейсе расширения не было — только встроенное поле, жёстко завязанное на внутреннюю логику FVD.
Системный поисковик Chrome я менял, но это никак не влияло на поведение FVD Speed Dial: расширение упрямо перенаправляло все запросы в Yahoo.
Поиск в Сети привел к статье на Хабр датированной 3 авг 2013. Данные устарели, но идею подхватил.
Где живёт расширение и что в нём есть
Расширение FVD Speed Dial (версия 81.8.3, ID llaficoajjainaijghjlofdfmbjpebpa) у меня стоит в портативной сборке Cent Browser:
CentBrowserPortableUser DataDefaultExtensionsllaficoajjainaijghjlofdfmbjpebpa81.8.3_0
jsnewtabsearch.js
stylesnewtabstyle.css
В обычном Chrome/Chromium путь к расширениям примерно такой:
-
Windows:
C:Users<имя>AppDataLocalGoogleChromeUser DataDefaultExtensions<id><версия>_0 -
Linux:
~/.config/google-chrome/Default/Extensions/<id>/<версия>_0
Найти свою папку проще всего через chrome://extensions → «Режим разработчика» → «Подробнее» → поле «Путь».
Дальше я отдал файлы js/newtab/search.js и styles/newtab/style.css ИИ‑ассистенту с просьбой понять, почему всё летит в Yahoo и можно ли добавить нормальный выбор поисковой системы прямо в новой вкладке.
Разбор логики: скрытый автодетект провайдера
ИИ быстро раскопал несколько ключевых моментов в search.js:
-
глобальный объект
Search.prototype.searchProviders— здесь перечислены системные провайдеры (fvd,yandex,bing,yahooи т.д.), каждый со своим URL поиска; -
настройки пользователя хранятся в
sd.searchprovider, но в интерфейсе новой вкладки выбора поисковика нет — пользователь до этих настроек не добирается; -
функция
doSearch()делает так:-
берёт текущий провайдер (
this.getProvider()), -
если это
fvd, вызываетthis.detectProvider(), -
detectProvider()по списку локалей и IP выбирает реальный провайдер (в моём случае стабильно попадала в ветку с Yahoo).
-
Получается, что поведение «всегда Yahoo» — это не вирус и не подмена поиска, а агрессивный автодетект, который после изменений сети стал считать Yahoo «правильным» вариантом.
Цель: добавить нормальный выбор ПС и отключить навязчивый автодетект
Я сформулировал задачу ИИ так:
-
Добавить выбор поисковой системы прямо в интерфейсе FVD Speed Dial (Google, Яндекс, DuckDuckGo и т.д.).
-
Сделать так, чтобы при явном выборе никакой автодетект провайдера не срабатывал.
-
Визуально отображать текущую ПС через иконку рядом со строкой поиска.
ИИ предложил использовать уже существующую инфраструктуру в search.js:
-
список провайдеров
searchProviders, -
настройки
sd.searchprovider, -
структуру UI: логотип
#searchLogo, список#searchList.
Оказалось, выбор ПС уже заложен в код, но не доведён до нормального UI.
Доработка JavaScript: реальные провайдеры и сохранение выбора
В Search.prototype.searchProviders мы оставили существующие записи и добавили явные системные поисковики:
Search.prototype.searchProviders = {
fvd: {
name: "Speed Dial",
url: "https://fvdmedia.com/addon/search?qq={q}&from=chromefvdsd&installtime={time}&searchtype={type}"
},
yandex: {
name: "Yandex",
url: "https://yandex.ru/yandsearch?clid=2028026&text={q}",
locale: ["ru", "by", "kz", "uz", "uk", "kg"],
ip: ["ru", "by", "kz", "uz", "uk", "ua", "kg"],
replace: function(url) { /* логика доменов yandex.ru / yandex.fr и т.д. */ }
},
bing: {
name: "Bing",
url: "https://search.fvdspeeddial.com/results.aspx?gd=SY1002769&searchsource=69&q={q}"
},
yahoo: {
name: "Yahoo",
url: "https://search.fvdspeeddial.com/results.aspx?gd=SY1002769&searchsource=69&q={q}"
},
google: {
name: "Google",
url: "https://www.google.com/search?q={q}"
},
duckduckgo: {
name: "DuckDuckGo",
url: "https://duckduckgo.com/?q={q}"
}
};
Функция fill() уже умела:
-
очищать
#searchList, -
пробегаться по
searchProviders, -
создавать
<li provider="<ключ>" class="provider-<ключ>">с именем поисковой системы, -
выставлять атрибут
providerна#searchLogoи подсвечивать активный пункт.
Чтобы выбор сразу отражался в UI, мы поправили обработчик клика:
Search.prototype.clickProvider = function(option) {
const provider = option.attr("provider");
this.setProvider(provider); // сохраняет в sd.searchprovider
this.fill(); // немедленно обновляет логотип и меню
this.menu("close");
};
Ключевой момент — поведение doSearch():
jsSearch.prototype.doSearch = async function(query) {
const fvdSpeedDial = this.fvdSpeedDial;
const Prefs = fvdSpeedDial.Prefs;
let url;
if (!query) {
const q = document.getElementById("q");
if (q.hasAttribute("clickUrl")) {
query = q.getAttribute("clickUrl");
} else {
query = q.value;
}
}
if (typeof query === "object" && query.clickurl) {
url = query.clickurl;
} else {
let provider = this.getProvider(); // читаем выбор пользователя
// Автодетект оставляем только в режиме "Speed Dial"
if (provider === "fvd") {
provider = this.detectProvider();
}
const providerData = this.searchProviders[provider];
if (String(query).trim().length === 0) {
return false;
}
await Analytics.fireSearchEvent(query, providerData?.name);
url = String(providerData.url)
.replace("{q}", encodeURIComponent(query))
.replace("{time}", Prefs.get("sd.installtime"))
.replace("{type}", Utils.getInstallVersion(fvdSpeedDial) >= 6930 ? 0 : 1)
.replace("{version}", Utils.getCurrentVersion());
if (typeof providerData.replace === "function") {
url = providerData.replace(url);
}
}
document.location = url;
};
Такое поведение даёт простой эффект:
-
если я явно выбрал Google, Яндекс или DuckDuckGo — всегда используется именно этот URL;
-
если оставил «родной» режим FVD (
fvd) — включается автодетект, и расширение само решает, куда отправить запрос (хочешь — пользуйся этим режимом, хочешь — нет).
Доработка CSS: иконки провайдеров и маленький баг с комментариями
Вторая часть истории — визуальный выбор. В styles/newtab/style.css уже был блок для логотипа #searchLogo, но часть правил оказалась закомментирована, из‑за чего иконка всегда оставалась дефолтной, даже если JS уже правильно выставлялprovider
ИИ помог быстро найти нужный фрагмент:
css.searchLogo {
cursor: pointer;
width: 32px;
height: 32px;
display: inline-block;
background-repeat: no-repeat;
background-size: 32px 32px;
background-position: center center;
margin-right: 5px;
margin-top: -2px;
position: relative;
opacity: 1;
transition: opacity 75ms;
background-image: url(images/providerfvd.png);
}
.searchLogo.fade {
opacity: 0;
}
.searchLogo:after {
content: "";
position: absolute;
width: 13px;
height: 0px;
box-shadow: 0px 0px 10px 1px #fff;
top: 36px;
left: 10px;
background: #ccc;
}
/* иконки поисковых систем */
.searchLogo[provider="fvd"] { background-image: url(images/providerfvd.png); }
.searchLogo[provider="autodetect"] { background-image: url(images/providerautodetect.png); }
.searchLogo[provider="yandex"] { background-image: url(images/provideryandex.png); }
.searchLogo[provider="yahoo"] { background-image: url(images/provideryahoo.png); }
.searchLogo[provider="bing"] { background-image: url(images/providerbing.png); }
.searchLogo[provider="google"] { background-image: url(images/providergoogle.png); }
.searchLogo[provider="duckduckgo"] { background-image: url(images/providerduckduckgo.png); }
Раньше этот блок был «убит» комментариями и странными селекторами вида .searchLogoprovidergoogle. После небольших правок и распаковки комментариев логотип начал корректно менять иконку при смене провайдера.
Сами изображения (providergoogle.png, providerduckduckgo.png, provideryandex.png и т.д.) уже были в images/ — их не пришлось искать или рисовать, достаточно было просто вернуть CSS к жизни.
Результат
В итоге с помощью ИИ и пары правок в двух файлах:
-
js/newtab/search.js -
styles/newtab/style.css
я получил то, чего не было «из коробки»:
-
полноценно работающий список поисковых систем в строке FVD Speed Dial (Google, Яндекс, DuckDuckGo, Bing, Yahoo и др.);
-
сохранение выбора между перезапусками браузера;
-
адекватное поведение автодетекта (только в режиме FVD, а не поверх моего выбора);
-
нормальные иконки провайдеров, которые меняются вместе с поисковой системой.
И главное — навязчивый Yahoo исчез из моей ежедневной рутины, а вместо ручного reverse‑engineering большую часть анализа кода сделал за меня ИИ.
Автор: krongg
