summaryrefslogtreecommitdiffstats
path: root/third_party/content_analysis_sdk/agent/include/content_analysis/sdk/analysis_agent.h
blob: 6f7617120a269d15f53a04670cca0ce766c9279e (plain)
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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
// Copyright 2022 The Chromium Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_ANALYSIS_AGENT_INCLUDE_CONTENT_ANALYSIS_SDK_ANALYSIS_AGENT_H_
#define CONTENT_ANALYSIS_AGENT_INCLUDE_CONTENT_ANALYSIS_SDK_ANALYSIS_AGENT_H_

#include <memory>
#include <string>

#include "content_analysis/sdk/analysis.pb.h"
#include "content_analysis/sdk/result_codes.h"

// This is the main include file for code using Content Analysis Connector
// Agent SDK.  No other include is needed.
//
// An agent begins by creating an instance of Agent using the factory
// function Agent::Create().  This instance should live as long as the agent
// intends to receive content analysis requests from Google Chrome.
//
// Agent::Create() must be passed an object that implements the
// AgentEventHandler interface.  Methods on this interface will be called
// at the approriate time to handle specific events.  The events are:
//
// - A Google Chrome browser has started or stopped.  This events contains
//   information about the browser such as process id and executable path.
// - A request to analyze content.  The agent reads and analyses the
//   request in to determine a verdict: allow or block.  When the verdict is
//   known the response is sent back to Google Chrome.
// - An acknowledgement that Google Chrome has properly received the agent's
//   verdict.
//
// The agent is not required to serialize event handling.  That is, content
// analysis events can be analyze in the background and the response does
// not need to be sent before OnAnalysisRequested() returns.
//
// Google Chrome thottles the number of requests sent to the agent to 5
// current requests at a time but this is subject to change.

namespace content_analysis {
namespace sdk {

// Represents information about one instance of a Google Chrome browser
// process that is connected to the agent.
struct BrowserInfo {
  unsigned long pid = 0;  // Process ID of Google Chrome browser process.
  std::string binary_path;  // The full path to the process's main binary.
};

// Represents one content analysis request as generated by a given user action
// in Google Chrome.
//
// The agent should retrieve information about the content analysis request
// using the GetRequest() method.  The agent should analyze the request and
// update the response, returned by GetResponse(), with a verdict (allow or
// block).  Once the verdict is set the response can be sent back to Google
// Chrome by calling Send().
//
// The default verdict is to allow the requested user action.  If the final
// verdict is to allow then the agent does not need to update the response and
// can simply call Send().
//
// If the final verdict should be to block, the agent should first update the
// response by calling SetEventVerdictToBlock() before calling Send().
//
// This class is not thread safe.  However, it may be passed to another thread
// as long as the agent properly serializses access to the event.
//
// See the demo directory for an example of how to use this class.
class ContentAnalysisEvent {
 public:
  virtual ~ContentAnalysisEvent() = default;

  // Prepares the event for graceful shutdown.  Upon return calls to all
  // other methods of this class will fail.
  virtual ResultCode Close() = 0;

  // Retrives information about the browser that generated this content
  // analysis event.
  virtual const BrowserInfo& GetBrowserInfo() const = 0;

  // Retrieves a read-only reference to the content analysis request received
  // from Google Chrome.
  virtual const ContentAnalysisRequest& GetRequest() const = 0;

  // Retrieves a writable reference to the content analysis response that will
  // be sent to Google Chrome as the verdict for the request of this event.
  // The agent may modify this response in place before calling Send().
  virtual ContentAnalysisResponse& GetResponse() = 0;

  // Send the verdict to Google Chrome.  Once this method is called further
  // changes to the response are ignored.
  virtual ResultCode Send() = 0;

  // Returns a string containing internal state of the object that is useful
  // for debugging.
  virtual std::string DebugString() const = 0;

 protected:
  ContentAnalysisEvent() = default;
  ContentAnalysisEvent(const ContentAnalysisEvent& rhs) = delete;
  ContentAnalysisEvent(ContentAnalysisEvent&& rhs) = delete;
  ContentAnalysisEvent& operator=(const ContentAnalysisEvent& rhs) = delete;
  ContentAnalysisEvent& operator=(ContentAnalysisEvent&& rhs) = delete;

};

// Agents should implement this interface in order to handle events as needed.
//
// OnBrowserConnected() and OnBrowserDisonnected() notify the agent when
// instances of Google Chome start and stop.  The agent may perform any one-time
// actions as required for these events.  The default action is to do nothing
// for both events.  If the agent does not need perform any special actions
// these methods do not need to be overridden.
//
// OnAnalysisRequested() notifies the agent of a new content analysis request
// from Google Chrome.  The agent should perform the analysis and respond to
// the event.  It is not required for the agent complete the analysis and
// respond to before this callback returns.  The agent may pass the
// ContentAnalysisEvent to a background task and respond when ready.  This
// callback has no default action and agents must override it.
//
// OnResponseAcknowledged() notifies the agent that Google Chrome has received
// the content analysis response and how it has handled it.
class AgentEventHandler {
 public:
  AgentEventHandler() = default;
  virtual ~AgentEventHandler() = default;

  // Called when a new Google Chrome browser instance connects to the agent.
  // This is always called before the first OnAnalysisRequested() from that
  // browser.
  virtual void OnBrowserConnected(const BrowserInfo& info) {}

  // Called when a Google Chrome browser instance disconnects from the agent.
  // The agent will no longer receive new content analysis requests from this
  // browser.
  virtual void OnBrowserDisconnected(const BrowserInfo& info) {}

