agent.cc (7797B)
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 <algorithm> 6 #include <fstream> 7 #include <iostream> 8 #include <string> 9 #include <regex> 10 #include <vector> 11 12 #include "content_analysis/sdk/analysis_agent.h" 13 #include "demo/handler.h" 14 #include "demo/handler_misbehaving.h" 15 16 using namespace content_analysis::sdk; 17 18 // Different paths are used depending on whether this agent should run as a 19 // use specific agent or not. These values are chosen to match the test 20 // values in chrome browser. 21 constexpr char kPathUser[] = "path_user"; 22 constexpr char kPathSystem[] = "brcm_chrm_cas"; 23 24 // Global app config. 25 std::string path = kPathSystem; 26 bool use_queue = false; 27 bool user_specific = false; 28 std::vector<unsigned long> delays = {0}; // In milliseconds. 29 unsigned long num_threads = 8u; 30 std::string save_print_data_path = ""; 31 RegexArray toBlock, toWarn, toReport; 32 static bool useMisbehavingHandler = false; 33 static std::string modeStr; 34 35 // Command line parameters. 36 constexpr const char* kArgDelaySpecific = "--delays="; 37 constexpr const char* kArgDelayMsSpecific = "--delaysMs="; 38 constexpr const char* kArgPath = "--path="; 39 constexpr const char* kArgQueued = "--queued"; 40 constexpr const char* kArgThreads = "--threads="; 41 constexpr const char* kArgUserSpecific = "--user"; 42 constexpr const char* kArgToBlock = "--toblock="; 43 constexpr const char* kArgToWarn = "--towarn="; 44 constexpr const char* kArgToReport = "--toreport="; 45 constexpr const char* kArgMisbehave = "--misbehave="; 46 constexpr const char* kArgHelp = "--help"; 47 constexpr const char* kArgSavePrintRequestDataTo = "--save-print-request-data-to="; 48 49 std::map<std::string, Mode> sStringToMode = { 50 #define AGENT_MODE(name) {#name, Mode::Mode_##name}, 51 #include "modes.h" 52 #undef AGENT_MODE 53 }; 54 55 std::map<Mode, std::string> sModeToString = { 56 #define AGENT_MODE(name) {Mode::Mode_##name, #name}, 57 #include "modes.h" 58 #undef AGENT_MODE 59 }; 60 61 std::vector<std::pair<std::string, std::regex>> 62 ParseRegex(const std::string str) { 63 std::vector<std::pair<std::string, std::regex>> ret; 64 for (auto it = str.begin(); it != str.end(); /* nop */) { 65 auto it2 = std::find(it, str.end(), ','); 66 ret.push_back(std::make_pair(std::string(it, it2), std::regex(it, it2))); 67 it = it2 == str.end() ? it2 : it2 + 1; 68 } 69 70 return ret; 71 } 72 73 bool ParseCommandLine(int argc, char* argv[]) { 74 for (int i = 1; i < argc; ++i) { 75 const std::string arg = argv[i]; 76 if (arg.find(kArgUserSpecific) == 0) { 77 // If kArgPath was already used, abort. 78 if (path != kPathSystem) { 79 std::cout << std::endl << "ERROR: use --path=<path> after --user"; 80 return false; 81 } 82 path = kPathUser; 83 user_specific = true; 84 } else if ((arg.find(kArgDelaySpecific) == 0) || 85 (arg.find(kArgDelayMsSpecific) == 0)) { 86 bool isSecs = (arg.find(kArgDelaySpecific) == 0); 87 std::string delaysStr = arg.substr(strlen(isSecs ? kArgDelaySpecific : kArgDelayMsSpecific)); 88 unsigned long scale = isSecs ? 1000 : 1; 89 delays.clear(); 90 size_t posStart = 0, posEnd; 91 unsigned long delay; 92 while ((posEnd = delaysStr.find(',', posStart)) != std::string::npos) { 93 delay = std::stoul(delaysStr.substr(posStart, posEnd - posStart)); 94 delay = std::min(delay*scale, 30*1000ul); 95 delays.push_back(delay); 96 posStart = posEnd + 1; 97 } 98 delay = std::stoul(delaysStr.substr(posStart)); 99 delay = std::min(delay*scale, 30*1000ul); 100 delays.push_back(delay); 101 } else if (arg.find(kArgPath) == 0) { 102 path = arg.substr(strlen(kArgPath)); 103 } else if (arg.find(kArgQueued) == 0) { 104 use_queue = true; 105 } else if (arg.find(kArgThreads) == 0) { 106 num_threads = std::stoul(arg.substr(strlen(kArgThreads))); 107 } else if (arg.find(kArgToBlock) == 0) { 108 toBlock = ParseRegex(arg.substr(strlen(kArgToBlock))); 109 } else if (arg.find(kArgToWarn) == 0) { 110 toWarn = ParseRegex(arg.substr(strlen(kArgToWarn))); 111 } else if (arg.find(kArgToReport) == 0) { 112 toReport = ParseRegex(arg.substr(strlen(kArgToReport))); 113 } else if (arg.find(kArgMisbehave) == 0) { 114 modeStr = arg.substr(strlen(kArgMisbehave)); 115 useMisbehavingHandler = true; 116 } else if (arg.find(kArgHelp) == 0) { 117 return false; 118 } else if (arg.find(kArgSavePrintRequestDataTo) == 0) { 119 int arg_len = strlen(kArgSavePrintRequestDataTo); 120 save_print_data_path = arg.substr(arg_len); 121 } 122 } 123 124 return true; 125 } 126 127 void PrintHelp() { 128 std::cout 129 << std::endl << std::endl 130 << "Usage: agent [OPTIONS]" << std::endl 131 << "A simple agent to process content analysis requests." << std::endl 132 << "Data containing the string 'block' blocks the request data from being used." << std::endl 133 << std::endl << "Options:" << std::endl 134 << kArgDelaySpecific << "<delay1,delay2,...> : Add delays to request processing in seconds. Delays are limited to 30 seconds and are applied round-robin to requests. Default is 0." << std::endl 135 << kArgDelayMsSpecific << "<delay1,delay2,...> : Like --delays but takes durations in milliseconds." << std::endl 136 << kArgPath << " <path> : Used the specified path instead of default. Must come after --user." << std::endl 137 << kArgQueued << " : Queue requests for processing in a background thread" << std::endl 138 << kArgThreads << " : When queued, number of threads in the request processing thread pool" << std::endl 139 << kArgUserSpecific << " : Make agent OS user specific." << std::endl 140 << kArgHelp << " : prints this help message" << std::endl 141 << kArgSavePrintRequestDataTo << " : saves the PDF data to the given file path for print requests" << std::endl 142 << kArgToBlock << "<regex> : Regular expression matching file and text content to block." << std::endl 143 << kArgToWarn << "<regex> : Regular expression matching file and text content to warn about." << std::endl 144 << kArgToReport << "<regex> : Regular expression matching file and text content to report." << std::endl 145 << kArgMisbehave << "<mode> : Use 'misbehaving' agent in given mode for testing purposes." << std::endl; 146 } 147 148 int main(int argc, char* argv[]) { 149 if (!ParseCommandLine(argc, argv)) { 150 PrintHelp(); 151 return 1; 152 } 153 154 auto handler = 155 useMisbehavingHandler 156 ? MisbehavingHandler::Create(modeStr, std::move(delays), save_print_data_path, std::move(toBlock), std::move(toWarn), std::move(toReport)) 157 : use_queue 158 ? std::make_unique<QueuingHandler>(num_threads, std::move(delays), save_print_data_path, std::move(toBlock), std::move(toWarn), std::move(toReport)) 159 : std::make_unique<Handler>(std::move(delays), save_print_data_path, std::move(toBlock), std::move(toWarn), std::move(toReport)); 160 161 if (!handler) { 162 std::cout << "[Demo] Failed to construct handler." << std::endl; 163 return 1; 164 } 165 166 // Each agent uses a unique name to identify itself with Google Chrome. 167 content_analysis::sdk::ResultCode rc; 168 auto agent = content_analysis::sdk::Agent::Create( 169 {path, user_specific}, std::move(handler), &rc); 170 if (!agent || rc != content_analysis::sdk::ResultCode::OK) { 171 std::cout << "[Demo] Error starting agent: " 172 << content_analysis::sdk::ResultCodeToString(rc) 173 << std::endl; 174 return 1; 175 }; 176 177 std::cout << "[Demo] " << agent->DebugString() << std::endl; 178 179 // Blocks, sending events to the handler until agent->Stop() is called. 180 rc = agent->HandleEvents(); 181 if (rc != content_analysis::sdk::ResultCode::OK) { 182 std::cout << "[Demo] Error from handling events: " 183 << content_analysis::sdk::ResultCodeToString(rc) 184 << std::endl; 185 std::cout << "[Demo] " << agent->DebugString() << std::endl; 186 } 187 188 return 0; 189 }