1 // Copyright 2016 The Chromium Authors. All rights reserved.
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 COMPONENTS_SAFE_BROWSING_CORE_FILE_TYPE_POLICIES_H_
6 #define COMPONENTS_SAFE_BROWSING_CORE_FILE_TYPE_POLICIES_H_
7 
8 #include <map>
9 #include <memory>
10 
11 #include "base/files/file_path.h"
12 #include "base/gtest_prod_util.h"
13 #include "base/synchronization/lock.h"
14 #include "components/safe_browsing/core/proto/download_file_types.pb.h"
15 
16 namespace safe_browsing {
17 
18 struct FileTypePoliciesSingletonTrait;
19 class FileTypePoliciesTestOverlay;
20 
21 // This holds a list of file types (aka file extensions) that we know about,
22 // with policies related to how Safe Browsing and the download UI should treat
23 // them.
24 //
25 // The data to populate it is read from a ResourceBundle and then also
26 // fetched periodically from Google to get the most up-to-date policies.
27 //
28 // This is thread safe. We assume it is updated at most every few hours.
29 
30 class FileTypePolicies {
31  public:
32   virtual ~FileTypePolicies();
33 
34   static FileTypePolicies* GetInstance();  // Singleton
35 
36   // Update the internal list from a binary proto fetched from the network.
37   // Same integrity checks apply. This can be called multiple times with new
38   // protos.
39   void PopulateFromDynamicUpdate(const std::string& binary_pb);
40 
41   //
42   // Static Utils
43   //
44 
45   // Returns the final extension with the leading dot, after stripping
46   // trailing dots and spaces.  It is difference from FilePath::Extension()
47   // and FilePath::FinalExtension().
48   // TODO(nparker): Consolidate. Maybe add this code to FinalExtension().
49   static base::FilePath::StringType GetFileExtension(
50       const base::FilePath& file);
51 
52   //
53   // Accessors
54   //
55   bool IsArchiveFile(const base::FilePath& file) const;
56 
57   // SBClientDownloadExtensions UMA histogram bucket for this file's type.
58   int64_t UmaValueForFile(const base::FilePath& file) const;
59 
60   // True if download protection should send a ping to check
61   // this type of file.
62   bool IsCheckedBinaryFile(const base::FilePath& file) const;
63 
64   // True if the user can select this file type to be opened automatically.
65   bool IsAllowedToOpenAutomatically(const base::FilePath& file) const;
66 
67   // Return the danger level of this file type.
68   DownloadFileType::DangerLevel GetFileDangerLevel(
69       const base::FilePath& file) const;
70 
71   // Return the type of ping we should send for this file
72   DownloadFileType::PingSetting PingSettingForFile(
73       const base::FilePath& file) const;
74 
75   float SampledPingProbability() const;
76 
77   DownloadFileType PolicyForFile(const base::FilePath& file) const;
78   DownloadFileType::PlatformSettings SettingsForFile(
79       const base::FilePath& file) const;
80 
81   // Return max size for which unpacking and/or binary feature extration is
82   // supported for the given file extension.
83   uint64_t GetMaxFileSizeToAnalyze(const std::string& ascii_ext) const;
84 
85   // Return max number of archived_binaries we should add to a download ping.
86   uint64_t GetMaxArchivedBinariesToReport() const;
87 
88  protected:
89   // Creator must call one of Populate* before calling other methods.
90   FileTypePolicies();
91 
92   // Used in metrics, do not reorder.
93   enum class UpdateResult {
94     SUCCESS = 1,
95     FAILED_EMPTY = 2,
96     FAILED_PROTO_PARSE = 3,
97     FAILED_DELTA_CHECK = 4,
98     FAILED_VERSION_CHECK = 5,
99     FAILED_DEFAULT_SETTING_SET = 6,
100     FAILED_WRONG_SETTINGS_COUNT = 7,
101     SKIPPED_VERSION_CHECK_EQUAL = 8,
102   };
103 
104   // Read data from an serialized protobuf and update the internal list
105   // only if it passes integrity checks.
106   virtual UpdateResult PopulateFromBinaryPb(const std::string& binary_pb);
107 
108   // Fetch the blob from the main resource bundle.
109   virtual std::string ReadResourceBundle();
110 
111   // Record the result of an update attempt.
112   virtual void RecordUpdateMetrics(UpdateResult result,
113                                    const std::string& src_name);
114 
115   // Return the ASCII lowercase extension w/o leading dot, or empty.
116   static std::string CanonicalizedExtension(const base::FilePath& file);
117 
118   // Look up the policy for a given ASCII ext.
119   virtual const DownloadFileType& PolicyForExtension(
120       const std::string& ext) const;
121 
122  private:
123   // Swap in a different config. This will rebuild file_type_by_ext_ index.
124   void SwapConfig(std::unique_ptr<DownloadFileTypeConfig>& new_config);
125   void SwapConfigLocked(std::unique_ptr<DownloadFileTypeConfig>& new_config);
126 
127   // Read data from the main ResourceBundle. This updates the internal list
128   // only if the data passes integrity checks. This is normally called once
129   // after construction.
130   void PopulateFromResourceBundle();
131 
132   // The latest config we've committed. Starts out null.
133   // Protected by lock_.
134   std::unique_ptr<DownloadFileTypeConfig> config_;
135 
136   // This references entries in config_.
137   // Protected by lock_.
138   std::map<std::string, const DownloadFileType*> file_type_by_ext_;
139 
140   // Type used if we can't load from disk.
141   // Written only in the constructor.
142   DownloadFileType last_resort_default_;
143 
144   mutable base::Lock lock_;
145 
146   FRIEND_TEST_ALL_PREFIXES(FileTypePoliciesTest, UnpackResourceBundle);
147   FRIEND_TEST_ALL_PREFIXES(FileTypePoliciesTest, BadProto);
148   FRIEND_TEST_ALL_PREFIXES(FileTypePoliciesTest, BadUpdateFromExisting);
149 
150   friend struct FileTypePoliciesSingletonTrait;
151   friend class FileTypePoliciesTestOverlay;
152 };
153 
154 }  // namespace safe_browsing
155 
156 #endif  // COMPONENTS_SAFE_BROWSING_CORE_FILE_TYPE_POLICIES_H_
157