  // Called when a Google Chrome browser requests a content analysis.
  virtual void OnAnalysisRequested(
      std::unique_ptr<ContentAnalysisEvent> event) = 0;

  // Called when a Google Chrome browser acknowledges the content analysis
  // response from the agent.  The default action is to do nothing.
  // If the agent does not need perform any special actions this methods does
  // not need to be overridden.
  virtual void OnResponseAcknowledged(
      const ContentAnalysisAcknowledgement& ack) {}

  // Called when a Google Chrome browser asks the agent to cancels one or
  // more content analysis requests.  This happens when the user presses the
  // Cancel button in the in-progress dialog.  This is expected to be a best
  // effort only; agents may choose to ignore this message or possibly only
  // cancel a subset of requests with the given user action id.
  //
  // The default action is to do nothing. If the agent does not need perform
  // any special actions this methods does not need to be overridden.
  virtual void OnCancelRequests(
      const ContentAnalysisCancelRequests& cancel) {}

  // Called whenever the Agent implementation detects an error.  `context`
  // is a string that provide a hint to the handler as to where the error
  // happened in the agent.  `error` represent the actual error detected.
  virtual void OnInternalError(const char* context, ResultCode error) {}
};

// Represents an agent that can perform content analysis for the Google Chrome
// browser.  This class holds the server endpoint that Google Chrome connects
// to when content analysis is required.
//
// Agent instances should outlive all ContentAnalysisEvent instances created
// with it. Agent instances are not thread safe except for Stop() which can be
// called from any thread to shutdown the agent.  Outstanding
// ContentAnalysisEvents created from this agent may or may not still complete.
//
// See the demo directory for an example of how to use this class.
class Agent {
 public:
  // Configuration options where creating an agent.  `name` is used to create
  // a channel between the agent and Google Chrome.
  struct Config {
    // Used to create a channel between the agent and Google Chrome.  Both must
    // use the same name to properly rendezvous with each other.  The channel
    // is platform specific.
    std::string name;

    // Set to true if there is a different agent instance per OS user.  Defaults
    // to false.
    bool user_specific = false;
  };

  // Creates a new agent instance.  If successful, an agent is returned.
  // Otherwise a nullptr is returned and `rc` contains the reason for the
  // failure.
  static std::unique_ptr<Agent> Create(
      Config config,
      std::unique_ptr<AgentEventHandler> handler,
      ResultCode* rc);

  virtual ~Agent() = default;

  // Returns the configuration parameters used to create the agent.
  virtual const Config& GetConfig() const = 0;

  // Handles events triggered on this agent and calls the coresponding
  // callbacks in the AgentEventHandler.  This method is blocking and returns
  // when Stop() is called or if an error occurs.
  virtual ResultCode HandleEvents() = 0;

  // Prepares the agent for graceful shutdown.  Any function blocked on
  // HandleEvents() will return.  It is safe to call this method from any
  // thread.
  virtual ResultCode Stop() = 0;

  // Returns a string containing internal state of the object that is useful
  // for debugging.
  virtual std::string DebugString() const = 0;

 protected:
  Agent() = default;
  Agent(const Agent& rhs) = delete;
  Agent(Agent&& rhs) = delete;
  Agent& operator=(const Agent& rhs) = delete;
  Agent& operator=(Agent&& rhs) = delete;
};

// Update the tag or status of `response`.  This function assumes that the
// response contains only one Result.  If one already exists it is updated
// otherwise a new Result is created.
//
// The response contained within ContentAnalysisEvent has already been updated.
// This function is useful only when create a new instance of
// ContentAnalysisResponse.
//
// If `tag` is not empty it will replace the result's tag.
// If `status` is not STATUS_UNKNOWN it will will replace the result's status.
ResultCode UpdateResponse(ContentAnalysisResponse& response,
                          const std::string& tag,
                          ContentAnalysisResponse::Result::Status status);

// Sets the response verdict of an event to `action`.  This is a convenience
// function that is equivalent to the following:
//
//   auto result = event->GetResponse().mutable_results(0);
//   auto rule = result->mutable_triggered_rules(0);
//   rule->set_action(action);
//
// This function assumes the event's response has already been initialized
// using UpdateResponse().
ResultCode SetEventVerdictTo(
    ContentAnalysisEvent* event,
    ContentAnalysisResponse::Result::TriggeredRule::Action action);

// Sets the reponse verdict of an event to "block".  This is a convenience
// function that is equivalent to the following:
//
//   SetEventVerdictTo(event,
//                     ContentAnalysisResponse::Result::TriggeredRule::BLOCK);
ResultCode SetEventVerdictToBlock(ContentAnalysisEvent* event);

// Helper class to handle the lifetime and access of print data.
class ScopedPrintHandle {
 public:
  virtual ~ScopedPrintHandle() = default;
  virtual const char* data() = 0;
  virtual size_t size() = 0;

 protected:
  ScopedPrintHandle() = default;

  ScopedPrintHandle(const ScopedPrintHandle&) = delete;
  ScopedPrintHandle& operator=(const ScopedPrintHandle&) = delete;

  ScopedPrintHandle(ScopedPrintHandle&&) = default;
  ScopedPrintHandle& operator=(ScopedPrintHandle&&) = default;
};

// Returns a `ScopedPrintHandle` initialized from the request's print data
// if it exists.
std::unique_ptr<ScopedPrintHandle>
CreateScopedPrintHandle(const ContentAnalysisRequest& request,
                        int64_t browser_pid);

}  // namespace sdk
}  // namespace content_analysis

#endif  // CONTENT_ANALYSIS_AGENT_INCLUDE_CONTENT_ANALYSIS_SDK_ANALYSIS_AGENT_H_