Reland "Unified Side Panel: Add image search key/value to json struct."

This reverts commit eb9de038b9d60fd365329bb1480cd2b2e115fae0.

Reason for revert: Fixing the broken UT's

Original change's description:
> Revert "Unified Side Panel: Add image search key/value to json struct."
>
> This reverts commit dec15ed8f48265ad21bbd4ec4463a5e4c3372345.
>
> Reason for revert: breaks on linux-chromeos-chrome, see https://ci.chromium.org/ui/p/chrome/builders/ci/linux-chromeos-chrome/24737/overview
>
> Original change's description:
> > Unified Side Panel: Add image search key/value to json struct.
> >
> > Added a new image search param to the json file and will use that to direct image search and region search requests to the unified side panel for search engines.
> >
> > Design Doc: go/unified-side-panel-non-google-dse
> >
> > - Direct 3P DSE requests to side panel only if the image search param exists and the unified side panel is turned on.
> > - If the unified side panel flag is turned off, the 3P DSE requests are redirected to a new tab.
> > - For lens requests, standardize the way rendering env variable query param gets added.
> > - Use default vector image search icon for the 3P DSE's.
> > - Changing Search Engine when side panel is opened closes side panel and  de-registers lens.
> >
> > For testing purposes, enabled side panel for Bing search engine and here are the demos:
> >
> > Region Search: https://drive.google.com/file/d/1wKde02oZL6EeFCJYwdPLfKo_p9qST-mE/view
> >
> > Image Search: https://drive.google.com/file/d/116hIj5fWda_hKZ_2VHa-L50gNWMsjAg9/view
> >
> > Changing Search Engine: https://drive.google.com/file/d/1lgO7yUV-pA6jpSXH6gZdFVT7-vGfqXh3/view
> >
> > NOTE: The existing browser tests for the lens unified side panel are broken, so did not add new browser tests for 3P DSE's, we will add them when fixing the browser tests in b/242909164.
> >
> > Bug: b/226186680
> > Change-Id: I268eb7d673e02d6a0a77838280f1c7014367f314
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3866097
> > Commit-Queue: Anudeep Palanki <[email protected]>
> > Reviewed-by: Ali Stanfield <[email protected]>
> > Reviewed-by: Evan Stade <[email protected]>
> > Reviewed-by: Orin Jaworski <[email protected]>
> > Reviewed-by: Avi Drissman <[email protected]>
> > Cr-Commit-Position: refs/heads/main@{#1045182}
>
> Bug: b/226186680
> Change-Id: I2bb922204f51bdb012eb6c0be120f76e1029e8c2
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3887281
> Owners-Override: Dominique Fauteux-Chapleau <[email protected]>
> Bot-Commit: Rubber Stamper <[email protected]>
> Commit-Queue: Dominique Fauteux-Chapleau <[email protected]>
> Auto-Submit: Dominique Fauteux-Chapleau <[email protected]>
> Commit-Queue: Rubber Stamper <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1045241}

Bug: b/226186680
Change-Id: I06106a90ce6fe289c6b87c004acea1c44f6fcf15
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3887228
Reviewed-by: Evan Stade <[email protected]>
Commit-Queue: Anudeep Palanki <[email protected]>
Reviewed-by: Orin Jaworski <[email protected]>
Reviewed-by: Ali Stanfield <[email protected]>
Reviewed-by: Avi Drissman <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1046528}
diff --git a/chrome/browser/android/context_menu/context_menu_native_delegate_impl.cc b/chrome/browser/android/context_menu/context_menu_native_delegate_impl.cc
index e91c457..bf5e49a 100644
--- a/chrome/browser/android/context_menu/context_menu_native_delegate_impl.cc
+++ b/chrome/browser/android/context_menu/context_menu_native_delegate_impl.cc
@@ -124,7 +124,7 @@
     return;
 
   CoreTabHelper::FromWebContents(web_contents_)
-      ->SearchByImageInNewTab(render_frame_host, context_menu_params_->src_url);
+      ->SearchByImage(render_frame_host, context_menu_params_->src_url);
 }
 
 void ContextMenuNativeDelegateImpl::RetrieveImageForShare(
diff --git a/chrome/browser/lens/region_search/lens_region_search_controller.cc b/chrome/browser/lens/region_search/lens_region_search_controller.cc
index 8cdf58e..55dd1e06 100644
--- a/chrome/browser/lens/region_search/lens_region_search_controller.cc
+++ b/chrome/browser/lens/region_search/lens_region_search_controller.cc
@@ -196,23 +196,13 @@
         lens::features::IsLensFullscreenSearchEnabled()
             ? lens::EntryPoint::CHROME_FULLSCREEN_SEARCH_MENU_ITEM
             : lens::EntryPoint::CHROME_REGION_SEARCH_MENU_ITEM;
-    lens::RenderingEnvironment rendering_environment =
-        lens::features::IsLensFullscreenSearchEnabled()
-            ? lens::RenderingEnvironment::
-                  ONELENS_AMBIENT_VISUAL_SEARCH_WEB_FULLSCREEN
-            : (lens::features::IsLensSidePanelEnabled()
-                   ? lens::RenderingEnvironment::
-                         ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL
-                   : lens::RenderingEnvironment::
-                         ONELENS_DESKTOP_WEB_FULLSCREEN);
-
-    bool use_side_panel = lens::features::IsLensSidePanelEnabled() &&
-                          !lens::features::IsLensFullscreenSearchEnabled();
-    core_tab_helper->SearchWithLensInNewTab(image, captured_image.Size(),
-                                            entry_point, rendering_environment,
-                                            use_side_panel);
+    core_tab_helper->SearchWithLens(
+        image, captured_image.Size(), entry_point,
+        /* is_region_search_request= */ true,
+        /* is_side_panel_enabled_for_feature= */
+        lens::features::IsLensSidePanelEnabledForRegionSearch());
   } else {
-    core_tab_helper->SearchByImageInNewTab(image, captured_image.Size());
+    core_tab_helper->SearchByImage(image, captured_image.Size());
   }
 
   RecordCaptureResult(lens::LensRegionSearchCaptureResult::SUCCESS);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 63ebaff..ec0ec68 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -3578,13 +3578,10 @@
   RenderFrameHost* render_frame_host = GetRenderFrameHost();
   if (!render_frame_host)
     return;
-
-  core_tab_helper->SearchWithLensInNewTab(
+  core_tab_helper->SearchWithLens(
       render_frame_host, params().src_url,
       lens::EntryPoint::CHROME_SEARCH_WITH_GOOGLE_LENS_CONTEXT_MENU_ITEM,
-      lens::features::IsLensSidePanelEnabled()
-          ? lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL
-          : lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN,
+      /* is_side_panel_enabled_for_feature= */
       lens::features::IsLensSidePanelEnabled());
 }
 
@@ -3650,7 +3647,7 @@
   RenderFrameHost* render_frame_host = GetRenderFrameHost();
   if (!render_frame_host)
     return;
-  core_tab_helper->SearchByImageInNewTab(render_frame_host, params().src_url);
+  core_tab_helper->SearchByImage(render_frame_host, params().src_url);
 }
 
 void RenderViewContextMenu::ExecLoadImage() {
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index dc5911c..99a6ce0 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -1813,6 +1813,7 @@
     data.SetURL(GetNonGoogleRegionSearchURL().spec());
     data.image_url = GetNonGoogleRegionSearchURL().spec();
     data.image_url_post_params = kRegionSearchPostParams;
+    data.side_image_search_param = "sideimagesearch";
 
     TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
     ASSERT_TRUE(template_url);
@@ -1946,10 +1947,10 @@
     // Match strings up to the query.
     std::size_t query_start_pos = side_panel_content.find("?");
     // Match the query parameters, without the value of start_time.
-    EXPECT_THAT(
-        side_panel_content,
-        testing::MatchesRegex(expected_content.substr(0, query_start_pos) +
-                              ".*ep=crs&re=dcsp&s=csp&st=\\d+"));
+    EXPECT_THAT(side_panel_content,
+                testing::MatchesRegex(
+                    expected_content.substr(0, query_start_pos) +
+                    ".*ep=crs&re=dcsp&s=csp&st=\\d+&sideimagesearch=1"));
     quit_closure_.Run();
   }
 
