[go: nahoru, domu]

[Waffle] Run generate_search_engine_icons.py as part of the build

The script generate_search_engine_icons.py is split in 3:
- download_search_engine_icons.py: downloads search engine icons
  from gstatic server. Generates the grdp file. Ran manually when
  the icons are updated.
- generate_search_engine_icons.py: generates the C++ code. Ran as
  part of the build.
- search_engine_icons_utils.py: shared utilities.

The refactoring involved changes such as:
- removing global variables
- creating helper functions `keyword_to_resource_name` and `get_used_engines_with_keywords` in `search_engine_icons_utils.py` to reduce code duplication
- removed log messages so that nothing is logged during a successful build.

Generated code:
generated_icon_utils-inc.cc: http://gpaste/6017060839096320
generated_search_engine_resource_ids-inc.cc:  https://paste.googleplex.com/5354399747014656


Change-Id: I21af4436508678208774010c499e85f659aaf00c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5149090
Reviewed-by: Jack Yammine <jyammine@google.com>
Commit-Queue: David Roger <droger@chromium.org>
Reviewed-by: Orin Jaworski <orinj@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1259393}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 16f56aea..19270d52f 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2070,6 +2070,7 @@
       "//components/safe_browsing/core/common:safe_browsing_policy_handler",
       "//components/safety_check",
       "//components/saved_tab_groups:core",
+      "//components/search_engines:generate_search_engine_icons",
       "//components/search_provider_logos",
       "//components/services/app_service",
       "//components/supervised_user/core/common",
diff --git a/chrome/browser/ui/webui/search_engine_choice/generated_icon_utils-inc.cc b/chrome/browser/ui/webui/search_engine_choice/generated_icon_utils-inc.cc
deleted file mode 100644
index 8b8fc10..0000000
--- a/chrome/browser/ui/webui/search_engine_choice/generated_icon_utils-inc.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This code is generated
-// using`tools/search_engine_choice/generate_search_engine_icons.py`. Don't
-// modify it manually.
-
-constexpr auto kSearchEngineIconPathMap =
-    base::MakeFixedFlatMap<std::u16string_view, std::string_view>(
-        {{u"bing.com", "chrome://theme/IDR_BING_COM_PNG"},
-         {u"search.brave.com", "chrome://theme/IDR_SEARCH_BRAVE_COM_PNG"},
-         {u"duckduckgo.com", "chrome://theme/IDR_DUCKDUCKGO_COM_PNG"},
-         {u"ecosia.org", "chrome://theme/IDR_ECOSIA_ORG_PNG"},
-         {u"karmasearch.org", "chrome://theme/IDR_KARMASEARCH_ORG_PNG"},
-         {u"lilo.org", "chrome://theme/IDR_LILO_ORG_PNG"},
-         {u"mail.ru", "chrome://theme/IDR_MAIL_RU_PNG"},
-         {u"mojeek.com", "chrome://theme/IDR_MOJEEK_COM_PNG"},
-         {u"nona.de", "chrome://theme/IDR_NONA_DE_PNG"},
-         {u"panda-search.org", "chrome://theme/IDR_PANDA_SEARCH_ORG_PNG"},
-         {u"quendu.com", "chrome://theme/IDR_QUENDU_COM_PNG"},
-         {u"qwant.com", "chrome://theme/IDR_QWANT_COM_PNG"},
-         {u"seznam.cz", "chrome://theme/IDR_SEZNAM_CZ_PNG"},
-         {u"seznam.sk", "chrome://theme/IDR_SEZNAM_SK_PNG"},
-         {u"yahoo.com", "chrome://theme/IDR_YAHOO_COM_PNG"},
-         {u"ar.yahoo.com", "chrome://theme/IDR_AR_YAHOO_COM_PNG"},
-         {u"at.yahoo.com", "chrome://theme/IDR_AT_YAHOO_COM_PNG"},
-         {u"au.yahoo.com", "chrome://theme/IDR_AU_YAHOO_COM_PNG"},
-         {u"br.yahoo.com", "chrome://theme/IDR_BR_YAHOO_COM_PNG"},
-         {u"ca.yahoo.com", "chrome://theme/IDR_CA_YAHOO_COM_PNG"},
-         {u"ch.yahoo.com", "chrome://theme/IDR_CH_YAHOO_COM_PNG"},
-         {u"cl.yahoo.com", "chrome://theme/IDR_CL_YAHOO_COM_PNG"},
-         {u"co.yahoo.com", "chrome://theme/IDR_CO_YAHOO_COM_PNG"},
-         {u"de.yahoo.com", "chrome://theme/IDR_DE_YAHOO_COM_PNG"},
-         {u"dk.yahoo.com", "chrome://theme/IDR_DK_YAHOO_COM_PNG"},
-         {u"es.yahoo.com", "chrome://theme/IDR_ES_YAHOO_COM_PNG"},
-         {u"fi.yahoo.com", "chrome://theme/IDR_FI_YAHOO_COM_PNG"},
-         {u"fr.yahoo.com", "chrome://theme/IDR_FR_YAHOO_COM_PNG"},
-         {u"hk.yahoo.com", "chrome://theme/IDR_HK_YAHOO_COM_PNG"},
-         {u"id.yahoo.com", "chrome://theme/IDR_ID_YAHOO_COM_PNG"},
-         {u"in.yahoo.com", "chrome://theme/IDR_IN_YAHOO_COM_PNG"},
-         {u"yahoo.co.jp", "chrome://theme/IDR_YAHOO_CO_JP_PNG"},
-         {u"mx.yahoo.com", "chrome://theme/IDR_MX_YAHOO_COM_PNG"},
-         {u"malaysia.yahoo.com", "chrome://theme/IDR_MALAYSIA_YAHOO_COM_PNG"},
-         {u"nl.yahoo.com", "chrome://theme/IDR_NL_YAHOO_COM_PNG"},
-         {u"nz.yahoo.com", "chrome://theme/IDR_NZ_YAHOO_COM_PNG"},
-         {u"pe.yahoo.com", "chrome://theme/IDR_PE_YAHOO_COM_PNG"},
-         {u"ph.yahoo.com", "chrome://theme/IDR_PH_YAHOO_COM_PNG"},
-         {u"se.yahoo.com", "chrome://theme/IDR_SE_YAHOO_COM_PNG"},
-         {u"sg.yahoo.com", "chrome://theme/IDR_SG_YAHOO_COM_PNG"},
-         {u"th.yahoo.com", "chrome://theme/IDR_TH_YAHOO_COM_PNG"},
-         {u"tr.yahoo.com", "chrome://theme/IDR_TR_YAHOO_COM_PNG"},
-         {u"tw.yahoo.com", "chrome://theme/IDR_TW_YAHOO_COM_PNG"},
-         {u"uk.yahoo.com", "chrome://theme/IDR_UK_YAHOO_COM_PNG"},
-         {u"yandex.by", "chrome://theme/IDR_YANDEX_BY_PNG"},
-         {u"yandex.com", "chrome://theme/IDR_YANDEX_COM_PNG"},
-         {u"yandex.kz", "chrome://theme/IDR_YANDEX_KZ_PNG"},
-         {u"yandex.ru", "chrome://theme/IDR_YANDEX_RU_PNG"},
-         {u"yandex.com.tr", "chrome://theme/IDR_YANDEX_COM_TR_PNG"},
-         {u"yep.com", "chrome://theme/IDR_YEP_COM_PNG"},
-         {u"info.com", "chrome://theme/IDR_INFO_COM_PNG"},
-         {u"metager.de", "chrome://theme/IDR_METAGER_DE_PNG"},
-         {u"oceanhero.today", "chrome://theme/IDR_OCEANHERO_TODAY_PNG"},
-         {u"privacywall.org", "chrome://theme/IDR_PRIVACYWALL_ORG_PNG"},
-         {u"google.com",
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-          "chrome://theme/IDR_GOOGLE_COM_PNG"
-#else
-          "chrome://theme/IDR_DEFAULT_FAVICON"
-#endif
-         }});
diff --git a/components/resources/search_engine_choice_scaled_resources.grdp b/components/resources/search_engine_choice_scaled_resources.grdp
index 98d2ce0..a8363036 100644
--- a/components/resources/search_engine_choice_scaled_resources.grdp
+++ b/components/resources/search_engine_choice_scaled_resources.grdp
@@ -5,24 +5,10 @@
   <if expr="_google_chrome">
     <structure type="chrome_scaled_image" name="IDR_GOOGLE_COM_PNG" file="google_chrome/google_search_logo.png" />
   </if>
