| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_ENTERPRISE_CONNECTORS_CORE_COMMON_H_ |
| #define COMPONENTS_ENTERPRISE_CONNECTORS_CORE_COMMON_H_ |
| |
| #include <map> |
| #include <optional> |
| #include <set> |
| #include <string> |
| #include <string_view> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/containers/fixed_flat_map.h" |
| #include "base/files/file_path.h" |
| #include "base/supports_user_data.h" |
| #include "build/blink_buildflags.h" |
| #include "components/enterprise/common/proto/connectors.pb.h" |
| #include "components/enterprise/common/proto/synced_from_google3/chrome_reporting_entity.pb.h" |
| #include "components/enterprise/connectors/core/reporting_constants.h" |
| #include "ui/gfx/range/range.h" |
| #include "url/gurl.h" |
| |
| #if BUILDFLAG(USE_BLINK) |
| #include "components/download/public/common/download_danger_type.h" // nogncheck |
| |
| namespace download { |
| class DownloadItem; |
| } // namespace download |
| #endif // BUILDFLAG(USE_BLINK) |
| |
| namespace signin { |
| class IdentityManager; |
| } |
| |
| namespace enterprise_connectors { |
| |
| // Alias to reduce verbosity when using TriggeredRule::Actions. |
| using TriggeredRule = ContentAnalysisResponse::Result::TriggeredRule; |
| |
| // Pair to specify the source and destination. |
| using SourceDestinationStringPair = std::pair<std::string, std::string>; |
| |
| // Alias to reduce verbosity when using Event::EventCase. |
| using EventCase = ::chrome::cros::reporting::proto::Event::EventCase; |
| |
| // Keys used to read a connector's policy values. |
| inline constexpr char kKeyServiceProvider[] = "service_provider"; |
| inline constexpr char kKeyLinuxVerification[] = "verification.linux"; |
| inline constexpr char kKeyMacVerification[] = "verification.mac"; |
| inline constexpr char kKeyWindowsVerification[] = "verification.windows"; |
| inline constexpr char kKeyEnable[] = "enable"; |
| inline constexpr char kKeyDisable[] = "disable"; |
| inline constexpr char kKeyUrlList[] = "url_list"; |
| inline constexpr char kKeySourceDestinationList[] = "source_destination_list"; |
| inline constexpr char kKeyTags[] = "tags"; |
| inline constexpr char kKeyBlockUntilVerdict[] = "block_until_verdict"; |
| inline constexpr char kKeyBlockPasswordProtected[] = "block_password_protected"; |
| inline constexpr char kKeyBlockLargeFiles[] = "block_large_files"; |
| inline constexpr char kKeyMinimumDataSize[] = "minimum_data_size"; |
| inline constexpr char kKeyEnabledEventNames[] = "enabled_event_names"; |
| inline constexpr char kKeyCustomMessages[] = "custom_messages"; |
| inline constexpr char kKeyRequireJustificationTags[] = |
| "require_justification_tags"; |
| inline constexpr char kKeyCustomMessagesTag[] = "tag"; |
| inline constexpr char kKeyCustomMessagesMessage[] = "message"; |
| inline constexpr char kKeyCustomMessagesLearnMoreUrl[] = "learn_more_url"; |
| inline constexpr char kKeyMimeTypes[] = "mime_types"; |
| inline constexpr char kKeyEnterpriseId[] = "enterprise_id"; |
| inline constexpr char kKeyDefaultAction[] = "default_action"; |
| inline constexpr char kKeyDomain[] = "domain"; |
| inline constexpr char kKeyEnabledOptInEvents[] = "enabled_opt_in_events"; |
| inline constexpr char kKeyOptInEventName[] = "name"; |
| inline constexpr char kKeyOptInEventUrlPatterns[] = "url_patterns"; |
| |
| // Available tags. |
| inline constexpr char kDlpTag[] = "dlp"; |
| inline constexpr char kMalwareTag[] = "malware"; |
| |
| // These values are persisted to logs. Entries should not be renumbered and |
| // numeric values should never be reused. Keep this enum in sync with |
| // EnterpriseReportingEventType in enums.xml. |
| // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.enterprise.connectors |
| enum class EnterpriseReportingEventType { |
| kUnknownEvent = 0, |
| kPasswordReuseEvent = 1, |
| kPasswordChangedEvent = 2, |
| kDangerousDownloadEvent = 3, |
| kInterstitialEvent = 4, |
| kSensitiveDataEvent = 5, |
| kUnscannedFileEvent = 6, |
| kLoginEvent = 7, |
| kPasswordBreachEvent = 8, |
| kUrlFilteringInterstitialEvent = 9, |
| kExtensionInstallEvent = 10, |
| kBrowserCrashEvent = 11, |
| kExtensionTelemetryEvent = 12, |
| kMaxValue = kExtensionTelemetryEvent, |
| }; |
| |
| // Mapping from event name to UMA enum for logging histogram. |
| inline constexpr auto kEventNameToUmaEnumMap = |
| base::MakeFixedFlatMap<std::string_view, EnterpriseReportingEventType>({ |
| {kKeyPasswordReuseEvent, |
| EnterpriseReportingEventType::kPasswordReuseEvent}, |
| {kKeyPasswordChangedEvent, |
| EnterpriseReportingEventType::kPasswordChangedEvent}, |
| {kKeyDangerousDownloadEvent, |
| EnterpriseReportingEventType::kDangerousDownloadEvent}, |
| {kKeyInterstitialEvent, |
| EnterpriseReportingEventType::kInterstitialEvent}, |
| {kKeySensitiveDataEvent, |
| EnterpriseReportingEventType::kSensitiveDataEvent}, |
| {kKeyUnscannedFileEvent, |
| EnterpriseReportingEventType::kUnscannedFileEvent}, |
| {kKeyLoginEvent, EnterpriseReportingEventType::kLoginEvent}, |
| {kKeyPasswordBreachEvent, |
| EnterpriseReportingEventType::kPasswordBreachEvent}, |
| {kKeyUrlFilteringInterstitialEvent, |
| EnterpriseReportingEventType::kUrlFilteringInterstitialEvent}, |
| {kExtensionInstallEvent, |
| EnterpriseReportingEventType::kExtensionInstallEvent}, |
| {kBrowserCrashEvent, EnterpriseReportingEventType::kBrowserCrashEvent}, |
| {kExtensionTelemetryEvent, |
| EnterpriseReportingEventType::kExtensionTelemetryEvent}, |
| }); |
| |
| // Struct holding the necessary data to tweak the behavior of the reporting |
| // Connector. |
| struct ReportingSettings { |
| ReportingSettings(); |
| ReportingSettings(const std::string& dm_token, bool per_profile); |
| ReportingSettings(ReportingSettings&&); |
| ReportingSettings(const ReportingSettings&); |
| ReportingSettings& operator=(ReportingSettings&&); |
| ~ReportingSettings(); |
| |
| std::set<std::string> enabled_event_names; |
| std::map<std::string, std::vector<std::string>> enabled_opt_in_events; |
| std::string dm_token; |
| |
| // Indicates if the report should be made for the profile, or the browser if |
| // false. |
| bool per_profile = false; |
| }; |
| |
| // Returns the pref path corresponding to an analysis connector. |
| const char* AnalysisConnectorPref(AnalysisConnector connector); |
| const char* AnalysisConnectorScopePref(AnalysisConnector connector); |
| |
| // Returns the highest precedence action in the given parameters. Writes the tag |
| // field of the result containing the highest precedence action into |tag|. |
| TriggeredRule::Action GetHighestPrecedenceAction( |
| const ContentAnalysisResponse& response, |
| std::string* tag); |
| TriggeredRule::Action GetHighestPrecedenceAction( |
| const TriggeredRule::Action& action_1, |
| const TriggeredRule::Action& action_2); |
| ContentAnalysisAcknowledgement::FinalAction GetHighestPrecedenceAction( |
| const ContentAnalysisAcknowledgement::FinalAction& action_1, |
| const ContentAnalysisAcknowledgement::FinalAction& action_2); |
| |
| // Struct used to persist metadata about a file in base::SupportsUserData |
| // through ScanResult. |
| struct FileMetadata { |
| FileMetadata( |
| const std::string& filename, |
| const std::string& sha256, |
| const std::string& mime_type, |
| int64_t size, |
| const ContentAnalysisResponse& scan_response = ContentAnalysisResponse()); |
| FileMetadata(FileMetadata&&); |
| FileMetadata(const FileMetadata&); |
| FileMetadata& operator=(const FileMetadata&); |
| ~FileMetadata(); |
| |
| std::string filename; |
| std::string sha256; |
| std::string mime_type; |
| int64_t size; |
| ContentAnalysisResponse scan_response; |
| }; |
| |
| // User data class to persist scanning results for multiple files corresponding |
| // to a single base::SupportsUserData object. |
| struct ScanResult : public base::SupportsUserData::Data { |
| ScanResult(); |
| explicit ScanResult(FileMetadata metadata); |
| ~ScanResult() override; |
| static const char kKey[]; |
| |
| std::vector<FileMetadata> file_metadata; |
| std::optional<std::u16string> user_justification; |
| }; |
| |
| // Enum to identify which message to show once scanning is complete. Ordered |
| // by precedence for when multiple files have conflicting results. |
| enum class FinalContentAnalysisResult { |
| // Show that an issue was found and that the upload is blocked. |
| FAILURE = 0, |
| |
| // Show that the scan failed and that the upload is blocked. |
| FAIL_CLOSED = 1, |
| |
| // Show that files were not uploaded since they were too large. |
| LARGE_FILES = 2, |
| |
| // Show that files were not uploaded since they were encrypted. |
| ENCRYPTED_FILES = 3, |
| |
| // Show that DLP checks failed, but that the user can proceed if they want. |
| WARNING = 4, |
| |
| // Show that no issue was found and that the user may proceed. |
| SUCCESS = 5, |
| }; |
| |
| // Result for a single request of the RequestHandler classes. |
| struct RequestHandlerResult { |
| RequestHandlerResult(); |
| ~RequestHandlerResult(); |
| RequestHandlerResult(RequestHandlerResult&&); |
| RequestHandlerResult& operator=(RequestHandlerResult&&); |
| RequestHandlerResult(const RequestHandlerResult&); |
| RequestHandlerResult& operator=(const RequestHandlerResult&); |
| |
| bool complies = false; |
| FinalContentAnalysisResult final_result = FinalContentAnalysisResult::FAILURE; |
| std::string tag; |
| std::string request_token; |
| ContentAnalysisResponse::Result::TriggeredRule::CustomRuleMessage |
| custom_rule_message; |
| }; |
| |
| // Calculates the ContentAnalysisAcknowledgement::FinalAction for an action |
| // based on the response it got from scanning. |
| ContentAnalysisAcknowledgement::FinalAction GetAckFinalAction( |
| const ContentAnalysisResponse& response); |
| |
| // Extracts the message string from the custom rule message field in the content |
| // analysis response. |
| std::u16string GetCustomRuleString( |
| const ContentAnalysisResponse::Result::TriggeredRule::CustomRuleMessage& |
| custom_rule_message); |
| |
| // Extracts the ranges and their corresponding links from the custom rule |
| // message field in the content analysis response. Used to style the custom rule |
| // message in the content analysis dialog. `offset` corresponds to its start |
| // index as we are inserting it in another message. |
| std::vector<std::pair<gfx::Range, GURL>> GetCustomRuleStyles( |
| const ContentAnalysisResponse::Result::TriggeredRule::CustomRuleMessage& |
| custom_rule_message, |
| size_t offset); |
| |
| // Simple custom rule message for tests, with one message segment containing the |
| // text and associated url. |
| ContentAnalysisResponse::Result::TriggeredRule::CustomRuleMessage |
| CreateSampleCustomRuleMessage(const std::u16string& msg, |
| const std::string& url); |
| |
| #if BUILDFLAG(USE_BLINK) |
| // Extracts the custom rule message from `download_item`. The rule for that |
| // message needs to have an action (WARN, BLOCK) corresponding to `danger_type`. |
| std::optional<ContentAnalysisResponse::Result::TriggeredRule::CustomRuleMessage> |
| GetDownloadsCustomRuleMessage(const download::DownloadItem* download_item, |
| download::DownloadDangerType danger_type); |
| #endif // BUILDFLAG(USE_BLINK) |
| |
| // Checks if |response| contains a negative malware verdict. |
| bool ContainsMalwareVerdict(const ContentAnalysisResponse& response); |
| |
| // Helper enum to get the corresponding regional url in service provider config |
| // for data region setting policy. |
| // LINT.IfChange(DataRegion) |
| enum class DataRegion { NO_PREFERENCE = 0, UNITED_STATES = 1, EUROPE = 2 }; |
| // LINT.ThenChange(//components/enterprise/connectors/core/service_provider_config.cc:DlpRegionEndpoints) |
| GURL GetRegionalizedEndpoint(base::span<const char* const> region_urls, |
| DataRegion data_region); |
| DataRegion ChromeDataRegionSettingToEnum(int chrome_data_region_setting); |
| |
| EnterpriseReportingEventType GetUmaEnumFromEventName( |
| std::string_view eventName); |
| |
| EnterpriseReportingEventType GetUmaEnumFromEventCase(EventCase eventCase); |
| |
| // The resulting action that chrome performed in response to a scan request. |
| // This maps to the event result in the real-time reporting. |
| enum class EventResult { |
| UNKNOWN, |
| |
| // The user was allowed to use the data without restriction. |
| ALLOWED, |
| |
| // The user was allowed to use the data but was warned that it may violate |
| // enterprise rules. |
| WARNED, |
| |
| // The user was not allowed to use the data. |
| BLOCKED, |
| |
| // The user has chosen to use the data even though it violated enterprise |
| // rules. |
| BYPASSED, |
| |
| // The user was not allowed to download the file locally. Download will |
| // proceed directly to cloud storage, if the user is logged in. |
| FORCED_SAVE_TO_CLOUD, |
| }; |
| |
| // Helper function to convert a EventResult to a string that. The format of |
| // string returned is processed by the sever. |
| std::string EventResultToString(EventResult result); |
| |
| // Returns the email address of the unconsented account signed in to the profile |
| // or an empty string if no account is signed in. If `identity_manager` is null |
| // then the empty string is returned. |
| std::string GetProfileEmail(signin::IdentityManager* identity_manager); |
| |
| // Returns the UMA metrics for tracking the successful uploaded event duration. |
| std::string GetSuccessfulUploadDurationUmaMetricName( |
| EnterpriseReportingEventType event_type); |
| |
| // Returns the UMA metrics for tracking the failed-to-upload event duration. |
| std::string GetFailedUploadDurationUmaMetricName( |
| EnterpriseReportingEventType event_type); |
| |
| // Access points used to record UMA metrics and specify which code location is |
| // initiating a deep scan. Any new caller of |
| // ContentAnalysisDelegate::CreateForWebContents should add an access point |
| // here instead of reusing an existing value. histograms.xml should also be |
| // updated by adding histograms with names |
| // "SafeBrowsing.DeepScan.<access-point>.BytesPerSeconds" |
| // "SafeBrowsing.DeepScan.<access-point>.Duration" |
| // "SafeBrowsing.DeepScan.<access-point>.<result>.Duration" |
| // for the new access point and every possible result. |
| // LINT.IfChange(DeepScanAccessPoint) |
| enum class DeepScanAccessPoint { |
| // A deep scan was initiated from downloading 1+ file(s). |
| DOWNLOAD, |
| |
| // A deep scan was initiated from uploading 1+ file(s) via a system dialog. |
| UPLOAD, |
| |
| // A deep scan was initiated from drag-and-dropping text or 1+ file(s). |
| DRAG_AND_DROP, |
| |
| // A deep scan was initiated from pasting text. |
| PASTE, |
| |
| // A deep scan was initiated from printing a page. |
| PRINT, |
| |
| // A deep scan was initiated from transferring 1+ file(s) within ChromeOS. |
| FILE_TRANSFER, |
| |
| kMaxValue = FILE_TRANSFER, |
| }; |
| // LINT.ThenChange(//tools/metrics/histograms/metadata/glic/enums.xml:DeepScanAccessPoint) |
| std::string DeepScanAccessPointToString(DeepScanAccessPoint access_point); |
| |
| } // namespace enterprise_connectors |
| |
| #endif // COMPONENTS_ENTERPRISE_CONNECTORS_CORE_COMMON_H_ |