tor-browser

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

event_win.cc (3487B)


      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 #include <ios>
      6 #include <sstream>
      7 #include <utility>
      8 
      9 #include "event_win.h"
     10 
     11 #include "common/utils_win.h"
     12 
     13 #include "agent_utils_win.h"
     14 #include "scoped_print_handle_win.h"
     15 
     16 namespace content_analysis {
     17 namespace sdk {
     18 
     19 // Writes a string to the pipe. Returns ERROR_SUCCESS if successful, else
     20 // returns GetLastError() of the write.  This function does not return until
     21 // the entire message has been sent (or an error occurs).
     22 static DWORD WriteMessageToPipe(HANDLE pipe, const std::string& message) {
     23  if (message.empty()) {
     24    return ERROR_SUCCESS;
     25  }
     26 
     27  internal::ScopedOverlapped overlapped;
     28  if (!overlapped.is_valid()) {
     29    return GetLastError();
     30  }
     31 
     32  DWORD err = ERROR_SUCCESS;
     33  const char* cursor = message.data();
     34  for (DWORD size = message.length(); size > 0;) {
     35    if (WriteFile(pipe, cursor, size, /*written=*/nullptr, overlapped)) {
     36      err = ERROR_SUCCESS;
     37      break;
     38    }
     39 
     40    // If an I/O is not pending, return the error.
     41    err = GetLastError();
     42    if (err != ERROR_IO_PENDING) {
     43      break;
     44    }
     45 
     46    DWORD written;
     47    if (!GetOverlappedResult(pipe, overlapped, &written, /*wait=*/TRUE)) {
     48      err = GetLastError();
     49      break;
     50    }
     51 
     52    cursor += written;
     53    size -= written;
     54  }
     55 
     56  return err;
     57 }
     58 
     59 
     60 ContentAnalysisEventWin::ContentAnalysisEventWin(
     61    HANDLE handle,
     62    const BrowserInfo& browser_info,
     63    ContentAnalysisRequest req)
     64    : ContentAnalysisEventBase(browser_info),
     65      hPipe_(handle) {
     66  *request() = std::move(req);
     67 }
     68 
     69 ContentAnalysisEventWin::~ContentAnalysisEventWin() {
     70  Shutdown();
     71 }
     72 
     73 ResultCode ContentAnalysisEventWin::Init() {
     74  // TODO(rogerta): do some extra validation of the request?
     75  if (request()->request_token().empty()) {
     76    return ResultCode::ERR_MISSING_REQUEST_TOKEN;
     77  }
     78 
     79  response()->set_request_token(request()->request_token());
     80 
     81  // Prepare the response so that ALLOW verdicts are the default().
     82  return UpdateResponse(*response(),
     83      request()->tags_size() > 0 ? request()->tags(0) : std::string(),
     84      ContentAnalysisResponse::Result::SUCCESS);
     85 }
     86 
     87 ResultCode ContentAnalysisEventWin::Close() {
     88  Shutdown();
     89  return ContentAnalysisEventBase::Close();
     90 }
     91 
     92 ResultCode ContentAnalysisEventWin::Send() {
     93  if (response_sent_) {
     94    return ResultCode::ERR_RESPONSE_ALREADY_SENT;
     95  }
     96 
     97  response_sent_ = true;
     98 
     99  DWORD err = WriteMessageToPipe(hPipe_,
    100                                 agent_to_chrome()->SerializeAsString());
    101  return ErrorToResultCode(err);
    102 }
    103 
    104 std::string ContentAnalysisEventWin::DebugString() const {
    105  std::stringstream state;
    106  state.setf(std::ios::boolalpha);
    107  state << "ContentAnalysisEventWin{handle=" << hPipe_;
    108  state << " pid=" << GetBrowserInfo().pid;
    109  state << " rtoken=" << GetRequest().request_token();
    110  state << " sent="  << response_sent_;
    111  state << "}" << std::ends;
    112 
    113  return state.str();
    114 }
    115 
    116 void ContentAnalysisEventWin::Shutdown() {
    117  if (hPipe_ != INVALID_HANDLE_VALUE) {
    118    // If no response has been sent yet, attempt to send it now.  Otherwise
    119    // the client may be stuck waiting.  After shutdown the agent will not
    120    // have any other chance to respond.
    121    if (!response_sent_) {
    122      Send();
    123    }
    124 
    125    // This event does not own the pipe, so don't close it.
    126    FlushFileBuffers(hPipe_);
    127    hPipe_ = INVALID_HANDLE_VALUE;
    128  }
    129 }
    130 
    131 }  // namespace sdk
    132 }  // namespace content_analysis