@@ -2055,8 +2056,8 @@
 #endif
 IN_PROC_BROWSER_TEST_F(SearchByRegionWithUnifiedSidePanelBrowserTest,
                        MAYBE_LensRegionSearchWithValidRegionUnifiedSidePanel) {
-  lens::CreateLensUnifiedSidePanelEntryForTesting(browser());
   SetupAndLoadPage("/empty.html");
+  lens::CreateLensUnifiedSidePanelEntryForTesting(browser());
   // We need a base::RunLoop to ensure that our test does not finish until the
   // side panel has opened and we have verified the URL.
   base::RunLoop loop;
@@ -2142,6 +2143,7 @@
     static const char kSearchURL[] = "/search?q={searchTerms}";
     static const char kImageSearchPostParams[] =
         "thumb={google:imageThumbnail}";
+    static const char kSideImageSearchParam[] = "sideimagesearch";
 
     TemplateURLService* model =
         TemplateURLServiceFactory::GetForProfile(browser()->profile());
@@ -2155,6 +2157,7 @@
     data.SetURL(embedded_test_server()->GetURL(kSearchURL).spec());
     data.image_url = GetImageSearchURL().spec();
     data.image_url_post_params = kImageSearchPostParams;
+    data.side_image_search_param = kSideImageSearchParam;
 
     TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
     ASSERT_TRUE(template_url);
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc
index 114f023..08a26ed 100644
--- a/chrome/browser/ui/tab_contents/core_tab_helper.cc
+++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser_command_controller.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "chrome/common/chrome_render_frame.mojom.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/grit/generated_resources.h"
@@ -61,10 +62,10 @@
 
 namespace {
 
-const int kImageSearchThumbnailMinSize = 300 * 300;
-const int kImageSearchThumbnailMaxWidth = 600;
-const int kImageSearchThumbnailMaxHeight = 600;
-
+constexpr int kImageSearchThumbnailMinSize = 300 * 300;
+constexpr int kImageSearchThumbnailMaxWidth = 600;
+constexpr int kImageSearchThumbnailMaxHeight = 600;
+constexpr char kUnifiedSidePanelVersion[] = "1";
 }  // namespace
 
 CoreTabHelper::CoreTabHelper(WebContents* web_contents)
@@ -94,62 +95,81 @@
 #endif
 }
 
