1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net; 6 7 import androidx.annotation.VisibleForTesting; 8 9 import java.nio.charset.StandardCharsets; 10 11 /** 12 * Network Traffic Annotations document the purpose of a particular network request, and its impact 13 * on privacy. 14 * 15 * This documentation is typically meant for system administrators in an enterprise setting. It 16 * should be easy for them to read and understand, and answer the following questions: 17 * 18 * 1. When and why does Chrome make this network request? 19 * 2. Does this network request send any sensitive data? 20 * 3. Where does the request go? (e.g. a Google server, a website the user is viewing...) 21 * 4. How can I disable it if I don't like it? 22 */ 23 public class NetworkTrafficAnnotationTag { 24 /** 25 * For network requests that aren't documented yet. These should be 26 * accompanied with a TODO with a bug/owner to write their documentation. 27 */ 28 public static final NetworkTrafficAnnotationTag NO_TRAFFIC_ANNOTATION_YET = 29 createComplete("undefined", "Nothing here yet."); 30 31 /** 32 * For network requests that don't need an annotation, because they're in an 33 * allowlisted file (see tools/traffic_annotation/safe_list.txt). 34 */ 35 public static final NetworkTrafficAnnotationTag MISSING_TRAFFIC_ANNOTATION = 36 createComplete("undefined", "Function called without traffic annotation."); 37 38 /** For network requests made in tests, don't bother writing documentation. */ 39 public static final NetworkTrafficAnnotationTag TRAFFIC_ANNOTATION_FOR_TESTS = 40 createComplete("test", "Traffic annotation for unit, browser and other tests"); 41 42 /** 43 * Create a self-contained tag describing a network request made by Chromium. This is the most 44 * common factory method. 45 * 46 * The C++ equivalent is DefineNetworkTrafficAnnotation(). 47 * 48 * @param uniqueId a String that uniquely identifies this annotations across all of Chromium 49 * source code. 50 * @param proto a text-encoded NetworkTrafficAnnotation protobuf (see 51 * chrome/browser/privacy/traffic_annotation.proto). 52 */ createComplete(String uniqueId, String proto)53 public static NetworkTrafficAnnotationTag createComplete(String uniqueId, String proto) { 54 return new NetworkTrafficAnnotationTag(uniqueId); 55 } 56 57 // TODO(crbug.com/1231780): Add Partial, Completing, Branched-Completing, and 58 // Mutable(?) factory methods. 59 60 /** 61 * At runtime, an annotation tag is just a hashCode. Most of the validation is done on CQ, so 62 * there's no point keeping track of everything at runtime. 63 * 64 * This field is referenced from C++, so don't change it without updating 65 * net/traffic_annotation/network_traffic_annotation.h. 66 */ 67 // TODO(crbug.com/1231780): Unlike the C++ version though, the string will still get compiled 68 // into the APK, and get loaded into memory when the constructor is called... Is there a way to 69 // tell Java, "No, I don't actually need this string at runtime"? We should investigate. 70 private final int mHashCode; 71 72 /** 73 * @return the hash code of uniqueId, which uniquely identifies this annotation. 74 */ getHashCode()75 public int getHashCode() { 76 return mHashCode; 77 } 78 79 /** 80 * Constructor for NetworkTrafficAnnotationTag. Consumers of this API should use 81 * CreateComplete() instead. 82 * 83 * @param uniqueId a String that uniquely identifies this annotation across all of Chromium 84 * source code. 85 */ NetworkTrafficAnnotationTag(String uniqueId)86 private NetworkTrafficAnnotationTag(String uniqueId) { 87 mHashCode = iterativeHash(uniqueId); 88 } 89 90 /** 91 * Returns the hashcode of a string, as per the recursive_hash() function used in C++ code. 92 * 93 * This is NOT the same as Java's built-in hashCode() function, because we really want to 94 * produce the same hashcode that auditor.py produces. 95 * 96 * @param s the String to calculate the hash on. 97 */ 98 @VisibleForTesting iterativeHash(String s)99 static int iterativeHash(String s) { 100 // Multiplying by 31 would cause an overflow if using `int', so use `long' instead. 101 long acc = 0; 102 // Encode the string as UTF-8. 103 byte[] bytes = s.getBytes(StandardCharsets.UTF_8); 104 for (byte b : bytes) { 105 acc = (acc * 31 + b) % 138003713; 106 } 107 // The final result always fits in an `int' thanks to the modulo. 108 return (int) acc; 109 } 110 } 111