blob: ac13e2fde242b8f717068221f98cada3f0142a7c [file] [log] [blame]
// 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.
#ifndef CHROME_BROWSER_UI_SIDE_PANEL_COMPANION_COMPANION_TAB_HELPER_H_
#define CHROME_BROWSER_UI_SIDE_PANEL_COMPANION_COMPANION_TAB_HELPER_H_
#include "chrome/browser/companion/core/mojom/companion.mojom.h"
#include "chrome/browser/ui/side_panel/side_panel_enums.h"
#include "components/lens/buildflags.h"
#include "components/lens/lens_metrics.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
#include "chrome/browser/lens/region_search/lens_region_search_controller.h"
#endif
namespace content {
class WebContents;
} // namespace content
namespace ui {
class ImageModel;
} // namespace ui
namespace companion {
class CompanionPageHandler;
// A per-tab class that facilitates the showing of the Companion side panel with
// values such as a text query. This class also owns the
// CompanionSidePanelController.
class CompanionTabHelper
: public content::WebContentsUserData<CompanionTabHelper>,
public content::WebContentsObserver {
public:
class Delegate {
public:
virtual ~Delegate() = default;
// Creates the companion SidePanelEntry and registers it to the contextual
// registry.
virtual void CreateAndRegisterEntry() = 0;
// Deregisters the companion SidePanelEntry.
virtual void DeregisterEntry() = 0;
// Shows the companion side panel.
virtual void ShowCompanionSidePanel(
SidePanelOpenTrigger side_panel_open_trigger) = 0;
// Triggers an update of the 'open in new tab' button.
virtual void UpdateNewTabButton(GURL url_to_open) = 0;
// Called when the companion side panel is closed.
virtual void OnCompanionSidePanelClosed() = 0;
// Retrieves the web contents for testing purposes.
virtual content::WebContents* GetCompanionWebContentsForTesting() = 0;
// Returns true if Companion is currently open and showing to the user.
virtual bool IsCompanionShowing() = 0;
// Set Companion as the active side panel entry in the given web contents.
virtual void SetCompanionAsActiveEntry(content::WebContents* contents) = 0;
// Add a callback to be called when Companion is fully loaded in the side
// panel, i.e. the spinner of the tab would stop spinning, Javascript is
// loaded and the onload event was dispatched.
virtual void AddCompanionFinishedLoadingCallback(
base::OnceCallback<void()> callback) = 0;
// Create a contextual Lens view to open in the companion panel.
virtual void OpenContextualLensView(
const content::OpenURLParams& params) = 0;
// Testing method to get the Lens view web contents.
virtual content::WebContents* GetLensViewWebContentsForTesting() = 0;
// Testing method to open lens results in a new tab.
virtual bool OpenLensResultsInNewTabForTesting() = 0;
// Testing method to check if the new tab button is enabled for Lens.
virtual bool IsLensLaunchButtonEnabledForTesting() = 0;
};
using CompanionLoadedCallback = base::OnceCallback<void()>;
CompanionTabHelper(const CompanionTabHelper&) = delete;
CompanionTabHelper& operator=(const CompanionTabHelper&) = delete;
~CompanionTabHelper() override;
// content::WebContentsObserver overrides.
void DidOpenRequestedURL(content::WebContents* new_contents,
content::RenderFrameHost* source_render_frame_host,
const GURL& url,
const content::Referrer& referrer,
WindowOpenDisposition disposition,
ui::PageTransition transition,
bool started_from_context_menu,
bool renderer_initiated) override;
// Add a callback to be called when Companion is fully loaded in the side
// panel, i.e. the spinner of the tab would stop spinning, Javascript is
// loaded and the onload event was dispatched.
void AddCompanionFinishedLoadingCallback(CompanionLoadedCallback callback);
// Shows the companion side panel.
void ShowCompanionSidePanel(SidePanelOpenTrigger trigger);
// Shows the companion side panel with query provided by the |search_url|.
void ShowCompanionSidePanelForSearchURL(const GURL& search_url);
// Shows the companion side panel with the image bytes passed via
// |thumbnail_data|.
void ShowCompanionSidePanelForImage(
const GURL& src_url,
const bool is_image_translate,
const std::string& additional_query_params_modified,
const std::vector<uint8_t>& thumbnail_data,
const gfx::Size& original_size,
const gfx::Size& downscaled_size,
const std::string& content_type);
// Returns the latest text query set by the client or an empty string if none.
// Clears the last previous query after returning a copy.
std::string GetTextQuery();
// Starts the region search controller with the specified parameters.
void StartRegionSearch(content::WebContents* web_contents,
bool use_fullscreen_capture,
lens::AmbientSearchEntryPoint entry_point =
lens::AmbientSearchEntryPoint::
CONTEXT_MENU_SEARCH_REGION_WITH_GOOGLE_LENS);
// Returns the latest image data saved to the helper and not passed to the
// handler or an empty pointer if none.
std::unique_ptr<side_panel::mojom::ImageQuery> GetImageQuery();
bool HasImageQuery();
// Returns the most recently set start time for the text query entry point.
std::unique_ptr<base::Time> GetTextQueryStartTime();
// Called when the companion side panel is closed. Used for cleaning up any
// local state.
void OnCompanionSidePanelClosed();
// Triggers the companion side panel entry to be created and registered for
// the tab.
void CreateAndRegisterEntry();
// Triggers the companion side panel entry to be deregistered for the tab.
void DeregisterEntry();
// Triggers an update for the 'open in new tab' button in the side panel
// header to make sure the visibility is correct.
void UpdateNewTabButton(GURL url_to_open);
base::WeakPtr<CompanionPageHandler> GetCompanionPageHandler();
void SetCompanionPageHandler(
base::WeakPtr<CompanionPageHandler> companion_page_handler);
// Returns the companion web contents for testing purposes.
content::WebContents* GetCompanionWebContentsForTesting();
// For caching entry point metrics.
// Called to cache the trigger which is later recorded as metrics as soon as
// the companion page opens up.
void SetMostRecentSidePanelOpenTrigger(
std::optional<SidePanelOpenTrigger> side_panel_open_trigger);
// Called to get the most recent value of trigger and immediately reset it.
std::optional<SidePanelOpenTrigger>
GetAndResetMostRecentSidePanelOpenTrigger();
// Create and register a contextual Lens entry.
void CreateAndRegisterLensEntry(const content::OpenURLParams& params,
std::u16string combobox_label,
const ui::ImageModel favicon);
// Open an already created contextual Lens view with provided params.
void OpenContextualLensView(const content::OpenURLParams& params);
// Delete the contextual lens view associated with this web contents.
void RemoveContextualLensView();
content::WebContents* GetLensViewWebContentsForTesting();
bool OpenLensResultsInNewTabForTesting();
bool IsLensLaunchButtonEnabledForTesting();
private:
explicit CompanionTabHelper(content::WebContents* web_contents);
friend class content::WebContentsUserData<CompanionTabHelper>;
// Sets the latest text query and shows the side panel with that query.
void SetTextQuery(const std::string& text_query);
// Sets appropriate source and target language parameters and translate
// filter.
GURL SetImageTranslateQueryParams(GURL upload_url);
// Extracts the text query from a query parameter contained in the search URL.
// Returns an empty string if the value does not exist.
std::string GetTextQueryFromSearchUrl(const GURL& search_url) const;
std::unique_ptr<side_panel::mojom::ImageQuery> image_query_;
std::unique_ptr<Delegate> delegate_;
std::string text_query_;
std::unique_ptr<base::Time> text_query_start_time_;
// Caches the trigger source for an in-progress companion page open action in
// the current tab. Should be cleared after the open action is complete.
std::optional<SidePanelOpenTrigger> side_panel_open_trigger_;
#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
std::unique_ptr<lens::LensRegionSearchController>
lens_region_search_controller_;
#endif // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
// A weak reference to the last-created WebUI object for this web contents.
base::WeakPtr<CompanionPageHandler> companion_page_handler_;
base::WeakPtrFactory<CompanionTabHelper> weak_factory_{this};
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
} // namespace companion
#endif // CHROME_BROWSER_UI_SIDE_PANEL_COMPANION_COMPANION_TAB_HELPER_H_