1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
// Copyright 2025 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_LENS_LENS_SEARCHBOX_CONTROLLER_H_
#define CHROME_BROWSER_UI_LENS_LENS_SEARCHBOX_CONTROLLER_H_
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/lens/core/mojom/lens_ghost_loader.mojom.h"
#include "chrome/browser/lens/core/mojom/lens_side_panel.mojom.h"
#include "chrome/browser/ui/webui/searchbox/lens_searchbox_client.h"
#include "chrome/browser/ui/webui/searchbox/lens_searchbox_handler.h"
#include "components/lens/proto/server/lens_overlay_response.pb.h"
#include "components/omnibox/browser/lens_suggest_inputs_utils.h"
#include "components/sessions/core/session_id.h"
#include "content/public/browser/web_contents.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
#include "url/gurl.h"
class LensSearchController;
using GetIsContextualSearchboxCallback =
lens::mojom::LensSidePanelPageHandler::GetIsContextualSearchboxCallback;
namespace lens {
struct SearchQuery;
// Controller for the Lens searchbox. This class is responsible for handling
// communications between the Lens WebUI searchbox and other Lens components.
// This class is responsible for both the overlay and side panel searchboxes.
class LensSearchboxController : public LensSearchboxClient {
public:
explicit LensSearchboxController(
LensSearchController* lens_search_controller);
~LensSearchboxController() override;
// This method is used to set up communication between this instance and the
// overlay ghost loader's WebUI. This is called by the WebUIController when
// the WebUI is executing javascript and ready to bind.
void BindOverlayGhostLoader(
mojo::PendingRemote<lens::mojom::LensGhostLoaderPage> page);
// This method is used to set up communication between this instance and the
// side panel's ghost loader WebUI. This is called by the WebUIController
// when the WebUI is executing javascript and ready to bind.
void BindSidePanelGhostLoader(
mojo::PendingRemote<lens::mojom::LensGhostLoaderPage> page);
// Must be called at the start of a session so the proper state is
// initialized.
void OnSessionStart();
// This method is used to set up communication between this instance and the
// searchbox WebUI. This is called by the WebUIController when the WebUI is
// executing javascript and has bound the handler. Takes ownership of
// `handler`.
void SetSidePanelSearchboxHandler(
std::unique_ptr<LensSearchboxHandler> handler);
// Passes ownership of the lens searchbox handler to the search bubble
// controller. This is called by the WebUIController when the WebUI is
// executing javascript and has bound the handler.
void SetContextualSearchboxHandler(
std::unique_ptr<LensSearchboxHandler> handler);
// This method is used to release the owned `SearchboxHandler` for the
// overlay. It should be called before the overlay web contents is destroyed
// since it contains a reference to that web contents.
void ResetOverlaySearchboxHandler();
// This method is used to release the owned `SearchboxHandler`. It should be
// called before the side panel web contents is destroyed since it contains a
// reference to that web contents.
void ResetSidePanelSearchboxHandler();
// Sets the input text for the searchbox. If the searchbox has not been bound,
// it stores it in `pending_text_query_` instead.
void SetSearchboxInputText(const std::string& text);
// Sets the thumbnail URI values on the searchbox if it is
// bound. If it hasn't yet been bound, stores the value in
// `pending_thumbnail_uri_` instead.
void SetSearchboxThumbnail(const std::string& thumbnail_uri);
// Handles the create of a new thumbnail from a bitmap.
void HandleThumbnailCreatedBitmap(const SkBitmap& thumbnail);
// Handles the creation of a new thumbnail based on the user selection.
void HandleThumbnailCreated(const std::string& thumbnail_bytes);
// Handles an update to the suggest inputs. This will be called whenever
// any part of the suggest inputs changes, such as when a new objects
// request is sent, or when an interaction data response is received.
void HandleSuggestInputsResponse(
lens::proto::LensOverlaySuggestInputs suggest_inputs);
// Cleans up internal state associated with the searchbox.
void CloseUI();
// Gets whether this is currently a contextual searchbox.
bool IsContextualSearchbox() const;
// Gets whether this searchbox is currently in the side panel. False if it is
// in the overlay.
bool IsSidePanelSearchbox() const;
// Returns whether the searchbox is in contextual mode by passing the result
// of IsContextualSearchbox() to the callback.
void GetIsContextualSearchbox(GetIsContextualSearchboxCallback callback);
// Waits for the handshake with the Lens backend to complete and then invokes
// the callback with the LensOverlaySuggestInputs. Callback will be invoked
// immediately if the handshake is already complete.
base::CallbackListSubscription GetLensSuggestInputsWhenReady(
::LensOverlaySuggestInputsCallback callback);
// Overridden from LensSearchboxClient:
const GURL& GetPageURL() const override;
SessionID GetTabId() const override;
metrics::OmniboxEventProto::PageClassification GetPageClassification()
const override;
std::string& GetThumbnail() override;
const lens::proto::LensOverlaySuggestInputs& GetLensSuggestInputs()
const override;
void OnTextModified() override;
void OnThumbnailRemoved() override;
void OnSuggestionAccepted(const GURL& destination_url,
AutocompleteMatchType::Type match_type,
bool is_zero_prefix_suggestion) override;
void OnFocusChanged(bool focused) override;
void OnPageBound() override;
void ShowGhostLoaderErrorState() override;
void OnZeroSuggestShown() override;
// Adds searchbox related state to the search query.
void AddSearchboxStateToSearchQuery(lens::SearchQuery& search_query);
private:
// Data class for storing state for the searchbox.
struct LensSearchboxInitializationData {
public:
LensSearchboxInitializationData() = default;
~LensSearchboxInitializationData() = default;
// The text query in the searchbox.
std::string text_query = "";
// The URI of the thumbnail in the searchbox.
std::string thumbnail_uri = "";
// The latest suggest inputs from the query controller.
lens::proto::LensOverlaySuggestInputs suggest_inputs_;
};
// Called on the UI thread with the processed thumbnail URI.
void OnThumbnailProcessed(const std::string& thumbnail_uri);
// Returns the WebContents associated with the tab this instance of Lens is
// invoked on.
content::WebContents* GetTabWebContents() const;
// Owns this.
const raw_ptr<LensSearchController> lens_search_controller_;
// The callbacks pending the handshake to complete so the Lens suggest inputs
// can be retrieved.
base::OnceCallbackList<void(
std::optional<lens::proto::LensOverlaySuggestInputs>)>
pending_suggest_inputs_callbacks_;
// Searchbox handler for passing in image and text selections. The handler is
// null if the WebUI containing the searchbox has not been initialized yet,
// like in the case of side panel opening. In addition, the handler may be
// initialized, but the remote not yet set because the WebUI calls SetPage()
// once it is ready to receive data from C++. Therefore, we must always check
// that:
// 1) searchbox_handler_ exists and
// 2) searchbox_handler_->IsRemoteBound() is true.
std::unique_ptr<LensSearchboxHandler> side_panel_searchbox_handler_;
// Handler for the contextual searchbox in the overlay. The handler is
// null if the WebUI containing the searchbox has not been initialized yet.
// In addition, the handler may be initialized, but the remote not yet set
// because the WebUI calls SetPage() once it is ready to receive data from
// C++. Therefore, we must always check that:
// 1) contextual_searchbox_handler_ exists and
// 2) contextual_searchbox_handler_->IsRemoteBound() is true.
// TODO(crbug.com/404941800): Does this actually need to be kept alive? Its
// currently unused.
std::unique_ptr<LensSearchboxHandler> overlay_searchbox_handler_;
// Connections to the overlay ghost loader WebUI. Only valid while
// `overlay_view_` is showing, and after the WebUI has started executing JS
// and has bound the connection.
mojo::Remote<lens::mojom::LensGhostLoaderPage> overlay_ghost_loader_page_;
// Connections to the side panel ghost loader WebUI. Only valid when the side
// panel is currently open and after the WebUI has started executing JS and
// has bound the connection.
mojo::Remote<lens::mojom::LensGhostLoaderPage> side_panel_ghost_loader_page_;
// The assembly data needed for the side panel entry to be created and shown.
std::unique_ptr<LensSearchboxInitializationData> init_data_;
// A pending text query to be loaded in the side panel. Needed when the side
// panel is not bound at the time of a text request.
std::optional<std::string> pending_text_query_ = std::nullopt;
// A pending thumbnail URI to be loaded in the side panel. Needed when the
// side panel is not bound at the time of a region request.
std::optional<std::string> pending_thumbnail_uri_ = std::nullopt;
// Must be last member.
base::WeakPtrFactory<LensSearchboxController> weak_factory_{this};
};
} // namespace lens
#endif // CHROME_BROWSER_UI_LENS_LENS_SEARCHBOX_CONTROLLER_H_
|