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