-  <structure type="chrome_scaled_image" name="IDR_BING_COM_PNG" file="search_engine_choice/bing_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_SEARCH_BRAVE_COM_PNG" file="search_engine_choice/search_brave_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_DUCKDUCKGO_COM_PNG" file="search_engine_choice/duckduckgo_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_ECOSIA_ORG_PNG" file="search_engine_choice/ecosia_org.png" />
-  <structure type="chrome_scaled_image" name="IDR_KARMASEARCH_ORG_PNG" file="search_engine_choice/karmasearch_org.png" />
-  <structure type="chrome_scaled_image" name="IDR_LILO_ORG_PNG" file="search_engine_choice/lilo_org.png" />
-  <structure type="chrome_scaled_image" name="IDR_MAIL_RU_PNG" file="search_engine_choice/mail_ru.png" />
-  <structure type="chrome_scaled_image" name="IDR_MOJEEK_COM_PNG" file="search_engine_choice/mojeek_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_NONA_DE_PNG" file="search_engine_choice/nona_de.png" />
-  <structure type="chrome_scaled_image" name="IDR_PANDA_SEARCH_ORG_PNG" file="search_engine_choice/panda_search_org.png" />
-  <structure type="chrome_scaled_image" name="IDR_QUENDU_COM_PNG" file="search_engine_choice/quendu_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_QWANT_COM_PNG" file="search_engine_choice/qwant_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_SEZNAM_CZ_PNG" file="search_engine_choice/seznam_cz.png" />
-  <structure type="chrome_scaled_image" name="IDR_SEZNAM_SK_PNG" file="search_engine_choice/seznam_cz.png" />
-  <structure type="chrome_scaled_image" name="IDR_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_AR_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_AT_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_AU_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_BING_COM_PNG" file="search_engine_choice/bing_com.png" />
   <structure type="chrome_scaled_image" name="IDR_BR_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_CA_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_CH_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
@@ -30,33 +16,47 @@
   <structure type="chrome_scaled_image" name="IDR_CO_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_DE_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_DK_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_DUCKDUCKGO_COM_PNG" file="search_engine_choice/duckduckgo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_ECOSIA_ORG_PNG" file="search_engine_choice/ecosia_org.png" />
   <structure type="chrome_scaled_image" name="IDR_ES_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_FI_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_FR_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_HK_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_ID_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_INFO_COM_PNG" file="search_engine_choice/info_com.png" />
   <structure type="chrome_scaled_image" name="IDR_IN_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_YAHOO_CO_JP_PNG" file="search_engine_choice/yahoo_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_MX_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_KARMASEARCH_ORG_PNG" file="search_engine_choice/karmasearch_org.png" />
+  <structure type="chrome_scaled_image" name="IDR_LILO_ORG_PNG" file="search_engine_choice/lilo_org.png" />
+  <structure type="chrome_scaled_image" name="IDR_MAIL_RU_PNG" file="search_engine_choice/mail_ru.png" />
   <structure type="chrome_scaled_image" name="IDR_MALAYSIA_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_METAGER_DE_PNG" file="search_engine_choice/metager_de.png" />
+  <structure type="chrome_scaled_image" name="IDR_MOJEEK_COM_PNG" file="search_engine_choice/mojeek_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_MX_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_NL_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_NONA_DE_PNG" file="search_engine_choice/nona_de.png" />
   <structure type="chrome_scaled_image" name="IDR_NZ_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_OCEANHERO_TODAY_PNG" file="search_engine_choice/oceanhero_today.png" />
