#ifndef CHROME_BROWSER_CONTEXTUAL_TASKS_CONTEXTUAL_TASKS_UI_H_
#define CHROME_BROWSER_CONTEXTUAL_TASKS_CONTEXTUAL_TASKS_UI_H_
#include <optional>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "base/uuid.h"
#include "chrome/browser/contextual_tasks/contextual_tasks_composebox_handler.h"
#include "chrome/browser/contextual_tasks/contextual_tasks_internals.mojom.h"
#include "chrome/browser/contextual_tasks/contextual_tasks_page_handler.h"
#include "chrome/browser/contextual_tasks/contextual_tasks_side_panel_coordinator.h"
#include "chrome/browser/contextual_tasks/task_info_delegate.h"
#include "chrome/browser/ui/webui/top_chrome/top_chrome_web_ui_controller.h"
#include "chrome/browser/ui/webui/top_chrome/top_chrome_webui_config.h"
#include "chrome/common/webui_url_constants.h"
#include "components/contextual_search/contextual_search_session_handle.h"
#include "components/contextual_tasks/public/contextual_task_context.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/url_constants.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/lens_server_proto/aim_communication.pb.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "ui/webui/mojo_web_ui_controller.h"
#include "ui/webui/resources/cr_components/composebox/composebox.mojom.h"
class BrowserWindowInterface;
class GoogleServiceAuthError;
namespace content {
struct OpenURLParams;
class BrowserContext;
class WebContentsObserver;
}
namespace signin {
class AccessTokenFetcher;
struct AccessTokenInfo;
}
namespace contextual_tasks {
class ContextualTasksService;
class ContextualTasksSidePanelCoordinator;
class ContextualTasksUiService;
}
namespace tabs {
class TabInterface;
}
class ContextualTasksComposeboxHandler;
class ContextualTasksInternalsPageHandler;
class ContextualTasksPageHandler;
class ContextualTasksUI : public TaskInfoDelegate,
public TopChromeWebUIController,
public contextual_tasks::mojom::PageHandlerFactory,
public composebox::mojom::PageHandlerFactory,
public contextual_tasks_internals::mojom::
ContextualTasksInternalsPageHandlerFactory {
public:
class FrameNavObserver : public content::WebContentsObserver {
public:
explicit FrameNavObserver(
content::WebContents* web_contents,
contextual_tasks::ContextualTasksUiService* ui_service,
contextual_tasks::ContextualTasksService* contextual_tasks_service,
TaskInfoDelegate* task_info_delegate);
~FrameNavObserver() override = default;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
private:
raw_ptr<contextual_tasks::ContextualTasksUiService> ui_service_;
raw_ptr<contextual_tasks::ContextualTasksService> contextual_tasks_service_;
raw_ref<TaskInfoDelegate> task_info_delegate_;
GURL last_committed_url_;
};
explicit ContextualTasksUI(content::WebUI* web_ui);
ContextualTasksUI(const ContextualTasksUI&) = delete;
ContextualTasksUI& operator=(const ContextualTasksUI&) = delete;
~ContextualTasksUI() override;
void CreatePageHandler(
mojo::PendingRemote<composebox::mojom::Page> pending_page,
mojo::PendingReceiver<composebox::mojom::PageHandler>
pending_page_handler,
mojo::PendingRemote<searchbox::mojom::Page> pending_searchbox_page,
mojo::PendingReceiver<searchbox::mojom::PageHandler>
pending_searchbox_handler) override;
void CreatePageHandler(
mojo::PendingRemote<contextual_tasks::mojom::Page> page,
mojo::PendingReceiver<contextual_tasks::mojom::PageHandler> page_handler)
override;
const std::optional<base::Uuid>& GetTaskId() override;
void SetTaskId(std::optional<base::Uuid> id) override;
const std::optional<std::string>& GetThreadId() override;
void SetThreadId(std::optional<std::string> id) override;
void SetThreadTurnId(std::optional<std::string> id) override;
const std::optional<std::string>& GetThreadTitle() override;
void SetThreadTitle(std::optional<std::string> title) override;
void SetIsAiPage(bool is_ai_page) override;
bool IsShownInTab() override;
BrowserWindowInterface* GetBrowser() override;
content::WebContents* GetWebUIWebContents() override;
void OnZeroStateChange(bool is_zero_state) override;
static bool IsZeroState(
const GURL& url,
contextual_tasks::ContextualTasksUiService* ui_service);
const GURL& GetInnerFrameUrl() const;
void CloseSidePanel();
contextual_search::ContextualSearchSessionHandle*
GetOrCreateContextualSessionHandle();
void BindInterface(
mojo::PendingReceiver<contextual_tasks::mojom::PageHandlerFactory>
pending_receiver);
void BindInterface(
mojo::PendingReceiver<composebox::mojom::PageHandlerFactory> receiver);
void BindInterface(
mojo::PendingReceiver<contextual_tasks_internals::mojom::
ContextualTasksInternalsPageHandlerFactory>
pending_receiver);
void CreatePageHandler(
mojo::PendingRemote<
contextual_tasks_internals::mojom::ContextualTasksInternalsPage> page,
mojo::PendingReceiver<contextual_tasks_internals::mojom::
ContextualTasksInternalsPageHandler> receiver)
override;
static constexpr std::string_view GetWebUIName() { return "ContextualTasks"; }
static base::RefCountedMemory* GetFaviconResourceBytes(
ui::ResourceScaleFactor scale_factor);
void OnSidePanelStateChanged();
virtual void DisableActiveTabContextSuggestion();
void OnActiveTabContextStatusChanged();
void OnLensOverlayStateChanged(bool is_showing);
void SetComposeboxHandlerForTesting(
std::unique_ptr<ContextualTasksComposeboxHandler> handler) {
composebox_handler_ = std::move(handler);
}
void OnPageContextEligibilityChecked(bool is_page_context_eligible);
virtual void PostMessageToWebview(const lens::ClientToAimMessage& message);
mojo::Remote<contextual_tasks::mojom::Page>& page() { return page_; }
void TransferNavigationToEmbeddedPage(content::OpenURLParams params);
bool IsActiveTabContextSuggestionShowing() const;
private:
void RequestOAuthToken();
void OnOAuthTokenReceived(GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info);
class InnerFrameCreationObvserver : public content::WebContentsObserver {
public:
explicit InnerFrameCreationObvserver(
content::WebContents* web_contents,
base::OnceCallback<void(content::WebContents*)> callback);
~InnerFrameCreationObvserver() override;
void InnerWebContentsCreated(
content::WebContents* inner_web_contents) override;
private:
base::OnceCallback<void(content::WebContents*)> callback_;
};
void OnInnerWebContentsCreated(content::WebContents* inner_contents);
void OnContextRetrievedForActiveTab(
int32_t tab_id,
const GURL& last_committed_url,
std::unique_ptr<contextual_tasks::ContextualTaskContext> context);
void UpdateSuggestedTabContext(tabs::TabInterface* tab);
void PushTaskDetailsToPage();
contextual_tasks::ContextualTasksSidePanelCoordinator*
GetSidePanelCoordinator();
std::unique_ptr<signin::AccessTokenFetcher> oauth_token_fetcher_;
base::OneShotTimer token_refresh_timer_;
std::unique_ptr<ContextualTasksComposeboxHandler> composebox_handler_;
raw_ptr<contextual_tasks::ContextualTasksUiService> ui_service_;
raw_ptr<contextual_tasks::ContextualTasksService> contextual_tasks_service_;
mojo::Receiver<composebox::mojom::PageHandlerFactory>
composebox_page_handler_factory_receiver_{this};
mojo::Receiver<contextual_tasks::mojom::PageHandlerFactory>
contextual_tasks_page_handler_factory_receiver_{this};
std::unique_ptr<ContextualTasksPageHandler> page_handler_;
mojo::Remote<composebox::mojom::Page> page_remote_;
std::unique_ptr<InnerFrameCreationObvserver>
inner_web_contents_creation_observer_;
std::unique_ptr<FrameNavObserver> nav_observer_;
base::WeakPtr<content::WebContents> embedded_web_contents_;
std::optional<base::Uuid> task_id_;
std::optional<std::string> thread_id_;
std::optional<std::string> thread_turn_id_;
std::optional<std::string> thread_title_;
mojo::Remote<contextual_tasks::mojom::Page> page_;
mojo::Receiver<contextual_tasks_internals::mojom::
ContextualTasksInternalsPageHandlerFactory>
contextual_tasks_internals_page_handler_receiver_{this};
std::unique_ptr<ContextualTasksInternalsPageHandler>
contextual_tasks_internals_page_handler_;
enum class WebUIState {
kUnknown,
kShownInTab,
kShownInSidePanel,
};
WebUIState previous_web_ui_state_ = WebUIState::kUnknown;
bool was_ai_page_ = false;
base::WeakPtrFactory<ContextualTasksUI> weak_ptr_factory_{this};
WEB_UI_CONTROLLER_TYPE_DECL();
};
class ContextualTasksUIConfig
: public DefaultTopChromeWebUIConfig<ContextualTasksUI> {
public:
ContextualTasksUIConfig()
: DefaultTopChromeWebUIConfig(content::kChromeUIScheme,
chrome::kChromeUIContextualTasksHost) {}
bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
std::unique_ptr<content::WebUIController> CreateWebUIController(
content::WebUI* web_ui,
const GURL& url) override;
};
#endif