blob: 7220c1db7c905fd3a826156ba89864f21bb9320f [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.net;
import androidx.annotation.VisibleForTesting;
import java.nio.charset.StandardCharsets;
/**
* Network Traffic Annotations document the purpose of a particular network request, and its impact
* on privacy.
*
* This documentation is typically meant for system administrators in an enterprise setting. It
* should be easy for them to read and understand, and answer the following questions:
*
* 1. When and why does Chrome make this network request?
* 2. Does this network request send any sensitive data?
* 3. Where does the request go? (e.g. a Google server, a website the user is viewing...)
* 4. How can I disable it if I don't like it?
*/
public class NetworkTrafficAnnotationTag {
/**
* For network requests that aren't documented yet. These should be
* accompanied with a TODO with a bug/owner to write their documentation.
*/
public static final NetworkTrafficAnnotationTag NO_TRAFFIC_ANNOTATION_YET =
createComplete("undefined", "Nothing here yet.");
/**
* For network requests that don't need an annotation, because they're in an
* allowlisted file (see tools/traffic_annotation/safe_list.txt).
*/
public static final NetworkTrafficAnnotationTag MISSING_TRAFFIC_ANNOTATION =
createComplete("undefined", "Function called without traffic annotation.");
/** For network requests made in tests, don't bother writing documentation. */
public static final NetworkTrafficAnnotationTag TRAFFIC_ANNOTATION_FOR_TESTS =
createComplete("test", "Traffic annotation for unit, browser and other tests");
/**
* Create a self-contained tag describing a network request made by Chromium. This is the most
* common factory method.
*
* The C++ equivalent is DefineNetworkTrafficAnnotation().
*
* @param uniqueId a String that uniquely identifies this annotations across all of Chromium
* source code.
* @param proto a text-encoded NetworkTrafficAnnotation protobuf (see
* chrome/browser/privacy/traffic_annotation.proto).
*/
public static NetworkTrafficAnnotationTag createComplete(String uniqueId, String proto) {
return new NetworkTrafficAnnotationTag(uniqueId);
}
// TODO(crbug.com/1231780): Add Partial, Completing, Branched-Completing, and
// Mutable(?) factory methods.
/**
* At runtime, an annotation tag is just a hashCode. Most of the validation is done on CQ, so
* there's no point keeping track of everything at runtime.
*
* This field is referenced from C++, so don't change it without updating
* net/traffic_annotation/network_traffic_annotation.h.
*/
// TODO(crbug.com/1231780): Unlike the C++ version though, the string will still get compiled
// into the APK, and get loaded into memory when the constructor is called... Is there a way to
// tell Java, "No, I don't actually need this string at runtime"? We should investigate.
private final int mHashCode;
/**
* @return the hash code of uniqueId, which uniquely identifies this annotation.
*/
public int getHashCode() {
return mHashCode;
}
/**
* Constructor for NetworkTrafficAnnotationTag. Consumers of this API should use
* CreateComplete() instead.
*
* @param uniqueId a String that uniquely identifies this annotation across all of Chromium
* source code.
*/
private NetworkTrafficAnnotationTag(String uniqueId) {
mHashCode = iterativeHash(uniqueId);
}
/**
* Returns the hashcode of a string, as per the recursive_hash() function used in C++ code.
*
* This is NOT the same as Java's built-in hashCode() function, because we really want to
* produce the same hashcode that auditor.py produces.
*
* @param s the String to calculate the hash on.
*/
@VisibleForTesting
static int iterativeHash(String s) {
// Multiplying by 31 would cause an overflow if using `int', so use `long' instead.
long acc = 0;
// Encode the string as UTF-8.
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
for (byte b : bytes) {
acc = (acc * 31 + b) % 138003713;
}
// The final result always fits in an `int' thanks to the modulo.
return (int) acc;
}
}