-void CoreTabHelper::SearchWithLensInNewTab(
-    content::RenderFrameHost* render_frame_host,
-    const GURL& src_url,
-    lens::EntryPoint entry_point,
-    lens::RenderingEnvironment rendering_environment,
-    bool use_side_panel) {
-  SearchByImageInNewTabImpl(
-      render_frame_host, src_url, kImageSearchThumbnailMinSize,
-      lens::features::GetMaxPixelsForImageSearch(),
-      lens::features::GetMaxPixelsForImageSearch(),
-      lens::GetQueryParametersForLensRequest(entry_point, rendering_environment,
-                                             use_side_panel),
-      use_side_panel);
+void CoreTabHelper::SearchWithLens(content::RenderFrameHost* render_frame_host,
+                                   const GURL& src_url,
+                                   lens::EntryPoint entry_point,
+                                   bool is_side_panel_enabled_for_feature) {
+  bool use_side_panel =
+      is_side_panel_enabled_for_feature &&
+      GetTemplateURLService()
+          ->IsSideImageSearchSupportedForDefaultSearchProvider();
+
+  SearchByImageImpl(render_frame_host, src_url, kImageSearchThumbnailMinSize,
+                    lens::features::GetMaxPixelsForImageSearch(),
+                    lens::features::GetMaxPixelsForImageSearch(),
+                    lens::GetQueryParametersForLensRequest(
+                        entry_point, use_side_panel,
+                        /** is_full_screen_region_search_request **/ false),
+                    use_side_panel);
 }
 
-void CoreTabHelper::SearchWithLensInNewTab(
-    gfx::Image image,
-    const gfx::Size& image_original_size,
-    lens::EntryPoint entry_point,
-    lens::RenderingEnvironment rendering_environment,
-    bool use_side_panel) {
-  SearchByImageInNewTabImpl(
-      image, image_original_size,
-      lens::GetQueryParametersForLensRequest(entry_point, rendering_environment,
-                                             use_side_panel),
-      use_side_panel);
+TemplateURLService* CoreTabHelper::GetTemplateURLService() {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+  DCHECK(profile);
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile);
+  DCHECK(template_url_service);
+  return template_url_service;
 }
 
-void CoreTabHelper::SearchByImageInNewTab(
-    content::RenderFrameHost* render_frame_host,
-    const GURL& src_url) {
-  SearchByImageInNewTabImpl(
-      render_frame_host, src_url, kImageSearchThumbnailMinSize,
-      kImageSearchThumbnailMaxWidth, kImageSearchThumbnailMaxHeight,
-      std::string(), /*use_side_panel=*/false);
+bool CoreTabHelper::IsSidePanelEnabledFor3PDse() {
+  return GetTemplateURLService()
+             ->IsSideImageSearchSupportedForDefaultSearchProvider() &&
+         base::FeatureList::IsEnabled(features::kUnifiedSidePanel);
 }
 
-void CoreTabHelper::SearchByImageInNewTab(
-    const gfx::Image& image,
-    const gfx::Size& image_original_size) {
-  SearchByImageInNewTabImpl(image, image_original_size,
-                            /*additional_query_params=*/std::string(),
-                            /*use_side_panel=*/false);
+void CoreTabHelper::SearchWithLens(gfx::Image image,
+                                   const gfx::Size& image_original_size,
+                                   lens::EntryPoint entry_point,
+                                   bool is_region_search_request,
+                                   bool is_side_panel_enabled_for_feature) {
+  bool use_side_panel =
+      is_side_panel_enabled_for_feature &&
+      GetTemplateURLService()
+          ->IsSideImageSearchSupportedForDefaultSearchProvider();
+  bool is_full_screen_region_search_request =
+      is_region_search_request &&
+      lens::features::IsLensFullscreenSearchEnabled();
+  auto lens_query_params = lens::GetQueryParametersForLensRequest(
+      entry_point, use_side_panel,
+      /* is_full_screen_region_search_request= */
+      is_full_screen_region_search_request);
+  SearchByImageImpl(image, image_original_size, lens_query_params,
+                    use_side_panel);
 }
 
-void CoreTabHelper::SearchByImageInNewTabImpl(
+void CoreTabHelper::SearchByImage(content::RenderFrameHost* render_frame_host,
+                                  const GURL& src_url) {
+  SearchByImageImpl(render_frame_host, src_url, kImageSearchThumbnailMinSize,
+                    kImageSearchThumbnailMaxWidth,
+                    kImageSearchThumbnailMaxHeight, std::string(),
+                    IsSidePanelEnabledFor3PDse());
+}
+
+void CoreTabHelper::SearchByImage(const gfx::Image& image,
+                                  const gfx::Size& image_original_size) {
+  SearchByImageImpl(image, image_original_size,
+                    /*additional_query_params=*/std::string(),
+                    IsSidePanelEnabledFor3PDse());
+}
+
+void CoreTabHelper::SearchByImageImpl(
     const gfx::Image& image,
     const gfx::Size& image_original_size,
     const std::string& additional_query_params,
     bool use_side_panel) {
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-
-  TemplateURLService* template_url_service =
-      TemplateURLServiceFactory::GetForProfile(profile);
-  DCHECK(template_url_service);
+  TemplateURLService* template_url_service = GetTemplateURLService();
   const TemplateURL* const default_provider =
       template_url_service->GetDefaultSearchProvider();
   DCHECK(default_provider);
@@ -171,10 +191,15 @@
   TemplateURLRef::PostContent post_content;
   GURL search_url(default_provider->image_url_ref().ReplaceSearchTerms(
       search_args, template_url_service->search_terms_data(), &post_content));
+  if (use_side_panel) {
+    search_url = template_url_service
+                     ->GenerateSideImageSearchURLForDefaultSearchProvider(
+                         search_url, kUnifiedSidePanelVersion);
+  }
   PostContentToURL(post_content, search_url, use_side_panel);
 }
 
-void CoreTabHelper::SearchByImageInNewTabImpl(
+void CoreTabHelper::SearchByImageImpl(
     content::RenderFrameHost* render_frame_host,
     const GURL& src_url,
     int thumbnail_min_size,
@@ -192,7 +217,7 @@
       thumbnail_min_size, gfx::Size(thumbnail_max_width, thumbnail_max_height),
       lens::features::GetSendImagesAsPng() ? chrome::mojom::ImageFormat::PNG
                                            : chrome::mojom::ImageFormat::JPEG,
-      base::BindOnce(&CoreTabHelper::DoSearchByImageInNewTab,
+      base::BindOnce(&CoreTabHelper::DoSearchByImage,
                      weak_factory_.GetWeakPtr(), std::move(chrome_render_frame),
                      src_url, additional_query_params, use_side_panel));
 }
@@ -359,7 +384,7 @@
 
 // Handles the image thumbnail for the context node, composes a image search
 // request based on the received thumbnail and opens the request in a new tab.
-void CoreTabHelper::DoSearchByImageInNewTab(
+void CoreTabHelper::DoSearchByImage(
     mojo::AssociatedRemote<chrome::mojom::ChromeRenderFrame>
         chrome_render_frame,
     const GURL& src_url,
@@ -379,12 +404,7 @@
                                std::move(log_data));
   }
 
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-
-  TemplateURLService* template_url_service =
-      TemplateURLServiceFactory::GetForProfile(profile);
-  DCHECK(template_url_service);
+  TemplateURLService* template_url_service = GetTemplateURLService();
   const TemplateURL* const default_provider =
       template_url_service->GetDefaultSearchProvider();
   DCHECK(default_provider);
@@ -399,6 +419,11 @@
   TemplateURLRef::PostContent post_content;
   GURL search_url(default_provider->image_url_ref().ReplaceSearchTerms(
       search_args, template_url_service->search_terms_data(), &post_content));
+  if (use_side_panel) {
+    search_url = template_url_service
+                     ->GenerateSideImageSearchURLForDefaultSearchProvider(
+                         search_url, kUnifiedSidePanelVersion);
+  }
   PostContentToURL(post_content, search_url, use_side_panel);
 }
 
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.h b/chrome/browser/ui/tab_contents/core_tab_helper.h
index bcf7e4e..8050a9d0 100644
--- a/chrome/browser/ui/tab_contents/core_tab_helper.h
+++ b/chrome/browser/ui/tab_contents/core_tab_helper.h
@@ -14,6 +14,7 @@
 #include "components/lens/lens_entrypoints.h"
 #include "components/lens/lens_rendering_environment.h"
 #include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_service.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -39,34 +40,38 @@
   void UpdateContentRestrictions(int content_restrictions);
 
   // Open the Lens standalone experience for the image that triggered the
-  // context menu. If |use_side_panel| is true, the page will be opened in a
-  // side panel rather than a new tab.
-  void SearchWithLensInNewTab(content::RenderFrameHost* render_frame_host,
-                              const GURL& src_url,
-                              lens::EntryPoint entry_point,
-                              lens::RenderingEnvironment rendering_environment,
-                              bool use_side_panel);
+  // context menu. If |is_side_panel_enabled_for_feature| is true and if the
+  // google lens supports opening requests in side panel, then the request will
+  // open in the side panel instead of new tab.
+  void SearchWithLens(content::RenderFrameHost* render_frame_host,
+                      const GURL& src_url,
+                      lens::EntryPoint entry_point,
+                      bool is_side_panel_enabled_for_feature);
 
   // Open the Lens experience for an image. Used for sending the bitmap selected
   // via Lens Region Search. |image_original_size| is specified in case of
-  // resizing that happens prior to passing the image to CoreTabHelper. If
-  // |use_side_panel| is true, the page will be opened in a side panel rather
-  // than a new tab.
-  void SearchWithLensInNewTab(gfx::Image image,
-                              const gfx::Size& image_original_size,
-                              lens::EntryPoint entry_point,
-                              lens::RenderingEnvironment rendering_environment,
-                              bool use_side_panel);
+  // resizing that happens prior to passing the image to |CoreTabHelper|. If
+  // |is_side_panel_enabled_for_feature| is true and if the search engine
+  // supports opening requests in side panel, then the request will open in the
+  // side panel instead of a new tab.
+  void SearchWithLens(gfx::Image image,
+                      const gfx::Size& image_original_size,
+                      lens::EntryPoint entry_point,
+                      bool is_region_search_request,
+                      bool is_side_panel_enabled_for_feature);
 
   // Perform an image search for the image that triggered the context menu.  The
   // |src_url| is passed to the search request and is not used directly to fetch
-  // the image resources.
-  void SearchByImageInNewTab(content::RenderFrameHost* render_frame_host,
-                             const GURL& src_url);
+  // the image resources. If the search engine supports opening requests in side
+  // panel, then the request will open in the side panel instead of a new tab.
+  void SearchByImage(content::RenderFrameHost* render_frame_host,
+                     const GURL& src_url);
 
-  // Performs an image search for the provided image.
-  void SearchByImageInNewTab(const gfx::Image& image,
-                             const gfx::Size& image_original_size);
+  // Performs an image search for the provided image. If the search engine
+  // supports opening requests in side panel, then the request will open in side
+  // panel instead of a new tab.
+  void SearchByImage(const gfx::Image& image,
+                     const gfx::Size& image_original_size);
 
   void set_new_tab_start_time(const base::TimeTicks& time) {
     new_tab_start_time_ = time;
@@ -94,7 +99,7 @@
   void OnWebContentsFocused(content::RenderWidgetHost*) override;
   void OnWebContentsLostFocus(content::RenderWidgetHost*) override;
 
-  void DoSearchByImageInNewTab(
+  void DoSearchByImage(
       mojo::AssociatedRemote<chrome::mojom::ChromeRenderFrame>
           chrome_render_frame,
       const GURL& src_url,
@@ -105,6 +110,13 @@
       const std::string& image_extension,
       const std::vector<lens::mojom::LatencyLogPtr> latency_logs);
 
+  // Wrapper method for fetching template URL service.
+  TemplateURLService* GetTemplateURLService();
+
+  // Helper function to check if the side panel is enabled for third party
+  // default search engines (3PDSE).
+  bool IsSidePanelEnabledFor3PDse();
+
   // Posts the bytes and content type to the specified URL If |use_side_panel|
   // is true, the content will open in a side panel, otherwise it will open in
   // a new tab.
@@ -117,17 +129,17 @@
   // not used directly to fetch the image resources. The
   // |additional_query_params| are also passed to the search request as part of
   // search args.
-  void SearchByImageInNewTabImpl(content::RenderFrameHost* render_frame_host,
-                                 const GURL& src_url,
-                                 int thumbnail_min_size,
-                                 int thumbnail_max_width,
-                                 int thumbnail_max_height,
-                                 const std::string& additional_query_params,
-                                 bool use_side_panel);
-  void SearchByImageInNewTabImpl(const gfx::Image& image,
-                                 const gfx::Size& image_original_size,
-                                 const std::string& additional_query_params,
-                                 bool use_side_panel);
+  void SearchByImageImpl(content::RenderFrameHost* render_frame_host,
+                         const GURL& src_url,
+                         int thumbnail_min_size,
+                         int thumbnail_max_width,
+                         int thumbnail_max_height,
+                         const std::string& additional_query_params,
+                         bool use_side_panel);
+  void SearchByImageImpl(const gfx::Image& image,
+                         const gfx::Size& image_original_size,
+                         const std::string& additional_query_params,
+                         bool use_side_panel);
 
   // The time when we started to create the new tab page.  This time is from
   // before we created this WebContents.
diff --git a/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc b/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc
index 5f2b572..c7d879e 100644
--- a/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc
+++ b/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc
@@ -337,13 +337,11 @@
   set_close_on_deactivate(!lens::features::EnablePersistentBubble());
 
   CoreTabHelper::FromWebContents(web_contents_.get())
-      ->SearchWithLensInNewTab(
-          image_, GetImageSize(), lens::EntryPoint::CHROME_SCREENSHOT_SEARCH,
-          lens::features::UseSidePanelForScreenshotSharing()
-              ? lens::RenderingEnvironment::
-                    ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL
-              : lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN,
-          lens::features::UseSidePanelForScreenshotSharing());
+      ->SearchWithLens(image_, GetImageSize(),
+                       lens::EntryPoint::CHROME_SCREENSHOT_SEARCH,
+                       /* is_region_search_request= */ false,
+                       /* is_side_panel_enabled_for_feature= */
+                       lens::features::UseSidePanelForScreenshotSharing());
 
   // Need to manually close the screenshot bubble if side panel is enabled
   if (lens::features::UseSidePanelForScreenshotSharing() &&
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.cc
index 2a6855a..88843a7 100644
--- a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.cc
@@ -9,6 +9,9 @@
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/scoped_observation.h"
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.h"
@@ -18,6 +21,9 @@
 #include "chrome/browser/ui/views/side_panel/side_panel_registry.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/omnibox/browser/vector_icons.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/search_engines/util.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/vector_icons.h"
@@ -27,6 +33,12 @@
   GetBrowserView()->side_panel_coordinator()->AddSidePanelViewStateObserver(
       this);
   lens_side_panel_view_ = nullptr;
+
+  auto* profile = GetBrowserView()->GetProfile();
+  template_url_service_ = TemplateURLServiceFactory::GetForProfile(profile);
+
+  if (template_url_service_ != nullptr)
+    template_url_service_->AddObserver(this);
 }
 
 BrowserView* LensSidePanelCoordinator::GetBrowserView() {
@@ -39,18 +51,34 @@
         ->side_panel_coordinator()
         ->RemoveSidePanelViewStateObserver(this);
   }
+
+  if (template_url_service_ != nullptr)
+    template_url_service_->RemoveObserver(this);
 }
 
-void LensSidePanelCoordinator::OnSidePanelDidClose() {
+void LensSidePanelCoordinator::DeregisterLensFromSidePanel() {
   lens_side_panel_view_ = nullptr;
   GetBrowserView()
       ->side_panel_coordinator()
       ->GetGlobalSidePanelRegistry()
       ->Deregister(SidePanelEntry::Key(SidePanelEntry::Id::kLens));
+}
+
+void LensSidePanelCoordinator::OnSidePanelDidClose() {
+  DeregisterLensFromSidePanel();
   base::RecordAction(
       base::UserMetricsAction("LensUnifiedSidePanel.HideSidePanel"));
 }
 
+void LensSidePanelCoordinator::OnTemplateURLServiceChanged() {
+  // When search engine changes, remove lens from the side panel to avoid
+  // a potentially mismatched state between the combo box label and lens side
+  // panel content.
+  DeregisterLensFromSidePanel();
+  base::RecordAction(base::UserMetricsAction(
+      "LensUnifiedSidePanel.RemoveLensEntry_SearchEngineChanged"));
+}
+
 void LensSidePanelCoordinator::OnEntryShown(SidePanelEntry* entry) {
   base::RecordAction(
       base::UserMetricsAction("LensUnifiedSidePanel.LensEntryShown"));
@@ -66,6 +94,26 @@
   return lens_side_panel_view_->IsLaunchButtonEnabledForTesting();
 }
 
+bool LensSidePanelCoordinator::IsDefaultSearchProviderGoogle() {
+  auto* profile = GetBrowserView()->GetProfile();
+  return search::DefaultSearchProviderIsGoogle(profile);
+}
+
+std::u16string LensSidePanelCoordinator::GetComboboxLabel() {
+  if (IsDefaultSearchProviderGoogle())
+    return l10n_util::GetStringUTF16(
+        IDS_SIDE_PANEL_COMBO_BOX_GOOGLE_LENS_LABEL);
+
+  return GetDefaultSearchEngineName(template_url_service_);
+}
+
+const gfx::VectorIcon& LensSidePanelCoordinator::GetComboboxIcon() {
+  if (IsDefaultSearchProviderGoogle())
+    return vector_icons::kGoogleLensLogoIcon;
+
+  return vector_icons::kImageSearchIcon;
+}
+
 void LensSidePanelCoordinator::RegisterEntryAndShow(
     const content::OpenURLParams& params) {
   base::RecordAction(base::UserMetricsAction("LensUnifiedSidePanel.LensQuery"));
@@ -84,10 +132,8 @@
     base::RecordAction(
         base::UserMetricsAction("LensUnifiedSidePanel.LensQuery_New"));
     auto entry = std::make_unique<SidePanelEntry>(
-        SidePanelEntry::Id::kLens,
-        l10n_util::GetStringUTF16(IDS_SIDE_PANEL_COMBO_BOX_GOOGLE_LENS_LABEL),
-        ui::ImageModel::FromVectorIcon(vector_icons::kGoogleLensLogoIcon,
-                                       ui::kColorIcon),
+        SidePanelEntry::Id::kLens, GetComboboxLabel(),
+        ui::ImageModel::FromVectorIcon(GetComboboxIcon(), ui::kColorIcon),
         base::BindRepeating(&LensSidePanelCoordinator::CreateLensWebView,
                             base::Unretained(this), params));
     entry->AddObserver(this);
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.h b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.h
index a0b405b..44b933b 100644
--- a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.h
+++ b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_entry_observer.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_view_state_observer.h"
+#include "components/search_engines/template_url_service_observer.h"
 
 class Browser;
 
@@ -21,7 +22,8 @@
 class LensSidePanelCoordinator
     : public BrowserUserData<LensSidePanelCoordinator>,
       public SidePanelViewStateObserver,
-      public SidePanelEntryObserver {
+      public SidePanelEntryObserver,
+      public TemplateURLServiceObserver {
  public:
   explicit LensSidePanelCoordinator(Browser* browser);
   LensSidePanelCoordinator(const LensSidePanelCoordinator&) = delete;
@@ -45,14 +47,27 @@
   void OnEntryShown(SidePanelEntry* entry) override;
   void OnEntryHidden(SidePanelEntry* entry) override;
 
+  bool IsDefaultSearchProviderGoogle();
+
+  std::u16string GetComboboxLabel();
+
+  const gfx::VectorIcon& GetComboboxIcon();
+
   BrowserView* GetBrowserView();
 
+  // Removes the lens entry from the side panel.
+  void DeregisterLensFromSidePanel();
+
+  // TemplateURLServiceObserver
+  void OnTemplateURLServiceChanged() override;
+
   // SidePanelViewStateObserver
   void OnSidePanelDidClose() override;
 
   std::unique_ptr<views::View> CreateLensWebView(
       const content::OpenURLParams& params);
 
+  raw_ptr<TemplateURLService> template_url_service_;
   base::WeakPtr<lens::LensUnifiedSidePanelView> lens_side_panel_view_;
 
   BROWSER_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc
index bbbf17ed..e2f0c470 100644
--- a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc
+++ b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc
@@ -50,7 +50,7 @@
 
 constexpr char kCloseAction[] = "LensUnifiedSidePanel.HideSidePanel";
 constexpr char kExpectedSidePanelContentUrlRegex[] =
-    ".*ep=ccm&re=dcsp&s=csp&st=\\d+&p=somepayload";
+    ".*ep=ccm&re=dcsp&s=csp&st=\\d+&p=somepayload&sideimagesearch=1";
 
 // Maintains image search test state. In particular, note that |menu_observer_|
 // must live until the right-click completes asynchronously.
@@ -68,17 +68,17 @@
   }
 
   void SetupUnifiedSidePanel() {
-    // ensures that the lens side panel coordinator is open and is valid when
-    // running the search
-    lens::CreateLensUnifiedSidePanelEntryForTesting(browser());
     SetupAndLoadValidImagePage();
+    // Ensures that the lens side panel coordinator is open and is valid when
+    // running the search.
+    lens::CreateLensUnifiedSidePanelEntryForTesting(browser());
     // The browser should open a side panel with the image.
     AttemptLensImageSearch();
 
-    // We need to verify the contents before opening the side panel
+    // We need to verify the contents before opening the side panel.
     content::WebContents* contents =
         lens::GetLensUnifiedSidePanelWebContentsForTesting(browser());
-    // // Wait for the side panel to open and finish loading web contents.
+    // Wait for the side panel to open and finish loading web contents.
     content::TestNavigationObserver nav_observer(contents);
     nav_observer.Wait();
   }
@@ -144,6 +144,7 @@
     data.SetURL(embedded_test_server()->GetURL(kSearchURL).spec());
     data.image_url = GetImageSearchURL().spec();
     data.image_url_post_params = kImageSearchPostParams;
+    data.side_image_search_param = "sideimagesearch";
 
     TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
     ASSERT_TRUE(template_url);
@@ -193,7 +194,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SearchImageWithUnifiedSidePanel,
-                       DisableOpenInNewTabForBadUrl) {
+                       EnablesOpenInNewTabForAnyUrlForNonGoogleDse) {
   SetupUnifiedSidePanel();
   EXPECT_TRUE(GetUnifiedSidePanel()->GetVisible());
 
@@ -210,8 +211,7 @@
       lens::GetLensUnifiedSidePanelWebContentsForTesting(browser()));
   nav_observer.Wait();
 
-  EXPECT_FALSE(
-      GetLensSidePanelCoordinator()->IsLaunchButtonEnabledForTesting());
+  EXPECT_TRUE(GetLensSidePanelCoordinator()->IsLaunchButtonEnabledForTesting());
 }
 
 IN_PROC_BROWSER_TEST_F(SearchImageWithUnifiedSidePanel,
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.cc b/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.cc
index 6e6c9f55..5255069d 100644
--- a/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.cc
+++ b/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.cc
@@ -8,6 +8,8 @@
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
@@ -17,6 +19,8 @@
 #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/lens/lens_features.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
@@ -78,7 +82,8 @@
   if (lens::features::GetEnableLensSidePanelFooter())
     CreateAndInstallFooter();
 
-  SetContentAndNewTabButtonVisible(false, false);
+  SetContentAndNewTabButtonVisible(/* visible= */ false,
+                                   /* enable_new_tab_button= */ false);
   auto* web_contents = web_view_->GetWebContents();
   web_contents->SetDelegate(this);
   Observe(web_contents);
@@ -88,14 +93,40 @@
   return web_view_->GetWebContents();
 }
 
+TemplateURLService* LensUnifiedSidePanelView::GetTemplateURLService() {
+  auto* web_contents = web_view_->GetWebContents();
+  DCHECK(web_contents);
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  DCHECK(profile);
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile);
+  DCHECK(template_url_service);
+  return template_url_service;
+}
+
+bool LensUnifiedSidePanelView::IsDefaultSearchProviderGoogle() {
+  auto* web_contents = web_view_->GetWebContents();
+  DCHECK(web_contents);
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  DCHECK(profile);
+  return search::DefaultSearchProviderIsGoogle(profile);
+}
+
 void LensUnifiedSidePanelView::LoadResultsInNewTab() {
-  const GURL url = lens::CreateURLForNewTab(
-      web_view_->GetWebContents()->GetLastCommittedURL());
+  const GURL last_committed_url =
+      web_view_->GetWebContents()->GetLastCommittedURL();
+  const GURL url = IsDefaultSearchProviderGoogle()
+                       ? lens::CreateURLForNewTab(last_committed_url)
+                       : last_committed_url;
   // If there is no payload parameter, we will have an empty URL. This means
   // we should return on empty and not close the side panel.
   if (url.is_empty())
     return;
-  content::OpenURLParams params(url, content::Referrer(),
+  const GURL modified_url =
+      GetTemplateURLService()->RemoveSideImageSearchParamFromURL(url);
+  content::OpenURLParams params(modified_url, content::Referrer(),
                                 WindowOpenDisposition::NEW_FOREGROUND_TAB,
                                 ui::PAGE_TRANSITION_TYPED,
                                 /*is_renderer_initiated=*/false);
@@ -108,6 +139,12 @@
 void LensUnifiedSidePanelView::DocumentOnLoadCompletedInPrimaryMainFrame() {
   auto last_committed_url = web_view_->GetWebContents()->GetLastCommittedURL();
 
+  if (!IsDefaultSearchProviderGoogle()) {
+    SetContentAndNewTabButtonVisible(/* visible= */ true,
+                                     /* enable_new_tab_button= */ true);
+    return;
+  }
+
   // Since Lens Web redirects to the actual UI using HTML redirection, this
   // method gets fired twice. This check ensures we only show the user the
   // rendered page and not the redirect. It also ensures we immediately render
@@ -115,7 +152,9 @@
   // TODO(243935799): Cleanup this check once Lens Web no longer redirects
   if (lens::ShouldPageBeVisible(last_committed_url))
     SetContentAndNewTabButtonVisible(
-        true, lens::IsValidLensResultUrl(last_committed_url));
+        /* visible= */ true,
+        /* enable_new_tab_button= */ lens::IsValidLensResultUrl(
+            last_committed_url));
 }
 
 // Catches case where Chrome errors. I.e. no internet connection
@@ -123,9 +162,14 @@
 void LensUnifiedSidePanelView::PrimaryPageChanged(content::Page& page) {
   auto last_committed_url = web_view_->GetWebContents()->GetLastCommittedURL();
 
-  if (page.GetMainDocument().IsErrorDocument())
-    SetContentAndNewTabButtonVisible(
-        true, lens::IsValidLensResultUrl(last_committed_url));
+  if (page.GetMainDocument().IsErrorDocument()) {
+    bool enable_new_tab_button =
+        IsDefaultSearchProviderGoogle()
+            ? lens::IsValidLensResultUrl(last_committed_url)
+            : true;
+    SetContentAndNewTabButtonVisible(/* visible= */ true,
+                                     enable_new_tab_button);
+  }
 }
 
 bool LensUnifiedSidePanelView::IsLaunchButtonEnabledForTesting() {
@@ -141,7 +185,8 @@
 
 void LensUnifiedSidePanelView::OpenUrl(const content::OpenURLParams& params) {
   side_panel_url_params_ = std::make_unique<content::OpenURLParams>(params);
-  SetContentAndNewTabButtonVisible(false, false);
+  SetContentAndNewTabButtonVisible(/* visible= */ false,
+                                   /* enable_new_tab_button= */ false);
   MaybeLoadURLWithParams();
 }
 
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.h b/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.h
index 61aee133..3b74ff7 100644
--- a/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.h
+++ b/chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.h
@@ -8,6 +8,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "components/search_engines/template_url_service.h"
 #include "content/public/browser/navigation_handle.h"
 #include "ui/views/layout/flex_layout_view.h"
 
@@ -56,6 +57,10 @@
  private:
   void CreateAndInstallFooter();
 
+  TemplateURLService* GetTemplateURLService();
+
+  bool IsDefaultSearchProviderGoogle();
+
   // Shows / hides the lens results and the loading view to avoid showing
   // loading artifacts. If the visible bool is false, show loading view else
   // show lens results view. Also enables/disables the new tab button depending
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc
index aa6af6c2..c308ed2b 100644
--- a/components/lens/lens_features.cc
+++ b/components/lens/lens_features.cc
@@ -164,6 +164,10 @@
          kEnableSidePanelForLens.Get();
 }
 
+bool IsLensSidePanelEnabledForRegionSearch() {
+  return IsLensSidePanelEnabled() && !IsLensFullscreenSearchEnabled();
+}
+
 bool GetSendImagesAsPng() {
   return base::FeatureList::IsEnabled(kLensStandalone) &&
          base::FeatureList::IsEnabled(kLensTransparentImagesFix);
diff --git a/components/lens/lens_features.h b/components/lens/lens_features.h
index 2b01e488..368a3ac 100644
--- a/components/lens/lens_features.h
+++ b/components/lens/lens_features.h
@@ -133,9 +133,12 @@
 // relevant Lens context menu strings.
 extern bool UseGoogleAsVisualSearchProvider();
 
-// Returns whether the Lens side panel is enabled.
+// Returns whether the Lens side panel is enabled for image search.
 extern bool IsLensSidePanelEnabled();
 
+// Returns whether the Lens side panel is enabled for region search.
+extern bool IsLensSidePanelEnabledForRegionSearch();
+
 // Returns whether to send images to Lens Standalone as PNG
 extern bool GetSendImagesAsPng();
 
diff --git a/components/lens/lens_url_utils.cc b/components/lens/lens_url_utils.cc
index 4b9a1fc..60ef572a 100644
--- a/components/lens/lens_url_utils.cc
+++ b/components/lens/lens_url_utils.cc
@@ -109,6 +109,18 @@
   return query_parameters;
 }
 
+lens::RenderingEnvironment GetRenderingEnvironment(
+    bool is_side_panel_request,
+    bool is_full_screen_region_search_request) {
+  if (is_full_screen_region_search_request)
+    return lens::RenderingEnvironment::
+        ONELENS_AMBIENT_VISUAL_SEARCH_WEB_FULLSCREEN;
+
+  if (is_side_panel_request)
+    return lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL;
+
+  return lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
+}
 }  // namespace
 
 namespace lens {
@@ -135,9 +147,12 @@
   return modified_url;
 }
 
-std::string GetQueryParametersForLensRequest(lens::EntryPoint ep,
-                                             lens::RenderingEnvironment re,
-                                             bool is_side_panel_request) {
+std::string GetQueryParametersForLensRequest(
+    lens::EntryPoint ep,
+    bool is_side_panel_request,
+    bool is_full_screen_region_search_request) {
+  auto re = GetRenderingEnvironment(is_side_panel_request,
+                                    is_full_screen_region_search_request);
   std::string query_string;
   for (auto const& param :
        GetLensQueryParametersMap(ep, re, is_side_panel_request))
diff --git a/components/lens/lens_url_utils.h b/components/lens/lens_url_utils.h
index f509326..2b4dd36f 100644
--- a/components/lens/lens_url_utils.h
+++ b/components/lens/lens_url_utils.h
@@ -35,9 +35,8 @@
 // GURL is unavailable to append to.
 extern std::string GetQueryParametersForLensRequest(
     lens::EntryPoint ep,
-    lens::RenderingEnvironment re,
-    bool is_side_panel_request);
-
+    bool is_side_panel_request,
+    bool is_full_screen_region_search_request);
 }  // namespace lens
 
 #endif  // COMPONENTS_LENS_LENS_URL_UTILS_H_
\ No newline at end of file
diff --git a/components/lens/lens_url_utils_unittest.cc b/components/lens/lens_url_utils_unittest.cc
index cac5a4fb..8e646bc 100644
--- a/components/lens/lens_url_utils_unittest.cc
+++ b/components/lens/lens_url_utils_unittest.cc
@@ -19,96 +19,79 @@
 TEST(LensUrlUtilsTest, GetRegionSearchNewTabQueryParameterTest) {
   lens::EntryPoint lens_region_search_ep =
       lens::EntryPoint::CHROME_REGION_SEARCH_MENU_ITEM;
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens_region_search_ep, re, /*is_side_panel_request=*/false);
+      lens_region_search_ep, /* is_side_panel_request= */ false,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("ep=crs&re=df&s=&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetImageSearchNewTabQueryParameterTest) {
   lens::EntryPoint lens_image_search_ep =
       lens::EntryPoint::CHROME_SEARCH_WITH_GOOGLE_LENS_CONTEXT_MENU_ITEM;
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens_image_search_ep, re, /*is_side_panel_request=*/false);
+      lens_image_search_ep, /* is_side_panel_request= */ false,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("ep=ccm&re=df&s=&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetRegionSearchSidePanelQueryParameterTest) {
   lens::EntryPoint lens_region_search_ep =
       lens::EntryPoint::CHROME_REGION_SEARCH_MENU_ITEM;
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens_region_search_ep, re, /*is_side_panel_request=*/true);
+      lens_region_search_ep, /* is_side_panel_request= */ true,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("ep=crs&re=dcsp&s=csp&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetImageSearchSidePanelQueryParameterTest) {
   lens::EntryPoint lens_image_search_ep =
       lens::EntryPoint::CHROME_SEARCH_WITH_GOOGLE_LENS_CONTEXT_MENU_ITEM;
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens_image_search_ep, re, /*is_side_panel_request=*/true);
+      lens_image_search_ep, /* is_side_panel_request= */ true,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("ep=ccm&re=dcsp&s=csp&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetOpenNewTabSidePanelParameterTest) {
   lens::EntryPoint lens_open_new_tab_side_panel_ep =
       lens::EntryPoint::CHROME_OPEN_NEW_TAB_SIDE_PANEL;
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens_open_new_tab_side_panel_ep, re, /*is_side_panel_request=*/false);
+      lens_open_new_tab_side_panel_ep, /* is_side_panel_request= */ false,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("ep=cnts&re=df&s=&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetFullscreenSearchQueryParameterTest) {
   lens::EntryPoint lens_ep =
       lens::EntryPoint::CHROME_FULLSCREEN_SEARCH_MENU_ITEM;
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_AMBIENT_VISUAL_SEARCH_WEB_FULLSCREEN;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens_ep, re, /*is_side_panel_request=*/false);
+      lens_ep, /* is_side_panel_request= */ false,
+      /* is_full_screen_region_search_request= */ true);
   EXPECT_THAT(query_param, MatchesRegex("ep=cfs&re=avsf&s=&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetScreenshotSearchQueryParameterTest) {
   lens::EntryPoint lens_ep = lens::EntryPoint::CHROME_SCREENSHOT_SEARCH;
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens_ep, re, /*is_side_panel_request=*/false);
+      lens_ep, /* is_side_panel_request= */ false,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("ep=css&re=df&s=&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetUnknownEntryPointTest) {
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens::EntryPoint::UNKNOWN, re, /*is_side_panel_request=*/false);
+      lens::EntryPoint::UNKNOWN, /* is_side_panel_request= */ false,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("re=df&s=&st=\\d+"));
 }
 
 TEST(LensUrlUtilsTest, GetUnknownEntryPointSidePanelTest) {
-  lens::RenderingEnvironment re =
-      lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL;
   std::string query_param = lens::GetQueryParametersForLensRequest(
-      lens::EntryPoint::UNKNOWN, re, /*is_side_panel_request=*/true);
+      lens::EntryPoint::UNKNOWN, /* is_side_panel_request= */ true,
+      /* is_full_screen_region_search_request= */ false);
   EXPECT_THAT(query_param, MatchesRegex("re=dcsp&s=csp&st=\\d+"));
 }
 
-TEST(LensUrlUtilsTest, GetUnknownRenderingEnvironmentTest) {
-  lens::EntryPoint ep = lens::EntryPoint::CHROME_REGION_SEARCH_MENU_ITEM;
-  std::string query_param = lens::GetQueryParametersForLensRequest(
-      ep, lens::RenderingEnvironment::RENDERING_ENV_UNKNOWN,
-      /*is_side_panel_request=*/false);
-  EXPECT_THAT(query_param, MatchesRegex("ep=crs&s=&st=\\d+"));
-}
-
 TEST(LensUrlUtilsTest, AppendRegionSearchNewTabQueryParameterTest) {
   lens::EntryPoint lens_region_search_ep =
       lens::EntryPoint::CHROME_REGION_SEARCH_MENU_ITEM;
@@ -116,7 +99,8 @@
       lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
-      original_url, lens_region_search_ep, re, /*is_side_panel_request=*/false);
+      original_url, lens_region_search_ep, re,
+      /* is_side_panel_request= */ false);
   EXPECT_THAT(url.query(), MatchesRegex("ep=crs&re=df&s=&st=\\d+"));
 }
 
