summaryrefslogtreecommitdiffstats
path: root/third_party/content_analysis_sdk/agent/src/agent_win.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/content_analysis_sdk/agent/src/agent_win.h')
-rw-r--r--third_party/content_analysis_sdk/agent/src/agent_win.h196
1 files changed, 196 insertions, 0 deletions
diff --git a/third_party/content_analysis_sdk/agent/src/agent_win.h b/third_party/content_analysis_sdk/agent/src/agent_win.h
new file mode 100644
index 0000000000..a6a0c73311
--- /dev/null
+++ b/third_party/content_analysis_sdk/agent/src/agent_win.h
@@ -0,0 +1,196 @@
+// 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_SRC_AGENT_WIN_H_
+#define CONTENT_ANALYSIS_AGENT_SRC_AGENT_WIN_H_
+
+#include <windows.h>
+
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "agent_base.h"
+
+namespace content_analysis {
+namespace sdk {
+
+// Agent implementaton for Windows.
+class AgentWin : public AgentBase {
+ public:
+ // Creates a new agent given the specific configuration and handler.
+ // If an error occurs during creation, `rc` is set to the specific
+ // error. Otherwise `rc` is ResultCode::OK.
+ AgentWin(Config config, std::unique_ptr<AgentEventHandler> handler,
+ ResultCode* rc);
+ ~AgentWin() override;
+
+ // Agent:
+ ResultCode HandleEvents() override;
+ ResultCode Stop() override;
+ std::string DebugString() const override;
+
+ // Handles one pipe event and returns. Used only in tests.
+ ResultCode HandleOneEventForTesting();
+
+ // Returns true if there is at least one client connected to this agent.
+ bool IsAClientConnectedForTesting();
+
+private:
+ // Represents one connection to a Google Chrome browser, or one pipe
+ // listening for a Google Chrome browser to connect.
+ class Connection {
+ public:
+ // Starts listening on a pipe with the given name. `is_first_pipe` should
+ // be true only for the first pipe created by the agent. If an error
+ // occurs while creating the connction object it is returned in `rc`.
+ // If no errors occur then rc is set to ResultCode::OK.
+ //
+ // When `user_specific` is true there is a different agent instance per OS
+ // user.
+ //
+ // `Connection` objects cannot be copied or moved because the OVERLAPPED
+ // structure cannot be changed or moved in memory while an I/O operation
+ // is in progress.
+ Connection(const std::string& pipename,
+ bool user_specific,
+ AgentEventHandler* handler,
+ bool is_first_pipe,
+ ResultCode* rc);
+ Connection(const Connection& other) = delete;
+ Connection(Connection&& other) = delete;
+ Connection& operator=(const Connection& other) = delete;
+ Connection& operator=(Connection&& other) = delete;
+ ~Connection();
+
+ bool IsValid() const { return handle_ != INVALID_HANDLE_VALUE; }
+ bool IsConnected() const { return is_connected_; }
+ HANDLE GetWaitHandle() const { return overlapped_.hEvent; }
+
+ // Resets this connection object to listen for a new Google Chrome browser.
+ // When `user_specific` is true there is a different agent instance per OS
+ // user.
+ ResultCode Reset(const std::string& pipename, bool user_specific);
+
+ // Hnadles an event for this connection. `wait_handle` corresponds to
+ // this connections wait handle.
+ ResultCode HandleEvent(HANDLE wait_handle);
+
+ // Append debuf information to the string stream.
+ void AppendDebugString(std::stringstream& state) const;
+
+ private:
+ // Listens for a new connection from Google Chrome.
+ ResultCode ConnectPipe();
+
+ // Resets this connection object to listen for a new Google Chrome browser.
+ // When `user_specific` is true there is a different agent instance per OS
+ // user.
+ ResultCode ResetInternal(const std::string& pipename,
+ bool user_specific,
+ bool is_first_pipe);
+
+ // Cleans up this connection object so that it can be reused with a new
+ // Google Chroem browser instance. The handles assocated with this object
+ // are not closed. On return, this object is neither connected nor
+ // listening and any buffer used to hold browser messages are cleared.
+ void Cleanup();
+
+ // Queues a read on the pipe to receive a message from Google Chrome.
+ // ERROR_SUCCESS, ERROR_IO_PENDING, and ERROR_MORE_DATA are successful
+ // return values. Other values represent an error with the connection.
+ // If `reset_cursor` is true the internal read buffer cursor is reset to
+ // the start of the buffer, otherwise it is unchanged.
+ ResultCode QueueReadFile(bool reset_cursor);
+
+ // Called when data from Google Chrome is available for reading from the
+ // pipe. ERROR_SUCCESS and ERROR_MORE_DATA are both successful return
+ // values. Other values represent an error with the connection.
+ //
+ // `done_reading` is true if the code has finished reading an entire message
+ // from chrome. Regardless of whether reading is done, `count` contains
+ // the number of bytes read.
+ //
+ // If `done_reading` is true, the data received from the browser is parsed
+ // as if it were a `ChromeToAgent` proto message and the handler is called
+ // as needed.
+ //
+ // If `done_reading` is false, the data received from the browser is
+ // appended to the data already received from the browser. `buffer_` is
+ // resized to allow reading more data from the browser.
+ //
+ // In all cases the caller is expected to use QueueReadFile() to continue
+ // reading data from the browser.
+ ResultCode OnReadFile(BOOL done_reading, DWORD count);
+
+ // Calls the appropriate method the handler depending on the message
+ // received from Google Chrome.
+ ResultCode CallHandler();
+
+ // Fills in the browser_info_ member of this Connection. Assumes
+ // IsConnected() is true.
+ ResultCode BuildBrowserInfo();
+
+ // Notifies the handler of the given error iff `rc` is not equal to
+ // ResultCode::OK. Appends the Google Chrome browser process id to the
+ // context before calling the handler. Also append `err` to the context
+ // if it is not ERROR_SUCCESS.
+ //
+ // Returns the error passed into the method.
+ ResultCode NotifyIfError(const char* context,
+ ResultCode rc,
+ DWORD err=ERROR_SUCCESS);
+
+ // The handler to call for various agent events.
+ AgentEventHandler* handler_ = nullptr;
+
+ // Members used to communicate with Google Chrome.
+ HANDLE handle_ = INVALID_HANDLE_VALUE;
+ OVERLAPPED overlapped_;
+
+ // True if this connection is assigned to a specific Google Chrome browser,
+ // otherwise this connection is listening for a new browser.
+ bool is_connected_ = false;
+
+ // Information about the Google Chrome browser process.
+ BrowserInfo browser_info_;
+
+ // Members used to read messages from Google Chrome.
+ std::vector<char> buffer_;
+ char* cursor_ = nullptr;
+ DWORD read_size_ = 0;
+ DWORD final_size_ = 0;
+ };
+
+ // Returns handles that can be used to wait for events from all handles
+ // managed by this agent. This includes all connection objects and the
+ // stop event. The stop event is always last in the list.
+ void GetHandles(std::vector<HANDLE>& wait_handles) const;
+
+ // Handles one pipe event and returns. If the return value is
+ // ResultCode::OK, the `stopped` argument is set to true if the agent
+ // should stop handling more events. If the return value is not
+ // ResultCode::OK, `stopped` is undefined.
+ ResultCode HandleOneEvent(std::vector<HANDLE>& wait_handles, bool* stopped);
+
+ // Performs a clean shutdown of the agent.
+ void Shutdown();
+
+ // Name used to create the pipes between the agent and Google Chrome browsers.
+ std::string pipename_;
+
+ // A list of pipes to already connected Google Chrome browsers.
+ // The first kMinNumListeningPipeInstances pipes in the list correspond to
+ // listening pipes.
+ std::vector<std::unique_ptr<Connection>> connections_;
+
+ // An event that is set when the agent should stop. Set in Stop().
+ HANDLE stop_event_ = nullptr;
+};
+
+} // namespace sdk
+} // namespace content_analysis
+
+#endif // CONTENT_ANALYSIS_AGENT_SRC_AGENT_WIN_H_