blob: c235423549d917becf3e0b1515c9d6a46c70190f [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LENS_LENS_OVERLAY_QUERY_CONTROLLER_H_
#define CHROME_BROWSER_UI_LENS_LENS_OVERLAY_QUERY_CONTROLLER_H_
#include <optional>
#include <string>
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h"
#include "chrome/browser/lens/core/mojom/lens.mojom.h"
#include "chrome/browser/lens/core/mojom/overlay_object.mojom.h"
#include "chrome/browser/lens/core/mojom/text.mojom.h"
#include "chrome/browser/ui/lens/lens_overlay_gen204_controller.h"
#include "chrome/browser/ui/lens/lens_overlay_request_id_generator.h"
#include "chrome/browser/ui/lens/lens_overlay_url_builder.h"
#include "chrome/browser/ui/lens/ref_counted_lens_overlay_client_logs.h"
#include "components/endpoint_fetcher/endpoint_fetcher.h"
#include "components/lens/lens_overlay_invocation_source.h"
#include "components/lens/lens_overlay_mime_type.h"
#include "components/lens/proto/server/lens_overlay_response.pb.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "third_party/lens_server_proto/lens_overlay_client_context.pb.h"
#include "third_party/lens_server_proto/lens_overlay_cluster_info.pb.h"
#include "third_party/lens_server_proto/lens_overlay_image_crop.pb.h"
#include "third_party/lens_server_proto/lens_overlay_image_data.pb.h"
#include "third_party/lens_server_proto/lens_overlay_interaction_request_metadata.pb.h"
#include "third_party/lens_server_proto/lens_overlay_selection_type.pb.h"
#include "third_party/lens_server_proto/lens_overlay_server.pb.h"
#include "third_party/lens_server_proto/lens_overlay_service_deps.pb.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
class Profile;
namespace signin {
class IdentityManager;
} // namespace signin
namespace variations {
class VariationsClient;
} // namespace variations
namespace lens {
// Data struct representing content data to be sent to the Lens server.
struct PageContent {
PageContent();
PageContent(std::vector<uint8_t> bytes, lens::MimeType content_type);
PageContent(const PageContent& other);
~PageContent();
public:
std::vector<uint8_t> bytes_;
lens::MimeType content_type_;
};
// Callback type alias for the lens overlay full image response.
using LensOverlayFullImageResponseCallback =
base::RepeatingCallback<void(std::vector<lens::mojom::OverlayObjectPtr>,
lens::mojom::TextPtr,
bool)>;
// Callback type alias for the lens overlay url response.
using LensOverlayUrlResponseCallback =
base::RepeatingCallback<void(lens::proto::LensOverlayUrlResponse)>;
// Callback type alias for the lens overlay interaction response.
using LensOverlayInteractionResponseCallback =
base::RepeatingCallback<void(lens::mojom::TextPtr)>;
// Callback type alias for the lens overlay suggest inputs response.
using LensOverlaySuggestInputsCallback =
base::RepeatingCallback<void(lens::proto::LensOverlaySuggestInputs)>;
// Callback type alias for the thumbnail image creation.
using LensOverlayThumbnailCreatedCallback =
base::RepeatingCallback<void(const std::string&)>;
// Callback type alias for the OAuth headers created.
using OAuthHeadersCreatedCallback =
base::OnceCallback<void(std::vector<std::string>)>;
using UploadProgressCallback =
base::RepeatingCallback<void(uint64_t position, uint64_t total)>;
// Manages queries on behalf of a Lens overlay.
class LensOverlayQueryController {
public:
LensOverlayQueryController(
LensOverlayFullImageResponseCallback full_image_callback,
LensOverlayUrlResponseCallback url_callback,
LensOverlayInteractionResponseCallback interaction_callback,
LensOverlaySuggestInputsCallback suggest_inputs_callback,
LensOverlayThumbnailCreatedCallback thumbnail_created_callback,
UploadProgressCallback page_content_upload_progress_callback,
variations::VariationsClient* variations_client,
signin::IdentityManager* identity_manager,
Profile* profile,
lens::LensOverlayInvocationSource invocation_source,
bool use_dark_mode,
lens::LensOverlayGen204Controller* gen204_controller);
virtual ~LensOverlayQueryController();
// Starts a query flow by sending a request to Lens using the screenshot,
// returning the response to the full image callback. Should be called
// exactly once. Override these methods to stub out network requests for
// testing.
virtual void StartQueryFlow(
const SkBitmap& screenshot,
GURL page_url,
std::optional<std::string> page_title,
std::vector<lens::mojom::CenterRotatedBoxPtr> significant_region_boxes,
base::span<const PageContent> underlying_page_contents,
lens::MimeType primary_content_type,
std::optional<uint32_t> pdf_current_page,
float ui_scale_factor,
base::TimeTicks invocation_time);
// Clears the state and resets stored values.
void EndQuery();
// Restarts the query flow if its in a state where no cluster info is
// available.
void MaybeRestartQueryFlow();
// Sends a full image request to translate the page.
virtual void SendFullPageTranslateQuery(const std::string& source_language,
const std::string& target_language);
// Sends a full image request with no translate options as a result of
// ending translate mode.
virtual void SendEndTranslateModeQuery();
// Resets the page content data to avoid using stale data in the request flow.
// Caller should call this before changing the page content data this class
// points to, to avoid dangling pointers.
virtual void ResetPageContentData();
// Sends requests to the server to update the page content and/or make a new
// full image request.
// The first content data is the most important and will be used for
// generating request types. `primary_content_type` is used for generating the
// request type and vit param.
virtual void SendUpdatedPageContent(
std::optional<base::span<const lens::PageContent>>
underlying_page_contents,
std::optional<lens::MimeType> primary_content_type,
std::optional<GURL> new_page_url,
std::optional<std::string> new_page_title,
std::optional<uint32_t> pdf_current_page,
const SkBitmap& screenshot);
// Sends a request to the server with a portion of the page content.
// `partial_content` should be a subset of the full page content. This request
// is used to give the server an early signal of the page content.
virtual void SendPartialPageContentRequest(
base::span<const std::u16string> partial_content);
// Sends a region search interaction. Expected to be called multiple times. If
// region_bytes are included, those will be sent to Lens instead of cropping
// the region out of the screenshot. This should be used to provide a higher
// definition image than image cropping would provide.
virtual void SendRegionSearch(
lens::mojom::CenterRotatedBoxPtr region,
lens::LensOverlaySelectionType lens_selection_type,
std::map<std::string, std::string> additional_search_query_params,
std::optional<SkBitmap> region_bytes);
// Sends a text-only interaction. Expected to be called multiple times.
virtual void SendTextOnlyQuery(
const std::string& query_text,
lens::LensOverlaySelectionType lens_selection_type,
std::map<std::string, std::string> additional_search_query_params);
// Sends a text query interaction contextualized to the current page. Expected
// to be called multiple times.
virtual void SendContextualTextQuery(
const std::string& query_text,
lens::LensOverlaySelectionType lens_selection_type,
std::map<std::string, std::string> additional_search_query_params);
// Sends a multimodal interaction. Expected to be called multiple times.
virtual void SendMultimodalRequest(
lens::mojom::CenterRotatedBoxPtr region,
const std::string& query_text,
lens::LensOverlaySelectionType lens_selection_type,
std::map<std::string, std::string> additional_search_query_params,
std::optional<SkBitmap> region_bytes);
// Sends a task completion Gen204 ping for certain user actions.
void SendTaskCompletionGen204IfEnabled(lens::mojom::UserAction user_action);
// Sends a semantic event Gen204 ping.
virtual void SendSemanticEventGen204IfEnabled(
lens::mojom::SemanticEvent event);
bool IsPageContentUploadInProgress() const {
return page_content_endpoint_fetcher_.get() != nullptr;
}
uint64_t gen204_id() const { return gen204_id_; }
// Testing method to reset the cluster info state.
void ResetRequestClusterInfoStateForTesting();
// Returns a vsrid string for opening in a new tab, to replace the vsrid in
// an existing query URL. Will not affect the state of this controller's
// request id generator or analytics id.
std::string GetVsridForNewTab();
base::TimeTicks partial_page_contents_request_start_time_for_testing() const {
return partial_page_contents_request_start_time_;
}
lens::LensOverlayRequestIdGenerator* request_id_generator_for_testing() {
return request_id_generator_.get();
}
lens::proto::LensOverlaySuggestInputs suggest_inputs_for_testing() {
return suggest_inputs_;
}
protected:
// Returns the EndpointFetcher to use with the given params. Protected to
// allow overriding in tests to mock server responses.
virtual std::unique_ptr<EndpointFetcher> CreateEndpointFetcher(
std::string request_string,
const GURL& fetch_url,
const HttpMethod& http_method,
const base::TimeDelta& timeout,
const std::vector<std::string>& request_headers,
const std::vector<std::string>& cors_exempt_headers,
const UploadProgressCallback upload_progress_callback);
// Sends a latency Gen204 ping if enabled, calculating the latency duration
// from the start time ticks and base::TimeTicks::Now(). The encoded request
// id is optional because not all latency events have an associated request
// id, such as the cluster info fetch.
virtual void SendLatencyGen204IfEnabled(
lens::LensOverlayGen204Controller::LatencyType latency_type,
base::TimeTicks start_time_ticks,
std::string vit_query_param_value,
std::optional<base::TimeDelta> cluster_info_latency,
std::optional<std::string> encoded_analytics_id,
std::optional<lens::LensOverlayRequestId> request_id);
// Sends a task completion Gen204 ping for certain user actions with
// the given analytics id. Protected to allow overriding in tests to
// check the encoded analytics id and request id.
virtual void SendTaskCompletionGen204IfEnabled(
std::string encoded_analytics_id,
lens::mojom::UserAction user_action,
lens::LensOverlayRequestId request_id);
// Sends a semantic event Gen204 ping. Protected to allow overriding in tests
// to check the request id. The request id can be unset for events that
// do not have an associated request id (e.g. text gleam view end).
virtual void SendSemanticEventGen204IfEnabled(
lens::mojom::SemanticEvent event,
std::optional<lens::LensOverlayRequestId> request_id);
// Updates the suggest inputs with the feature params and latest cluster info
// response, then runs the callback. The request id in the suggest inputs will
// if the parameter is not null.
virtual void RunSuggestInputsCallback();
// The callback for full image requests, including upon query flow start
// and interaction retries.
LensOverlayFullImageResponseCallback full_image_callback_;
// The callback for interaction requests, including text received.
LensOverlayInteractionResponseCallback interaction_response_callback_;
// Suggest inputs callback, used for sending Lens suggest data to the
// search box.
LensOverlaySuggestInputsCallback suggest_inputs_callback_;
// Callback for when a thumbnail image is created from a region selection.
LensOverlayThumbnailCreatedCallback thumbnail_created_callback_;
// Callback for when the page content upload progress is updated.
UploadProgressCallback page_content_upload_progress_callback_;
private:
enum class QueryControllerState {
// StartQueryFlow has not been called and the query controller is
// inactive.
kOff = 0,
// StartQueryFlow has been called, but the cluster info has not been
// received so we cannot proceed to sending the full image request.
kAwaitingClusterInfoResponse = 1,
// The cluster info response has been received so we can proceed to sending
// the full image request.
kReceivedClusterInfoResponse = 2,
// The full image response has not been received, or is no longer valid.
kAwaitingFullImageResponse = 3,
// The full image response has been received and the query controller can
// send interaction requests.
kReceivedFullImageResponse = 4,
// The full image response has been received and resulted in an error
// response.
kReceivedFullImageErrorResponse = 5,
// The cluster info has expired and a new query flow needs to be started.
kClusterInfoExpired = 6,
};
// Data class for constructing a fetch request to the Lens servers.
// All fields that are required for the request should use std::unique_ptr to
// validate all fields are non-null prior to making a request. If a field does
// not need to be set, but should be included if it is set, use std::optional.
struct LensServerFetchRequest {
public:
LensServerFetchRequest(
std::unique_ptr<lens::LensOverlayRequestId> request_id,
base::TimeTicks query_start_time);
~LensServerFetchRequest();
// Returns the sequence ID of the request this data belongs to. Used
// for cancelling any requests that have been superseded by another.
int sequence_id() const { return request_id_->sequence_id(); }
// The request ID for this request.
const std::unique_ptr<lens::LensOverlayRequestId> request_id_;
// The start time of the query.
const base::TimeTicks query_start_time_;
// The request to be sent to the server. Must be set prior to making the
// request.
std::unique_ptr<lens::LensOverlayServerRequest> request_;
// The headers to attach to the request.
std::unique_ptr<std::vector<std::string>> request_headers_;
// A callback to run once the request has been sent. This is optional, but
// can be used to run some logic once the request has been sent.
std::optional<base::OnceClosure> request_sent_callback_;
};
// Updates the request id based on the given update mode and returns the
// request id proto. Also updates the suggest signals with the new request id
// and runs the suggest inputs callback.
std::unique_ptr<lens::LensOverlayRequestId> GetNextRequestId(
RequestIdUpdateMode update_mode);
// Makes a LensOverlayServerClusterInfoRequest to get the cluster info. Will
// continue to the FullImageRequest once a response is received.
void FetchClusterInfoRequest();
// Creates the endpoint fetcher and sends the cluster info request.
void PerformClusterInfoFetchRequest(base::TimeTicks query_start_time,
std::vector<std::string> request_headers);
// Handles the response from the cluster info request. If a successful request
// was made, kicks off the full image request to use the retrieved server
// session id. If the request failed, the full image request will still be
// tried, just without the server session id.
void ClusterInfoFetchResponseHandler(
base::TimeTicks query_start_time,
std::unique_ptr<EndpointResponse> response);
// Processes the screenshot and fetches a full image request.
void PrepareAndFetchFullImageRequest();
// Does any preprocessing on the image data outside of encoding the
// screenshot bytes that needs to be done before attaching the ImageData to
// the full image request.
void PrepareImageDataForFullImageRequest(
scoped_refptr<lens::RefCountedLensOverlayClientLogs> ref_counted_logs,
lens::ImageData image_data);
// Creates the FullImageRequest that is sent to the server and tries to
// perform the request. If all async flows have not finished, the attempt to
// perform the request will be ignored, and the last async flow to finish
// will perform the request.
void CreateFullImageRequestAndTryPerformFullImageRequest(
int sequence_id,
scoped_refptr<lens::RefCountedLensOverlayClientLogs> ref_counted_logs,
lens::ImageData image_data);
// Creates the OAuth headers to be used in the full image request. If the
// users OAuth is unavailable, will fallback to using the API key. If all
// async flows have not finished, the attempt to perform the request will be
// ignored, and the last async flow to finish will perform the request.
void CreateOAuthHeadersAndTryPerformFullPageRequest(int sequence_id);
// Called when an asynchronous piece of data needed to make the full image
// request is ready. Once this has been invoked with every necessary piece of
// data with the same sequence_id, it will call PerformFullImageRequest to
// send the request to the server. Ignores any data received from an old
// sequence_id.
void FullImageRequestDataReady(int sequence_id,
lens::LensOverlayServerRequest request);
void FullImageRequestDataReady(int sequence_id,
std::vector<std::string> headers);
// Helper to the above, used to actually validate the data prior to calling
// PerformFullImageRequest().
void FullImageRequestDataHelper(int sequence_id);
// Verifies the given sequence_id is still the most recent.
bool IsCurrentFullImageSequence(int sequence_id);
// Creates the endpoint fetcher and send the full image request to the server.
void PerformFullImageRequest();
// Handles the endpoint fetch response for the full image request.
void FullImageFetchResponseHandler(
int request_sequence_id,
std::unique_ptr<EndpointResponse> response);
// Runs the full image callback with empty response data, for errors.
void RunFullImageCallbackForError();
// Prepares the data needed for the page content request (aka compression) and
// then sends the request.
void PrepareAndFetchPageContentRequest();
// Creates chunk upload requests for the given chunks.
void PrepareAndFetchUploadChunkRequests(lens::LensOverlayRequestId request_id,
std::vector<std::string> chunks);
// Performs the chunk upload requests.
void PrepareAndFetchUploadChunkRequestsPart2(
std::vector<std::string> headers);
// Performs the chunk upload request with the given index.
void FetchUploadChunkRequest(size_t chunk_request_index);
// Handles the endpoint fetch response for chunk upload requests. When a
// response is received for the last chunk, initiates the page content
// request.
void UploadChunkResponseHandler(lens::LensOverlayRequestId request_id,
size_t total_chunks,
std::unique_ptr<EndpointResponse> response);
// Creates the PageContentRequest that is sent to the server and performs the
// request. Prefer to use PrepareAndFetchPageContentRequest() directly since
// it calls this method after doing the necessary preprocessing. By this
// point, the preprocessing should be complete and it is expected that the
// request will be sent. If a check needs to be done before sending the
// request, it myst be done in PrepareAndFetchPageContentRequest() instead of
// this method.
void PrepareAndFetchPageContentRequestPart2(
lens::LensOverlayRequestId request_id,
lens::Payload payload);
// Performs the page content request. This is a send and forget request, so we
// are not expecting a response.
void PerformPageContentRequest(lens::LensOverlayServerRequest request,
std::vector<std::string> headers);
// Handles the endpoint fetch response for the page content request.
void PageContentResponseHandler(lens::LensOverlayRequestId request_id,
std::unique_ptr<EndpointResponse> response);
// Handles the prgress of the page content upload request.
void PageContentUploadProgressHandler(uint64_t position, uint64_t total);
// Marks that the page content upload is no longer in progress and sends the
// pending contextual query.
void PageContentUploadFinished();
// Creates a full image request with the partial page content bytes and sends
// it to the server.
void PrepareAndFetchPartialPageContentRequest();
// Performs the partial page content request. This is a send and forget
// request, so we are not expecting to use the response.
void PerformPartialPageContentRequest(lens::LensOverlayServerRequest request,
std::vector<std::string> headers);
// Handles the endpoint fetch response for the partial page content request.
void PartialPageContentResponseHandler(
lens::LensOverlayRequestId request_id,
std::unique_ptr<EndpointResponse> response);
// Sends the interaction data, triggering async image cropping and fetching
// the request.
void SendInteraction(
lens::mojom::CenterRotatedBoxPtr region,
std::optional<std::string> query_text,
std::optional<std::string> object_id,
lens::LensOverlaySelectionType selection_type,
std::map<std::string, std::string> additional_search_query_params,
std::optional<SkBitmap> region_bytes);
// Creates the interaction request that is sent to the server and tries to
// perform the interaction request. If not all asynchronous flows have
// finished, the attempt to perform the request will be ignored. Only the last
// asynchronous flow to finish will perform the request.
void CreateInteractionRequestAndTryPerformInteractionRequest(
int sequence_id,
lens::mojom::CenterRotatedBoxPtr region,
std::optional<std::string> query_text,
std::optional<std::string> object_id,
scoped_refptr<lens::RefCountedLensOverlayClientLogs> ref_counted_logs,
std::optional<lens::ImageCrop> image_crop);
// Creates the OAuth headers that get attached to the interaction request to
// authenticate the user. After, tries to perform the interaction request. If
// not all asynchronous flows have finished, the attempt to perform the
// request will be ignored. Only the last asynchronous flow to finish will
// perform the request.
void CreateOAuthHeadersAndTryPerformInteractionRequest(int sequence_id);
// Called when an asynchronous piece of data needed to make the interaction
// request is ready. Once this has been invoked with every necessary piece of
// data with the same sequence_id, it will call PerformInteractionRequest to
// send the request to the server. Ignores any data received from an old
// sequence_id.
void InteractionRequestDataReady(int sequence_id,
lens::LensOverlayServerRequest request);
void InteractionRequestDataReady(int sequence_id,
std::vector<std::string> headers);
// If all data needed to PerformInteractionRequest is available, will call
// PerformInteractionRequest to fetch the request. If any async flow has not
// finished, it will ignore the request with the assumption
// TryPerformInteractionRequest will be called again once the flow has
// finished. Will also ensure the full image response has been received. If
// the full image response has not been received, will kick off the full image
// response flow with a callback to send this interaction request after.
void TryPerformInteractionRequest(int sequence_id);
// Verifies the given sequence_id is still the most recent.
bool IsCurrentInteractionSequence(int sequence_id);
// Creates the endpoint fetcher and send the full image request to the server.
void PerformInteractionRequest();
// Creates the URL to load in the side panel and sends it to the callback.
void CreateSearchUrlAndSendToCallback(
std::optional<std::string> query_text,
std::map<std::string, std::string> additional_search_query_params,
lens::LensOverlaySelectionType selection_type,
std::unique_ptr<lens::LensOverlayRequestId> request_id);
// Handles the endpoint fetch response for an interaction request.
void InteractionFetchResponseHandler(
int sequence_id,
std::unique_ptr<EndpointResponse> response);
// Runs the interaction callback with empty response data, for errors.
void RunInteractionCallbackForError();
// Sends a full image request latency Gen204 ping if enabled. Also logs the
// cluster info latency if it is available.
void SendFullImageLatencyGen204IfEnabled(base::TimeTicks start_time_ticks,
bool is_translate_query,
std::string vit_query_param_value);
// Logs a latency gen204 for an initial latency gen204, only once per type
// per query flow, if gen204 logging is enabled.
void SendInitialLatencyGen204IfNotAlreadySent(
lens::LensOverlayGen204Controller::LatencyType latency_type,
std::string vit_query_param_value,
std::optional<lens::LensOverlayRequestId> request_id);
// Performs the given server request.
void PerformFetchRequest(
lens::LensOverlayServerRequest* request,
std::vector<std::string>* request_headers,
const base::TimeDelta& timeout,
base::OnceCallback<void(std::unique_ptr<EndpointFetcher>)>
fetcher_created_callback,
EndpointFetcherCallback response_received_callback,
const UploadProgressCallback upload_progress_callback =
base::NullCallback());
// Creates an endpoint fetcher with the given request_headers to perform the
// given request. Calls fetcher_created_callback when the EndpointFetcher is
// created to keep it alive while the request is being made.
// response_received_callback is invoked once the request returns a response.
void PerformFetchRequest(
std::string request_string,
std::vector<std::string>* request_headers,
const base::TimeDelta& timeout,
base::OnceCallback<void(std::unique_ptr<EndpointFetcher>)>
fetcher_created_callback,
EndpointFetcherCallback response_received_callback,
const UploadProgressCallback upload_progress_callback,
GURL fetch_url);
// Creates a client context proto to be attached to a server request.
lens::LensOverlayClientContext CreateClientContext();
// Fetches the OAuth headers and calls the callback with the headers. If the
// OAuth cannot be retrieve (like if the user is not logged in), the callback
// will be called with an empty vector. Returns the access token fetcher
// making the request so it can be kept alive.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
CreateOAuthHeadersAndContinue(OAuthHeadersCreatedCallback callback);
// Gets the visual search interaction log data param as a base64url
// encoded string.
std::string GetEncodedVisualSearchInteractionLogData(
lens::LensOverlaySelectionType selection_type);
// Creates the metadata for an interaction request using the latest
// interaction and image crop data.
lens::LensOverlayServerRequest CreateInteractionRequest(
lens::mojom::CenterRotatedBoxPtr region,
std::optional<std::string> query_text,
std::optional<std::string> object_id,
std::optional<lens::ImageCrop> image_crop,
lens::LensOverlayClientLogs client_logs);
// Resets the request cluster info state.
void ResetRequestClusterInfoState();
// Callback for when the interaction response returned text that should be
// passed to the overlay.
void RunInteractionResponseTextReceivedCallback(lens::mojom::TextPtr text);
// Callback for when the full image endpoint fetcher is created.
void OnFullImageEndpointFetcherCreated(
lens::LensOverlayRequestId request_id,
std::unique_ptr<EndpointFetcher> endpoint_fetcher);
// Callback for when the page content endpoint fetcher is created.
void OnPageContentEndpointFetcherCreated(
lens::LensOverlayRequestId request_id,
std::unique_ptr<EndpointFetcher> endpoint_fetcher);
// Callback for when the partial page content endpoint fetcher is created.
void OnPartialPageContentEndpointFetcherCreated(
lens::LensOverlayRequestId request_id,
std::unique_ptr<EndpointFetcher> endpoint_fetcher);
// Callback for when the interaction endpoint fetcher is created.
void OnInteractionEndpointFetcherCreated(
lens::LensOverlayRequestId request_id,
std::unique_ptr<EndpointFetcher> endpoint_fetcher);
// Callback for when a chunk upload endpoint fetcher is created.
void OnChunkUploadEndpointFetcherCreated(
lens::LensOverlayRequestId request_id,
std::unique_ptr<EndpointFetcher> endpoint_fetcher);
// Returns whether or not the contextual search query should be sent now or
// held until the full page content upload is finished. This is only true if
// the page content upload is finished and the cluster info is available. If
// the cluster info is not available, the query should be held until the
// cluster info becomes available.
bool ShouldSendContextualSearchQuery();
// Returns whether the partial page content contains enough text to yield
// detailed enough results.
bool IsPartialPageContentSubstantial();
// The request id generator.
std::unique_ptr<lens::LensOverlayRequestIdGenerator> request_id_generator_;
// The original screenshot image.
SkBitmap original_screenshot_;
// The dimensions of the resized bitmap. Needed in case geometry needs to be
// recaclulated. For example, in the case of translated words.
gfx::Size resized_bitmap_size_;
// The page url. Empty if it is not allowed to be shared.
GURL page_url_;
// The page title, if it is allowed to be shared.
std::optional<std::string> page_title_;
// The current page of the PDF document if page_content_type_ is kPdf.
std::optional<uint32_t> pdf_current_page_;
// Options needed to send a translate request with the proper parameters.
struct TranslateOptions {
std::string source_language;
std::string target_language;
TranslateOptions(const std::string& source, const std::string& target)
: source_language(source), target_language(target) {}
};
std::optional<TranslateOptions> translate_options_;
// Bounding boxes for significant regions identified in the original
// screenshot image.
std::vector<lens::mojom::CenterRotatedBoxPtr> significant_region_boxes_;
// The UI Scaling Factor of the underlying page, if it has been passed in.
// Else 0.
float ui_scale_factor_ = 0;
// The time the query flow was invoked.
base::TimeTicks invocation_time_;
// The time the page contents request was started.
base::TimeTicks page_contents_request_start_time_;
// The time the partial page contents request was started.
base::TimeTicks partial_page_contents_request_start_time_;
// The current state.
QueryControllerState query_controller_state_ = QueryControllerState::kOff;
// The callback for full image requests, including upon query flow start
// and interaction retries.
LensOverlayUrlResponseCallback url_callback_;
// The last received cluster info.
std::optional<lens::LensOverlayClusterInfo> cluster_info_ = std::nullopt;
// The callback for issuing a pending interaction request. Will be used to
// send the interaction request after the cluster info is available and the
// full image request id sequence is ready, if the interaction occurred
// before the full image response was received.
base::OnceClosure pending_interaction_callback_;
// TODO(b/370805019): All our flows are requesting the same headers, so
// ideally we use one fetcher that returns the same headers wherever they are
// needed.
// The access token fetcher used for getting OAuth for cluster info requests.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
cluster_info_access_token_fetcher_;
// The access token fetcher used for getting OAuth for full image requests.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
full_image_access_token_fetcher_;
// The access token fetcher used for getting OAuth for chunk upload requests.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
chunk_upload_access_token_fetcher_;
// The access token fetcher used for getting OAuth for page content requests.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
page_content_access_token_fetcher_;
// The access token fetcher used for getting OAuth for partial page content
// requests.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
partial_page_content_access_token_fetcher_;
// The access token fetcher used for getting OAuth for interaction requests.
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
interaction_access_token_fetcher_;
// The request id to use for the first batch of requests. The requests sent on
// the start of the query flow will use this request id. Subsequent requests
// will use the request id generator.
std::unique_ptr<lens::LensOverlayRequestId> initial_request_id_;
// The data for the full image request in progress. Is null if no full image
// request has been made.
std::unique_ptr<LensServerFetchRequest> latest_full_image_request_data_;
// The data for the interaction request in progress. Is null if no interaction
// request has been made.
std::unique_ptr<LensServerFetchRequest> latest_interaction_request_data_;
// The endpoint fetcher used for the cluster info request.
std::unique_ptr<EndpointFetcher> cluster_info_endpoint_fetcher_;
// The endpoint fetcher used for the full image request.
std::unique_ptr<EndpointFetcher> full_image_endpoint_fetcher_;
// The endpoint fetcher used for the page content request.
std::unique_ptr<EndpointFetcher> page_content_endpoint_fetcher_;
// The endpoint fetcher used for the partial page content request.
std::unique_ptr<EndpointFetcher> partial_page_content_endpoint_fetcher_;
// The endpoint fetcher used for the interaction request. Only the last
// endpoint fetcher is kept; additional fetch requests will discard
// earlier unfinished requests.
std::unique_ptr<EndpointFetcher> interaction_endpoint_fetcher_;
// The endpoint fetchers used for the chunk upload requests.
std::vector<std::unique_ptr<EndpointFetcher>> chunk_upload_endpoint_fetchers_;
// Task runner used to compress page content bytes on a separate thread.
scoped_refptr<base::TaskRunner> compression_task_runner_;
// Tracks the compress tasks currently running for page content requests.
std::unique_ptr<base::CancelableTaskTracker> compression_task_tracker_;
// Task runner used to encode/downscale the JPEG images on a separate thread.
scoped_refptr<base::TaskRunner> encoding_task_runner_;
// Tracks the encoding/downscaling tasks currently running for follow up
// interactions. Does not track the encoding for the full image request
// because it is assumed this request will finish, never need to be
// cancelled, and all other tasks will wait on it if needed.
std::unique_ptr<base::CancelableTaskTracker> encoding_task_tracker_;
// Bounding boxes for significant regions identified in the original
// screenshot image.
std::vector<lens::LensOverlayUploadChunkRequest>
pending_upload_chunk_requests_;
std::vector<std::string> pending_upload_chunk_headers_;
// The current suggest inputs. The fields in this proto are updated
// whenever new data is available (i.e. after an objects or interaction
// response is received) and the overlay controller notified via the
// suggest inputs callback.
lens::proto::LensOverlaySuggestInputs suggest_inputs_;
// Owned by Profile, and thus guaranteed to outlive this instance.
const raw_ptr<variations::VariationsClient> variations_client_;
// Unowned IdentityManager for fetching access tokens. Could be null for
// incognito profiles.
const raw_ptr<signin::IdentityManager> identity_manager_;
const raw_ptr<Profile> profile_;
// The data of the content the user is viewing. Owned by
// LensOverlayController. Will be empty if no data to the underlying page
// could be provided.
base::raw_span<const PageContent> underlying_page_contents_;
// The primary content type the underlying_page_contents_ is associated with.
// This MimeType is used for generating the request type and vit param.
lens::MimeType primary_content_type_;
// A span of text that represents a part of the content held in underlying
// content bytes.
base::raw_span<const std::u16string> partial_content_;
// Whether or not the parent interaction query has been sent. This should
// always be the first interaction in a query flow.
bool parent_query_sent_ = false;
// Whether or not a page content upload request is in progress.
bool page_content_request_in_progress_ = false;
// Callback for a pending contextual query that is waiting for the page
// content request to finish uploading.
base::OnceClosure pending_contextual_query_callback_;
// Whether or not this is the first page contents request being sent to the
// server. Used to determine whether or not to generate a new request id for
// the next request.
bool is_first_page_contents_request_ = true;
// Whether or not this is the first partial page contents request being sent
// to the server. Used to determine whether or not to generate a new request
// id for the next request.
bool is_first_partial_page_contents_request_ = true;
// The invocation source that triggered the query flow.
lens::LensOverlayInvocationSource invocation_source_;
// Whether or not to use dark mode in search urls. This is only calculated
// once per session because the search box theme is also only set once
// per session.
bool use_dark_mode_;
// The controller for sending gen204 pings. Owned and set by the overlay
// controller. Guaranteed to outlive this class.
const raw_ptr<lens::LensOverlayGen204Controller> gen204_controller_;
// The current gen204 id for logging, set on each overlay invocation.
uint64_t gen204_id_ = 0;
// The latest request id. Updated on each full-image and interaction
// request. This may differ from the request id in the
// latest_interaction_request_data_ if the user makes a text-only query,
// because no interaction request is made in that case even though the request
// id is incremented.
lens::LensOverlayRequestId latest_request_id_;
// The latest encoded analytics id. Updated on each full-image and
// interaction request. This may differ from the analytics id in the
// latest_interaction_request_data_ if the user makes a text-only query,
// because no interaction request is made in that case even though the
// request id is incremented. This is always equal to the analytics id in the
// latest_request_id_ field.
std::string latest_encoded_analytics_id_;
// The time it took from sending the cluster info request to receiving
// the response.
std::optional<base::TimeDelta> cluster_info_fetch_response_time_;
// Latency event gen204 request tracker. Used to determine whether or not to
// log initial latency metrics for the request. This is only used to track
// latency events that should only be logged once per query flow.
base::flat_set<lens::LensOverlayGen204Controller::LatencyType>
sent_initial_latency_request_events_;
base::WeakPtrFactory<LensOverlayQueryController> weak_ptr_factory_{this};
};
} // namespace lens
#endif // CHROME_BROWSER_UI_LENS_LENS_OVERLAY_QUERY_CONTROLLER_H_