blob: 6b4de824bced6641e78e8b0f5c9f0deeb838dc98 [file] [log] [blame] [view]
Allen Robinsonb0efcfa2019-06-25 13:24:041# Integrating a feature with the origin trials framework
chasejc74a4c9c2017-02-10 20:38:092
3To expose your feature via the origin trials framework, there are a few code
4changes required.
5
6[TOC]
7
8## Code Changes
9
Jason Chasedbd8b9732020-11-26 17:18:4310NOTE: You can land these code changes before requesting to run an origin trial.
11These code changes make it possible to control a feature via an origin trial,
12but don't require an origin trial to be approved. For more on the process, see
13[Running an Origin Trial].
14
chasejc74a4c9c2017-02-10 20:38:0915### Runtime Enabled Features
16
Kent Tamurab10f7eda2017-09-15 06:45:2017First, you’ll need to configure [runtime\_enabled\_features.json5]. This is
chasejc74a4c9c2017-02-10 20:38:0918explained in the file, but you use `origin_trial_feature_name` to associate your
19runtime feature flag with a name for your origin trial. The name can be the
20same as your runtime feature flag, or different. Eventually, this configured
Allen Robinsonb0efcfa2019-06-25 13:24:0421name will be used in the origin trials developer console. You can have both
22`status: experimental` and `origin_trial_feature_name` if you want your feature
23to be enabled either by using the `--enable-experimental-web-platform-features`
24flag **or** the origin trial.
chasejc74a4c9c2017-02-10 20:38:0925
Christian Biesinger0651e8252022-01-25 17:18:0826You will have to change all callers of the no-argument overload of
27`RuntimeEnabledFeatures::FooEnabled()` to the overload that takes a
28`const FeatureContext*`. You can pass an `ExecutionContext` here
29(e.g. using `ExecutionContext::From(ScriptState*)`).
30
chasejc74a4c9c2017-02-10 20:38:0931You may have a feature that is not available on all platforms, or need to limit
32the trial to specific platforms. Use `origin_trial_os: [list]` to specify which
33platforms will allow the trial to be enabled. The list values are case-
34insensitive, but must match one of the defined `OS_<platform>` macros (see
35[build_config.h]).
36
37#### Examples
38
39Flag name and trial name are the same:
40```
41{
42 name: "MyFeature",
43 origin_trial_feature_name: "MyFeature",
44 status: "experimental",
45},
46```
47Flag name and trial name are different:
48```
49{
50 name: "MyFeature",
51 origin_trial_feature_name: "MyFeatureTrial",
52 status: "experimental",
53},
54```
55Trial limited to specific platform:
56``` json
57{
58 name: "MyFeature",
59 origin_trial_feature_name: "MyFeature",
60 origin_trial_os: ["android"],
61 status: "experimental",
62},
63```
64
Rodney Ding533e41a2020-01-15 20:17:1865### CSS Properties
66
67You can also run experiment for new CSS properties with origin trial. After you
68have configured your feature in [runtime\_enabled\_features.json5] as above, head
69to [css\_properties.json5]. As explained in the file, you use `runtime_flag` to associate
70the CSS property with the feature you just defined. This will automatically link the CSS
71property to the origin trial defined in the runtime feature. It will be available
72in both JavaScript (`Element.style`) and CSS (including `@supports`) when the trial
73is enabled.
74
75
76**Example:** [origin-trial-test-property] defines a test css property controlled via
77runtime feature `OriginTrialsSampleAPI` and subsequently an origin trial named `Frobulate`.
78
chasejc74a4c9c2017-02-10 20:38:0979### Gating Access
80
81Once configured, there are two mechanisms to gate access to your feature behind
82an origin trial. You can use either mechanism, or both, as appropriate to your
83feature implementation.
84
851. A native C++ method that you can call in Blink code at runtime to expose your
Allen Robinsonb0efcfa2019-06-25 13:24:0486 feature: `bool RuntimeEnabledFeatures::MyFeatureEnabled(ExecutionContext*)`
872. An IDL attribute \[[RuntimeEnabled]\] that you can use to automatically
88 generate code to expose and hide JavaScript methods/attributes/objects.
chasejc74a4c9c2017-02-10 20:38:0989```
Allen Robinsonb0efcfa2019-06-25 13:24:0490[RuntimeEnabled=MyFeature]
chasejc74a4c9c2017-02-10 20:38:0991partial interface Navigator {
92 readonly attribute MyFeatureManager myFeature;
93}
94```
95
Allen Robinsonb0efcfa2019-06-25 13:24:0496**NOTE:** Your feature implementation must not persist the result of the enabled
97check. Your code should simply call
98`RuntimeEnabledFeatures::MyFeatureEnabled(ExecutionContext*)` as often as
99necessary to gate access to your feature.
100
Rodney Ding533e41a2020-01-15 20:17:18101**NOTE:** For CSS properties, you do not need to edit the IDL files, as the exposure
102on the [CSSStyleDeclaration] is handled at runtime.
103
104**ISSUE:** In the rare cases where the origin trial token is added via script after
105the css style declaration, the css property will be enabled and is fully functional,
106however it will not appear on the [CSSStyleDeclaration] interface, i.e. not accessible
107in `Element.style`. This issue is tracked in crbug/1041993.
108
Ruslan Burakov53cefa72019-05-09 08:22:25109### Web Feature Counting
110
111Once the feature is created, in order to run the origin trial you need to track
112how often users use your feature. You can do it in two ways.
113
114#### Increment counter in your c++ code.
115
1161. Add your feature counter to end of [web\_feature.mojom]:
117
118```
119enum WebFeature {
120 // ...
121 kLastFeatureBeforeYours = 1235,
122 // Here, increment the last feature count before yours by 1.
123 kMyFeature = 1236,
124
125 kNumberOfFeatures, // This enum value must be last.
126};
127```
1282. Run [update\_use\_counter\_feature\_enum.py] to update the UMA mapping.
129
1303. Increment your feature counter in c++ code.
131```c++
Allen Robinsonb0efcfa2019-06-25 13:24:04132#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
Ruslan Burakov53cefa72019-05-09 08:22:25133
134// ...
135
Allen Robinsonb0efcfa2019-06-25 13:24:04136 if (RuntimeEnabledFeatures::MyFeatureEnabled(context)) {
Ruslan Burakov53cefa72019-05-09 08:22:25137 UseCounter::Count(context, WebFeature::kMyFeature);
138 }
139```
140
141#### Update counter with \[Measure\] IDL attribute
142
1431. Add \[[Measure]\] IDL attribute
144```
145partial interface Navigator {
Allen Robinsonb0efcfa2019-06-25 13:24:04146 [RuntimeEnabled=MyFeature, Measure]
Ruslan Burakov53cefa72019-05-09 08:22:25147 readonly attribute MyFeatureManager myFeature;
148```
149
1502. The code to increment your feature counter will be generated in V8
151 automatically. But it requires you to follow \[[Measure]\] IDL attribute
152 naming convention when you will add your feature counter to
153 [web\_feature.mojom].
154```
155enum WebFeature {
156 // ...
157 kLastFeatureBeforeYours = 1235,
158 // Here, increment the last feature count before yours by 1.
159 kV8Navigator_MyFeature_AttributeGetter = 1236,
160
161 kNumberOfFeatures, // This enum value must be last.
162};
163```
164
chasejc74a4c9c2017-02-10 20:38:09165## Limitations
166
Allen Robinsonb0efcfa2019-06-25 13:24:04167What you can't do, because of the nature of these origin trials, is know at
chasejc74a4c9c2017-02-10 20:38:09168either browser or renderer startup time whether your feature is going to be used
169in the current page/context. This means that if you require lots of expensive
170processing to begin (say you index the user's hard drive, or scan an entire city
171for interesting weather patterns,) that you will have to either do it on browser
172startup for *all* users, just in case it's used, or do it on first access. (If
173you go with first access, then only people trying the experiment will notice the
174delay, and hopefully only the first time they use it.). We are investigating
175providing a method like `OriginTrials::myFeatureShouldInitialize()` that will
176hint if you should do startup initialization. For example, this could include
177checks for trials that have been revoked (or throttled) due to usage, if the
178entire origin trials framework has been disabled, etc. The method would be
179conservative and assume initialization is required, but it could avoid expensive
180startup in some known scenarios.
181
182Similarly, if you need to know in the browser process whether a feature should
183be enabled, then you will have to either have the renderer inform it at runtime,
184or else just assume that it's always enabled, and gate access to the feature
185from the renderer.
186
187## Testing
188
Steve Kobes6d752cb2019-01-16 01:37:46189To test an origin trial feature during development, follow these steps:
chasejc74a4c9c2017-02-10 20:38:09190
Steve Kobes6d752cb2019-01-16 01:37:461911. Use [generate_token.py] to generate a token signed with the test private key.
192 You can generate signed tokens for any origin that you need to help you test,
193 including localhost or 127.0.0.1. Example:
chasejc74a4c9c2017-02-10 20:38:09194
Steve Kobes6d752cb2019-01-16 01:37:46195 ```
196 tools/origin_trials/generate_token.py http://localhost:8000 MyFeature
197 ```
chasejc74a4c9c2017-02-10 20:38:09198
Jason Chasedbd8b9732020-11-26 17:18:43199 There are additional flags to generate third-party tokens, set the expiry
200 date, and control other options. See the command help for details (`--help`).
201 For example, to generate a third-party token, with [user subset exclusion]:
202
203 ```
204 tools/origin_trials/generate_token.py --is-third-party --usage-restriction=subset http://localhost:8000 MyFeature
205 ```
206
Steve Kobes6d752cb2019-01-16 01:37:462072. Copy the token from the end of the output and use it in a `<meta>` tag or
208 an `Origin-Trial` header as described in the [Developer Guide].
chasejc74a4c9c2017-02-10 20:38:09209
Steve Kobes6d752cb2019-01-16 01:37:462103. Run Chrome with the test public key by passing:
211 `--origin-trial-public-key=dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=`
212
Andrii Sagaidakdbc6a772019-12-12 03:43:39213You can also run Chrome with both the test public key and the default public key along side by passing:
214`--origin-trial-public-key=dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=,fMS4mpO6buLQ/QMd+zJmxzty/VQ6B1EUZqoCU04zoRU=`
215
Steve Kobes6d752cb2019-01-16 01:37:46216The `--origin-trial-public-key` switch is not needed with `content_shell`, as it
217uses the test public key by default.
218
219The test private key is stored in the repo at `tools/origin_trials/eftest.key`.
220It's also used by Origin Trials unit tests and web tests.
221
222If you cannot set command-line switches (e.g., on Chrome OS), you can also
223directly modify [chrome_origin_trial_policy.cc].
chasejc74a4c9c2017-02-10 20:38:09224
Mason Freed9ee18c762020-08-18 20:57:21225To see additional information about origin trial token parsing (including reasons
226for failures, or token names for successful tokens), you can add these switches:
227
228 `--vmodule=trial_token=2,origin_trial_context=1`
229
230If you are building with `is_debug=false`, then you will also need to add
231`dcheck_always_on=true` to your build options, and add this to the command line:
232
233 `--enable-logging=stderr`
234
235
Kent Tamura59ffb022018-11-27 05:30:56236### Web Tests
Allen Robinsonb0efcfa2019-06-25 13:24:04237When using the \[RuntimeEnabled\] IDL attribute, you should add web tests
Ian Clellanda94fcfb2017-07-20 03:43:48238to verify that the V8 bindings code is working as expected. Depending on how
chasej0ac7dd22017-02-23 18:16:17239your feature is exposed, you'll want tests for the exposed interfaces, as well
240as tests for script-added tokens. For examples, refer to the existing tests in
241[origin_trials/webexposed].
242
chasejc74a4c9c2017-02-10 20:38:09243[build_config.h]: /build/build_config.h
244[chrome_origin_trial_policy.cc]: /chrome/common/origin_trials/chrome_origin_trial_policy.cc
chasejc74a4c9c2017-02-10 20:38:09245[generate_token.py]: /tools/origin_trials/generate_token.py
246[Developer Guide]: https://github.com/jpchase/OriginTrials/blob/gh-pages/developer-guide.md
Allen Robinsonb0efcfa2019-06-25 13:24:04247[RuntimeEnabled]: /third_party/blink/renderer/bindings/IDLExtendedAttributes.md#RuntimeEnabled_i_m_a_c
Kent Tamura59ffb022018-11-27 05:30:56248[origin_trials/webexposed]: /third_party/blink/web_tests/http/tests/origin_trials/webexposed/
Kent Tamura6943cf792018-04-09 05:24:54249[runtime\_enabled\_features.json5]: /third_party/blink/renderer/platform/runtime_enabled_features.json5
Lucas Furukawa Gadani6c24cdae2018-04-27 00:28:40250[trial_token_unittest.cc]: /third_party/blink/common/origin_trials/trial_token_unittest.cc
Stephen McGruer2669ba3d2022-05-17 20:38:53251[web\_feature.mojom]: /third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
Ruslan Burakov53cefa72019-05-09 08:22:25252[update\_use\_counter\_feature\_enum.py]: /tools/metrics/histograms/update_use_counter_feature_enum.py
253[Measure]: /third_party/blink/renderer/bindings/IDLExtendedAttributes.md#Measure_i_m_a_c
Rodney Ding533e41a2020-01-15 20:17:18254[css\_properties.json5]: /third_party/blink/renderer/core/css/css_properties.json5
255[origin-trial-test-property]: https://chromium.googlesource.com/chromium/src/+/ff2ab8b89745602c8300322c2a0158e210178c7e/third_party/blink/renderer/core/css/css_properties.json5#2635
256[CSSStyleDeclaration]: /third_party/blink/renderer/core/css/css_style_declaration.idl
Jason Chasedbd8b9732020-11-26 17:18:43257[Running an Origin Trial]: https://www.chromium.org/blink/origin-trials/running-an-origin-trial
258[user subset exclusion]: https://docs.google.com/document/d/1xALH9W7rWmX0FpjudhDeS2TNTEOXuPn4Tlc9VmuPdHA/edit#heading=h.myaz1twlipw