@@ -127,7 +111,8 @@
       lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
-      original_url, lens_image_search_ep, re, /*is_side_panel_request=*/false);
+      original_url, lens_image_search_ep, re,
+      /* is_side_panel_request= */ false);
   EXPECT_THAT(url.query(), MatchesRegex("ep=ccm&re=df&s=&st=\\d+"));
 }
 
@@ -138,7 +123,8 @@
       lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL;
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
-      original_url, lens_region_search_ep, re, /*is_side_panel_request=*/true);
+      original_url, lens_region_search_ep, re,
+      /* is_side_panel_request= */ true);
   EXPECT_THAT(url.query(), MatchesRegex("ep=crs&re=dcsp&s=csp&st=\\d+"));
 }
 
@@ -149,7 +135,8 @@
       lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_CHROME_SIDE_PANEL;
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
-      original_url, lens_image_search_ep, re, /*is_side_panel_request=*/true);
+      original_url, lens_image_search_ep, re,
+      /* is_side_panel_request= */ true);
   EXPECT_THAT(url.query(), MatchesRegex("ep=ccm&re=dcsp&s=csp&st=\\d+"));
 }
 
@@ -161,7 +148,7 @@
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
       original_url, lens_open_new_tab_side_panel_ep, re,
-      /*is_side_panel_request=*/false);
+      /* is_side_panel_request= */ false);
   EXPECT_THAT(url.query(), MatchesRegex("ep=cnts&re=df&s=&st=\\d+"));
 }
 
@@ -172,7 +159,7 @@
       lens::RenderingEnvironment::ONELENS_AMBIENT_VISUAL_SEARCH_WEB_FULLSCREEN;
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
-      original_url, lens_ep, re, /*is_side_panel_request=*/false);
+      original_url, lens_ep, re, /* is_side_panel_request= */ false);
   EXPECT_THAT(url.query(), MatchesRegex("ep=cfs&re=avsf&s=&st=\\d+"));
 }
 
@@ -182,7 +169,7 @@
       lens::RenderingEnvironment::ONELENS_DESKTOP_WEB_FULLSCREEN;
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
-      original_url, lens_ep, re, /*is_side_panel_request=*/false);
+      original_url, lens_ep, re, /* is_side_panel_request= */ false);
   EXPECT_THAT(url.query(), MatchesRegex("ep=css&re=df&s=&st=\\d+"));
 }
 
@@ -192,7 +179,7 @@
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
       original_url, lens::EntryPoint::UNKNOWN, re,
-      /*is_side_panel_request=*/false);
+      /* is_side_panel_request= */ false);
   EXPECT_THAT(url.query(), MatchesRegex("re=df&s=&st=\\d+"));
 }
 
@@ -201,7 +188,7 @@
   GURL original_url = GURL("https://lens.google.com/");
   GURL url = lens::AppendOrReplaceQueryParametersForLensRequest(
       original_url, ep, lens::RenderingEnvironment::RENDERING_ENV_UNKNOWN,
-      /*is_side_panel_request=*/false);
+      /* is_side_panel_request= */ false);
   EXPECT_THAT(url.query(), MatchesRegex("ep=crs&s=&st=\\d+"));
 }
 
diff --git a/components/search_engines/default_search_manager.cc b/components/search_engines/default_search_manager.cc
index 9dc6f6a..ee6a178 100644
--- a/components/search_engines/default_search_manager.cc
+++ b/components/search_engines/default_search_manager.cc
@@ -64,6 +64,8 @@
 const char DefaultSearchManager::kImageURLPostParams[] =
     "image_url_post_params";
 const char DefaultSearchManager::kSideSearchParam[] = "side_search_param";
+const char DefaultSearchManager::kSideImageSearchParam[] =
+    "side_image_search_param";
 
 const char DefaultSearchManager::kSafeForAutoReplace[] = "safe_for_autoreplace";
 const char DefaultSearchManager::kInputEncodings[] = "input_encodings";
diff --git a/components/search_engines/default_search_manager.h b/components/search_engines/default_search_manager.h
index b570d88..c5ec7922 100644
--- a/components/search_engines/default_search_manager.h
+++ b/components/search_engines/default_search_manager.h
@@ -46,6 +46,7 @@
   static const char kSuggestionsURLPostParams[];
   static const char kImageURLPostParams[];
   static const char kSideSearchParam[];
+  static const char kSideImageSearchParam[];
 
   static const char kSafeForAutoReplace[];
   static const char kInputEncodings[];
diff --git a/components/search_engines/prepopulated_engines.json b/components/search_engines/prepopulated_engines.json
index 9058209..d952eeac 100644
--- a/components/search_engines/prepopulated_engines.json
+++ b/components/search_engines/prepopulated_engines.json
@@ -122,6 +122,7 @@
       "contextual_search_url": "{google:baseURL}_/contextualsearch?{google:contextualSearchVersion}{google:contextualSearchContextData}",
       "image_url_post_params": "encoded_image={google:imageThumbnail},image_url={google:imageURL},sbisrc={google:imageSearchSource},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight}",
       "side_search_param": "sidesearch",
+      "side_image_search_param": "sideimagesearch",
       "alternate_urls": [
         "{google:baseURL}#q={searchTerms}",
         "{google:baseURL}search#q={searchTerms}",
diff --git a/components/search_engines/prepopulated_engines_schema.json b/components/search_engines/prepopulated_engines_schema.json
index c4532201..09df292 100644
--- a/components/search_engines/prepopulated_engines_schema.json
+++ b/components/search_engines/prepopulated_engines_schema.json
@@ -51,6 +51,9 @@
     // The parameter appended to the engine's search URL when constructing the
     // URL for the side search side panel.
     { "field": "side_search_param", "type": "string", "optional": true },
+    // The parameter appended to the engine's |image_url| URL when constructing the
+    // URL for the image search entry in the side panel.
+    { "field": "side_image_search_param", "type": "string", "optional": true },
     // A list of URL patterns that can be used, in addition to |search_url|,
     // to extract search terms from a URL.
     // If "search_url_post_params" is not empty, then all alternate URLs are
diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc
index de6dd490..4b4da881 100644
--- a/components/search_engines/template_url.cc
+++ b/components/search_engines/template_url.cc
@@ -1707,6 +1707,10 @@
   return !side_search_param().empty();
 }
 
+bool TemplateURL::IsSideImageSearchSupported() const {
+  return !side_image_search_param().empty();
+}
+
 GURL TemplateURL::GenerateSideSearchURL(
     const GURL& search_url,
     const std::string& version,
@@ -1716,6 +1720,31 @@
   return net::AppendQueryParameter(search_url, side_search_param(), version);
 }
 
