tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

agent_win.h (7790B)


      1 // Copyright 2022 The Chromium Authors.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CONTENT_ANALYSIS_AGENT_SRC_AGENT_WIN_H_
      6 #define CONTENT_ANALYSIS_AGENT_SRC_AGENT_WIN_H_
      7 
      8 #include <windows.h>
      9 
     10 #include <memory>
     11 #include <sstream>
     12 #include <string>
     13 #include <vector>
     14 
     15 #include "agent_base.h"
     16 
     17 namespace content_analysis {
     18 namespace sdk {
     19 
     20 // Agent implementaton for Windows.
     21 class AgentWin : public AgentBase {
     22 public:
     23  // Creates a new agent given the specific configuration and handler.
     24  // If an error occurs during creation, `rc` is set to the specific
     25  // error.  Otherwise `rc` is ResultCode::OK.
     26  AgentWin(Config config, std::unique_ptr<AgentEventHandler> handler,
     27           ResultCode* rc);
     28  ~AgentWin() override;
     29 
     30  // Agent:
     31  ResultCode HandleEvents() override;
     32  ResultCode Stop() override;
     33  std::string DebugString() const override;
     34 
     35  // Handles one pipe event and returns.  Used only in tests.
     36  ResultCode HandleOneEventForTesting();
     37 
     38  // Returns true if there is at least one client connected to this agent.
     39  bool IsAClientConnectedForTesting();
     40 
     41 private:
     42  // Represents one connection to a Google Chrome browser, or one pipe
     43  // listening for a Google Chrome browser to connect.
     44  class Connection {
     45   public:
     46    // Starts listening on a pipe with the given name. `is_first_pipe` should
     47    // be true only for the first pipe created by the agent.  If an error
     48    // occurs while creating the connction object it is returned in `rc`.
     49    // If no errors occur then rc is set to ResultCode::OK.
     50    //
     51    // When `user_specific` is true there is a different agent instance per OS
     52    // user.
     53    //
     54    // `Connection` objects cannot be copied or moved because the OVERLAPPED
     55    // structure cannot be changed or moved in memory while an I/O operation
     56    // is in progress.
     57    Connection(const std::string& pipename,
     58               bool user_specific,
     59               AgentEventHandler* handler,
     60               bool is_first_pipe,
     61               ResultCode* rc);
     62    Connection(const Connection& other) = delete;
     63    Connection(Connection&& other) = delete;
     64    Connection& operator=(const Connection& other) = delete;
     65    Connection& operator=(Connection&& other) = delete;
     66    ~Connection();
     67 
     68    bool IsValid() const { return handle_ != INVALID_HANDLE_VALUE; }
     69    bool IsConnected() const { return is_connected_; }
     70    HANDLE GetWaitHandle() const { return overlapped_.hEvent; }
     71 
     72    // Resets this connection object to listen for a new Google Chrome browser.
     73    // When `user_specific` is true there is a different agent instance per OS
     74    // user.
     75    ResultCode Reset(const std::string& pipename, bool user_specific);
     76 
     77    // Hnadles an event for this connection.  `wait_handle` corresponds to
     78    // this connections wait handle.
     79    ResultCode HandleEvent(HANDLE wait_handle);
     80 
     81    // Append debuf information to the string stream.
     82    void AppendDebugString(std::stringstream& state) const;
     83 
     84   private:
     85    // Listens for a new connection from Google Chrome.
     86    ResultCode ConnectPipe();
     87 
     88    // Resets this connection object to listen for a new Google Chrome browser.
     89    // When `user_specific` is true there is a different agent instance per OS
     90    // user.
     91    ResultCode ResetInternal(const std::string& pipename,
     92                             bool user_specific,
     93                             bool is_first_pipe);
     94 
     95    // Cleans up this connection object so that it can be reused with a new
     96    // Google Chroem browser instance.  The handles assocated with this object
     97    // are not closed.  On return, this object is neither connected nor
     98    // listening and any buffer used to hold browser messages are cleared.
     99    void Cleanup();
    100 
    101    // Queues a read on the pipe to receive a message from Google Chrome.
    102    // ERROR_SUCCESS, ERROR_IO_PENDING, and ERROR_MORE_DATA are successful
    103    // return values. Other values represent an error with the connection.
    104    // If `reset_cursor` is true the internal read buffer cursor is reset to
    105    // the start of the buffer, otherwise it is unchanged.
    106    ResultCode QueueReadFile(bool reset_cursor);
    107 
    108    // Called when data from Google Chrome is available for reading from the
    109    // pipe. ERROR_SUCCESS and ERROR_MORE_DATA are both successful return
    110    // values.  Other values represent an error with the connection.
    111    //
    112    // `done_reading` is true if the code has finished reading an entire message
    113    // from chrome.  Regardless of whether reading is done, `count` contains
    114    // the number of bytes read.
    115    //
    116    // If `done_reading` is true, the data received from the browser is parsed
    117    // as if it were a `ChromeToAgent` proto message and the handler is called
    118    // as needed.
    119    //
    120    // If `done_reading` is false, the data received from the browser is
    121    // appended to the data already received from the browser.  `buffer_` is
    122    // resized to allow reading more data from the browser.
    123    //
    124    // In all cases the caller is expected to use QueueReadFile() to continue
    125    // reading data from the browser.
    126    ResultCode OnReadFile(BOOL done_reading, DWORD count);
    127 
    128    // Calls the appropriate method the handler depending on the message
    129    // received from Google Chrome.
    130    ResultCode CallHandler();
    131 
    132    // Fills in the browser_info_ member of this Connection.  Assumes
    133    // IsConnected() is true.
    134    ResultCode BuildBrowserInfo();
    135 
    136    // Notifies the handler of the given error iff `rc` is not equal to
    137    // ResultCode::OK.  Appends the Google Chrome browser process id to the
    138    // context before calling the handler.  Also append `err` to the context
    139    // if it is not ERROR_SUCCESS.
    140    //
    141    // Returns the error passed into the method.
    142    ResultCode NotifyIfError(const char* context,
    143                             ResultCode rc,
    144                             DWORD err=ERROR_SUCCESS);
    145 
    146    // The handler to call for various agent events.
    147    AgentEventHandler* handler_ = nullptr;
    148 
    149    // Members used to communicate with Google Chrome.
    150    HANDLE handle_ = INVALID_HANDLE_VALUE;
    151    OVERLAPPED overlapped_;
    152 
    153    // True if this connection is assigned to a specific Google Chrome browser,
    154    // otherwise this connection is listening for a new browser.
    155    bool is_connected_ = false;
    156 
    157    // Information about the Google Chrome browser process.
    158    BrowserInfo browser_info_;
    159 
    160    // Members used to read messages from Google Chrome.
    161    std::vector<char> buffer_;
    162    char* cursor_ = nullptr;
    163    DWORD read_size_ = 0;
    164    DWORD final_size_ = 0;
    165  };
    166 
    167  // Returns handles that can be used to wait for events from all handles
    168  // managed by this agent.  This includes all connection objects and the
    169  // stop event.  The stop event is always last in the list.
    170  void GetHandles(std::vector<HANDLE>& wait_handles) const;
    171 
    172  // Handles one pipe event and returns.  If the return value is
    173  // ResultCode::OK, the `stopped` argument is set to true if the agent
    174  // should stop handling more events.  If the return value is not
    175  // ResultCode::OK, `stopped` is undefined.
    176  ResultCode HandleOneEvent(std::vector<HANDLE>& wait_handles, bool* stopped);
    177 
    178  // Performs a clean shutdown of the agent.
    179  void Shutdown();
    180 
    181  // Name used to create the pipes between the agent and Google Chrome browsers.
    182  std::string pipename_;
    183 
    184  // A list of pipes to already connected Google Chrome browsers.
    185  // The first kMinNumListeningPipeInstances pipes in the list correspond to
    186  // listening pipes.
    187  std::vector<std::unique_ptr<Connection>> connections_;
    188 
    189  // An event that is set when the agent should stop.  Set in Stop().
    190  HANDLE stop_event_ = nullptr;
    191 };
    192 
    193 }  // namespace sdk
    194 }  // namespace content_analysis
    195 
    196 #endif  // CONTENT_ANALYSIS_AGENT_SRC_AGENT_WIN_H_