+  <structure type="chrome_scaled_image" name="IDR_PANDA_SEARCH_ORG_PNG" file="search_engine_choice/panda_search_org.png" />
   <structure type="chrome_scaled_image" name="IDR_PE_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_PH_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_PRIVACYWALL_ORG_PNG" file="search_engine_choice/privacywall_org.png" />
+  <structure type="chrome_scaled_image" name="IDR_QUENDU_COM_PNG" file="search_engine_choice/quendu_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_QWANT_COM_PNG" file="search_engine_choice/qwant_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_SEARCH_BRAVE_COM_PNG" file="search_engine_choice/search_brave_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_SEZNAM_CZ_PNG" file="search_engine_choice/seznam_cz.png" />
+  <structure type="chrome_scaled_image" name="IDR_SEZNAM_SK_PNG" file="search_engine_choice/seznam_cz.png" />
   <structure type="chrome_scaled_image" name="IDR_SE_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_SG_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_TH_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_TR_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_TW_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_UK_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_YAHOO_COM_PNG" file="search_engine_choice/yahoo_com.png" />
+  <structure type="chrome_scaled_image" name="IDR_YAHOO_CO_JP_PNG" file="search_engine_choice/yahoo_com.png" />
   <structure type="chrome_scaled_image" name="IDR_YANDEX_BY_PNG" file="search_engine_choice/yandex_by.png" />
   <structure type="chrome_scaled_image" name="IDR_YANDEX_COM_PNG" file="search_engine_choice/yandex_by.png" />
+  <structure type="chrome_scaled_image" name="IDR_YANDEX_COM_TR_PNG" file="search_engine_choice/yandex_by.png" />
   <structure type="chrome_scaled_image" name="IDR_YANDEX_KZ_PNG" file="search_engine_choice/yandex_by.png" />
   <structure type="chrome_scaled_image" name="IDR_YANDEX_RU_PNG" file="search_engine_choice/yandex_by.png" />
-  <structure type="chrome_scaled_image" name="IDR_YANDEX_COM_TR_PNG" file="search_engine_choice/yandex_by.png" />
   <structure type="chrome_scaled_image" name="IDR_YEP_COM_PNG" file="search_engine_choice/yep_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_INFO_COM_PNG" file="search_engine_choice/info_com.png" />
-  <structure type="chrome_scaled_image" name="IDR_METAGER_DE_PNG" file="search_engine_choice/metager_de.png" />
-  <structure type="chrome_scaled_image" name="IDR_OCEANHERO_TODAY_PNG" file="search_engine_choice/oceanhero_today.png" />
-  <structure type="chrome_scaled_image" name="IDR_PRIVACYWALL_ORG_PNG" file="search_engine_choice/privacywall_org.png" />
 </grit-part>
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn
index 564f52e..20cc19b 100644
--- a/components/search_engines/BUILD.gn
+++ b/components/search_engines/BUILD.gn
@@ -115,6 +115,7 @@
   if (!is_android) {
     sources += [ "generated_marketing_snippets.cc" ]
     deps += [
+      ":generate_search_engine_icons",
       "//components/resources:components_scaled_resources_grit",
       "//ui/resources",
     ]
@@ -259,3 +260,32 @@
     ]
   }
 }
