blob: 13d6fc05b6706f1391a8f163b43bc74155408482 [file] [log] [blame]
// 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 COMPONENTS_LENS_TAB_CONTEXTUALIZATION_CONTROLLER_H_
#define COMPONENTS_LENS_TAB_CONTEXTUALIZATION_CONTROLLER_H_
#include <memory>
#include <optional>
#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/task_runner.h"
#include "components/lens/contextual_input.h"
#include "components/lens/lens_bitmap_processing.h"
#include "components/tabs/public/tab_interface.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "pdf/buildflags.h"
#include "ui/base/unowned_user_data/scoped_unowned_user_data.h"
#if BUILDFLAG(ENABLE_PDF)
#include "components/pdf/browser/pdf_document_helper.h"
#include "pdf/mojom/pdf.mojom.h"
#endif // BUILDFLAG(ENABLE_PDF)
namespace viz {
struct CopyOutputBitmapWithMetadata;
} // namespace viz
namespace optimization_guide {
class PageContextEligibility;
struct AIPageContentResult;
} // namespace optimization_guide
namespace lens {
class TabContextualizationController : public content::WebContentsObserver {
public:
explicit TabContextualizationController(tabs::TabInterface* tab);
~TabContextualizationController() override;
DECLARE_USER_DATA(TabContextualizationController);
static TabContextualizationController* From(tabs::TabInterface* tab);
// Callback type alias for when the page context is retrieved.
using GetPageContextCallback = base::OnceCallback<void(
std::unique_ptr<lens::ContextualInputData> page_content_data)>;
// Callback type alias for when the page context and eligibility are
// retrieved. The frame metadata will be empty if the page is not eligible.
using GetApcResultCallback = base::OnceCallback<void(
bool page_context_eligible,
std::optional<optimization_guide::AIPageContentResult> apc)>;
// Callback type alias for when the annotated page content is retrieved.
using GetAnnotatedPageContentCallback = base::OnceCallback<void(
std::optional<optimization_guide::AIPageContentResult> result)>;
// Callback type alias for when the screenshot is captured.
using CaptureScreenshotCallback = base::OnceCallback<void(const SkBitmap&)>;
// Triggers initial page context eligibility check on the current page.
// Equivalent to calling `optimization_guide::IsPageContextEligible()` with
// empty frame_metadata. Only needed for the Chromnient use case, lower
// priority to implement.
void GetInitialPageContextEligibility(GetApcResultCallback callback);
// Returns whether the page is context eligible based on the latest cached
// state. If the page context eligibility API has not been loaded, this will
// return false. Only needed for the Chromnient use case, lower priority to
// implement.
bool GetCurrentPageContextEligibility();
// Gets contextual page content for the tab.
virtual void GetPageContext(GetPageContextCallback callback);
// Updates current page eligibility once received.
void OnEligibilityChecked(
bool is_page_context_eligible,
std::optional<optimization_guide::AIPageContentResult> apc);
// Starts the steps needed to update the page context eligibility.
void UpdatePageContextEligibility(GetApcResultCallback callback);
// Captures a screenshot of the current tab's viewport, downscales it if
// necessary, and calls the callback with the screenshot.
virtual void CaptureScreenshot(
std::optional<lens::ImageEncodingOptions> image_options,
CaptureScreenshotCallback callback);
private:
// Creates the eligibility API if it has not been created.
void CreatePageContextEligibilityAPI();
// Called when the page context eligibility API is loaded.
void OnPageContextEligibilityAPILoaded(
optimization_guide::PageContextEligibility* page_context_eligibility);
// content::WebContentsObserver:
void PrimaryPageChanged(content::Page& page) override;
// TabInterface::WillDiscardContentsCallback:
void WillDiscardContents(tabs::TabInterface* tab,
content::WebContents* old_contents,
content::WebContents* new_contents);
// Gets the annotated page content from the page context eligibility API.
void GetAnnotatedPageContent(GetAnnotatedPageContentCallback callback);
// Callback for when the annotated page content is received. Checks if the
// page is eligible and returns the result to the callback.
void OnAnnotatedPageContentReceived(
GetApcResultCallback callback,
std::optional<optimization_guide::AIPageContentResult> result);
// GetApcResultCallback for when the APC and eligibility are received
// for the GetPageContext flow. Adds the APC to the contextual input data and
// returns it to the callback.
void OnApcAndEligibilityReceivedForGetPageContext(
GetPageContextCallback callback,
std::unique_ptr<lens::ContextualInputData> data,
bool page_context_eligible,
std::optional<optimization_guide::AIPageContentResult> result);
#if BUILDFLAG(ENABLE_PDF)
// Callback for when the PDF bytes are received. Triggers the PDF page
// index fetch and adds the pdf data to the contextual input data.
void OnPdfBytesReceived(std::unique_ptr<lens::ContextualInputData> data,
GetPageContextCallback callback,
pdf::mojom::PdfListener::GetPdfBytesStatus status,
const std::vector<uint8_t>& bytes,
uint32_t page_count);
// Callback for when the PDF page index is received.
// Adds the PDF page index to the contextual input data and returns it to the
// callback.
void OnPdfPageIndexReceived(std::unique_ptr<lens::ContextualInputData> data,
GetPageContextCallback callback,
std::optional<uint32_t> page_index);
#endif // BUILDFLAG(ENABLE_PDF)
// Downscales the screenshot if it exceeds the max dimension and calls the
// callback with the downscaled screenshot.
void DownscaleScreenshotAndContinue(
base::ScopedClosureRunner decrement_capturer_count_runner,
std::optional<lens::ImageEncodingOptions> image_options,
CaptureScreenshotCallback callback,
const viz::CopyOutputBitmapWithMetadata& result);
// Called when screenshot is captured. Calls the callback with the supplied
// contextual input data including the screenshot.
void AddScreenshotToContextDataAndContinue(
GetPageContextCallback callback,
std::unique_ptr<lens::ContextualInputData> data,
const SkBitmap& screenshot);
// The page context eligibility API if it has been fetched. Can be nullptr.
raw_ptr<optimization_guide::PageContextEligibility>
page_context_eligibility_ = nullptr;
::ui::ScopedUnownedUserData<TabContextualizationController>
scoped_unowned_user_data_;
const raw_ptr<tabs::TabInterface> tab_;
base::CallbackListSubscription tab_subscription_;
// Task runner used to downscale the tab screenshot in the background.
scoped_refptr<base::TaskRunner> screenshot_task_runner_;
bool is_page_context_eligible_ = false;
base::WeakPtrFactory<TabContextualizationController> weak_ptr_factory_{this};
};
} // namespace lens
#endif // COMPONENTS_LENS_TAB_CONTEXTUALIZATION_CONTROLLER_H_