+GURL TemplateURL::GenerateSideImageSearchURL(const GURL& image_search_url,
+                                             const std::string& version) const {
+  DCHECK(IsSideImageSearchSupported());
+  std::string value;
+  if (net::GetValueForKeyInQuery(image_search_url, side_image_search_param(),
+                                 &value) &&
+      value == version)
+    return image_search_url;
+
+  return net::AppendOrReplaceQueryParameter(image_search_url,
+                                            side_image_search_param(), version);
+}
+
+GURL TemplateURL::RemoveSideImageSearchParamFromURL(
+    const GURL& image_search_url) const {
+  if (!IsSideImageSearchSupported())
+    return image_search_url;
+  std::string value;
+  if (!net::GetValueForKeyInQuery(image_search_url, side_image_search_param(),
+                                  &value))
+    return image_search_url;
+  return net::AppendOrReplaceQueryParameter(image_search_url,
+                                            side_image_search_param(), "");
+}
+
 void TemplateURL::CopyFrom(const TemplateURL& other) {
   if (this == &other)
     return;
diff --git a/components/search_engines/template_url.h b/components/search_engines/template_url.h
index e3a470e3..dd79155 100644
--- a/components/search_engines/template_url.h
+++ b/components/search_engines/template_url.h
@@ -718,6 +718,9 @@
   const std::string& side_search_param() const {
     return data_.side_search_param;
   }
+  const std::string& side_image_search_param() const {
+    return data_.side_image_search_param;
+  }
   const std::vector<std::string>& alternate_urls() const {
     return data_.alternate_urls;
   }
@@ -851,12 +854,24 @@
   // Returns true if this search engine supports the side search feature.
   bool IsSideSearchSupported() const;
 
+  // Returns true if this search engine supports the side image search feature.
+  bool IsSideImageSearchSupported() const;
+
   // Takes a search URL belonging to this search engine and generates the URL
   // appropriate for the side search side panel.
   GURL GenerateSideSearchURL(const GURL& search_url,
                              const std::string& version,
                              const SearchTermsData& search_terms_data) const;
 
+  // Takes a search URL belonging to this image search engine and generates the
+  // URL appropriate for the image search in the side panel.
+  GURL GenerateSideImageSearchURL(const GURL& image_search_url,
+                                  const std::string& version) const;
+
+  // Takes a search URL that belongs to this image search in the side panel and
+  // removes the side image search param from the URL.
+  GURL RemoveSideImageSearchParamFromURL(const GURL& image_search_url) const;
+
   // TemplateURL internally caches values derived from a passed SearchTermsData
   // to make its functions quick. This method invalidates any cached values and
   // it should be called after SearchTermsData has been changed.
diff --git a/components/search_engines/template_url_data.cc b/components/search_engines/template_url_data.cc
index 18ec409..ac8c269 100644
--- a/components/search_engines/template_url_data.cc
+++ b/components/search_engines/template_url_data.cc
@@ -72,6 +72,7 @@
                                  base::StringPiece suggest_url_post_params,
                                  base::StringPiece image_url_post_params,
                                  base::StringPiece side_search_param,
+                                 base::StringPiece side_image_search_param,
                                  base::StringPiece favicon_url,
                                  base::StringPiece encoding,
                                  const base::Value& alternate_urls_list,
@@ -88,6 +89,7 @@
       suggestions_url_post_params(suggest_url_post_params),
       image_url_post_params(image_url_post_params),
       side_search_param(side_search_param),
+      side_image_search_param(side_image_search_param),
       favicon_url(favicon_url),
       safe_for_autoreplace(true),
       id(0),
@@ -156,6 +158,8 @@
   res += base::trace_event::EstimateMemoryUsage(search_url_post_params);
   res += base::trace_event::EstimateMemoryUsage(suggestions_url_post_params);
   res += base::trace_event::EstimateMemoryUsage(image_url_post_params);
+  res += base::trace_event::EstimateMemoryUsage(side_search_param);
+  res += base::trace_event::EstimateMemoryUsage(side_image_search_param);
   res += base::trace_event::EstimateMemoryUsage(favicon_url);
   res += base::trace_event::EstimateMemoryUsage(originating_url);
   res += base::trace_event::EstimateMemoryUsage(input_encodings);
diff --git a/components/search_engines/template_url_data.h b/components/search_engines/template_url_data.h
index 28e670dd..5393d78 100644
--- a/components/search_engines/template_url_data.h
+++ b/components/search_engines/template_url_data.h
@@ -40,6 +40,7 @@
                   base::StringPiece suggest_url_post_params,
                   base::StringPiece image_url_post_params,
                   base::StringPiece side_search_param,
+                  base::StringPiece side_image_search_param,
                   base::StringPiece favicon_url,
                   base::StringPiece encoding,
                   const base::Value& alternate_urls_list,
@@ -96,6 +97,10 @@
   // for the side search side panel.
   std::string side_search_param;
 
+  // The parameter appended to the engine's image URL when constructing the
+  // URL for the image search entry in the side panel.
+  std::string side_image_search_param;
+
   // Favicon for the TemplateURL.
   GURL favicon_url;
 
diff --git a/components/search_engines/template_url_data_unittest.cc b/components/search_engines/template_url_data_unittest.cc
index d1c5cca..db85d0d89 100644
--- a/components/search_engines/template_url_data_unittest.cc
+++ b/components/search_engines/template_url_data_unittest.cc
@@ -16,7 +16,7 @@
       base::StringPiece(), base::StringPiece(), base::StringPiece(),
       base::StringPiece(), base::StringPiece(), base::StringPiece(),
       base::StringPiece(), base::StringPiece(), base::StringPiece(),
-      base::ListValue(), false, false, 0);
+      base::StringPiece(), base::ListValue(), false, false, 0);
 
   EXPECT_EQ(u"shortname", data.short_name());
   EXPECT_EQ(u"keyword", data.keyword());
diff --git a/components/search_engines/template_url_data_util.cc b/components/search_engines/template_url_data_util.cc
index 5a1abf8..474d240 100644
--- a/components/search_engines/template_url_data_util.cc
+++ b/components/search_engines/template_url_data_util.cc
@@ -113,6 +113,11 @@
   if (side_search_param) {
     result->side_search_param = *side_search_param;
   }
+  const std::string* side_image_search_param =
+      dict.FindString(DefaultSearchManager::kSideImageSearchParam);
+  if (side_image_search_param) {
+    result->side_image_search_param = *side_image_search_param;
+  }
   absl::optional<bool> safe_for_autoreplace =
       dict.FindBool(DefaultSearchManager::kSafeForAutoReplace);
   if (safe_for_autoreplace) {
@@ -224,6 +229,8 @@
                          data.image_url_post_params);
   url_dict->SetStringKey(DefaultSearchManager::kSideSearchParam,
                          data.side_search_param);
+  url_dict->SetStringKey(DefaultSearchManager::kSideImageSearchParam,
+                         data.side_image_search_param);
 
   url_dict->SetBoolKey(DefaultSearchManager::kSafeForAutoReplace,
                        data.safe_for_autoreplace);
@@ -282,6 +289,7 @@
       ToStringPiece(engine.suggest_url_post_params),
       ToStringPiece(engine.image_url_post_params),
       ToStringPiece(engine.side_search_param),
+      ToStringPiece(engine.side_image_search_param),
       ToStringPiece(engine.favicon_url), ToStringPiece(engine.encoding),
       alternate_urls,
       ToStringPiece(engine.preconnect_to_search_url) == "ALLOWED",
@@ -340,6 +348,7 @@
     std::string suggest_url_post_params;
     std::string image_url_post_params;
     std::string side_search_param;
+    std::string side_image_search_param;
     std::string preconnect_to_search_url;
     std::string prefetch_likely_navigations;
 
@@ -383,6 +392,10 @@
     if (string_value) {
       side_search_param = *string_value;
     }
+    string_value = engine.FindStringKey("side_image_search_param");
+    if (string_value) {
+      side_image_search_param = *string_value;
+    }
     string_value = engine.FindStringKey("preconnect_to_search_url");
     if (string_value) {
       preconnect_to_search_url = *string_value;
@@ -396,7 +409,7 @@
         name, keyword, search_url, suggest_url, image_url, new_tab_url,
         contextual_search_url, logo_url, doodle_url, search_url_post_params,
         suggest_url_post_params, image_url_post_params, side_search_param,
-        favicon_url, encoding, *alternate_urls,
+        side_image_search_param, favicon_url, encoding, *alternate_urls,
         preconnect_to_search_url.compare("ALLOWED") == 0,
         prefetch_likely_navigations.compare("ALLOWED") == 0, *id);
   }
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
index 4970adb..c9294ae 100644
--- a/components/search_engines/template_url_service.cc
+++ b/components/search_engines/template_url_service.cc
@@ -822,6 +822,12 @@
   return default_provider && default_provider->IsSideSearchSupported();
 }
 
+bool TemplateURLService::IsSideImageSearchSupportedForDefaultSearchProvider()
+    const {
+  const TemplateURL* default_provider = GetDefaultSearchProvider();
+  return default_provider && default_provider->IsSideImageSearchSupported();
+}
+
 GURL TemplateURLService::GenerateSideSearchURLForDefaultSearchProvider(
     const GURL& search_url,
     const std::string& version) const {
@@ -830,6 +836,22 @@
                                                            search_terms_data());
 }
 