+
+if (!is_android) {
+  action("generate_search_engine_icons") {
+    script = "//tools/search_engine_choice/generate_search_engine_icons.py"
+
+    inputs = [
+      "//tools/search_engine_choice/generate_search_engine_icons_config.json",
+      "//components/search_engines/prepopulated_engines.json",
+      "//components/search_engines/template_url_prepopulate_data.cc",
+      "//tools/json_comment_eater/json_comment_eater.py",
+      "//tools/search_engine_choice/generate_search_engine_icons.py",
+      "//tools/search_engine_choice/search_engine_icons_utils.py",
+    ]
+
+    outputs = [
+      "$target_gen_dir/generated_search_engine_resource_ids-inc.cc",
+      "$root_gen_dir/chrome/browser/ui/webui/search_engine_choice/generated_icon_utils-inc.cc",
+    ]
+
+    args = [
+      rebase_path("//", root_build_dir),
+      rebase_path("$target_gen_dir/generated_search_engine_resource_ids-inc.cc",
+                  root_build_dir),
+      rebase_path(
+          "$target_gen_dir/../../chrome/browser/ui/webui/search_engine_choice/generated_icon_utils-inc.cc",
+          root_build_dir),
+    ]
+  }
+}
diff --git a/components/search_engines/generated_search_engine_resource_ids-inc.cc b/components/search_engines/generated_search_engine_resource_ids-inc.cc
deleted file mode 100644
index d03f2c91..0000000
--- a/components/search_engines/generated_search_engine_resource_ids-inc.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This code is generated
-// using`tools/search_engine_choice/generate_search_engine_icons.py`. Don't
-// modify it manually.
-
-constexpr auto kSearchEngineResourceIdMap =
-    base::MakeFixedFlatMap<std::u16string_view, int>(
-        {{u"bing.com", IDR_BING_COM_PNG},
-         {u"search.brave.com", IDR_SEARCH_BRAVE_COM_PNG},
-         {u"duckduckgo.com", IDR_DUCKDUCKGO_COM_PNG},
-         {u"ecosia.org", IDR_ECOSIA_ORG_PNG},
-         {u"karmasearch.org", IDR_KARMASEARCH_ORG_PNG},
-         {u"lilo.org", IDR_LILO_ORG_PNG},
-         {u"mail.ru", IDR_MAIL_RU_PNG},
-         {u"mojeek.com", IDR_MOJEEK_COM_PNG},
-         {u"nona.de", IDR_NONA_DE_PNG},
-         {u"panda-search.org", IDR_PANDA_SEARCH_ORG_PNG},
-         {u"quendu.com", IDR_QUENDU_COM_PNG},
-         {u"qwant.com", IDR_QWANT_COM_PNG},
-         {u"seznam.cz", IDR_SEZNAM_CZ_PNG},
-         {u"seznam.sk", IDR_SEZNAM_SK_PNG},
-         {u"yahoo.com", IDR_YAHOO_COM_PNG},
-         {u"ar.yahoo.com", IDR_AR_YAHOO_COM_PNG},
-         {u"at.yahoo.com", IDR_AT_YAHOO_COM_PNG},
-         {u"au.yahoo.com", IDR_AU_YAHOO_COM_PNG},
-         {u"br.yahoo.com", IDR_BR_YAHOO_COM_PNG},
-         {u"ca.yahoo.com", IDR_CA_YAHOO_COM_PNG},
-         {u"ch.yahoo.com", IDR_CH_YAHOO_COM_PNG},
-         {u"cl.yahoo.com", IDR_CL_YAHOO_COM_PNG},
-         {u"co.yahoo.com", IDR_CO_YAHOO_COM_PNG},
-         {u"de.yahoo.com", IDR_DE_YAHOO_COM_PNG},
-         {u"dk.yahoo.com", IDR_DK_YAHOO_COM_PNG},
-         {u"es.yahoo.com", IDR_ES_YAHOO_COM_PNG},
-         {u"fi.yahoo.com", IDR_FI_YAHOO_COM_PNG},
-         {u"fr.yahoo.com", IDR_FR_YAHOO_COM_PNG},
-         {u"hk.yahoo.com", IDR_HK_YAHOO_COM_PNG},
-         {u"id.yahoo.com", IDR_ID_YAHOO_COM_PNG},
-         {u"in.yahoo.com", IDR_IN_YAHOO_COM_PNG},
-         {u"yahoo.co.jp", IDR_YAHOO_CO_JP_PNG},
-         {u"mx.yahoo.com", IDR_MX_YAHOO_COM_PNG},
-         {u"malaysia.yahoo.com", IDR_MALAYSIA_YAHOO_COM_PNG},
-         {u"nl.yahoo.com", IDR_NL_YAHOO_COM_PNG},
-         {u"nz.yahoo.com", IDR_NZ_YAHOO_COM_PNG},
-         {u"pe.yahoo.com", IDR_PE_YAHOO_COM_PNG},
-         {u"ph.yahoo.com", IDR_PH_YAHOO_COM_PNG},
-         {u"se.yahoo.com", IDR_SE_YAHOO_COM_PNG},
-         {u"sg.yahoo.com", IDR_SG_YAHOO_COM_PNG},
-         {u"th.yahoo.com", IDR_TH_YAHOO_COM_PNG},
-         {u"tr.yahoo.com", IDR_TR_YAHOO_COM_PNG},
-         {u"tw.yahoo.com", IDR_TW_YAHOO_COM_PNG},
-         {u"uk.yahoo.com", IDR_UK_YAHOO_COM_PNG},
-         {u"yandex.by", IDR_YANDEX_BY_PNG},
-         {u"yandex.com", IDR_YANDEX_COM_PNG},
-         {u"yandex.kz", IDR_YANDEX_KZ_PNG},
-         {u"yandex.ru", IDR_YANDEX_RU_PNG},
-         {u"yandex.com.tr", IDR_YANDEX_COM_TR_PNG},
-         {u"yep.com", IDR_YEP_COM_PNG},
-         {u"info.com", IDR_INFO_COM_PNG},
-         {u"metager.de", IDR_METAGER_DE_PNG},
-         {u"oceanhero.today", IDR_OCEANHERO_TODAY_PNG},
-         {u"privacywall.org", IDR_PRIVACYWALL_ORG_PNG},
-         {u"google.com",
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-          IDR_GOOGLE_COM_PNG
-#else
-          IDR_DEFAULT_FAVICON
-#endif
-         }});
diff --git a/tools/search_engine_choice/download_search_engine_icons.py b/tools/search_engine_choice/download_search_engine_icons.py
new file mode 100644
index 0000000..abab2a8
--- /dev/null
+++ b/tools/search_engine_choice/download_search_engine_icons.py
@@ -0,0 +1,224 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Handles the download of the search engine favicons.
+
+For all search engines referenced in template_url_prepopulate_data.cc,
+downloads their Favicon, scales it and puts it as resource into the repository
+for display, e.g. in the search engine choice UI and settings.
+
+This should be run whenever template_url_prepopulate_data.cc changes the list of
+search engines used per country, or whenever prepopulated_engines.json changes
+a favicon.
+
+To run:
+`python3 tools/search_engine_choice/download_search_engine_icons.py`.
+"""
+
+import hashlib
+import json
+import os
+import sys
+import requests
+
+import search_engine_icons_utils
+
+
+def get_image_hash(image_path):
+  """Gets the hash of the image that's passed as argument.
+
+  This is needed to check whether the downloaded image was already added in the
+  repo or not.
+
+  Args:
+    image_path: The path of the image for which we want to get the hash.
+
+  Returns:
+    The hash of the image that's passed as argument.
+  """
+  with open(image_path, 'rb') as image:
+    return hashlib.sha256(image.read()).hexdigest()
+
+
+def delete_files_in_directory(directory_path):
+  """Deletes previously generated icons.
+
+  Deletes the icons that were previously created and added to directory_path.
+
+  Args:
+    directory_path: The path of the directory where the icons live.
+
+  Raises:
+    OSError: Error occurred while deleting files in {directory_path}
+  """
+  try:
+    files = os.listdir(directory_path)
+    for file in files:
+      file_path = os.path.join(directory_path, file)
+
+      # Only remove pngs.
+      filename = os.path.basename(file_path)
+      if filename.endswith('.png') and os.path.isfile(file_path):
+        os.remove(file_path)
+    print('All files deleted successfully from ' + directory_path)
+  except OSError:
+    print('Error occurred while deleting files in ' + directory_path)
+
+
+def download_icons_from_android_search():
+  """Downloads icons from the android_search gstatic directory.
+
+  Goes through all search engines in `prepopulated_engines.json` and downloads
+  the corresponding 96x96 icon from the appropriate subfolder of
+  https://www.gstatic.com/android_search/search_providers/. Because there is no
+  way to list the contents of a directory on gstatic and because some
+  subfolders are not named exactly the same as in `prepopulated_engines.json`,
+  this function loads a config file `generate_search_engine_icons_config.json`
+  with the extra information needed to locate the icons.
+
+  The Google Search icon is not downloaded because it already exists in the
+  repo. Search engines not relevant to the to the default search engine choice
+  screen are ignored.
+  """
+  for percent in ['100', '200', '300']:
+    delete_files_in_directory(
+        f'components/resources/default_{percent}_percent/search_engine_choice')
+
+  with open(search_engine_icons_utils.config_file_path, 'r',
+            encoding='utf-8') as config_json:
+    config_data = json.loads(json_comment_eater.Nom(config_json.read()))
+    icon_hash_to_name = {}
+
+    for (engine, keyword) in sorted(
+        search_engine_icons_utils.get_used_engines_with_keywords("")):
+      icon_name = search_engine_icons_utils.keyword_to_identifer(keyword)
+      icon_full_path = f'components/resources/default_100_percent/search_engine_choice/{icon_name}.png'
+      if engine in config_data['engine_aliases']:
+        engine = config_data['engine_aliases'][engine]
+
+      directory_url = f'https://www.gstatic.com/android_search/search_providers/{engine}/'
+      try_filenames = []
+      if engine in config_data['non_default_icon_filenames']:
+        try_filenames = [
+            config_data['non_default_icon_filenames'][engine] + 'mdpi.png'
+        ]
+      try_filenames = try_filenames + [
+          f'{engine}_icon_mdpi.png',
+          f'{engine}_mdpi.png',
+          'mdpi.png',
+      ]
+      any_found = False
+      for filename in try_filenames:
+        icon_url = directory_url + filename
+        try:
+          img_data = requests.get(icon_url)
+        except requests.exceptions.RequestException as e:
+          print('Error when loading URL {icon_url}: {e}')
+          continue
+        if img_data.status_code == 200:
+          with open(icon_full_path, 'wb') as icon_file:
+            icon_file.write(img_data.content)
+          any_found = True
+          break
+      if not any_found:
+        print('WARNING: no icon found for search engine: ' + engine)
+        continue
+
+      icon_hash = get_image_hash(icon_full_path)
+      if icon_hash in icon_hash_to_name:
+        # We already have this icon.
+        engine_keyword_to_icon_name[keyword] = icon_hash_to_name[icon_hash]
+        os.remove(icon_full_path)
+        continue
+
+      # Download hidpi versions
+      # If the low dpi version is basename_mdpi.png, download basename_xhdpi.png
+      # and basename_xxhdpi.png.
+      for (resource_path, hidpi) in [('default_200_percent', 'xhdpi'),
+                                     ('default_300_percent', 'xxhdpi')]:
+        # Replace the substring "mdpi" by "xhdpi" or "xxhdpi" from the end.
+        (basename, mdpi_suffix, png_extension) = icon_url.rpartition('mdpi')
+        hidpi_url = basename + hidpi + png_extension
+        hidpi_path = f'components/resources/{resource_path}/search_engine_choice/{icon_name}.png'
+        try:
+          img_data = requests.get(hidpi_url)
+        except requests.exceptions.RequestException as e:
+          print('Error when loading URL {hidpi_url}: {e}')
+          continue
+        if img_data.status_code == 200:
+          with open(hidpi_path, 'wb') as icon_file:
+            icon_file.write(img_data.content)
+        else:
+          print('WARNING: no %s icon found for search engine: %s' %
+                (hidpi, engine))
+
+      engine_keyword_to_icon_name[keyword] = icon_name
+      icon_hash_to_name[icon_hash] = icon_name
+  print('Finished downloading icons')
+  os.system('tools/resources/optimize-png-files.sh search_engine_choice')
+
+
+def generate_icon_resource_code():
+  """Links the downloaded icons to their respective resource id.
+
+  Generates the code to link the icons to a resource ID in
+  `search_engine_choice_scaled_resources.grdp`
+  """
+  print('Writing to search_engine_choice_scaled_resources.grdp...')
+  with open('components/resources/search_engine_choice_scaled_resources.grdp',
+            'w',
+            encoding='utf-8',
+            newline='') as grdp_file:
+    grdp_file.write('<?xml version="1.0" encoding="utf-8"?>\n')
+    grdp_file.write(
+        '<!-- This file is generated using generate_search_engine_icons.py'
+        ' -->\n')
+    grdp_file.write("<!-- Don't modify it manually -->\n")
+    grdp_file.write('<grit-part>\n')
+
+    # Add the google resource id.
+    grdp_file.write('  <if expr="_google_chrome">\n')
+    grdp_file.write('    <structure type="chrome_scaled_image"'
+                    ' name="IDR_GOOGLE_COM_PNG"'
+                    ' file="google_chrome/google_search_logo.png" />\n')
+    grdp_file.write('  </if>\n')
+
+    # Add the remaining resource ids, sorted alphabetically.
+    resources = []
+    for engine_keyword, icon_name in engine_keyword_to_icon_name.items():
+      resource_id = search_engine_icons_utils.keyword_to_resource_name(
+          engine_keyword)
+      resources.append((resource_id, icon_name))
+
+    for resource_id, icon_name in sorted(resources):
+      grdp_file.write(
+          f'  <structure type="chrome_scaled_image" name="{resource_id}" file="search_engine_choice/{icon_name}.png" />\n'
+      )
+
+    grdp_file.write('</grit-part>\n')
+
+
+if sys.platform != 'linux':
+  print(
+      'Warning: This script has not been tested outside of the Linux platform')
+
+# Move to working directory to `src/`.
+current_file_path = os.path.dirname(__file__)
+os.chdir(current_file_path)
+os.chdir('../../')
+
+sys.path.insert(0,
+                os.path.normpath(current_file_path + "/../json_comment_eater"))
+try:
+  import json_comment_eater
+finally:
+  sys.path.pop(0)
+
+# This is a dictionary of engine keyword to corresponding icon name. Have an
+# empty icon name would mean that we weren't able to download the favicon for
+# that engine.
+engine_keyword_to_icon_name = {}
+
+download_icons_from_android_search()
+generate_icon_resource_code()
+print('Icon download completed.')
diff --git a/tools/search_engine_choice/generate_search_engine_icons.py b/tools/search_engine_choice/generate_search_engine_icons.py
index df03e37..7bf40f0 100644
--- a/tools/search_engine_choice/generate_search_engine_icons.py
+++ b/tools/search_engine_choice/generate_search_engine_icons.py
@@ -1,277 +1,28 @@
 # Copyright 2023 The Chromium Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-"""Handles the download of the search engine favicons.
 
