Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 1 | # Network Traffic Annotations |
| 2 | |
| 3 | [TOC] |
| 4 | |
| 5 | This document presents a practical guide to using network traffic annotations in |
| 6 | Chrome. |
| 7 | |
| 8 | |
| 9 | ## Problem Statement |
| 10 | |
| 11 | To make Chrome’s network communication transparent, we would need to be able to |
| 12 | provide the following answers: |
| 13 | * What is the intent behind each network request? |
| 14 | * What user data is sent in the request, and where does it go? |
| 15 | |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 16 | Besides these requirements, the following information helps users, admins, and |
| 17 | help desk: |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 18 | * How can a network communication be stopped or controlled? |
| 19 | * What are the traces of the communication on the client? |
| 20 | |
| 21 | It should be noted that the technical details of requests are not necessarily |
| 22 | important to the users, but in order to provide the intended transparency, we |
| 23 | need to show that we have covered all bases and there are no back doors. |
| 24 | |
| 25 | |
| 26 | ## The Solution |
| 27 | |
| 28 | We can provide up to date, in-line documentation on origin, intent, payload, and |
| 29 | control mechanisms of each network communication. This is done by adding a |
| 30 | `NetworkTrafficAnnotationTag` to all network communication functions. |
| 31 | Please note that as the goal is to specify the intent behind each network |
| 32 | request and its payload, this metadata does not need to be transmitted with the |
| 33 | request during runtime and it is sufficient to have it in appropriate positions |
| 34 | in the code. Having that as an argument of all network communication functions |
| 35 | is a mechanism to enforce its existence and showing the users our intent to |
| 36 | cover the whole repository. |
| 37 | |
| 38 | |
| 39 | ## Best Practices |
| 40 | |
| 41 | ### Where to add annotation? |
| 42 | All network requests are ultimately sending data through sockets or native API |
| 43 | functions, but we should note that the concern is about the main intent of the |
| 44 | communication and not the implementation details. Therefore we do not need to |
| 45 | specify this data separately for each call to each function that is used in the |
| 46 | process and it is sufficient that the most rational point of origin would be |
| 47 | annotated and the annotation would be passed through the downstream steps. |
| 48 | Best practices for choosing annotation code site include where: |
| 49 | 1. The origin of user’s intent or internal requirement for the request is |
| 50 | stated. |
| 51 | 2. The controls over stopping or limiting the request (Chrome settings or |
| 52 | policies) are enforced. |
| 53 | 3. The data that is sent is specified. |
| 54 | If there is a conflict between where is the best annotation point, please refer |
| 55 | to the `Partial Annotations` section for an approach to split annotation. |
| 56 | |
| 57 | ### Merged Requests |
| 58 | There are cases where requests are received from multiple sources and merged |
| 59 | into one connection, like when a socket merges several data frames and sends |
| 60 | them together, or a device location is requested by different components, and |
| 61 | just one network request is made to fetch it. In these cases, the merge point |
| 62 | can ensure that all received requests are properly annotated and just pass one |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 63 | of them to the downstream step. It can also pass a local annotation stating that |
| 64 | it is a merged request on behalf of other requests of type X, which were ensured |
| 65 | to all have annotations. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 66 | This decision is driven from the fact that we do not need to transmit the |
| 67 | annotation metadata in runtime and enforced annotation arguments are just to |
| 68 | ensure that the request is annotated somewhere upstream. |
| 69 | |
| 70 | |
| 71 | ## Coverage |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 72 | Network traffic annotations are currently enforced on all url requests and |
| 73 | socket writes, except for the code which is not compiled on Windows or Linux. |
| 74 | This effort may expand to ChromeOS in future and currently there is no plan to |
| 75 | expand it to other platforms. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 76 | |
| 77 | |
| 78 | ## Network Traffic Annotation Tag |
| 79 | |
| 80 | `net::NetworkTrafficAnnotationTag` is the main definition for annotations. There |
| 81 | are few variants of it that are specified in later sections. The goal is to have |
| 82 | one object of this type or its variants as an argument of all functions that |
| 83 | create a network request. |
| 84 | |
| 85 | ### Content of Annotation Tag |
Glenn Hartmann | db9723b3 | 2022-01-07 14:57:25 | [diff] [blame] | 86 | Each network traffic annotation should specify the following items, as defined |
| 87 | in the `NetworkTrafficAnnotation` message of |
| 88 | `chrome/browser/privacy/traffic_annotation.proto`: |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 89 | * `uniqueـid`: A globally unique identifier that must stay unchanged while the |
| 90 | network request carries the same semantic meaning. If the network request gets |
| 91 | a new meaning, this ID needs to be changed. The purpose of this ID is to give |
| 92 | humans a chance to reference NetworkTrafficAnnotations externally even when |
| 93 | those change a little bit (e.g. adding a new piece of data that is sent along |
| 94 | with a network request). IDs of one component should have a shared prefix so |
| 95 | that sorting all NetworkTrafficAnnotations by unique_id groups those that |
| 96 | belong to the same component together. |
Glenn Hartmann | db9723b3 | 2022-01-07 14:57:25 | [diff] [blame] | 97 | * `source`: These set of fields specify the location of annotation in |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 98 | the source code. These fields are automatically set and do not need |
| 99 | specification. |
Glenn Hartmann | db9723b3 | 2022-01-07 14:57:25 | [diff] [blame] | 100 | * `semantics`: These set of fields specify meta information about the |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 101 | network request’s content and reason. |
| 102 | * `sender`: What component triggers the request. The components should be |
| 103 | human readable and don’t need to reflect the components/ directory. Avoid |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 104 | abbreviations, and use a common value for all annotations in one component. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 105 | * `description`: Plaintext description of the network request in language |
| 106 | that is understandable by admins (ideally also users). Please avoid |
| 107 | acronyms and describe the feature and the feature's value proposition as |
| 108 | well. |
| 109 | * `trigger`: What user action triggered the network request. Use a textual |
| 110 | description. This should be a human readable string. |
Xinghui Lu | 5b9477d | 2023-05-04 20:15:55 | [diff] [blame] | 111 | * `user_data`: What nature of data is being sent, as enums. |
| 112 | Any personally identifiable (PII) data, provided by user or generated |
| 113 | by Google, should be pointed out. You can include multiple |
| 114 | values, and you may want to supplement this with the data field. |
Sugandha Goyal | 0ccc740 | 2022-10-21 13:35:55 | [diff] [blame] | 115 | All available User data enums can be found [here](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/privacy/traffic_annotation.proto?q=UserDataType). |
Xinghui Lu | 5b9477d | 2023-05-04 20:15:55 | [diff] [blame] | 116 | * `data`: Textual description of data being sent, for things that aren't |
| 117 | covered by user_data enum values. You can also use this field if |
Sugandha Goyal | 0ccc740 | 2022-10-21 13:35:55 | [diff] [blame] | 118 | more context needs to be provided to describe user_data. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 119 | * `destination`: Target of the network request. It can be either the website |
| 120 | that user visits and interacts with, a Google service, a request that does |
| 121 | not go to network and just fetches a local resource, or other endpoints |
| 122 | like a service hosting PAC scripts. The distinction between a Google owned |
| 123 | service and website can be difficult when the user navigates to google.com |
| 124 | or searches with the omnibar. Therefore follow the following guideline: If |
| 125 | the source code has hardcoded that the request goes to Google (e.g. for |
| 126 | ZeroSuggest), use `GOOGLE_OWNED_SERVICE`. If the request can go to other |
| 127 | domains and is perceived as a part of a website rather than a native |
Nicolas Arciniega | 15745e2 | 2019-10-09 20:42:35 | [diff] [blame] | 128 | browser feature, use `WEBSITE`. Use `LOCAL` if the request is processed |
Xinghui Lu | 5b9477d | 2023-05-04 20:15:55 | [diff] [blame] | 129 | locally and doesn't go to network. If the request goes to a third-party proxy |
| 130 | first and then is forwarded to a Google service, use `PROXIED_GOOGLE_OWNED_SERVICE`. |
| 131 | Otherwise use `OTHER`. If `OTHER` is used, please add plain text description in `destination_other` field. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 132 | * `destination_other`: Human readable description in case the destination |
| 133 | points to `OTHER`. |
Xinghui Lu | 5b9477d | 2023-05-04 20:15:55 | [diff] [blame] | 134 | * `internal`: Data that is meant to be visible internally, example point of contacts, |
Sugandha Goyal | fcdaf21 | 2022-11-22 15:07:40 | [diff] [blame] | 135 | should be placed inside internal field. This field should not be used in any |
Sugandha Goyal | 1815279 | 2022-10-19 22:01:43 | [diff] [blame] | 136 | external reports. |
Xinghui Lu | 5b9477d | 2023-05-04 20:15:55 | [diff] [blame] | 137 | * `contacts`: A person's or team's email address who are point-of-contact |
Chris Mullins | cb7ba91 | 2023-07-24 20:48:14 | [diff] [blame] | 138 | for questions, issues, or bugs related to this network request. An |
| 139 | OWNERS file may also be specified using the `owners` field. |
Sugandha Goyal | 0ccc740 | 2022-10-21 13:35:55 | [diff] [blame] | 140 | * `last_reviewed`: Date when this annotation was last reviewed in YYYY-MM-DD format. |
Glenn Hartmann | db9723b3 | 2022-01-07 14:57:25 | [diff] [blame] | 141 | * `policy`: These set of fields specify the controls that a user may have |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 142 | on disabling or limiting the network request and its trace. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 143 | * `cookies_allowed`: Specifies if this request stores and uses cookies or |
| 144 | not. Use values `YES` or `NO`. |
| 145 | * `cookies_store`: If a request sends or stores cookies/channel IDs/... (i.e. |
| 146 | if `cookies_allowed` is true), we want to know which cookie store is being |
| 147 | used. The answer to this question can typically be derived from the |
| 148 | URLRequestContext that is being used. The three most common cases will be: |
| 149 | * If `cookies_allowed` is false, leave this field unset. |
| 150 | * If the profile's default URLRequestContext is being used (e.g. from |
| 151 | `Profile::GetRequestContext())`, this means that the user's normal |
| 152 | cookies sent. In this case, put `user` here. |
| 153 | * If the system URLRequestContext is being used (for example via |
| 154 | `io_thread()->system_url_request_context_getter())`, put `system` here. |
| 155 | * Otherwise, please explain (e.g. SafeBrowsing uses a separate cookie |
| 156 | store). |
| 157 | * `setting`: Human readable description of how to enable/disable a feature |
| 158 | that triggers this network request by a user (e.g. “Disable ‘Use a web |
| 159 | service to help resolve spelling errors.’ in settings under Advanced”). |
| 160 | Note that settings look different on different platforms, make sure your |
| 161 | description works everywhere! |
| 162 | * `chrome_policy`: Policy configuration that disables or limits this network |
Aiden Chiavatti | 479d874a | 2023-01-25 23:25:35 | [diff] [blame] | 163 | request. This would be a text serialized protobuf of any **non-device** |
| 164 | enterprise policy. See policy list or |
Glenn Hartmann | db9723b3 | 2022-01-07 14:57:25 | [diff] [blame] | 165 | `out/Debug/gen/components/policy/proto/chrome_settings.proto` for the full |
| 166 | list of policies. |
Aiden Chiavatti | 479d874a | 2023-01-25 23:25:35 | [diff] [blame] | 167 | * Note: Use `chrome_device_policy` instead for device policies. |
| 168 | * `chrome_device_policy`: Policy configuration that disables or limits this |
| 169 | network request. This would be a text serialized protobuf of any |
| 170 | **device** enterprise policy. See |
| 171 | `components/policy/proto/chrome_device_policy.proto` for the full list of |
| 172 | policies. |
| 173 | * Note: Use `chrome_policy` instead for non-device policies (e.g. user |
| 174 | policies). |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 175 | * `policy_exception_justification`: If there is no policy to disable or limit |
Ramin Halavati | c7c0bb03 | 2018-01-30 16:44:48 | [diff] [blame] | 176 | this request, a justification can be presented here. |
Sugandha Goyal | 0ccc740 | 2022-10-21 13:35:55 | [diff] [blame] | 177 | * `deprecated_policies`: Policy names disabling or limiting this network request |
| 178 | which are currently deprecated. These should be a subset of the policies in the |
Xinghui Lu | 5b9477d | 2023-05-04 20:15:55 | [diff] [blame] | 179 | `chrome_policy` field. If a policy is removed from the `chrome_policy` field, |
Sugandha Goyal | 0ccc740 | 2022-10-21 13:35:55 | [diff] [blame] | 180 | then it should be removed from this field also. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 181 | * `comments`: If required, any human readable extra comments. |
| 182 | |
| 183 | ### Format and Examples |
| 184 | Traffic annotations are kept in code as serialized protobuf. To define a |
| 185 | `NetworkTrafficAnnotationTag`, you may use the function |
| 186 | `net::DefineNetworkTrafficAnnotation`, with two arguments, the unique id, and |
| 187 | all other fields bundled together as a serialized protobuf string. |
| 188 | |
| 189 | #### Good examples |
| 190 | ```cpp |
| 191 | net::NetworkTrafficAnnotationTag traffic_annotation = |
| 192 | net::DefineNetworkTrafficAnnotation("spellcheck_lookup", R"( |
| 193 | semantics { |
| 194 | sender: "Online Spellcheck" |
| 195 | description: |
| 196 | "Chrome can provide smarter spell-checking by sending text you " |
| 197 | "type into the browser to Google's servers, allowing you to use " |
| 198 | "the same spell-checking technology used by Google products, such " |
| 199 | "as Docs. If the feature is enabled, Chrome will send the entire " |
| 200 | "contents of text fields as you type in them to Google along with " |
| 201 | "the browser’s default language. Google returns a list of " |
| 202 | "suggested spellings, which will be displayed in the context menu." |
| 203 | trigger: "User types text into a text field or asks to correct a " |
| 204 | "misspelled word." |
Nicolas Ouellet-Payeur | 7a9724ae | 2023-02-09 16:03:27 | [diff] [blame] | 205 | internal { |
| 206 | contacts { |
| 207 | email: "chrome-spellcheck@google.com" |
| 208 | } |
| 209 | } |
Sugandha Goyal | 0ccc740 | 2022-10-21 13:35:55 | [diff] [blame] | 210 | user_data { |
| 211 | type: USER_CONTENT |
| 212 | } |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 213 | data: "Text a user has typed into a text field. No user identifier " |
| 214 | "is sent along with the text." |
| 215 | destination: GOOGLE_OWNED_SERVICE |
Sugandha Goyal | 0ccc740 | 2022-10-21 13:35:55 | [diff] [blame] | 216 | last_reviewed: "2022-10-17" |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 217 | } |
| 218 | policy { |
| 219 | cookies_allowed: NO |
| 220 | setting: |
| 221 | "You can enable or disable this feature via 'Use a web service to " |
| 222 | "help resolve spelling errors.' in Chrome's settings under " |
| 223 | "Advanced. The feature is disabled by default." |
| 224 | chrome_policy { |
| 225 | SpellCheckServiceEnabled { |
| 226 | SpellCheckServiceEnabled: false |
| 227 | } |
| 228 | } |
| 229 | })"); |
| 230 | ``` |
| 231 | |
| 232 | ```cpp |
| 233 | net::NetworkTrafficAnnotationTag traffic_annotation2 = |
| 234 | net::DefineNetworkTrafficAnnotation( |
| 235 | "safe_browsing_chunk_backup_request", |
| 236 | R"( |
| 237 | semantics { |
| 238 | sender: "Safe Browsing" |
| 239 | description: |
| 240 | "Safe Browsing updates its local database of bad sites every 30 " |
| 241 | "minutes or so. It aims to keep all users up-to-date with the same " |
| 242 | "set of hash-prefixes of bad URLs." |
| 243 | trigger: |
| 244 | "On a timer, approximately every 30 minutes." |
| 245 | data: |
| 246 | "The state of the local DB is sent so the server can send just the " |
| 247 | "changes. This doesn't include any user data." |
| 248 | destination: GOOGLE_OWNED_SERVICE |
Sugandha Goyal | fcdaf21 | 2022-11-22 15:07:40 | [diff] [blame] | 249 | internal { |
| 250 | contacts { |
| 251 | email: "chrome-safebrowsing@google.com" |
| 252 | } |
| 253 | } |
Nicolas Ouellet-Payeur | 7a9724ae | 2023-02-09 16:03:27 | [diff] [blame] | 254 | user_data { |
| 255 | type: NONE |
| 256 | } |
| 257 | last_reviewed: "2023-01-01" |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 258 | } |
| 259 | policy { |
| 260 | cookies_allowed: YES |
| 261 | cookies_store: "Safe Browsing cookie store" |
| 262 | setting: |
| 263 | "Users can disable Safe Browsing by unchecking 'Protect you and " |
| 264 | "your device from dangerous sites' in Chromium settings under " |
| 265 | "Privacy. The feature is enabled by default." |
| 266 | chrome_policy { |
| 267 | SafeBrowsingEnabled { |
| 268 | policy_options {mode: MANDATORY} |
| 269 | SafeBrowsingEnabled: false |
| 270 | } |
| 271 | } |
| 272 | })"); |
| 273 | ``` |
| 274 | |
| 275 | #### Bad Examples |
| 276 | ```cpp |
| 277 | net::NetworkTrafficAnnotationTag bad_traffic_annotation = |
| 278 | net::DefineNetworkTrafficAnnotation( |
| 279 | ... |
| 280 | trigger: "Chrome sends this when [obscure event that is not related to " |
| 281 | "anything user-perceivable]." |
| 282 | // Please specify the exact user action that results in this request. |
| 283 | data: "This sends everything the feature needs to know." |
| 284 | // Please be precise, name the data items. If they are too many, name |
| 285 | // the sensitive user data and general classes of other data and refer |
| 286 | // to a document specifying the details. |
| 287 | ... |
| 288 | policy_exception_justification: "None." |
| 289 | // Check again! Most features can be disabled or limited by a policy. |
| 290 | ... |
| 291 | })"); |
| 292 | ``` |
| 293 | |
| 294 | #### Empty Template |
| 295 | You can copy/paste the following template to define an annotation. |
| 296 | ```cpp |
| 297 | net::NetworkTrafficAnnotationTag traffic_annotation = |
| 298 | net::DefineNetworkTrafficAnnotation("...", R"( |
| 299 | semantics { |
| 300 | sender: "..." |
| 301 | description: "..." |
| 302 | trigger: "..." |
| 303 | data: "..." |
| 304 | destination: WEBSITE/GOOGLE_OWNED_SERVICE/OTHER |
| 305 | } |
| 306 | policy { |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 307 | cookies_allowed: NO/YES |
| 308 | cookies_store: "..." |
| 309 | setting: "..." |
| 310 | chrome_policy { |
| 311 | [POLICY_NAME] { |
| 312 | [POLICY_NAME]: ... |
| 313 | } |
| 314 | } |
| 315 | policy_exception_justification = "..." |
| 316 | } |
| 317 | comments: "..." |
| 318 | )"); |
| 319 | ``` |
| 320 | |
| 321 | |
| 322 | ## Testing for errors |
| 323 | |
| 324 | There are several checks that should be done on annotations before submitting a |
| 325 | change list. These checks include: |
| 326 | * The annotations are syntactically correct. |
| 327 | * They have all required fields. |
| 328 | * Partial annotations and completing parts match (please refer to the next |
| 329 | section). |
| 330 | * Annotations are not incorrectly defined. |
| 331 | * e.g., traffic_annotation = NetworkTrafficAnnotation({1}). |
| 332 | * All usages from Chrome have annotation. |
Bella Bah | af76f4a | 2020-08-03 22:22:56 | [diff] [blame] | 333 | * That the annotation appears in |
| 334 | `tools/traffic_annotation/summary/grouping.xml`. When adding a new annotation, |
| 335 | it must also be included in `grouping.xml` for reporting purposes (please |
| 336 | refer to the **Annotations Review**). |
Bella Bah | 2b772c13 | 2020-08-05 17:01:37 | [diff] [blame] | 337 | |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 338 | |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 339 | ### Presubmit tests |
Nicolas Ouellet-Payeur | 3566294 | 2021-08-03 16:01:37 | [diff] [blame] | 340 | To perform tests prior to submit, one can use the `auditor.py` |
| 341 | script. It runs over the whole repository, extracts |
| 342 | all the annotations from C++ code, and then checks them for correctness. |
Ehsan Kia | 735f6b4 | 2020-02-27 18:14:59 | [diff] [blame] | 343 | |
Nicolas Ouellet-Payeur | 3566294 | 2021-08-03 16:01:37 | [diff] [blame] | 344 | Running the `auditor.py` script requires a build directory in which you just |
| 345 | built the `chrome` target. You can invoke it like this: |
| 346 | `vpython3 tools/traffic_annotation/scripts/auditor/auditor.py |
| 347 | --build-path=out/Default` |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 348 | |
| 349 | ### Waterfall tests |
| 350 | Two commit queue trybots test traffic annotations on changed files using the |
| 351 | scripts in `tools/traffic_annotation/scripts`. To run these tests faster and to |
Nicolas Arciniega | 15745e2 | 2019-10-09 20:42:35 | [diff] [blame] | 352 | avoid spamming the commit queue if an unforeseen error has happened in |
| 353 | downstream scripts or tools, they are run in error resilient mode, only on |
| 354 | changed files, and using heuristics to decide which files to process. |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 355 | An FYI bot runs more detailed tests on the whole repository and with different |
| 356 | switches, to make sure that the heuristics that trybot tests use and the limited |
| 357 | scope of tests have not neglected any issues. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 358 | |
| 359 | |
| 360 | ## Annotations Review |
| 361 | |
Ramin Halavati | 6c1526e | 2018-04-06 05:44:38 | [diff] [blame] | 362 | Network traffic annotations require review before landing in code and this is |
| 363 | enforced through keeping a summary of annotations in |
Bella Bah | af76f4a | 2020-08-03 22:22:56 | [diff] [blame] | 364 | `tools/traffic_annotation/summary/annotations.xml`. Once a new annotation is added, |
| 365 | one is updated, or deleted, this file should also be updated. To update the |
Nicolas Ouellet-Payeur | 3566294 | 2021-08-03 16:01:37 | [diff] [blame] | 366 | `annotations.xml` file automatically, one can run `auditor.py` |
Bella Bah | af76f4a | 2020-08-03 22:22:56 | [diff] [blame] | 367 | as specified in presubmit tests. But if it is not possible to do so (e.g., if |
| 368 | you are changing the code from an unsupported platform or you don’t have a |
| 369 | compiled build directory), the code can be submitted to the trybot and the test |
Bella Bah | 2b772c13 | 2020-08-05 17:01:37 | [diff] [blame] | 370 | on trybot will tell you the required modifications. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 371 | |
Bella Bah | af76f4a | 2020-08-03 22:22:56 | [diff] [blame] | 372 | In order to help make external reports easier, annotation unique ids should be |
| 373 | mentioned in `tools/traffic_annotation/summary/grouping.xml`. Once a new |
| 374 | annotation is added, or a preexisting annotation's unique id changes, this file |
| 375 | should also be updated. When adding a new annotation, make sure it is placed |
| 376 | within an appropriate group of `grouping.xml`. In the rare case that none of |
| 377 | the groups are appropriate, one can create a new group for the annotation; the |
| 378 | arrangement of annotations and group names in `grouping.xml` may be later |
| 379 | updated by a technical writer to better coincide with the external reports. |
Ramin Halavati | 2e7ffe4f | 2017-11-13 11:19:35 | [diff] [blame] | 380 | |
| 381 | ## Partial Annotations (Advanced) |
| 382 | |
| 383 | There are cases where the network traffic annotation cannot be fully specified |
| 384 | in one place. For example, in one place we know the trigger of a network request |
| 385 | and in another place we know the data that will be sent. In these cases, we |
| 386 | prefer that both parts of the annotation appear in context so that they are |
| 387 | updated if code changes. Partial annotations help splitting the network traffic |
| 388 | annotation into two pieces. In these cases, we call the first part, the partial |
| 389 | annotation, and the part the completes it, the completing annotation. Partial |
| 390 | annotations and completing annotations do not need to have all annotation |
| 391 | fields, but their composition should have all required fields. |
| 392 | |
| 393 | ### Defining a Partial Annotation |
| 394 | To define a partial annotation, one can use |
| 395 | `net::DefinePartialNetworkTrafficAnnotation` function. Besides the unique id and |
| 396 | annotation text, this function requires the unique id of the completing part. |
| 397 | For example, a partial annotation that only specifies the semantics part or a |
| 398 | request with unique id "omnibox_prefetch_image", and is completed later using an |
| 399 | annotation with unique id "bitmap_fetcher", can be defined as follows: |
| 400 | |
| 401 | ```cpp |
| 402 | net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation = |
| 403 | net::DefinePartialNetworkTrafficAnnotation("omnibox_prefetch_image", |
| 404 | "bitmap_fetcher", R"( |
| 405 | semantics { |
| 406 | sender: "Omnibox" |
| 407 | Description: "..." |
| 408 | Trigger: "..." |
| 409 | Data: "..." |
| 410 | destination: WEBSITE |
| 411 | })"); |
| 412 | ``` |
| 413 | |
| 414 | ### Nx1 Partial Annotations |
| 415 | The cases where several partial annotations may be completed by one completing |
| 416 | annotation are called Nx1. This also matches where N=1. To define a completing |
| 417 | annotation for such cases, one can use net::CompleteNetworkTrafficAnnotation |
| 418 | function. This function receives a unique id, the annotation text, and a |
| 419 | `net::PartialNetworkTrafficAnnotationTag` object. Here is an example of a |
| 420 | completing part for the previous example: |
| 421 | |
| 422 | ```cpp |
| 423 | net::NetworkTrafficAnnotationTag traffic_annotation = |
| 424 | net::CompleteNetworkTrafficAnnotation("bitmap_fetcher", |
| 425 | partial_traffic_annotation, R"( |
| 426 | policy { |
| 427 | cookies_allowed: YES |
| 428 | cookies_store: "user" |
| 429 | setting: "..." |
| 430 | chrome_policy {...} |
| 431 | })"); |
| 432 | ``` |
| 433 | |
| 434 | ### 1xN Partial Annotations |
| 435 | There are cases where one partial traffic annotation may be completed by |
| 436 | different completing annotations. In these cases, |
| 437 | `net::BranchedCompleteNetworkTrafficAnnotation` function can be used. This |
| 438 | function has an extra argument that is common between all branches and is |
| 439 | referred to by the partial annotation. For the above examples, if there would be |
| 440 | two different ways of completing the received partial annotation, the following |
| 441 | the definition can be used: |
| 442 | |
| 443 | ```cpp |
| 444 | if (...) { |
| 445 | return net::BranchedCompleteNetworkTrafficAnnotation( |
| 446 | "bitmap_fetcher_type1", "bitmap_fetcher", |
| 447 | partial_traffic_annotation, R"( |
| 448 | policy { |
| 449 | cookies_allowed: YES |
| 450 | cookies_store: "user" |
| 451 | setting: "..." |
| 452 | chrome_policy {...} |
| 453 | })"); |
| 454 | } else { |
| 455 | return net::BranchedCompleteNetworkTrafficAnnotation( |
| 456 | "bitmap_fetcher_type2", "bitmap_fetcher", |
| 457 | partial_traffic_annotation, R"( |
| 458 | policy { |
| 459 | cookies_allowed: YES |
| 460 | cookies_store: "system" |
| 461 | setting: "..." |
| 462 | chrome_policy {...} |
| 463 | })"); |
| 464 | ``` |
| 465 | |
| 466 | Please refer to `tools/traffic_annotation/sample_traffic_annotation.cc` for more |
| 467 | detailed examples. |
| 468 | |
| 469 | |
| 470 | ## Mutable Annotations (Advanced) |
| 471 | |
| 472 | `net::NetworkTrafficAnnotationTag` and `net::PartialNetworkTrafficAnnotationTag` |
| 473 | are defined with constant internal argument(s), so that once they are created, |
| 474 | they cannot be modified. There are very few exceptions that may require |
| 475 | modification of the annotation value, like the ones used by mojo interfaces |
| 476 | where after serialization, the annotation object is first created, then receives |
| 477 | value. In these cases, `net::MutableNetworkTrafficAnnotationTag` and |
| 478 | `net::MutablePartialNetworkTrafficAnnotationTag` can be used which do not have |
rhalavati@chromium.org | d7c93b3b | 2018-01-19 08:39:07 | [diff] [blame] | 479 | this limitation. |
Nicolas Ouellet-Payeur | 3566294 | 2021-08-03 16:01:37 | [diff] [blame] | 480 | |
rhalavati@chromium.org | d7c93b3b | 2018-01-19 08:39:07 | [diff] [blame] | 481 | Mutable annotations have a run time check before being converted into normal |
| 482 | annotations to ensure their content is valid. Therefore it is suggested that |
| 483 | they would be used only if there is no other way around it. Use cases are |
Nicolas Ouellet-Payeur | 3566294 | 2021-08-03 16:01:37 | [diff] [blame] | 484 | checked with `auditor.py` to ensure proper initialization values for the |
| 485 | mutable annotations. |
Ramin Halavati | c56d170 | 2017-11-30 09:23:01 | [diff] [blame] | 486 | |
| 487 | |
| 488 | ## Mojo Interfaces (Advanced) |
| 489 | |
| 490 | For serialization of network traffic annotation and partial network traffic |
| 491 | annotation tags, you can use the mutable mojo interfaces defined in |
Nicolas Arciniega | 15745e2 | 2019-10-09 20:42:35 | [diff] [blame] | 492 | `/services/network/public/mojom`. |