• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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