1 // Copyright 2017 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 TOOLS_TRAFFIC_ANNOTATION_AUDITOR_TRAFFIC_ANNOTATION_AUDITOR_H_
6 #define TOOLS_TRAFFIC_ANNOTATION_AUDITOR_TRAFFIC_ANNOTATION_AUDITOR_H_
7 
8 #include <vector>
9 
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "third_party/protobuf/src/google/protobuf/compiler/importer.h"
13 #include "third_party/protobuf/src/google/protobuf/dynamic_message.h"
14 #include "tools/traffic_annotation/auditor/auditor_result.h"
15 #include "tools/traffic_annotation/auditor/instance.h"
16 #include "tools/traffic_annotation/auditor/traffic_annotation_exporter.h"
17 #include "tools/traffic_annotation/traffic_annotation.pb.h"
18 
19 // Holds an item of safe list rules for auditor.
20 struct AuditorException {
21   enum class ExceptionType {
22     ALL,                // Ignore all errors (doesn't check the files at all).
23     MISSING,            // Ignore missing annotations.
24     DIRECT_ASSIGNMENT,  // Ignore direct assignment of annotation value.
25     TEST_ANNOTATION,    // Ignore usages of annotation for tests.
26     MUTABLE_TAG,        // Ignore CreateMutableNetworkTrafficAnnotationTag().
27     EXCEPTION_TYPE_LAST = MUTABLE_TAG,
28   } type;
29 
TypeFromStringAuditorException30   static bool TypeFromString(const std::string& type_string,
31                              ExceptionType* type_value) {
32     if (type_string == "all") {
33       *type_value = ExceptionType::ALL;
34     } else if (type_string == "missing") {
35       *type_value = ExceptionType::MISSING;
36     } else if (type_string == "direct_assignment") {
37       *type_value = ExceptionType::DIRECT_ASSIGNMENT;
38     } else if (type_string == "test_annotation") {
39       *type_value = ExceptionType::TEST_ANNOTATION;
40     } else if (type_string == "mutable_tag") {
41       *type_value = ExceptionType::MUTABLE_TAG;
42     } else {
43       return false;
44     }
45     return true;
46   }
47 };
48 
49 
50 class TrafficAnnotationAuditor {
51  public:
52   // Creates an auditor object, storing the following paths:
53   //   |source_path|: Path to the src directory.
54   //   |build_path|: Path to a compiled build directory.
55   //   |path_filters|: Filters to limit where we're scanning the source.
56   TrafficAnnotationAuditor(const base::FilePath& source_path,
57                            const base::FilePath& build_path,
58                            const std::vector<std::string>& path_filters);
59   ~TrafficAnnotationAuditor();
60 
61   // Runs extractor.py and puts its output in |extractor_raw_output_|. If
62   // |filter_files_based_on_heuristics| flag is set, the list of files will be
63   // received from repository and heuristically filtered to only process the
64   // relevant files. If |use_compile_commands| flag is set, the list of files is
65   // extracted from compile_commands.json instead of git and will not be
66   // filtered.  If the extractor returns errors, the tool is run again to record
67   // errors. Errors are written to |errors_file| if it is not empty, otherwise
68   // LOG(ERROR).
69   bool RunExtractor(bool filter_files_based_on_heuristics,
70                     bool use_compile_commands,
71                     const base::FilePath& errors_file,
72                     int* exit_code);
73 
74   // Parses the output of extractor.py (|extractor_raw_output_|) and populates
75   // |extracted_annotations_|, |extracted_calls_|, and |errors_|.
76   // Errors include not finding the file, incorrect content, or missing or not
77   // provided annotations.
78   bool ParseExtractorRawOutput();
79 
80   // Computes the hash value of a traffic annotation unique id.
81   static int ComputeHashValue(const std::string& unique_id);
82 
83   // Loads the safe list file and populates |safe_list_|.
84   bool LoadSafeList();
85 
86   // Checks to see if a |file_path| matches a safe list with given type.
87   bool IsSafeListed(const std::string& file_path,
88                     AuditorException::ExceptionType exception_type);
89 
90   // Checks to see if annotation contents are valid. Complete annotations should
91   // have all required fields and be consistent, and incomplete annotations
92   // should be completed with each other. Merges all matching incomplete
93   // annotations and adds them to |extracted_annotations_|, adds errors
94   // to |errors| and purges all incomplete annotations.
95   void CheckAnnotationsContents();
96 
97   // Checks to see if all functions that need annotations have one.
98   void CheckAllRequiredFunctionsAreAnnotated();
99 
100   // Checks if a call instance can stay not annotated.
101   bool CheckIfCallCanBeUnannotated(const CallInstance& call);
102 
103   // Performs all checks on extracted annotations and calls. The input path
104   // filters are passed so that the data for files that were not tested would be
105   // read from annotations.xml. If |report_xml_updates| is set and
106   // annotations.xml requires updates, the updates are added to |errors_|.
107   bool RunAllChecks(bool report_xml_updates);
108 
109   // Returns a mapping of reserved unique ids' hash codes to the unique ids'
110   // texts. This list includes all unique ids that are defined in
111   // net/traffic_annotation/network_traffic_annotation.h and
112   // net/traffic_annotation/network_traffic_annotation_test_helper.h
113   static const std::map<int, std::string>& GetReservedIDsMap();
114 
115   // Returns a set of reserved unique ids' hash codes. This set includes all
116   // unique ids that are defined in
117   // net/traffic_annotation/network_traffic_annotation.h and
118   // net/traffic_annotation/network_traffic_annotation_test_helper.h
119   static std::set<int> GetReservedIDsSet();
120 
extractor_raw_output()121   std::string extractor_raw_output() const { return extractor_raw_output_; }
122 
set_extractor_raw_output(const std::string & raw_output)123   void set_extractor_raw_output(const std::string& raw_output) {
124     extractor_raw_output_ = raw_output;
125   }
126 
extracted_annotations()127   const std::vector<AnnotationInstance>& extracted_annotations() const {
128     return extracted_annotations_;
129   }
130 
SetExtractedAnnotationsForTesting(const std::vector<AnnotationInstance> & annotations)131   void SetExtractedAnnotationsForTesting(
132       const std::vector<AnnotationInstance>& annotations) {
133     extracted_annotations_ = annotations;
134   }
135 
SetExtractedCallsForTesting(const std::vector<CallInstance> & calls)136   void SetExtractedCallsForTesting(const std::vector<CallInstance>& calls) {
137     extracted_calls_ = calls;
138   }
139 
SetGroupedAnnotationUniqueIDsForTesting(std::set<std::string> & annotation_unique_ids)140   void SetGroupedAnnotationUniqueIDsForTesting(
141       std::set<std::string>& annotation_unique_ids) {
142     grouped_annotation_unique_ids_ = annotation_unique_ids;
143   }
144 
extracted_calls()145   const std::vector<CallInstance>& extracted_calls() const {
146     return extracted_calls_;
147   }
148 
errors()149   const std::vector<AuditorResult>& errors() const { return errors_; }
150 
exporter()151   const TrafficAnnotationExporter& exporter() const { return exporter_; }
152 
ClearErrorsForTesting()153   void ClearErrorsForTesting() { errors_.clear(); }
154 
ClearCheckedDependenciesForTesting()155   void ClearCheckedDependenciesForTesting() { checked_dependencies_.clear(); }
156 
157   // Sets the path to a file that would be used to mock the output of
158   // 'gn refs --all [build directory] [file path]' in tests.
SetGnFileForTesting(const base::FilePath & file_path)159   void SetGnFileForTesting(const base::FilePath& file_path) {
160     gn_file_for_test_ = file_path;
161   }
162 
ClearPathFilters()163   void ClearPathFilters() { path_filters_.clear(); }
164 
165   std::unique_ptr<google::protobuf::Message> CreateAnnotationProto();
166 
167   // Produces the set of annotation unique_ids that appear in grouping.xml
168   // Returns false if grouping.xml cannot be loaded.
169   bool GetGroupingAnnotationsUniqueIDs(
170       base::FilePath grouping_xml_path,
171       std::set<std::string>* annotation_unique_ids) const;
172 
173  private:
174   const base::FilePath source_path_;
175   const base::FilePath build_path_;
176   std::vector<std::string> path_filters_;
177   std::set<std::string> grouped_annotation_unique_ids_;
178 
179   // Variables used to dynamic the NetworkTrafficAnnotation proto.
180   std::unique_ptr<google::protobuf::DescriptorPool> descriptor_pool_;
181   google::protobuf::DynamicMessageFactory message_factory_;
182   std::unique_ptr<google::protobuf::Message> annotation_prototype_;
183 
184   base::FilePath absolute_source_path_;
185 
186   TrafficAnnotationExporter exporter_;
187 
188   std::string extractor_raw_output_;
189   std::vector<AnnotationInstance> extracted_annotations_;
190   std::vector<CallInstance> extracted_calls_;
191   std::vector<AuditorResult> errors_;
192 
193   bool safe_list_loaded_;
194   std::vector<std::string>
195       safe_list_[static_cast<int>(
196                      AuditorException::ExceptionType::EXCEPTION_TYPE_LAST) +
197                  1];
198 
199   // Adds all archived annotations (from annotations.xml) that match the
200   // following features, to |extracted_annotations_|:
201   //  1- Not deprecated.
202   //  2- OS list includes current platform.
203   //  2- Has a path (is not a reserved word).
204   //  3- Path matches an item in |path_filters_|.
205   void AddMissingAnnotations();
206 
207   // Generates files list to run extractor on. Please refer to RunExtractor
208   // function's comment.
209   void GenerateFilesListForExtractor(bool filter_files_based_on_heuristics,
210                                      bool use_compile_commands,
211                                      std::vector<std::string>* file_paths);
212 
213   // Write flags to the options file, for RunExtractor.
214   void WritePythonScriptOptions(FILE* options_file);
215 
216   base::FilePath gn_file_for_test_;
217   std::map<std::string, bool> checked_dependencies_;
218 };
219 
220 #endif  // TOOLS_TRAFFIC_ANNOTATION_AUDITOR_TRAFFIC_ANNOTATION_AUDITOR_H_
221