-For all search engines referenced in template_url_prepopulate_data.cc,
-downloads their Favicon, scales it and puts it as resource into the repository
-for display, e.g. in the search engine choice UI and settings.
-
-This should be run whenever template_url_prepopulate_data.cc changes the list of
-search engines used per country, or whenever prepopulated_engines.json changes
-a favicon.
-
-To run:
-`python3 tools/search_engine_choice/generate_search_engine_icons.py`.
-"""
-
-import hashlib
-import json
-import os
-import re
 import sys
-import requests
+
+import search_engine_icons_utils
 
 
-def get_image_hash(image_path):
-  """Gets the hash of the image that's passed as argument.
-
-  This is needed to check whether the downloaded image was already added in the
-  repo or not.
-
-  Args:
-    image_path: The path of the image for which we want to get the hash.
-
-  Returns:
-    The hash of the image that's passed as argument.
-  """
-  with open(image_path, 'rb') as image:
-    return hashlib.sha256(image.read()).hexdigest()
-
-
-def keyword_to_identifer(keyword):
-  """Sanitized keyword to be used as identifier.
-
-  Replaces characters we find in prepopulates_engines.json's keyword field into
-  ones that are valid in file names and variable names.
-
-  Args:
-    keyword: the keyword string as in the json file.
-
-  Returns:
-    The keyword string with characters replaced that don't work in a variable or
-    file name.
-  """
-  return keyword.replace('.', '_').replace('-', '_')
-
-
-def populate_used_engines():
-  """Populates the `used_engines` set.
-
-  Populates the `used_engines` set by checking which engines are used in
-  `template_url_prepopulate_data.cc`.
-  """
-  print('Populating used engines set')
-  SE_NAME_REGEX = re.compile(r'.*SearchEngineTier::[A-Za-z]+, &(.+)},')
-  with open('../search_engines/template_url_prepopulate_data.cc',
-            'r',
-            encoding='utf-8') as file:
-    lines = file.readlines()
-    for line in lines:
-      match = SE_NAME_REGEX.match(line)
-      if match:
-        used_engines.add(match.group(1))
-
-
-def delete_files_in_directory(directory_path):
-  """Deletes previously generated icons.
-
-  Deletes the icons that were previously created and added to directory_path.
-
-  Args:
-    directory_path: The path of the directory where the icons live.
-
-  Raises:
-    OSError: Error occurred while deleting files in {directory_path}
-  """
-  try:
-    files = os.listdir(directory_path)
-    for file in files:
-      file_path = os.path.join(directory_path, file)
-
-      # Only remove pngs.
-      filename = os.path.basename(file_path)
-      if filename.endswith('.png') and os.path.isfile(file_path):
-        os.remove(file_path)
-    print('All files deleted successfully from ' + directory_path)
-  except OSError:
-    print('Error occurred while deleting files in ' + directory_path)
-
-
-def download_icons_from_android_search():
-  """Downloads icons from the android_search gstatic directory.
-
-  Goes through all search engines in `prepopulated_engines.json` and downloads
-  the corresponding 96x96 icon from the appropriate subfolder of
-  https://www.gstatic.com/android_search/search_providers/. Because there is no
-  way to list the contents of a directory on gstatic and because some
-  subfolders are not named exactly the same as in `prepopulated_engines.json`,
-  this function loads a config file `generate_search_engine_icons_config.json`
-  with the extra information needed to locate the icons.
-
-  The Google Search icon is not downloaded because it already exists in the
-  repo. Search engines not relevant to the to the default search engine choice
-  screen are ignored.
-  """
-  config_file_path = '../../tools/search_engine_choice/generate_search_engine_icons_config.json'
-  prepopulated_engines_file_path = '../search_engines/prepopulated_engines.json'
-  image_destination_path = 'search_engine_choice/'
-
-  delete_files_in_directory('./default_100_percent/' + image_destination_path)
-  delete_files_in_directory('./default_200_percent/' + image_destination_path)
-  delete_files_in_directory('./default_300_percent/' + image_destination_path)
-
-  with open(config_file_path, 'r', encoding='utf-8') as config_json, open(
-      prepopulated_engines_file_path, 'r', encoding='utf-8') as engines_json:
-    config_data = json.loads(json_comment_eater.Nom(config_json.read()))
-    engine_data = json.loads(json_comment_eater.Nom(engines_json.read()))
-
-    icon_hash_to_name = {}
-
-    for engine in engine_data['elements']:
-      if engine not in used_engines or engine in config_data['ignored_engines']:
-        continue
-
-      search_engine_keyword = engine_data['elements'][engine]['keyword']
-      icon_name = keyword_to_identifer(search_engine_keyword)
-      icon_full_path = './default_100_percent/' + image_destination_path + f'{icon_name}.png'
-      if engine in config_data['engine_aliases']:
-        engine = config_data['engine_aliases'][engine]
-
-      directory_url = f'https://www.gstatic.com/android_search/search_providers/{engine}/'
-      try_filenames = []
-      if engine in config_data['non_default_icon_filenames']:
-        try_filenames = [
-            config_data['non_default_icon_filenames'][engine] + 'mdpi.png'
-        ]
-      try_filenames = try_filenames + [
-          f'{engine}_icon_mdpi.png',
-          f'{engine}_mdpi.png',
-          'mdpi.png',
-      ]
-      any_found = False
-      for filename in try_filenames:
-        icon_url = directory_url + filename
-        try:
-          img_data = requests.get(icon_url)
-        except requests.exceptions.RequestException as e:
-          print('Error when loading URL {icon_url}: {e}')
-          continue
-        if img_data.status_code == 200:
-          with open(icon_full_path, 'wb') as icon_file:
-            icon_file.write(img_data.content)
-          any_found = True
-          found_url = icon_url
-          break
-      if not any_found:
-        print('WARNING: no icon found for search engine: %s' % engine)
-        continue
-
-      icon_hash = get_image_hash(icon_full_path)
-      if icon_hash in icon_hash_to_name:
-        # We already have this icon.
-        engine_keyword_to_icon_name[search_engine_keyword] = icon_hash_to_name[
-            icon_hash]
-        os.remove(icon_full_path)
-        continue
-
-      # Download hidpi versions
-      # If the low dpi version is basename_mdpi.png, download basename_xhdpi.png
-      # and basename_xxhdpi.png.
-      for (resource_path, hidpi) in [('./default_200_percent/', 'xhdpi'),
-                                     ('./default_300_percent/', 'xxhdpi')]:
-        # Replace the substring "mdpi" by "xhdpi" or "xxhdpi" from the end.
-        (basename, mdpi_suffix, png_extension) = icon_url.rpartition('mdpi')
-        hidpi_url = basename + hidpi + png_extension
-        hidpi_path = resource_path + image_destination_path + f'{icon_name}.png'
-        try:
-          img_data = requests.get(hidpi_url)
-        except requests.exceptions.RequestException as e:
-          print('Error when loading URL {hidpi_url}: {e}')
-          continue
-        if img_data.status_code == 200:
-          with open(hidpi_path, 'wb') as icon_file:
-            icon_file.write(img_data.content)
-        else:
-          print('WARNING: no %s icon found for search engine: %s' %
-                (suffix, engine))
-
-      engine_keyword_to_icon_name[search_engine_keyword] = icon_name
-      icon_hash_to_name[icon_hash] = icon_name
-  print('Finished downloading icons')
-  os.system('../../tools/resources/optimize-png-files.sh ' +
-            image_destination_path)
-
-
-def generate_icon_resource_code():
-  """Links the downloaded icons to their respective resource id.
-
-  Generates the code to link the icons to a resource ID in
-  `search_engine_choice_scaled_resources.grdp`
-  """
-  print('Writing to search_engine_choice_scaled_resources.grdp...')
-  with open('./search_engine_choice_scaled_resources.grdp',
-            'w',
-            encoding='utf-8',
-            newline='') as grdp_file:
-    grdp_file.write('<?xml version="1.0" encoding="utf-8"?>\n')
-    grdp_file.write(
-        '<!-- This file is generated using generate_search_engine_icons.py'
-        ' -->\n')
-    grdp_file.write("<!-- Don't modify it manually -->\n")
-    grdp_file.write('<grit-part>\n')
-
-    # Add the google resource id.
-    grdp_file.write('  <if expr="_google_chrome">\n')
-    grdp_file.write('    <structure type="chrome_scaled_image"'
-                    ' name="IDR_GOOGLE_COM_PNG"'
-                    ' file="google_chrome/google_search_logo.png" />\n')
-    grdp_file.write('  </if>\n')
-
-    # Add the remaining resource ids.
-    for engine_keyword, icon_name in engine_keyword_to_icon_name.items():
-      resource_id = 'IDR_' + keyword_to_identifer(
-          engine_keyword).upper() + '_PNG'
-      grdp_file.write('  <structure type="chrome_scaled_image" name="' +
-                      resource_id + '" file="search_engine_choice/' +
-                      icon_name + '.png" />\n')
-
-    grdp_file.write('</grit-part>\n')
-
-
-def generate_icon_path_map():
+def generate_icon_path_map(output_filename, engine_keywords):
   """Generates the `kSearchEngineIconPathMap` map.
 
   The code is generated in `search_engine_choice/generated_icon_utils-inc.cc`.
   """
-  print('Creating `kSearchEngineIconPathMap`...')
-
-  with open(
-      '../../chrome/browser/ui/webui/search_engine_choice/generated_icon_utils-inc.cc',
-      'w',
-      encoding='utf-8',
-      newline='') as utils_file:
-
-    # Add the copyright notice.
-    utils_file.write('// Copyright 2023 The Chromium Authors\n')
-    utils_file.write('// Use of this source code is governed by a BSD-style'
-                     ' license that can be\n')
-    utils_file.write('// found in the LICENSE file.\n\n')
-
-    utils_file.write(
-        ("// This code is generated using"
-         "`tools/search_engine_choice/generate_search_engine_icons.py`."
-         " Don't modify it manually.\n\n"))
-
+  with open(output_filename, 'w', encoding='utf-8', newline='') as utils_file:
     utils_file.write('constexpr auto kSearchEngineIconPathMap =\n')
     utils_file.write(
         '\tbase::MakeFixedFlatMap<std::u16string_view, std::string_view>({\n')
 
-    for engine_keyword in engine_keyword_to_icon_name:
-      engine_name = keyword_to_identifer(engine_keyword)
-      utils_file.write('\t\t{u"' + engine_keyword + '",\n')
-      utils_file.write('\t\t "chrome://theme/IDR_' + engine_name.upper() +
-                       '_PNG"},\n')
+    for engine_keyword in engine_keywords:
+      resource_name = search_engine_icons_utils.keyword_to_resource_name(
+          engine_keyword)
+      utils_file.write('\t\t{')
+      utils_file.write(f'u"{engine_keyword}", "chrome://theme/{resource_name}"')
+      utils_file.write('},\n')
 
     # Add Google to the map
     utils_file.write('\t\t{u"google.com",\n')
@@ -283,37 +34,22 @@
     utils_file.write('\t}});\n')
 
 
-def generate_icon_resource_id_map():
+def generate_icon_resource_id_map(output_filename, engine_keywords):
   """Generates the `kSearchEngineResourceIdMap` map.
 
   The code is generated in
   `components/search_engines/generated_search_engine_resource_ids-inc.cc`.
   """
-  print('Creating `kSearchEngineResourceIdMap`...')
-
-  with open(
-      '../../components/search_engines/generated_search_engine_resource_ids-inc.cc',
-      'w',
-      encoding='utf-8',
-      newline='') as utils_file:
-
-    # Add the copyright notice.
-    utils_file.write('// Copyright 2023 The Chromium Authors\n')
-    utils_file.write('// Use of this source code is governed by a BSD-style'
-                     ' license that can be\n')
-    utils_file.write('// found in the LICENSE file.\n\n')
-    utils_file.write(
-        ("// This code is generated using"
-         "`tools/search_engine_choice/generate_search_engine_icons.py`."
-         " Don't modify it manually.\n\n"))
-
+  with open(output_filename, 'w', encoding='utf-8', newline='') as utils_file:
     utils_file.write('constexpr auto kSearchEngineResourceIdMap =\n')
     utils_file.write('\tbase::MakeFixedFlatMap<std::u16string_view, int>({\n')
 
-    for engine_keyword in engine_keyword_to_icon_name:
-      engine_name = keyword_to_identifer(engine_keyword)
-      utils_file.write('\t\t{u"' + engine_keyword + '",\n')
-      utils_file.write('\t\t IDR_' + engine_name.upper() + '_PNG},\n')
+    for engine_keyword in engine_keywords:
+      resource_name = search_engine_icons_utils.keyword_to_resource_name(
+          engine_keyword)
+      utils_file.write('\t\t{')
+      utils_file.write(f'u"{engine_keyword}", {resource_name}')
+      utils_file.write('},\n')
 
     # Add Google to the map
     utils_file.write('\t\t{u"google.com",\n')
@@ -325,36 +61,16 @@
     utils_file.write('\t}});\n\n')
 
 
-if sys.platform != 'linux':
-  print(
-      'Warning: This script has not been tested outside of the Linux platform')
+if len(sys.argv) >= 3:
+  src_dir = sys.argv[1]
+  generated_search_engine_resource_ids_file = sys.argv[2]
+  generated_icon_utils_file = sys.argv[3]
 
-current_file_path = os.path.dirname(__file__)
-os.chdir(current_file_path)
-
-sys.path.insert(0,
-                os.path.normpath(current_file_path + "/../json_comment_eater"))
-try:
-  import json_comment_eater
-finally:
-  sys.path.pop(0)
-
-# Move to working directory to `src/components/resources/`.
-os.chdir('../../components/resources')
-
-# A set of search engines that are used in `template_url_prepopulate_data.cc`
-used_engines = set()
-
-# This is a dictionary of engine keyword to corresponding icon name. Have an
-# empty icon name would mean that we weren't able to download the favicon for
-# that engine.
-engine_keyword_to_icon_name = {}
-
-populate_used_engines()
-download_icons_from_android_search()
-generate_icon_resource_code()
-generate_icon_path_map()
-generate_icon_resource_id_map()
-# Format the generated code
-os.system('git cl format')
-print('Icon and code generation completed.')
+engine_keywords = {
+    keyword
+    for (engine, keyword
+         ) in search_engine_icons_utils.get_used_engines_with_keywords(src_dir)
+}
+generate_icon_path_map(generated_icon_utils_file, engine_keywords)
+generate_icon_resource_id_map(generated_search_engine_resource_ids_file,
+                              engine_keywords)
diff --git a/tools/search_engine_choice/search_engine_icons_utils.py b/tools/search_engine_choice/search_engine_icons_utils.py
new file mode 100644
index 0000000..a09a604
--- /dev/null
+++ b/tools/search_engine_choice/search_engine_icons_utils.py
@@ -0,0 +1,92 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import re
+import sys
+
+config_file_path = 'tools/search_engine_choice/generate_search_engine_icons_config.json'
+prepopulated_data_src_path = 'components/search_engines/template_url_prepopulate_data.cc'
+prepopulated_engines_file_path = 'components/search_engines/prepopulated_engines.json'
+
+
+def keyword_to_identifer(keyword):
+  """Sanitized keyword to be used as identifier.
+
+  Replaces characters we find in prepopulates_engines.json's keyword field into
+  ones that are valid in file names and variable names.
+
+  Args:
+    keyword: the keyword string as in the json file.
+
+  Returns:
+    The keyword string with characters replaced that don't work in a variable or
+    file name.
+  """
+  return keyword.replace('.', '_').replace('-', '_')
+
+
+def keyword_to_resource_name(keyword):
+  """Resource name associated with a search engine keyword.
+
+  Args:
+    keyword: the keyword string as in the json file.
+
+  Returns:
+    The resource name for the icon, e.g. IDR_GOOGLE_COM_PNG.
+  """
+  icon_filename = keyword_to_identifer(keyword)
+  return 'IDR_' + icon_filename.upper() + '_PNG'
+
+
+def get_used_engines(src_dir):
+  """Returns the set of used engines.
+
+  Returns the set of used engines. by checking which engines are used in
+  `template_url_prepopulate_data.cc`.
+  """
+  print('Populating used engines set')
+  used_engines = set()
+  SE_NAME_REGEX = re.compile(r'.*SearchEngineTier::[A-Za-z]+, &(.+)},')
+  with open(src_dir + config_file_path, 'r',
+            encoding='utf-8') as config_json, open(src_dir +
+                                                   prepopulated_data_src_path,
+                                                   'r',
+                                                   encoding='utf-8') as file:
+    config_data = json.loads(json_comment_eater.Nom(config_json.read()))
+    lines = file.readlines()
+    for line in lines:
+      match = SE_NAME_REGEX.match(line)
+      if match:
+        engine = match.group(1)
+        if not engine in config_data['ignored_engines']:
+          used_engines.add(engine)
+  return used_engines
+
+
+def get_used_engines_with_keywords(src_dir):
+  """Returns the set of used engines with their keyword.
+
+  Reads the keyword from `components/search_engines/prepopulated_engines.json`.
+  Returns a set of pairs (engine, keyword).
+  """
+  used_engines_with_keywords = set()
+  with open(src_dir + prepopulated_engines_file_path, 'r',
+            encoding='utf-8') as engines_json:
+    engine_data = json.loads(json_comment_eater.Nom(engines_json.read()))
+    used_engines = get_used_engines(src_dir)
+    for used_engine in used_engines:
+      used_engines_with_keywords.add(
+          (used_engine, engine_data['elements'][used_engine]['keyword']))
+  return used_engines_with_keywords
+
+
+current_file_path = os.path.dirname(__file__)
+sys.path.insert(0,
+                os.path.normpath(current_file_path + "/../json_comment_eater"))
+try:
+  import json_comment_eater
+finally:
+  sys.path.pop(0)