Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 1 | # Integrating a feature with the Origin Trials framework |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 2 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 3 | To expose your feature via the [Origin Trials framework], there are a few code |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 4 | changes required. |
| 5 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 6 | *** note |
| 7 | **WARNING:** This is only available for features implemented in Blink. |
| 8 | *** |
| 9 | |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 10 | [TOC] |
| 11 | |
| 12 | ## Code Changes |
| 13 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 14 | *** promo |
| 15 | **NOTE:** You can land these code changes before requesting to run an origin |
| 16 | trial. |
Jason Chase | dbd8b973 | 2020-11-26 17:18:43 | [diff] [blame] | 17 | These code changes make it possible to control a feature via an origin trial, |
| 18 | but don't require an origin trial to be approved. For more on the process, see |
| 19 | [Running an Origin Trial]. |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 20 | *** |
Jason Chase | dbd8b973 | 2020-11-26 17:18:43 | [diff] [blame] | 21 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 22 | ### Step 1: Add Runtime Enabled Feature in Blink for Origin Trial |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 23 | |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 24 | First, you’ll need to configure [`runtime_enabled_features.json5`]. If you don't |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 25 | have a Blink's [Runtime Enabled Feature] flag yet, you will need to add an entry |
| 26 | in this file. |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 27 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 28 | The following fields of an entry are relevant: |
Christian Biesinger | 0651e825 | 2022-01-25 17:18:08 | [diff] [blame] | 29 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 30 | - `name`: The name of your runtime enabled feature, e.g. `"MyFeature"`. |
| 31 | - `origin_trial_feature_name`: The name of your runtime enabled feature in the |
| 32 | origin trial. This can be the same as your runtime feature flag (i.e. `name` |
| 33 | field), or different. Eventually, this configured name will be used in the |
| 34 | origin trials developer console. |
| 35 | - `origin_trial_os`: Specifies a `[list]` of platforms where they will allow the |
| 36 | trial to be enabled. The list values are case-insensitive, but must match one |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 37 | of the defined `OS_<platform>` macros (see [`build_config.h`]). |
Panos Astithas | f9ce0566 | 2023-11-14 02:20:41 | [diff] [blame] | 38 | - `origin_trial_allows_third_party`: Must be enabled to allow third-party tokens |
| 39 | to work correctly. Set to true, if (and only if) you intend to support |
| 40 | third-party matching. |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 41 | - `base_feature`: Generates a `base::Feature` in the `blink::features` |
Kent Tamura | 0bc0a453 | 2023-02-17 04:18:38 | [diff] [blame] | 42 | namespace if the value is not `"none"`. It helps to control the Origin Trial |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 43 | remotely. See also [Generate a `base::Feature` instance from a Blink Feature]. |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 44 | |
| 45 | Not specific to Origin Trial: |
| 46 | |
| 47 | - `status`: Controls when the runtime enabled feature is enabled in Blink. See |
| 48 | also [the Status table]. |
| 49 | - `base_feature_status`: Controls when the `base::Feature` defined by |
| 50 | `base_feature` is enabled. |
| 51 | |
| 52 | More details are explained in the json5 file and in the above linked doc. |
| 53 | |
Evelynn Kaplan | 72b8f1b | 2025-03-27 15:50:06 | [diff] [blame] | 54 | If the runtime enabled feature flag is [used in C++](#1_in-c), you will have to |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 55 | change all callers of the no-argument overload of |
| 56 | `RuntimeEnabledFeatures::MyFeatureEnabled()` to the overload that takes a |
| 57 | `const FeatureContext*`. You can pass an `ExecutionContext` here, e.g. using |
| 58 | `ExecutionContext::From(ScriptState*)`. |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 59 | |
| 60 | #### Examples |
| 61 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 62 | RuntimeEnabledFeature flag name, trial name and `base::Feature` are all the |
| 63 | same: |
| 64 | |
| 65 | ```json |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 66 | { |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 67 | name: "MyFeature", // Generates `RuntimeEnabledFeatures::MyFeatureEnabled()` |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 68 | origin_trial_feature_name: "MyFeature", |
| 69 | status: "experimental", |
Kent Tamura | 0bc0a453 | 2023-02-17 04:18:38 | [diff] [blame] | 70 | // No need to specify base_feature. |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 71 | }, |
| 72 | ``` |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 73 | |
Kent Tamura | 0bc0a453 | 2023-02-17 04:18:38 | [diff] [blame] | 74 | RuntimeEnabledFeature flag name, trial name, and `base::Feature` name are |
| 75 | different: |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 76 | |
| 77 | ```json |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 78 | { |
| 79 | name: "MyFeature", |
| 80 | origin_trial_feature_name: "MyFeatureTrial", |
Kent Tamura | 0bc0a453 | 2023-02-17 04:18:38 | [diff] [blame] | 81 | base_feature: "MyBaseFeature", // Generates blink::features::kMyBaseFeature |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 82 | status: "experimental", |
| 83 | }, |
| 84 | ``` |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 85 | |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 86 | Trial limited to specific platform: |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 87 | |
| 88 | ```json |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 89 | { |
| 90 | name: "MyFeature", |
| 91 | origin_trial_feature_name: "MyFeature", |
| 92 | origin_trial_os: ["android"], |
| 93 | status: "experimental", |
| 94 | }, |
| 95 | ``` |
| 96 | |
Peter Birk Pakkenberg | f6ca525 | 2022-09-05 08:54:05 | [diff] [blame] | 97 | #### WebView considerations |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 98 | |
| 99 | Because WebView is built as part of the `"android"` os target, it is not |
| 100 | possible to exclude a trial from WebView if it is enabled on Android. |
Peter Birk Pakkenberg | f6ca525 | 2022-09-05 08:54:05 | [diff] [blame] | 101 | |
| 102 | If the feature under trial can be enabled on WebView alongside other Android |
| 103 | platforms, this is preferred. |
| 104 | |
| 105 | In situations where this is not feasible, the recommended solution is to |
| 106 | explicitly disable the origin trial in |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 107 | `AwMainDelegate::BasicStartupComplete()` in [`aw_main_delegate.cc`] by |
Peter Birk Pakkenberg | f6ca525 | 2022-09-05 08:54:05 | [diff] [blame] | 108 | appending the `embedder_support::kOriginTrialDisabledFeatures` switch with the |
| 109 | disabled trial names as values. |
| 110 | |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 111 | See https://crrev.com/c/3733267 for an example of how this can be done. |
Peter Birk Pakkenberg | f6ca525 | 2022-09-05 08:54:05 | [diff] [blame] | 112 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 113 | ### Step 2: Gating Access |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 114 | |
| 115 | Once configured, there are two mechanisms to gate access to your feature behind |
| 116 | an origin trial. You can use either mechanism, or both, as appropriate to your |
| 117 | feature implementation. |
| 118 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 119 | #### 1) In C++ |
| 120 | |
| 121 | A native C++ method that you can call in Blink code at runtime to expose your |
| 122 | feature: |
| 123 | |
| 124 | ```cpp |
| 125 | bool RuntimeEnabledFeatures::MyFeatureEnabled(ExecutionContext*) |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 126 | ``` |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 127 | |
| 128 | *** note |
| 129 | **WARNING:** Your feature implementation must not persist the result of the |
| 130 | enabled check. Your code should simply call |
| 131 | `RuntimeEnabledFeatures::MyFeatureEnabled(ExecutionContext*)` as often as |
| 132 | necessary to gate access to your feature. |
| 133 | *** |
| 134 | |
| 135 | #### 2-1) In Web IDL |
| 136 | |
| 137 | An IDL attribute \[[RuntimeEnabled]\] that you can use to automatically generate |
| 138 | code to expose and hide JavaScript methods/attributes/objects. |
| 139 | |
| 140 | ```cpp |
Allen Robinson | b0efcfa | 2019-06-25 13:24:04 | [diff] [blame] | 141 | [RuntimeEnabled=MyFeature] |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 142 | partial interface Navigator { |
| 143 | readonly attribute MyFeatureManager myFeature; |
| 144 | } |
| 145 | ``` |
| 146 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 147 | #### 2-2) CSS Properties |
Allen Robinson | b0efcfa | 2019-06-25 13:24:04 | [diff] [blame] | 148 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 149 | *** promo |
| 150 | **NOTE:** For CSS properties, you do not need to edit the IDL files, as the |
| 151 | exposure on the [CSSStyleDeclaration] is handled at runtime. |
| 152 | *** |
Rodney Ding | 533e41a | 2020-01-15 20:17:18 | [diff] [blame] | 153 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 154 | You can also run experiment for new CSS properties with origin trial. After you |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 155 | have configured your feature in [`runtime_enabled_features.json5`] as above, |
| 156 | head to [`css_properties.json5`]. As explained in the file, you use |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 157 | `runtime_flag` to associate the CSS property with the feature you just defined. |
| 158 | This will automatically link the CSS property to the origin trial defined in the |
| 159 | runtime feature. It will be available in both JavaScript (`Element.style`) and |
| 160 | CSS (including `@supports`) when the trial is enabled. |
Rodney Ding | 533e41a | 2020-01-15 20:17:18 | [diff] [blame] | 161 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 162 | *** promo |
| 163 | **EXAMPLE:** [origin-trial-test-property] defines a test css property controlled |
| 164 | via runtime feature `OriginTrialsSampleAPI` and subsequently an origin trial |
| 165 | named `Frobulate`. |
| 166 | *** |
| 167 | |
| 168 | *** note |
| 169 | **ISSUE:** In the rare cases where the origin trial token is added via script |
| 170 | after the css style declaration, the css property will be enabled and is fully |
| 171 | functional, however it will not appear on the [CSSStyleDeclaration] interface, |
| 172 | i.e. not accessible in `Element.style`. This issue is tracked in crbug/1041993. |
| 173 | *** |
| 174 | |
| 175 | ### Step 3: Mapping Runtime Enabled Feature to `base::Feature` (optional) |
| 176 | |
| 177 | Given the following example: |
| 178 | |
| 179 | ```json |
| 180 | { |
| 181 | name: "MyFeature", |
| 182 | origin_trial_feature_name: "MyFeature", |
| 183 | base_feature: "MyFeature", |
| 184 | status: "experimental", |
| 185 | }, |
| 186 | ``` |
| 187 | |
| 188 | ```cpp |
| 189 | [RuntimeEnabled=MyFeature] |
| 190 | interface MyFeatureAPI { |
| 191 | readonly attribute bool dummy; |
| 192 | } |
| 193 | ``` |
| 194 | |
| 195 | ```cpp |
| 196 | // third_party/blink/.../my_feature_api.cc |
| 197 | bool MyFeatureAPI::ConnectToBrowser() { |
| 198 | if (base::FeatureList::IsEnabled(blink::features::kMyFeature) { |
| 199 | // Do something |
| 200 | } |
| 201 | return false; |
| 202 | } |
| 203 | ``` |
| 204 | |
| 205 | The above example shows a new feature relies on a `base::Feature` generated from |
| 206 | the `base_feature` definition in json file, e.g. `blink::features::kMyFeature`, |
| 207 | in addition to the runtime enabled feature flag `MyFeature`. |
| 208 | However, their values are not associated. |
| 209 | |
| 210 | In addition, due to the [limitation](#limitations), the runtime enabled feature |
| 211 | flag is not available in the browser process **by default**: |
| 212 | |
| 213 | > if you need to know in the browser process whether a feature should |
| 214 | > be enabled, then you will have to either have the renderer inform it at |
| 215 | > runtime, or else just assume that it's always enabled, and gate access to the |
| 216 | > feature from the renderer. |
| 217 | |
| 218 | *** note |
| 219 | **TLDR:** Turning on `MyFeature` doesn't automatically turning on |
| 220 | `blink::features::kMyFeature`, and vice versa. |
| 221 | *** |
| 222 | |
| 223 | To mitigate the issue, there are several options: |
| 224 | |
| 225 | #### Option 1: Fully Enabling `base::Feature`, e.g. `kMyFeature` |
| 226 | |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 227 | And letting Origin Trial decide when your feature (via runtime enabled feature |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 228 | flag `blink::features::MyFeature`) is available, as suggested in the above |
| 229 | quote. The `base::Feature` can be enabled via a remote Finch config, or by |
| 230 | updating the default value in C++. |
| 231 | |
| 232 | However, after the Origin Trial ends, it will be impossible to ramp up the |
| 233 | feature by Finch if the part controlled by `MyFeature` cannot be enabled |
| 234 | independently. For example, if you have a new Web API `MyFeatureAPI`, enabling |
| 235 | `MyFeature` will just make the IDL available to everyone without the |
| 236 | Blink/browser implementation. |
| 237 | |
| 238 | *** note |
| 239 | **Example Bug:** https://crbug.com/1360678. |
| 240 | *** |
| 241 | |
| 242 | #### Option 2: Setting Up a Custom Mapping |
| 243 | |
| 244 | 1. Make `MyFeature` depend on `blink::features::kMyFeature` so that the feature |
| 245 | is not enabled if `features::kMyFeatures` is not enabled. In |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 246 | [third_party/blink/renderer/core/origin_trials/origin_trial_context.cc](/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc): |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 247 | |
| 248 | ```cpp |
| 249 | bool OriginTrialContext::CanEnableTrialFromName(const StringView& trial_name) { |
| 250 | ... |
| 251 | if (trial_name == "MyFeature") { |
| 252 | return base::FeatureList::IsEnabled(blink::features::kMyFeatures); |
| 253 | } |
| 254 | } |
| 255 | ``` |
| 256 | |
| 257 | 2. Add custom relationship for `MyFeature` and `blink::features::kMyFeature` to |
| 258 | handle your use case. |
| 259 | |
| 260 | Read |
| 261 | [**Determine how your feature is initialized: Depends on the status of a base::Feature**](initialize_blink_features.md#step-2_determine-how-your-feature-is-initialized) |
| 262 | first. If the mappings described there don't meet your use case, refer to |
| 263 | the following examples. |
| 264 | |
| 265 | In [content/child/runtime_features.cc](https://source.chromium.org/chromium/chromium/src/+/main:content/child/runtime_features.cc): |
| 266 | |
| 267 | ```cpp |
| 268 | void SetCustomizedRuntimeFeaturesFromCombinedArgs( |
| 269 | const base::CommandLine& command_line) { |
| 270 | // Example 1: https://bit.ly/configuring-trust-tokens |
| 271 | // Example 2: https://crrev.com/c/3878922/14/content/child/runtime_features.cc |
| 272 | } |
| 273 | ``` |
| 274 | |
| 275 | ### Step 4: Web Feature Counting |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 276 | |
| 277 | Once the feature is created, in order to run the origin trial you need to track |
| 278 | how often users use your feature. You can do it in two ways. |
| 279 | |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 280 | #### Increment counter in your C++ code |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 281 | |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 282 | 1. Add your feature counter to the end of [`webdx_feature.mojom`] (or |
| 283 | [`web_feature.mojom`] if it's a feature that's somehow not expected to be |
| 284 | described in the [web platform dx |
| 285 | repository](https://github.com/web-platform-dx/web-features/))" |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 286 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 287 | ```cpp |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 288 | enum WebDXFeature { |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 289 | // ... |
| 290 | kLastFeatureBeforeYours = 1235, |
| 291 | // Here, increment the last feature count before yours by 1. |
| 292 | kMyFeature = 1236, |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 293 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 294 | kNumberOfFeatures, // This enum value must be last. |
| 295 | }; |
| 296 | ``` |
| 297 | |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 298 | 2. Run [`update_use_counter_feature_enum.py`] to update the UMA mappings. |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 299 | |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 300 | 3. Increment your feature counter in C++ code. |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 301 | |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 302 | ```cpp |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 303 | #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 304 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 305 | // ... |
| 306 | |
| 307 | if (RuntimeEnabledFeatures::MyFeatureEnabled(context)) { |
| 308 | UseCounter::Count(context, WebFeature::kMyFeature); |
| 309 | } |
| 310 | ``` |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 311 | |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 312 | #### Update counter with \[MeasureAs\] IDL attribute |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 313 | |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 314 | 1. Add \[[MeasureAs="WebDXFeature::kMyFeature"]\] IDL attribute |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 315 | |
| 316 | ```cpp |
| 317 | partial interface Navigator { |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 318 | [RuntimeEnabled=MyFeature, MeasureAs="WebDXFeature::kMyFeature"] |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 319 | readonly attribute MyFeatureManager myFeature; |
| 320 | ``` |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 321 | |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 322 | Alternatively, if your feature counter doesn't fit as a WebDXFeature use |
| 323 | counter, make it a WebFeature instead and drop the WebDXFeature:: prefix (and |
| 324 | quotes) in the \[[MeasureAs]\] attribute above, or use \[[Measure]\] instead |
| 325 | and follow the \[[Measure]\] IDL attribute naming convention. |
| 326 | |
| 327 | 2. Add your use counter to [`webdx_feature.mojom`] (or alternatively to |
| 328 | [`web_feature.mojom`]). The code to increment your feature counter will be |
| 329 | generated in the V8 bindings code automatically. |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 330 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 331 | ```cpp |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 332 | enum WebDXFeature { |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 333 | // ... |
| 334 | kLastFeatureBeforeYours = 1235, |
| 335 | // Here, increment the last feature count before yours by 1. |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 336 | kMyFeature = 1236, |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 337 | |
| 338 | kNumberOfFeatures, // This enum value must be last. |
| 339 | }; |
| 340 | ``` |
| 341 | |
| 342 | ### Step 5: Add Web Tests |
| 343 | |
| 344 | When using the \[[RuntimeEnabled]\] IDL attribute, you should add web tests |
| 345 | to verify that the V8 bindings code is working as expected. Depending on how |
| 346 | your feature is exposed, you'll want tests for the exposed interfaces, as well |
| 347 | as tests for script-added tokens. For examples, refer to the existing tests in |
| 348 | [origin_trials/webexposed]. |
Ruslan Burakov | 53cefa7 | 2019-05-09 08:22:25 | [diff] [blame] | 349 | |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 350 | ## Limitations |
| 351 | |
Allen Robinson | b0efcfa | 2019-06-25 13:24:04 | [diff] [blame] | 352 | What you can't do, because of the nature of these origin trials, is know at |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 353 | either browser or renderer startup time whether your feature is going to be used |
| 354 | in the current page/context. This means that if you require lots of expensive |
| 355 | processing to begin (say you index the user's hard drive, or scan an entire city |
| 356 | for interesting weather patterns,) that you will have to either do it on browser |
| 357 | startup for *all* users, just in case it's used, or do it on first access. (If |
| 358 | you go with first access, then only people trying the experiment will notice the |
| 359 | delay, and hopefully only the first time they use it.). We are investigating |
| 360 | providing a method like `OriginTrials::myFeatureShouldInitialize()` that will |
| 361 | hint if you should do startup initialization. For example, this could include |
| 362 | checks for trials that have been revoked (or throttled) due to usage, if the |
| 363 | entire origin trials framework has been disabled, etc. The method would be |
| 364 | conservative and assume initialization is required, but it could avoid expensive |
| 365 | startup in some known scenarios. |
| 366 | |
| 367 | Similarly, if you need to know in the browser process whether a feature should |
| 368 | be enabled, then you will have to either have the renderer inform it at runtime, |
| 369 | or else just assume that it's always enabled, and gate access to the feature |
| 370 | from the renderer. |
| 371 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 372 | ## Manual Testing |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 373 | |
Steve Kobes | 6d752cb | 2019-01-16 01:37:46 | [diff] [blame] | 374 | To test an origin trial feature during development, follow these steps: |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 375 | |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 376 | 1. Use [`generate_token.py`] to generate a token signed with the test private key. |
Steve Kobes | 6d752cb | 2019-01-16 01:37:46 | [diff] [blame] | 377 | You can generate signed tokens for any origin that you need to help you test, |
| 378 | including localhost or 127.0.0.1. Example: |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 379 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 380 | ```bash |
| 381 | tools/origin_trials/generate_token.py http://localhost:8000 MyFeature |
| 382 | ``` |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 383 | |
Jason Chase | dbd8b973 | 2020-11-26 17:18:43 | [diff] [blame] | 384 | There are additional flags to generate third-party tokens, set the expiry |
| 385 | date, and control other options. See the command help for details (`--help`). |
| 386 | For example, to generate a third-party token, with [user subset exclusion]: |
| 387 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 388 | ```bash |
| 389 | tools/origin_trials/generate_token.py --is-third-party --usage-restriction=subset http://localhost:8000 MyFeature |
| 390 | ``` |
Jason Chase | dbd8b973 | 2020-11-26 17:18:43 | [diff] [blame] | 391 | |
Steve Kobes | 6d752cb | 2019-01-16 01:37:46 | [diff] [blame] | 392 | 2. Copy the token from the end of the output and use it in a `<meta>` tag or |
| 393 | an `Origin-Trial` header as described in the [Developer Guide]. |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 394 | |
Steve Kobes | 6d752cb | 2019-01-16 01:37:46 | [diff] [blame] | 395 | 3. Run Chrome with the test public key by passing: |
| 396 | `--origin-trial-public-key=dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=` |
| 397 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 398 | You can also run Chrome with both the test public key and the default public key |
| 399 | along side by passing: |
Andrii Sagaidak | dbc6a77 | 2019-12-12 03:43:39 | [diff] [blame] | 400 | `--origin-trial-public-key=dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=,fMS4mpO6buLQ/QMd+zJmxzty/VQ6B1EUZqoCU04zoRU=` |
| 401 | |
Nate Fischer | b3b80ef | 2023-08-17 15:59:24 | [diff] [blame] | 402 | *** promo |
| 403 | **TIP:** See |
| 404 | [this doc](https://www.chromium.org/developers/how-tos/run-chromium-with-flags/) |
| 405 | to apply commandline switches for Chrome for Android and |
| 406 | [this doc](/android_webview/docs/commandline-flags.md) to apply commandline |
| 407 | switches for Android WebView. |
| 408 | *** |
| 409 | |
Steve Kobes | 6d752cb | 2019-01-16 01:37:46 | [diff] [blame] | 410 | The `--origin-trial-public-key` switch is not needed with `content_shell`, as it |
| 411 | uses the test public key by default. |
| 412 | |
| 413 | The test private key is stored in the repo at `tools/origin_trials/eftest.key`. |
| 414 | It's also used by Origin Trials unit tests and web tests. |
| 415 | |
| 416 | If you cannot set command-line switches (e.g., on Chrome OS), you can also |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 417 | directly modify [`chrome_origin_trial_policy.cc`]. |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 418 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 419 | To see additional information about origin trial token parsing (including |
| 420 | reasons for failures, or token names for successful tokens), you can add these |
| 421 | switches: |
Mason Freed | 9ee18c76 | 2020-08-18 20:57:21 | [diff] [blame] | 422 | |
| 423 | `--vmodule=trial_token=2,origin_trial_context=1` |
| 424 | |
| 425 | If you are building with `is_debug=false`, then you will also need to add |
| 426 | `dcheck_always_on=true` to your build options, and add this to the command line: |
| 427 | |
| 428 | `--enable-logging=stderr` |
| 429 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 430 | ## Related Documents |
Mason Freed | 9ee18c76 | 2020-08-18 20:57:21 | [diff] [blame] | 431 | |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 432 | - [Chromium Feature API & Finch (Googler-only)](http://go/finch-feature-api) |
| 433 | - [Configuration: Prefs, Settings, Features, Switches & Flags](configuration.md) |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 434 | - [Runtime Enabled Features] |
Ming-Ying Chung | c23505d6 | 2022-09-22 10:07:33 | [diff] [blame] | 435 | - [Initialization of Blink runtime features in content layer](initialize_blink_features.md) |
chasej | 0ac7dd2 | 2017-02-23 18:16:17 | [diff] [blame] | 436 | |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 437 | [Origin Trials framework]: https://googlechrome.github.io/OriginTrials/developer-guide.html |
| 438 | [Runtime Enabled Feature]: /third_party/blink/renderer/platform/RuntimeEnabledFeatures.md |
| 439 | [Runtime Enabled Features]: /third_party/blink/renderer/platform/RuntimeEnabledFeatures.md |
| 440 | [Generate a `base::Feature` instance from a Blink Feature]: /third_party/blink/renderer/platform/RuntimeEnabledFeatures.md#generate-a-instance-from-a-blink-feature |
| 441 | [the Status table]: /third_party/blink/renderer/platform/RuntimeEnabledFeatures.md#adding-a-runtime-enabled-feature |
| 442 | [`build_config.h`]: /build/build_config.h |
| 443 | [`chrome_origin_trial_policy.cc`]: /chrome/common/origin_trials/chrome_origin_trial_policy.cc |
| 444 | [`generate_token.py`]: /tools/origin_trials/generate_token.py |
chasej | c74a4c9c | 2017-02-10 20:38:09 | [diff] [blame] | 445 | [Developer Guide]: https://github.com/jpchase/OriginTrials/blob/gh-pages/developer-guide.md |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 446 | [RuntimeEnabled]: /third_party/blink/renderer/bindings/IDLExtendedAttributes.md#RuntimeEnabled |
| 447 | [origin_trials/webexposed]: /third_party/blink/web_tests/http/tests/origin_trials/webexposed/ |
| 448 | [`runtime_enabled_features.json5`]: /third_party/blink/renderer/platform/runtime_enabled_features.json5 |
Johnny Stenback | fc32f1c0 | 2024-08-03 00:15:46 | [diff] [blame] | 449 | [`webdx_feature.mojom`]: /third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 450 | [`web_feature.mojom`]: /third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom |
| 451 | [`update_use_counter_feature_enum.py`]: /tools/metrics/histograms/update_use_counter_feature_enum.py |
| 452 | [Measure]: /third_party/blink/renderer/bindings/IDLExtendedAttributes.md#Measure |
| 453 | [`css_properties.json5`]: /third_party/blink/renderer/core/css/css_properties.json5 |
Rodney Ding | 533e41a | 2020-01-15 20:17:18 | [diff] [blame] | 454 | [origin-trial-test-property]: https://chromium.googlesource.com/chromium/src/+/ff2ab8b89745602c8300322c2a0158e210178c7e/third_party/blink/renderer/core/css/css_properties.json5#2635 |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 455 | [CSSStyleDeclaration]: /third_party/blink/renderer/core/css/css_style_declaration.idl |
Jason Chase | dbd8b973 | 2020-11-26 17:18:43 | [diff] [blame] | 456 | [Running an Origin Trial]: https://www.chromium.org/blink/origin-trials/running-an-origin-trial |
| 457 | [user subset exclusion]: https://docs.google.com/document/d/1xALH9W7rWmX0FpjudhDeS2TNTEOXuPn4Tlc9VmuPdHA/edit#heading=h.myaz1twlipw |
Nate Fischer | 151aa1e | 2023-08-17 15:36:33 | [diff] [blame] | 458 | [`aw_main_delegate.cc`]: /android_webview/lib/aw_main_delegate.cc |