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
|
// 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_ACTOR_EXECUTION_ENGINE_H_
#define CHROME_BROWSER_ACTOR_EXECUTION_ENGINE_H_
#include <memory>
#include <optional>
#include "base/callback_list.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/safe_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/types/id_type.h"
#include "chrome/browser/actor/aggregated_journal.h"
#include "chrome/browser/actor/task_id.h"
#include "chrome/browser/actor/tools/tool_controller.h"
#include "chrome/common/actor.mojom-forward.h"
#include "components/optimization_guide/proto/features/actions_data.pb.h"
#include "components/tabs/public/tab_interface.h"
#include "content/public/browser/web_contents_observer.h"
class GURL;
class Profile;
namespace mojo_base {
class ProtoWrapper;
}
namespace content {
class WebContents;
} // namespace content
namespace tabs {
class TabInterface;
} // namespace tabs
namespace url {
class Origin;
} // namespace url
namespace actor {
class ActorTask;
class ToolRequest;
// Coordinates the execution of a multi-step task.
class ExecutionEngine {
public:
using ActionResultCallback = base::OnceCallback<void(mojom::ActionResultPtr)>;
using ActionsResultCallback =
base::OnceCallback<void(optimization_guide::proto::ActionsResult)>;
explicit ExecutionEngine(Profile* profile);
// Old instances of ExecutionEngine assume that all actions are scoped to a
// single tab. This constructor supports this use case, but this is
// deprecated. Do not add new consumers
ExecutionEngine(Profile* profile, tabs::TabInterface* tab);
ExecutionEngine(const ExecutionEngine&) = delete;
ExecutionEngine& operator=(const ExecutionEngine&) = delete;
~ExecutionEngine();
// This cannot be in the constructor as we first construct the
// ExecutionEngine, then the ActorTask.
void SetOwner(ActorTask* task);
static void RegisterWithProfile(Profile* profile);
// Cancels any in-progress actions with the reason: "kTaskPaused".
void CancelOngoingActions(mojom::ActionResultCode reason);
// Returns the tab associated with the current task if it exists.
tabs::TabInterface* GetTabOfCurrentTask() const;
// Returns true if a task is currently active.
bool HasTask() const;
// Returns true if a task is currently active in `tab`.
bool HasTaskForTab(const content::WebContents* tab) const;
// Performs the next action in the current task.
void Act(const optimization_guide::proto::BrowserAction& action,
ActionResultCallback callback);
// Performs the next action in the current task.
void Act(const optimization_guide::proto::Actions& actions,
ActionsResultCallback callback);
// Gets called when a new observation is made for the actor task.
void DidObserveContext(const mojo_base::ProtoWrapper&);
// Returns last observed page content, nullptr if no observation has been
// made.
const optimization_guide::proto::AnnotatedPageContent*
GetLastObservedPageContent();
// Invalidated anytime `actions_` is reset.
base::WeakPtr<ExecutionEngine> GetWeakPtr();
private:
class NewTabWebContentsObserver;
// If there are no actions remaining, calls CompleteActions.
// Otherwise, calls SafetyChecksForNextAction().
void KickOffNextAction(mojom::ActionResultPtr previous_action_result);
// Performs safety checks for next action. This is asynchronous.
void SafetyChecksForNextAction();
// Performs synchronous safety checks for the next action. If everything
// passes calls tool_controller_.Invoke().
void DidFinishAsyncSafetyChecks(const url::Origin& evaluated_origin,
bool may_act);
// Synchronously executes the next action. There are several types of actions,
// including renderer-scoped actions, tab-scoped actions, and global actions.
void ExecuteNextAction();
// Called each time an action finishes.
void FinishOneAction(mojom::ActionResultPtr result);
// Calls out to CompleteActionsV1 or CompleteActionsV2.
void CompleteActions(mojom::ActionResultPtr result);
// Calls `callback` and clears `actions_v1_`.
void CompleteActionsV1(mojom::ActionResultPtr result);
// Calls `callback` and clears `actions_v2_`.
void CompleteActionsV2(mojom::ActionResultPtr result);
void OnTabWillDetach(tabs::TabInterface* tab,
tabs::TabInterface::DetachReason reason);
const GURL& LastCommittedURLOfCurrentTask();
const optimization_guide::proto::Action& GetNextAction();
// Returns the tab associated with the action or nullptr.
tabs::TabInterface* GetTab(const optimization_guide::proto::Action& action);
static std::optional<base::TimeDelta> action_observation_delay_for_testing_;
raw_ptr<Profile> profile_;
base::SafeRef<AggregatedJournal> journal_;
// Stores the last observed page content for TOCTOU check.
std::unique_ptr<optimization_guide::proto::AnnotatedPageContent>
last_observed_page_content_;
template <typename ActionT, typename CallbackT>
struct ActionWithCallback {
ActionWithCallback(const ActionT& actions, CallbackT callback)
: proto(actions), callback(std::move(callback)) {}
~ActionWithCallback() = default;
ActionWithCallback(const ActionWithCallback&) = delete;
ActionWithCallback& operator=(const ActionWithCallback&) = delete;
ActionT proto;
CallbackT callback;
};
// TODO(crbug.com/411462297): This assumes all tasks are scoped to a tab,
// which is not true. This should eventually be removed.
bool tab_scoped_actions_deprecated_ = false;
raw_ptr<tabs::TabInterface> tab_;
base::CallbackListSubscription tab_will_detach_subscription_;
// Owns `this`.
raw_ptr<ActorTask> task_;
// Tool request currently being invoked.
std::unique_ptr<ToolRequest> active_tool_request_;
// Created when task_ is set. Handles execution details for an individual tool
// request.
std::unique_ptr<ToolController> tool_controller_;
// A sequence of actions that the model has requested. When it is finished
// being processed it is reset.
// This is deprecated; do not add new use cases.
std::optional<ActionWithCallback<optimization_guide::proto::BrowserAction,
ActionResultCallback>>
actions_v1_;
// A sequence of actions that the model has requested. When it is finished
// being processed it is reset.
std::optional<ActionWithCallback<optimization_guide::proto::Actions,
ActionsResultCallback>>
actions_v2_;
// The index of the in-progress action.
int action_index_ = 0;
SEQUENCE_CHECKER(sequence_checker_);
// Normally, a WeakPtrFactory only invalidates its WeakPtrs when the object is
// destroyed. However, this class invalidates WeakPtrs anytime a new set of
// actions is passed in. This effectively cancels any ongoing async actions.
base::WeakPtrFactory<ExecutionEngine> actions_weak_ptr_factory_{this};
};
} // namespace actor
#endif // CHROME_BROWSER_ACTOR_EXECUTION_ENGINE_H_
|