+GURL TemplateURLService::GenerateSideImageSearchURLForDefaultSearchProvider(
+    const GURL& search_url,
+    const std::string& version) const {
+  DCHECK(IsSideImageSearchSupportedForDefaultSearchProvider());
+  return GetDefaultSearchProvider()->GenerateSideImageSearchURL(search_url,
+                                                                version);
+}
+
+GURL TemplateURLService::RemoveSideImageSearchParamFromURL(
+    const GURL& search_url) const {
+  if (!IsSideImageSearchSupportedForDefaultSearchProvider())
+    return search_url;
+  return GetDefaultSearchProvider()->RemoveSideImageSearchParamFromURL(
+      search_url);
+}
+
 bool TemplateURLService::IsExtensionControlledDefaultSearch() const {
   return default_search_provider_source_ ==
       DefaultSearchManager::FROM_EXTENSION;
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h
index 0591ee0..9cfadab 100644
--- a/components/search_engines/template_url_service.h
+++ b/components/search_engines/template_url_service.h
@@ -312,11 +312,25 @@
   // feature.
   bool IsSideSearchSupportedForDefaultSearchProvider() const;
 
+  // Returns true if the default search provider supports the opening
+  // image search requests in the side panel.
+  bool IsSideImageSearchSupportedForDefaultSearchProvider() const;
+
   // Generates a side search URL for the default search provider's search url.
   GURL GenerateSideSearchURLForDefaultSearchProvider(
       const GURL& search_url,
       const std::string& version) const;
 
+  // Generates a side image search URL for the default search provider's image
+  // search url.
+  GURL GenerateSideImageSearchURLForDefaultSearchProvider(
+      const GURL& image_search_url,
+      const std::string& version) const;
+
+  // Takes a search URL that belongs to this image search in the side panel and
+  // removes the side image search param from the URL.
+  GURL RemoveSideImageSearchParamFromURL(const GURL& image_search_url) const;
+
   // Returns true if the default search is managed through group policy.
   bool is_default_search_managed() const {
     return default_search_provider_source_ == DefaultSearchManager::FROM_POLICY;
diff --git a/components/search_engines/template_url_service_util_unittest.cc b/components/search_engines/template_url_service_util_unittest.cc
index 8970367..4dbd32a 100644
--- a/components/search_engines/template_url_service_util_unittest.cc
+++ b/components/search_engines/template_url_service_util_unittest.cc
@@ -26,7 +26,7 @@
       "" /* contextual_search_url */, "" /* logo_url */, "" /* doodle_url */,
       "" /* search_url_post_params */, "" /* suggest_url_post_params */,
       "" /* image_url_post_params */, "" /* side_search_param */,
-      "" /* favicon_url */, "UTF-8",
+      "" /* side_image_search_param */, "" /* favicon_url */, "UTF-8",
       base::ListValue() /* alternate_urls_list */,
       false /* preconnect_to_search_url */,
       false /* prefetch_likely_navigations */, prepopulate_id);
diff --git a/components/search_engines/template_url_unittest.cc b/components/search_engines/template_url_unittest.cc
index ae658aa..3a7a3bc 100644
--- a/components/search_engines/template_url_unittest.cc
+++ b/components/search_engines/template_url_unittest.cc
@@ -2222,3 +2222,41 @@
                               &generated_url);
   EXPECT_EQ("https://www.google.com/search?q=foo", generated_url.spec());
 }
+
+TEST_F(TemplateURLTest, SideImageSearchParams) {
+  TemplateURLData data;
+  data.side_image_search_param = "sideimagesearch";
+  TemplateURL url(data);
+
+  // Adds query param with provided version to URL.
+  GURL result =
+      url.GenerateSideImageSearchURL(GURL("http://foo.com/?q=123"), "1");
+  EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=1", result.spec());
+
+  // Does not add query param if the provided URL already has that param and
+  // version.
+  result = url.GenerateSideImageSearchURL(
+      GURL("http://foo.com/?q=123&sideimagesearch=1"), "1");
+  EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=1", result.spec());
+
+  // Updates version if the version on the query param does not match.
+  result = url.GenerateSideImageSearchURL(
+      GURL("http://foo.com/?q=123&sideimagesearch=2"), "1");
+  EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=1", result.spec());
+
+  // Does nothing if the URL does not have the param.
+  result = url.RemoveSideImageSearchParamFromURL(GURL("http://foo.com/?q=123"));
+  EXPECT_EQ("http://foo.com/?q=123", result.spec());
+
+  // Removes the param if the provided URL has it.
+  result = url.RemoveSideImageSearchParamFromURL(
+      GURL("http://foo.com/?q=123&sideimagesearch=1"));
+  EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=", result.spec());
+
+  // Removes the first instance of the query param that exist in the URL. This
+  // should not happen but just asserting for expected behavior.
+  result = url.RemoveSideImageSearchParamFromURL(
+      GURL("http://foo.com/?q=123&sideimagesearch=1&sideimagesearch=2"));
+  EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=&sideimagesearch=2",
+            result.spec());
+}
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn
index 18273ae..d3bbe76e 100644
--- a/components/vector_icons/BUILD.gn
+++ b/components/vector_icons/BUILD.gn
@@ -65,6 +65,7 @@
     "history.icon",
     "https_valid.icon",
     "https_valid_arrow.icon",
+    "image_search.icon",
     "info_outline.icon",
     "insert_drive_file_outline.icon",
     "keyboard.icon",
diff --git a/components/vector_icons/image_search.icon b/components/vector_icons/image_search.icon
new file mode 100644
index 0000000..76cc6185
--- /dev/null
+++ b/components/vector_icons/image_search.icon
@@ -0,0 +1,54 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 3.6f, 14.4f,
+CUBIC_TO, 3.27f, 14.4f, 2.98f, 14.28f, 2.75f, 14.05f,
+CUBIC_TO, 2.52f, 13.82f, 2.4f, 13.54f, 2.4f, 13.2f,
+LINE_TO, 2.4f, 4.4f,
+CUBIC_TO, 2.4f, 4.07f, 2.52f, 3.79f, 2.75f, 3.55f,
+CUBIC_TO, 2.98f, 3.32f, 3.27f, 3.2f, 3.6f, 3.2f,
+LINE_TO, 6.8f, 3.2f,
+LINE_TO, 6.8f, 4.4f,
+LINE_TO, 3.6f, 4.4f,
+LINE_TO, 3.6f, 13.2f,
+LINE_TO, 12.4f, 13.2f,
+LINE_TO, 12.4f, 9.35f,
+LINE_TO, 13.6f, 10.55f,
+LINE_TO, 13.6f, 13.2f,
+CUBIC_TO, 13.6f, 13.54f, 13.48f, 13.82f, 13.25f, 14.05f,
+CUBIC_TO, 13.02f, 14.28f, 12.73f, 14.4f, 12.4f, 14.4f,
+CLOSE,
+MOVE_TO, 4.4f, 12,
+LINE_TO, 6.2f, 9.6f,
+LINE_TO, 7.4f, 11.2f,
+LINE_TO, 9.2f, 8.8f,
+LINE_TO, 11.6f, 12,
+CLOSE,
+MOVE_TO, 14.35f, 9.6f,
+LINE_TO, 12.3f, 7.55f,
+CUBIC_TO, 12.08f, 7.7f, 11.84f, 7.8f, 11.59f, 7.88f,
+CUBIC_TO, 11.34f, 7.96f, 11.08f, 8, 10.8f, 8,
+CUBIC_TO, 10.02f, 8, 9.36f, 7.73f, 8.82f, 7.18f,
+CUBIC_TO, 8.27f, 6.64f, 8, 5.98f, 8, 5.2f,
+CUBIC_TO, 8, 4.42f, 8.27f, 3.76f, 8.82f, 3.22f,
+CUBIC_TO, 9.36f, 2.67f, 10.02f, 2.4f, 10.8f, 2.4f,
+CUBIC_TO, 11.58f, 2.4f, 12.24f, 2.67f, 12.78f, 3.22f,
+CUBIC_TO, 13.33f, 3.76f, 13.6f, 4.42f, 13.6f, 5.2f,
+CUBIC_TO, 13.6f, 5.48f, 13.56f, 5.74f, 13.48f, 5.99f,
+CUBIC_TO, 13.41f, 6.24f, 13.29f, 6.48f, 13.15f, 6.7f,
+LINE_TO, 15.2f, 8.75f,
+CLOSE,
+MOVE_TO, 10.8f, 6.8f,
+CUBIC_TO, 11.25f, 6.8f, 11.62f, 6.64f, 11.93f, 6.33f,
+CUBIC_TO, 12.25f, 6.02f, 12.4f, 5.64f, 12.4f, 5.2f,
+CUBIC_TO, 12.4f, 4.75f, 12.25f, 4.38f, 11.93f, 4.07f,
+CUBIC_TO, 11.62f, 3.75f, 11.25f, 3.6f, 10.8f, 3.6f,
+CUBIC_TO, 10.36f, 3.6f, 9.98f, 3.75f, 9.67f, 4.07f,
+CUBIC_TO, 9.36f, 4.38f, 9.2f, 4.75f, 9.2f, 5.2f,
+CUBIC_TO, 9.2f, 5.64f, 9.36f, 6.02f, 9.67f, 6.33f,
+CUBIC_TO, 9.98f, 6.64f, 10.36f, 6.8f, 10.8f, 6.8f,
+CLOSE,
+MOVE_TO, 10.8f, 6.8f,
+CLOSE