зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1811076: Part 4 - Add gtests for correctly-behaving and misbehaving DLP agents
Unit tests for mozilla::contentanalysis::ContentAnalysis class. ContentAnalysis must remain responsive, regardless of the behavior of the agent. Differential Revision: https://phabricator.services.mozilla.com/D189570
This commit is contained in:
Родитель
10a9ab9367
Коммит
9ebb7f35a4
|
@ -41,6 +41,7 @@ TEST_HARNESS_BINS = [
|
|||
"crashinject",
|
||||
"geckodriver",
|
||||
"http3server",
|
||||
"content_analysis_sdk_agent",
|
||||
"minidumpwriter",
|
||||
"pk12util",
|
||||
"screenshot",
|
||||
|
@ -459,6 +460,7 @@ ARCHIVE_FILES = {
|
|||
"chrome/**",
|
||||
"chrome.manifest",
|
||||
"components/**",
|
||||
"content_analysis_sdk_agent",
|
||||
"http3server",
|
||||
"*.ini",
|
||||
"localization/**",
|
||||
|
|
|
@ -795,6 +795,7 @@ class WinArtifactJob(ArtifactJob):
|
|||
("bin/ssltunnel.exe", ("bin", "bin")),
|
||||
("bin/xpcshell.exe", ("bin", "bin")),
|
||||
("bin/http3server.exe", ("bin", "bin")),
|
||||
("bin/content_analysis_sdk_agent.exe", ("bin", "bin")),
|
||||
("bin/plugins/gmp-*/*/*", ("bin/plugins", "bin")),
|
||||
("bin/plugins/*", ("bin/plugins", "plugins")),
|
||||
("bin/components/*", ("bin/components", "bin/components")),
|
||||
|
|
|
@ -28,6 +28,12 @@ class ContentAnalysisEventWin : public ContentAnalysisEventBase {
|
|||
ResultCode Close() override;
|
||||
ResultCode Send() override;
|
||||
std::string DebugString() const override;
|
||||
std::string SerializeStringToSendToBrowser() {
|
||||
return agent_to_chrome()->SerializeAsString();
|
||||
}
|
||||
void SetResponseSent() { response_sent_ = true; }
|
||||
|
||||
HANDLE Pipe() const { return hPipe_; }
|
||||
|
||||
private:
|
||||
void Shutdown();
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
|
||||
#include "content_analysis/sdk/analysis_agent.h"
|
||||
#include "demo/handler.h"
|
||||
#include "demo/handler_misbehaving.h"
|
||||
|
||||
using namespace content_analysis::sdk;
|
||||
|
||||
// Different paths are used depending on whether this agent should run as a
|
||||
// use specific agent or not. These values are chosen to match the test
|
||||
|
@ -25,6 +28,8 @@ unsigned long delay = 0; // In seconds.
|
|||
unsigned long num_threads = 8u;
|
||||
std::string save_print_data_path = "";
|
||||
RegexArray toBlock, toWarn, toReport;
|
||||
static bool useMisbehavingHandler = false;
|
||||
static std::string modeStr;
|
||||
|
||||
// Command line parameters.
|
||||
constexpr const char* kArgDelaySpecific = "--delay=";
|
||||
|
@ -35,9 +40,22 @@ constexpr const char* kArgUserSpecific = "--user";
|
|||
constexpr const char* kArgToBlock = "--toblock=";
|
||||
constexpr const char* kArgToWarn = "--towarn=";
|
||||
constexpr const char* kArgToReport = "--toreport=";
|
||||
constexpr const char* kArgMisbehave = "--misbehave=";
|
||||
constexpr const char* kArgHelp = "--help";
|
||||
constexpr const char* kArgSavePrintRequestDataTo = "--save-print-request-data-to=";
|
||||
|
||||
std::map<std::string, Mode> sStringToMode = {
|
||||
#define AGENT_MODE(name) {#name, Mode::Mode_##name},
|
||||
#include "modes.h"
|
||||
#undef AGENT_MODE
|
||||
};
|
||||
|
||||
std::map<Mode, std::string> sModeToString = {
|
||||
#define AGENT_MODE(name) {Mode::Mode_##name, #name},
|
||||
#include "modes.h"
|
||||
#undef AGENT_MODE
|
||||
};
|
||||
|
||||
std::vector<std::pair<std::string, std::regex>>
|
||||
ParseRegex(const std::string str) {
|
||||
std::vector<std::pair<std::string, std::regex>> ret;
|
||||
|
@ -78,6 +96,9 @@ bool ParseCommandLine(int argc, char* argv[]) {
|
|||
toWarn = ParseRegex(arg.substr(strlen(kArgToWarn)));
|
||||
} else if (arg.find(kArgToReport) == 0) {
|
||||
toReport = ParseRegex(arg.substr(strlen(kArgToReport)));
|
||||
} else if (arg.find(kArgMisbehave) == 0) {
|
||||
modeStr = arg.substr(strlen(kArgMisbehave));
|
||||
useMisbehavingHandler = true;
|
||||
} else if (arg.find(kArgHelp) == 0) {
|
||||
return false;
|
||||
} else if (arg.find(kArgSavePrintRequestDataTo) == 0) {
|
||||
|
@ -105,6 +126,7 @@ void PrintHelp() {
|
|||
<< kArgToBlock << "<regex> : Regular expression matching file and text content to block." << std::endl
|
||||
<< kArgToWarn << "<regex> : Regular expression matching file and text content to warn about." << std::endl
|
||||
<< kArgToReport << "<regex> : Regular expression matching file and text content to report." << std::endl
|
||||
<< kArgMisbehave << "<mode> : Use 'misbehaving' agent in given mode for testing purposes." << std::endl
|
||||
<< kArgHelp << " : prints this help message" << std::endl;
|
||||
}
|
||||
|
||||
|
@ -115,9 +137,17 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
// TODO: Add toBlock, toWarn, toReport to QueueingHandler
|
||||
auto handler = use_queue
|
||||
? std::make_unique<QueuingHandler>(num_threads, delay, save_print_data_path)
|
||||
: std::make_unique<Handler>(delay, save_print_data_path, std::move(toBlock), std::move(toWarn), std::move(toReport));
|
||||
auto handler =
|
||||
useMisbehavingHandler
|
||||
? MisbehavingHandler::Create(delay, modeStr)
|
||||
: use_queue
|
||||
? std::make_unique<QueuingHandler>(num_threads, delay, save_print_data_path)
|
||||
: std::make_unique<Handler>(delay, save_print_data_path, std::move(toBlock), std::move(toWarn), std::move(toReport));
|
||||
|
||||
if (!handler) {
|
||||
std::cout << "[Demo] Failed to construct handler." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Each agent uses a unique name to identify itself with Google Chrome.
|
||||
content_analysis::sdk::ResultCode rc;
|
||||
|
|
|
@ -51,8 +51,8 @@ class Handler : public content_analysis::sdk::AgentEventHandler {
|
|||
DumpEvent(stream, event.get());
|
||||
|
||||
bool success = true;
|
||||
std::optional<ContentAnalysisResponse_Result_TriggeredRule_Action> caResponse =
|
||||
ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK;
|
||||
std::optional<content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action> caResponse =
|
||||
content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK;
|
||||
|
||||
if (event->GetRequest().has_text_content()) {
|
||||
caResponse = DecideCAResponse(
|
||||
|
@ -80,16 +80,16 @@ class Handler : public content_analysis::sdk::AgentEventHandler {
|
|||
stream << " Verdict: ";
|
||||
if (caResponse) {
|
||||
switch (caResponse.value()) {
|
||||
case ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK:
|
||||
case content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK:
|
||||
stream << "BLOCK";
|
||||
break;
|
||||
case ContentAnalysisResponse_Result_TriggeredRule_Action_WARN:
|
||||
case content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_WARN:
|
||||
stream << "WARN";
|
||||
break;
|
||||
case ContentAnalysisResponse_Result_TriggeredRule_Action_REPORT_ONLY:
|
||||
case content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_REPORT_ONLY:
|
||||
stream << "REPORT_ONLY";
|
||||
break;
|
||||
case ContentAnalysisResponse_Result_TriggeredRule_Action_ACTION_UNSPECIFIED:
|
||||
case content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_ACTION_UNSPECIFIED:
|
||||
stream << "ACTION_UNSPECIFIED";
|
||||
break;
|
||||
default:
|
||||
|
@ -332,27 +332,27 @@ class Handler : public content_analysis::sdk::AgentEventHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::optional<ContentAnalysisResponse_Result_TriggeredRule_Action>
|
||||
std::optional<content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action>
|
||||
DecideCAResponse(const std::string& content, std::stringstream& stream) {
|
||||
for (auto& r : toBlock_) {
|
||||
if (std::regex_search(content, r.second)) {
|
||||
stream << "'" << content << "' matches BLOCK regex '"
|
||||
<< r.first << "'" << std::endl;
|
||||
return ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK;
|
||||
return content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK;
|
||||
}
|
||||
}
|
||||
for (auto& r : toWarn_) {
|
||||
if (std::regex_search(content, r.second)) {
|
||||
stream << "'" << content << "' matches WARN regex '"
|
||||
<< r.first << "'" << std::endl;
|
||||
return ContentAnalysisResponse_Result_TriggeredRule_Action_WARN;
|
||||
return content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_WARN;
|
||||
}
|
||||
}
|
||||
for (auto& r : toReport_) {
|
||||
if (std::regex_search(content, r.second)) {
|
||||
stream << "'" << content << "' matches REPORT_ONLY regex '"
|
||||
<< r.first << "'" << std::endl;
|
||||
return ContentAnalysisResponse_Result_TriggeredRule_Action_REPORT_ONLY;
|
||||
return content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule_Action_REPORT_ONLY;
|
||||
}
|
||||
}
|
||||
stream << "'" << content << "' was ALLOWed\n";
|
||||
|
|
|
@ -0,0 +1,495 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CONTENT_ANALYSIS_DEMO_HANDLER_MISBEHAVING_H_
|
||||
#define CONTENT_ANALYSIS_DEMO_HANDLER_MISBEHAVING_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <regex>
|
||||
#include <windows.h>
|
||||
|
||||
#include "content_analysis/sdk/analysis.pb.h"
|
||||
#include "content_analysis/sdk/analysis_agent.h"
|
||||
#include "agent/src/event_win.h"
|
||||
|
||||
enum class Mode {
|
||||
// Have to use a "Mode_" prefix to avoid preprocessing problems in StringToMode
|
||||
#define AGENT_MODE(name) Mode_##name,
|
||||
#include "modes.h"
|
||||
#undef AGENT_MODE
|
||||
};
|
||||
|
||||
extern std::map<std::string, Mode> sStringToMode;
|
||||
extern std::map<Mode, std::string> sModeToString;
|
||||
|
||||
// Writes a string to the pipe. Returns ERROR_SUCCESS if successful, else
|
||||
// returns GetLastError() of the write. This function does not return until
|
||||
// the entire message has been sent (or an error occurs).
|
||||
static DWORD WriteBigMessageToPipe(HANDLE pipe, const std::string& message) {
|
||||
std::cout << "[demo] WriteBigMessageToPipe top, message size is "
|
||||
<< message.size() << std::endl;
|
||||
if (message.empty()) {
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
OVERLAPPED overlapped;
|
||||
memset(&overlapped, 0, sizeof(overlapped));
|
||||
overlapped.hEvent = CreateEvent(/*securityAttr=*/nullptr,
|
||||
/*manualReset=*/TRUE,
|
||||
/*initialState=*/FALSE,
|
||||
/*name=*/nullptr);
|
||||
if (overlapped.hEvent == nullptr) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
DWORD err = ERROR_SUCCESS;
|
||||
const char* cursor = message.data();
|
||||
for (DWORD size = message.length(); size > 0;) {
|
||||
std::cout << "[demo] WriteBigMessageToPipe top of loop, remaining size "
|
||||
<< size << std::endl;
|
||||
if (WriteFile(pipe, cursor, size, /*written=*/nullptr, &overlapped)) {
|
||||
std::cout << "[demo] WriteBigMessageToPipe: success" << std::endl;
|
||||
err = ERROR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
// If an I/O is not pending, return the error.
|
||||
err = GetLastError();
|
||||
if (err != ERROR_IO_PENDING) {
|
||||
std::cout
|
||||
<< "[demo] WriteBigMessageToPipe: returning error from WriteFile "
|
||||
<< err << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD written;
|
||||
if (!GetOverlappedResult(pipe, &overlapped, &written, /*wait=*/TRUE)) {
|
||||
err = GetLastError();
|
||||
std::cout << "[demo] WriteBigMessageToPipe: returning error from "
|
||||
"GetOverlappedREsult "
|
||||
<< err << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// reset err for the next loop iteration
|
||||
err = ERROR_SUCCESS;
|
||||
std::cout << "[demo] WriteBigMessageToPipe: bottom of loop, wrote "
|
||||
<< written << std::endl;
|
||||
cursor += written;
|
||||
size -= written;
|
||||
}
|
||||
|
||||
CloseHandle(overlapped.hEvent);
|
||||
return err;
|
||||
}
|
||||
|
||||
// An AgentEventHandler that does various misbehaving things
|
||||
class MisbehavingHandler final : public content_analysis::sdk::AgentEventHandler {
|
||||
public:
|
||||
using Event = content_analysis::sdk::ContentAnalysisEvent;
|
||||
|
||||
static
|
||||
std::unique_ptr<AgentEventHandler> Create(unsigned long delay,
|
||||
const std::string& modeStr) {
|
||||
auto it = sStringToMode.find(modeStr);
|
||||
if (it == sStringToMode.end()) {
|
||||
std::cout << "\"" << modeStr << "\""
|
||||
<< " is not a valid mode!" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::unique_ptr<AgentEventHandler>(new MisbehavingHandler(delay, it->second));
|
||||
}
|
||||
|
||||
private:
|
||||
MisbehavingHandler(unsigned long delay, Mode mode) : delay_(delay), mode_(mode) {}
|
||||
|
||||
template <size_t N>
|
||||
DWORD SendBytesOverPipe(const unsigned char (&bytes)[N],
|
||||
const std::unique_ptr<Event>& event) {
|
||||
content_analysis::sdk::ContentAnalysisEventWin* eventWin =
|
||||
static_cast<content_analysis::sdk::ContentAnalysisEventWin*>(
|
||||
event.get());
|
||||
HANDLE pipe = eventWin->Pipe();
|
||||
std::string s(reinterpret_cast<const char*>(bytes), N);
|
||||
return WriteBigMessageToPipe(pipe, s);
|
||||
}
|
||||
|
||||
// Analyzes one request from Google Chrome and responds back to the browser
|
||||
// with either an allow or block verdict.
|
||||
void AnalyzeContent(std::unique_ptr<Event> event) {
|
||||
// An event represents one content analysis request and response triggered
|
||||
// by a user action in Google Chrome. The agent determines whether the
|
||||
// user is allowed to perform the action by examining event->GetRequest().
|
||||
// The verdict, which can be "allow" or "block" is written into
|
||||
// event->GetResponse().
|
||||
|
||||
std::cout << std::endl << "----------" << std::endl << std::endl;
|
||||
|
||||
DumpRequest(event->GetRequest());
|
||||
std::cout << "Mode is " << sModeToString[mode_] << std::endl;
|
||||
|
||||
if (mode_ == Mode::Mode_largeResponse) {
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
content_analysis::sdk::ContentAnalysisResponse_Result* result =
|
||||
event->GetResponse().add_results();
|
||||
result->set_tag("someTag");
|
||||
content_analysis::sdk::ContentAnalysisResponse_Result_TriggeredRule*
|
||||
triggeredRule = result->add_triggered_rules();
|
||||
triggeredRule->set_rule_id("some_id");
|
||||
triggeredRule->set_rule_name("some_name");
|
||||
}
|
||||
} else if (mode_ ==
|
||||
Mode::Mode_invalidUtf8StringStartByteIsContinuationByte) {
|
||||
// protobuf docs say
|
||||
// "A string must always contain UTF-8 encoded text."
|
||||
// So let's try something invalid
|
||||
// Anything with bits 10xxxxxx is only a continuation code point
|
||||
event->GetResponse().set_request_token("\x80\x41\x41\x41");
|
||||
} else if (mode_ ==
|
||||
Mode::Mode_invalidUtf8StringEndsInMiddleOfMultibyteSequence) {
|
||||
// f0 byte indicates there should be 3 bytes following it, but here
|
||||
// there are only 2
|
||||
event->GetResponse().set_request_token("\x41\xf0\x90\x8d");
|
||||
} else if (mode_ == Mode::Mode_invalidUtf8StringOverlongEncoding) {
|
||||
// codepoint U+20AC, should be encoded in 3 bytes (E2 82 AC)
|
||||
// instead of 4
|
||||
event->GetResponse().set_request_token("\xf0\x82\x82\xac");
|
||||
} else if (mode_ == Mode::Mode_invalidUtf8StringMultibyteSequenceTooShort) {
|
||||
// f0 byte indicates there should be 3 bytes following it, but here
|
||||
// there are only 2 (\x41 is not a continuation byte)
|
||||
event->GetResponse().set_request_token("\xf0\x90\x8d\x41");
|
||||
} else if (mode_ == Mode::Mode_invalidUtf8StringDecodesToInvalidCodePoint) {
|
||||
// decodes to U+1FFFFF, but only up to U+10FFFF is a valid code point
|
||||
event->GetResponse().set_request_token("\xf7\xbf\xbf\xbf");
|
||||
} else if (mode_ == Mode::Mode_stringWithEmbeddedNull) {
|
||||
event->GetResponse().set_request_token("\x41\x00\x41");
|
||||
} else if (mode_ == Mode::Mode_zeroResults) {
|
||||
event->GetResponse().clear_results();
|
||||
} else if (mode_ == Mode::Mode_resultWithInvalidStatus) {
|
||||
// This causes an assertion failure and the process exits
|
||||
// So we just serialize this ourselves below
|
||||
/*content_analysis::sdk::ContentAnalysisResponse_Result* result =
|
||||
event->GetResponse().mutable_results(0);
|
||||
result->set_status(
|
||||
static_cast<
|
||||
::content_analysis::sdk::ContentAnalysisResponse_Result_Status>(
|
||||
100));*/
|
||||
} else {
|
||||
bool block = false;
|
||||
|
||||
if (event->GetRequest().has_text_content()) {
|
||||
block = ShouldBlockRequest(event->GetRequest().text_content());
|
||||
} else if (event->GetRequest().has_file_path()) {
|
||||
block = ShouldBlockRequest(event->GetRequest().file_path());
|
||||
}
|
||||
|
||||
if (block) {
|
||||
auto rc = content_analysis::sdk::SetEventVerdictToBlock(event.get());
|
||||
std::cout << " Verdict: block";
|
||||
if (rc != content_analysis::sdk::ResultCode::OK) {
|
||||
std::cout << " error: "
|
||||
<< content_analysis::sdk::ResultCodeToString(rc)
|
||||
<< std::endl;
|
||||
std::cout << " " << event->DebugString() << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
std::cout << " Verdict: allow" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// If a delay is specified, wait that much.
|
||||
if (delay_ > 0) {
|
||||
std::cout << "[Demo] delaying request processing for " << delay_ << "s"
|
||||
<< std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(delay_));
|
||||
}
|
||||
|
||||
if (mode_ == Mode::Mode_largeResponse) {
|
||||
content_analysis::sdk::ContentAnalysisEventWin* eventWin =
|
||||
static_cast<content_analysis::sdk::ContentAnalysisEventWin*>(
|
||||
event.get());
|
||||
HANDLE pipe = eventWin->Pipe();
|
||||
std::cout << "largeResponse about to write" << std::endl;
|
||||
DWORD result = WriteBigMessageToPipe(
|
||||
pipe, eventWin->SerializeStringToSendToBrowser());
|
||||
std::cout << "largeResponse done writing with error " << result
|
||||
<< std::endl;
|
||||
eventWin->SetResponseSent();
|
||||
} else if (mode_ == Mode::Mode_resultWithInvalidStatus) {
|
||||
content_analysis::sdk::ContentAnalysisEventWin* eventWin =
|
||||
static_cast<content_analysis::sdk::ContentAnalysisEventWin*>(
|
||||
event.get());
|
||||
HANDLE pipe = eventWin->Pipe();
|
||||
std::string serializedString = eventWin->SerializeStringToSendToBrowser();
|
||||
// The last byte is the status value. Set it to 100
|
||||
serializedString[serializedString.length() - 1] = 100;
|
||||
WriteBigMessageToPipe(pipe, serializedString);
|
||||
} else if (mode_ == Mode::Mode_messageTruncatedInMiddleOfString) {
|
||||
unsigned char bytes[5];
|
||||
bytes[0] = 10; // field 1 (request_token), LEN encoding
|
||||
bytes[1] = 13; // length 13
|
||||
bytes[2] = 65; // "A"
|
||||
bytes[3] = 66; // "B"
|
||||
bytes[4] = 67; // "C"
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageWithInvalidWireType) {
|
||||
unsigned char bytes[5];
|
||||
bytes[0] = 15; // field 1 (request_token), "7" encoding (invalid value)
|
||||
bytes[1] = 3; // length 3
|
||||
bytes[2] = 65; // "A"
|
||||
bytes[3] = 66; // "B"
|
||||
bytes[4] = 67; // "C"
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageWithUnusedFieldNumber) {
|
||||
unsigned char bytes[5];
|
||||
bytes[0] = 82; // field 10 (this is invalid), LEN encoding
|
||||
bytes[1] = 3; // length 3
|
||||
bytes[2] = 65; // "A"
|
||||
bytes[3] = 66; // "B"
|
||||
bytes[4] = 67; // "C"
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageWithWrongStringWireType) {
|
||||
unsigned char bytes[2];
|
||||
bytes[0] = 10; // field 1 (request_token), VARINT encoding (but should be
|
||||
// a string/LEN)
|
||||
bytes[1] = 42; // value 42
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageWithZeroTag) {
|
||||
unsigned char bytes[1];
|
||||
// The protobuf deserialization code seems to handle this
|
||||
// in a special case.
|
||||
bytes[0] = 0;
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageWithZeroFieldButNonzeroWireType) {
|
||||
// The protobuf deserialization code seems to handle this
|
||||
// in a special case.
|
||||
unsigned char bytes[5];
|
||||
bytes[0] = 2; // field 0 (invalid), LEN encoding
|
||||
bytes[1] = 3; // length 13
|
||||
bytes[2] = 65; // "A"
|
||||
bytes[3] = 66; // "B"
|
||||
bytes[4] = 67; // "C"
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageWithGroupEnd) {
|
||||
// GROUP_ENDs are obsolete and the deserialization code
|
||||
// handles them in a special case.
|
||||
unsigned char bytes[1];
|
||||
bytes[0] = 12; // field 1 (request_token), GROUP_END encoding
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageTruncatedInMiddleOfVarint) {
|
||||
unsigned char bytes[2];
|
||||
bytes[0] = 16; // field 2 (status), VARINT encoding
|
||||
bytes[1] = 128; // high bit is set, indicating there
|
||||
// should be a byte after this
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else if (mode_ == Mode::Mode_messageTruncatedInMiddleOfTag) {
|
||||
unsigned char bytes[1];
|
||||
bytes[0] = 128; // tag is actually encoded as a VARINT, so set the high
|
||||
// bit, indicating there should be a byte after this
|
||||
SendBytesOverPipe(bytes, event);
|
||||
} else {
|
||||
std::cout << "(misbehaving) Handler::AnalyzeContent() about to call "
|
||||
"event->Send(), mode is "
|
||||
<< sModeToString[mode_] << std::endl;
|
||||
// Send the response back to Google Chrome.
|
||||
auto rc = event->Send();
|
||||
if (rc != content_analysis::sdk::ResultCode::OK) {
|
||||
std::cout << "[Demo] Error sending response: "
|
||||
<< content_analysis::sdk::ResultCodeToString(rc) << std::endl;
|
||||
std::cout << event->DebugString() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void OnBrowserConnected(
|
||||
const content_analysis::sdk::BrowserInfo& info) override {
|
||||
std::cout << std::endl << "==========" << std::endl;
|
||||
std::cout << "Browser connected pid=" << info.pid << std::endl;
|
||||
}
|
||||
|
||||
void OnBrowserDisconnected(
|
||||
const content_analysis::sdk::BrowserInfo& info) override {
|
||||
std::cout << std::endl
|
||||
<< "Browser disconnected pid=" << info.pid << std::endl;
|
||||
std::cout << "==========" << std::endl;
|
||||
}
|
||||
|
||||
void OnAnalysisRequested(std::unique_ptr<Event> event) override {
|
||||
// If the agent is capable of analyzing content in the background, the
|
||||
// events may be handled in background threads. Having said that, a
|
||||
// event should not be assumed to be thread safe, that is, it should not
|
||||
// be accessed by more than one thread concurrently.
|
||||
//
|
||||
// In this example code, the event is handled synchronously.
|
||||
AnalyzeContent(std::move(event));
|
||||
}
|
||||
void OnResponseAcknowledged(
|
||||
const content_analysis::sdk::ContentAnalysisAcknowledgement& ack)
|
||||
override {
|
||||
const char* final_action = "<Unknown>";
|
||||
if (ack.has_final_action()) {
|
||||
switch (ack.final_action()) {
|
||||
case content_analysis::sdk::ContentAnalysisAcknowledgement::
|
||||
ACTION_UNSPECIFIED:
|
||||
final_action = "<Unspecified>";
|
||||
break;
|
||||
case content_analysis::sdk::ContentAnalysisAcknowledgement::ALLOW:
|
||||
final_action = "Allow";
|
||||
break;
|
||||
case content_analysis::sdk::ContentAnalysisAcknowledgement::REPORT_ONLY:
|
||||
final_action = "Report only";
|
||||
break;
|
||||
case content_analysis::sdk::ContentAnalysisAcknowledgement::WARN:
|
||||
final_action = "Warn";
|
||||
break;
|
||||
case content_analysis::sdk::ContentAnalysisAcknowledgement::BLOCK:
|
||||
final_action = "Block";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Ack: " << ack.request_token() << std::endl;
|
||||
std::cout << " Final action: " << final_action << std::endl;
|
||||
}
|
||||
void OnCancelRequests(
|
||||
const content_analysis::sdk::ContentAnalysisCancelRequests& cancel)
|
||||
override {
|
||||
std::cout << "Cancel: " << std::endl;
|
||||
std::cout << " User action ID: " << cancel.user_action_id() << std::endl;
|
||||
}
|
||||
|
||||
void OnInternalError(const char* context,
|
||||
content_analysis::sdk::ResultCode error) override {
|
||||
std::cout << std::endl
|
||||
<< "*ERROR*: context=\"" << context << "\" "
|
||||
<< content_analysis::sdk::ResultCodeToString(error) << std::endl;
|
||||
}
|
||||
|
||||
void DumpRequest(
|
||||
const content_analysis::sdk::ContentAnalysisRequest& request) {
|
||||
std::string connector = "<Unknown>";
|
||||
if (request.has_analysis_connector()) {
|
||||
switch (request.analysis_connector()) {
|
||||
case content_analysis::sdk::FILE_DOWNLOADED:
|
||||
connector = "download";
|
||||
break;
|
||||
case content_analysis::sdk::FILE_ATTACHED:
|
||||
connector = "attach";
|
||||
break;
|
||||
case content_analysis::sdk::BULK_DATA_ENTRY:
|
||||
connector = "bulk-data-entry";
|
||||
break;
|
||||
case content_analysis::sdk::PRINT:
|
||||
connector = "print";
|
||||
break;
|
||||
case content_analysis::sdk::FILE_TRANSFER:
|
||||
connector = "file-transfer";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string url =
|
||||
request.has_request_data() && request.request_data().has_url()
|
||||
? request.request_data().url()
|
||||
: "<No URL>";
|
||||
|
||||
std::string tab_title =
|
||||
request.has_request_data() && request.request_data().has_tab_title()
|
||||
? request.request_data().tab_title()
|
||||
: "<No tab title>";
|
||||
|
||||
std::string filename =
|
||||
request.has_request_data() && request.request_data().has_filename()
|
||||
? request.request_data().filename()
|
||||
: "<No filename>";
|
||||
|
||||
std::string digest =
|
||||
request.has_request_data() && request.request_data().has_digest()
|
||||
? request.request_data().digest()
|
||||
: "<No digest>";
|
||||
|
||||
std::string file_path =
|
||||
request.has_file_path() ? request.file_path() : "<none>";
|
||||
|
||||
std::string text_content =
|
||||
request.has_text_content() ? request.text_content() : "<none>";
|
||||
|
||||
std::string machine_user =
|
||||
request.has_client_metadata() &&
|
||||
request.client_metadata().has_browser() &&
|
||||
request.client_metadata().browser().has_machine_user()
|
||||
? request.client_metadata().browser().machine_user()
|
||||
: "<No machine user>";
|
||||
|
||||
std::string email =
|
||||
request.has_request_data() && request.request_data().has_email()
|
||||
? request.request_data().email()
|
||||
: "<No email>";
|
||||
|
||||
time_t t = request.expires_at();
|
||||
|
||||
std::string user_action_id = request.has_user_action_id()
|
||||
? request.user_action_id()
|
||||
: "<No user action id>";
|
||||
|
||||
std::cout << "Request: " << request.request_token() << std::endl;
|
||||
std::cout << " User action ID: " << user_action_id << std::endl;
|
||||
std::cout << " Expires at: " << ctime(&t); // Returned string includes \n.
|
||||
std::cout << " Connector: " << connector << std::endl;
|
||||
std::cout << " URL: " << url << std::endl;
|
||||
std::cout << " Tab title: " << tab_title << std::endl;
|
||||
std::cout << " Filename: " << filename << std::endl;
|
||||
std::cout << " Digest: " << digest << std::endl;
|
||||
std::cout << " Filepath: " << file_path << std::endl;
|
||||
std::cout << " Text content: '" << text_content << "'" << std::endl;
|
||||
std::cout << " Machine user: " << machine_user << std::endl;
|
||||
std::cout << " Email: " << email << std::endl;
|
||||
}
|
||||
|
||||
bool ReadContentFromFile(const std::string& file_path, std::string* content) {
|
||||
std::ifstream file(file_path,
|
||||
std::ios::in | std::ios::binary | std::ios::ate);
|
||||
if (!file.is_open()) return false;
|
||||
|
||||
// Get file size. This example does not handle files larger than 1MB.
|
||||
// Make sure content string can hold the contents of the file.
|
||||
int size = file.tellg();
|
||||
if (size > 1024 * 1024) return false;
|
||||
|
||||
content->resize(size + 1);
|
||||
|
||||
// Read file into string.
|
||||
file.seekg(0, std::ios::beg);
|
||||
file.read(&(*content)[0], size);
|
||||
content->at(size) = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShouldBlockRequest(const std::string& content) {
|
||||
// Determines if the request should be blocked. (not needed for the
|
||||
// misbehaving agent)
|
||||
std::cout << "'" << content << "' was not blocked\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long delay_;
|
||||
Mode mode_;
|
||||
};
|
||||
|
||||
#endif // CONTENT_ANALYSIS_DEMO_HANDLER_MISBEHAVING_H_
|
|
@ -0,0 +1,25 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// #define AGENT_MODE(name) to do what you want and then #include this file
|
||||
|
||||
AGENT_MODE(largeResponse)
|
||||
AGENT_MODE(invalidUtf8StringStartByteIsContinuationByte)
|
||||
AGENT_MODE(invalidUtf8StringEndsInMiddleOfMultibyteSequence)
|
||||
AGENT_MODE(invalidUtf8StringOverlongEncoding)
|
||||
AGENT_MODE(invalidUtf8StringMultibyteSequenceTooShort)
|
||||
AGENT_MODE(invalidUtf8StringDecodesToInvalidCodePoint)
|
||||
AGENT_MODE(stringWithEmbeddedNull)
|
||||
AGENT_MODE(zeroResults)
|
||||
AGENT_MODE(resultWithInvalidStatus)
|
||||
AGENT_MODE(messageTruncatedInMiddleOfString)
|
||||
AGENT_MODE(messageWithInvalidWireType)
|
||||
AGENT_MODE(messageWithUnusedFieldNumber)
|
||||
AGENT_MODE(messageWithWrongStringWireType)
|
||||
AGENT_MODE(messageWithZeroTag)
|
||||
AGENT_MODE(messageWithZeroFieldButNonzeroWireType)
|
||||
AGENT_MODE(messageWithGroupEnd)
|
||||
AGENT_MODE(messageTruncatedInMiddleOfVarint)
|
||||
AGENT_MODE(messageTruncatedInMiddleOfTag)
|
|
@ -58,3 +58,5 @@ DEFINES["GOOGLE_PROTOBUF_NO_RTTI"] = True
|
|||
DEFINES["GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER"] = True
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
||||
TEST_DIRS += ["tests/gtest"]
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "content_analysis/sdk/analysis_client.h"
|
||||
#include "TestContentAnalysis.h"
|
||||
#include <processenv.h>
|
||||
#include <synchapi.h>
|
||||
|
||||
using namespace content_analysis::sdk;
|
||||
|
||||
MozAgentInfo LaunchAgentNormal(const wchar_t* aToBlock) {
|
||||
nsString cmdLineArguments;
|
||||
if (aToBlock && aToBlock[0] != 0) {
|
||||
cmdLineArguments.Append(L" --toblock=.*");
|
||||
cmdLineArguments.Append(aToBlock);
|
||||
cmdLineArguments.Append(L".*");
|
||||
}
|
||||
cmdLineArguments.Append(L" --user");
|
||||
cmdLineArguments.Append(L" --path=");
|
||||
nsString pipeName;
|
||||
GeneratePipeName(L"contentanalysissdk-gtest-", pipeName);
|
||||
cmdLineArguments.Append(pipeName);
|
||||
MozAgentInfo agentInfo;
|
||||
LaunchAgentWithCommandLineArguments(cmdLineArguments, pipeName, agentInfo);
|
||||
return agentInfo;
|
||||
}
|
||||
|
||||
TEST(ContentAnalysis, TextShouldNotBeBlocked)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentNormal(L"block");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("should succeed");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
ASSERT_STREQ("request token", response.request_token().c_str());
|
||||
ASSERT_EQ(1, response.results().size());
|
||||
ASSERT_EQ(ContentAnalysisResponse_Result_Status_SUCCESS,
|
||||
response.results().Get(0).status());
|
||||
ASSERT_EQ(0, response.results().Get(0).triggered_rules_size());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysis, TextShouldBeBlocked)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentNormal(L"block");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("should be blocked");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
ASSERT_STREQ("request token", response.request_token().c_str());
|
||||
ASSERT_EQ(1, response.results().size());
|
||||
ASSERT_EQ(ContentAnalysisResponse_Result_Status_SUCCESS,
|
||||
response.results().Get(0).status());
|
||||
ASSERT_EQ(1, response.results().Get(0).triggered_rules_size());
|
||||
ASSERT_EQ(ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK,
|
||||
response.results().Get(0).triggered_rules(0).action());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysis, FileShouldNotBeBlocked)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentNormal(L"block");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_file_path("..\\..\\_tests\\gtest\\allowedFile.txt");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
ASSERT_STREQ("request token", response.request_token().c_str());
|
||||
ASSERT_EQ(1, response.results().size());
|
||||
ASSERT_EQ(ContentAnalysisResponse_Result_Status_SUCCESS,
|
||||
response.results().Get(0).status());
|
||||
ASSERT_EQ(0, response.results().Get(0).triggered_rules_size());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysis, FileShouldBeBlocked)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentNormal(L"block");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_file_path("..\\..\\_tests\\gtest\\blockedFile.txt");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
ASSERT_STREQ("request token", response.request_token().c_str());
|
||||
ASSERT_EQ(1, response.results().size());
|
||||
ASSERT_EQ(ContentAnalysisResponse_Result_Status_SUCCESS,
|
||||
response.results().Get(0).status());
|
||||
ASSERT_EQ(1, response.results().Get(0).triggered_rules_size());
|
||||
ASSERT_EQ(ContentAnalysisResponse_Result_TriggeredRule_Action_BLOCK,
|
||||
response.results().Get(0).triggered_rules(0).action());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef mozilla_testcontentanalysis_h
|
||||
#define mozilla_testcontentanalysis_h
|
||||
|
||||
#include "content_analysis/sdk/analysis_client.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "nsString.h"
|
||||
struct MozAgentInfo {
|
||||
PROCESS_INFORMATION processInfo;
|
||||
std::unique_ptr<content_analysis::sdk::Client> client;
|
||||
};
|
||||
|
||||
void GeneratePipeName(const wchar_t* prefix, nsString& pipeName);
|
||||
void LaunchAgentWithCommandLineArguments(const nsString& cmdLineArguments,
|
||||
const nsString& pipeName,
|
||||
MozAgentInfo& agentInfo);
|
||||
#endif
|
|
@ -0,0 +1,416 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "content_analysis/sdk/analysis_client.h"
|
||||
#include "TestContentAnalysis.h"
|
||||
#include <processenv.h>
|
||||
#include <synchapi.h>
|
||||
#include <windows.h>
|
||||
|
||||
using namespace content_analysis::sdk;
|
||||
|
||||
namespace {
|
||||
MozAgentInfo LaunchAgentMisbehaving(const wchar_t* mode) {
|
||||
nsString cmdLineArguments;
|
||||
cmdLineArguments.Append(L" --misbehave=");
|
||||
cmdLineArguments.Append(mode);
|
||||
cmdLineArguments.Append(L" --user");
|
||||
cmdLineArguments.Append(L" --path=");
|
||||
nsString pipeName;
|
||||
GeneratePipeName(L"contentanalysissdk-gtest-", pipeName);
|
||||
cmdLineArguments.Append(pipeName);
|
||||
MozAgentInfo agentInfo;
|
||||
LaunchAgentWithCommandLineArguments(cmdLineArguments, pipeName, agentInfo);
|
||||
return agentInfo;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Disabled for now
|
||||
/*TEST(ContentAnalysisMisbehaving, LargeResponse)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"largeResponse");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
ASSERT_STREQ("request token", response.request_token().c_str());
|
||||
ASSERT_EQ(1001, response.results().size());
|
||||
|
||||
BOOL terminateResult = ::TerminateProcess(MozAgentInfo.processInfo.hProcess,
|
||||
0); ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}*/
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, InvalidUtf8StringStartByteIsContinuationByte)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"invalidUtf8StringStartByteIsContinuationByte");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
// The protobuf spec says that strings must be valid UTF-8. So it's OK if
|
||||
// this gets mangled, just want to make sure it doesn't cause a crash
|
||||
// or invalid memory access or something.
|
||||
ASSERT_STREQ("\x80\x41\x41\x41", response.request_token().c_str());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving,
|
||||
InvalidUtf8StringEndsInMiddleOfMultibyteSequence)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(
|
||||
L"invalidUtf8StringEndsInMiddleOfMultibyteSequence");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
// The protobuf spec says that strings must be valid UTF-8. So it's OK if
|
||||
// this gets mangled, just want to make sure it doesn't cause a crash
|
||||
// or invalid memory access or something.
|
||||
ASSERT_STREQ("\x41\xf0\x90\x8d", response.request_token().c_str());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, InvalidUtf8StringMultibyteSequenceTooShort)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"invalidUtf8StringMultibyteSequenceTooShort");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
// The protobuf spec says that strings must be valid UTF-8. So it's OK if
|
||||
// this gets mangled, just want to make sure it doesn't cause a crash
|
||||
// or invalid memory access or something.
|
||||
ASSERT_STREQ("\xf0\x90\x8d\x41", response.request_token().c_str());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, InvalidUtf8StringDecodesToInvalidCodePoint)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"invalidUtf8StringDecodesToInvalidCodePoint");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
// The protobuf spec says that strings must be valid UTF-8. So it's OK if
|
||||
// this gets mangled, just want to make sure it doesn't cause a crash
|
||||
// or invalid memory access or something.
|
||||
ASSERT_STREQ("\xf7\xbf\xbf\xbf", response.request_token().c_str());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, InvalidUtf8StringOverlongEncoding)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"invalidUtf8StringOverlongEncoding");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
// The protobuf spec says that strings must be valid UTF-8. So it's OK if
|
||||
// this gets mangled, just want to make sure it doesn't cause a crash
|
||||
// or invalid memory access or something.
|
||||
ASSERT_STREQ("\xf0\x82\x82\xac", response.request_token().c_str());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, StringWithEmbeddedNull)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"stringWithEmbeddedNull");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
std::string expected("\x41\x00\x41");
|
||||
ASSERT_EQ(expected, response.request_token());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, ZeroResults)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"zeroResults");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
ASSERT_EQ(0, response.results().size());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, ResultWithInvalidStatus)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"resultWithInvalidStatus");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
request.set_text_content("unused");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
ASSERT_EQ(1, response.results().size());
|
||||
// protobuf will fail to read this because it's an invalid value.
|
||||
// (and leave status at its default value of 0)
|
||||
// just make sure we can get the value without throwing
|
||||
ASSERT_GE(static_cast<int>(response.results(0).status()), 0);
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageTruncatedInMiddleOfString)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"messageTruncatedInMiddleOfString");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageWithInvalidWireType)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"messageWithInvalidWireType");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageWithUnusedFieldNumber)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"messageWithUnusedFieldNumber");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
ASSERT_EQ(0, MozAgentInfo.client->Send(request, &response));
|
||||
// protobuf will read the value and store it in an unused section
|
||||
// just make sure we can get a value without throwing
|
||||
ASSERT_STREQ("", response.request_token().c_str());
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageWithWrongStringWireType)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"messageWithWrongStringWireType");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageWithZeroTag)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"messageWithZeroTag");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageWithZeroFieldButNonzeroWireType)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"messageWithZeroFieldButNonzeroWireType");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageWithGroupEnd)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"messageWithZeroFieldButNonzeroWireType");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageTruncatedInMiddleOfVarint)
|
||||
{
|
||||
auto MozAgentInfo =
|
||||
LaunchAgentMisbehaving(L"messageTruncatedInMiddleOfVarint");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
||||
|
||||
TEST(ContentAnalysisMisbehaving, MessageTruncatedInMiddleOfTag)
|
||||
{
|
||||
auto MozAgentInfo = LaunchAgentMisbehaving(L"messageTruncatedInMiddleOfTag");
|
||||
// Exit the test early if the process failed to launch
|
||||
ASSERT_NE(MozAgentInfo.processInfo.dwProcessId, 0UL);
|
||||
ASSERT_NE(nullptr, MozAgentInfo.client.get());
|
||||
|
||||
ContentAnalysisRequest request;
|
||||
request.set_request_token("request token");
|
||||
ContentAnalysisResponse response;
|
||||
// The response is an invalid serialization of protobuf, so this should fail
|
||||
ASSERT_EQ(-1, MozAgentInfo.client->Send(request, &response));
|
||||
|
||||
BOOL terminateResult =
|
||||
::TerminateProcess(MozAgentInfo.processInfo.hProcess, 0);
|
||||
ASSERT_NE(FALSE, terminateResult)
|
||||
<< "Failed to terminate content_analysis_sdk_agent process";
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TestContentAnalysis.h"
|
||||
#include <combaseapi.h>
|
||||
#include <pathcch.h>
|
||||
#include <rpc.h>
|
||||
#include <windows.h>
|
||||
|
||||
void GeneratePipeName(const wchar_t* prefix, nsString& pipeName) {
|
||||
pipeName = u""_ns;
|
||||
pipeName.Append(prefix);
|
||||
UUID uuid;
|
||||
ASSERT_EQ(RPC_S_OK, UuidCreate(&uuid));
|
||||
// 39 == length of a UUID string including braces and NUL.
|
||||
wchar_t guidBuf[39] = {};
|
||||
ASSERT_EQ(39, StringFromGUID2(uuid, guidBuf, 39));
|
||||
// omit opening and closing braces (and trailing null)
|
||||
pipeName.Append(&guidBuf[1], 36);
|
||||
}
|
||||
|
||||
void LaunchAgentWithCommandLineArguments(const nsString& cmdLineArguments,
|
||||
const nsString& pipeName,
|
||||
MozAgentInfo& agentInfo) {
|
||||
wchar_t progName[MAX_PATH] = {};
|
||||
// content_analysis_sdk_agent.exe is either next to firefox.exe (for local
|
||||
// builds), or in ../../tests/bin/ (for try/treeherder builds)
|
||||
DWORD nameSize = ::GetModuleFileNameW(nullptr, progName, MAX_PATH);
|
||||
ASSERT_NE(DWORD{0}, nameSize);
|
||||
ASSERT_EQ(S_OK, PathCchRemoveFileSpec(progName, nameSize));
|
||||
wchar_t normalizedPath[MAX_PATH] = {};
|
||||
nsString test1 = nsString(progName) + u"\\content_analysis_sdk_agent.exe"_ns;
|
||||
ASSERT_EQ(S_OK, PathCchCanonicalize(normalizedPath, MAX_PATH, test1.get()));
|
||||
nsString agentPath;
|
||||
if (::PathFileExistsW(normalizedPath)) {
|
||||
agentPath = nsString(normalizedPath);
|
||||
}
|
||||
if (agentPath.IsEmpty()) {
|
||||
nsString unNormalizedPath =
|
||||
nsString(progName) +
|
||||
u"\\..\\..\\tests\\bin\\content_analysis_sdk_agent.exe"_ns;
|
||||
ASSERT_EQ(S_OK, PathCchCanonicalize(normalizedPath, MAX_PATH,
|
||||
unNormalizedPath.get()));
|
||||
if (::PathFileExistsW(normalizedPath)) {
|
||||
agentPath = nsString(normalizedPath);
|
||||
}
|
||||
}
|
||||
ASSERT_FALSE(agentPath.IsEmpty());
|
||||
nsString localCmdLine = nsString(agentPath) + u" "_ns + cmdLineArguments;
|
||||
STARTUPINFOW startupInfo = {sizeof(startupInfo)};
|
||||
PROCESS_INFORMATION processInfo;
|
||||
BOOL ok =
|
||||
::CreateProcessW(nullptr, localCmdLine.get(), nullptr, nullptr, FALSE, 0,
|
||||
nullptr, nullptr, &startupInfo, &processInfo);
|
||||
// The documentation for CreateProcessW() says that any non-zero value is a
|
||||
// success
|
||||
if (!ok) {
|
||||
// Show the last error
|
||||
ASSERT_EQ(0UL, GetLastError())
|
||||
<< "Failed to launch content_analysis_sdk_agent";
|
||||
}
|
||||
// Allow time for the agent to set up the pipe
|
||||
::Sleep(2000);
|
||||
content_analysis::sdk::Client::Config config;
|
||||
config.name = NS_ConvertUTF16toUTF8(pipeName);
|
||||
config.user_specific = true;
|
||||
auto clientPtr = content_analysis::sdk::Client::Create(config);
|
||||
ASSERT_NE(nullptr, clientPtr.get());
|
||||
|
||||
agentInfo.processInfo = processInfo;
|
||||
agentInfo.client = std::move(clientPtr);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Program("content_analysis_sdk_agent")
|
||||
|
||||
DEFINES["UNICODE"] = True
|
||||
DEFINES["GOOGLE_PROTOBUF_NO_RTTI"] = True
|
||||
DEFINES["GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER"] = True
|
||||
|
||||
SOURCES += [
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/src/agent_base.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/src/agent_utils_win.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/src/agent_win.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/src/event_base.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/src/event_win.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/src/scoped_print_handle_base.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/src/scoped_print_handle_win.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/common/utils_win.cc",
|
||||
"../../../../../../third_party/content_analysis_sdk/demo/agent.cc",
|
||||
"../../../content_analysis/sdk/analysis.pb.cc",
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"../../../",
|
||||
"../../../../../../third_party/content_analysis_sdk",
|
||||
"../../../../../../third_party/content_analysis_sdk/agent/include/",
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
"mozglue",
|
||||
"protobuf",
|
||||
"zlib",
|
||||
]
|
||||
|
||||
OS_LIBS += [
|
||||
"advapi32",
|
||||
]
|
|
@ -0,0 +1 @@
|
|||
allow me
|
|
@ -0,0 +1 @@
|
|||
block me
|
|
@ -0,0 +1,23 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"../..",
|
||||
"../../../../../third_party/content_analysis_sdk/browser/include/",
|
||||
]
|
||||
|
||||
if CONFIG["OS_TARGET"] == "WINNT":
|
||||
UNIFIED_SOURCES += [
|
||||
"TestContentAnalysis.cpp",
|
||||
"TestContentAnalysisMisbehaving.cpp",
|
||||
"TestContentAnalysisUtils.cpp",
|
||||
]
|
||||
DIRS += ["agent"]
|
||||
OS_LIBS += ["pathcch"]
|
||||
|
||||
TEST_HARNESS_FILES.gtest += ["allowedFile.txt", "blockedFile.txt"]
|
||||
|
||||
FINAL_LIBRARY = "xul-gtest"
|
|
@ -4,6 +4,8 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Library('protobuf')
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Core', 'General')
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче