summaryrefslogtreecommitdiff
path: root/chromium/docs/origin_trials_integration.md
blob: 396990e84ae8bf1619fe315d3151a1adc8500d9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# Integrating a feature with the origin trials framework

To expose your feature via the origin trials framework, there are a few code
changes required.

[TOC]

## Code Changes

### Runtime Enabled Features

First, you’ll need to configure [runtime\_enabled\_features.json5]. This is
explained in the file, but you use `origin_trial_feature_name` to associate your
runtime feature flag with a name for your origin trial.  The name can be the
same as your runtime feature flag, or different.  Eventually, this configured
name will be used in the origin trials developer console. You can have both
`status: experimental` and `origin_trial_feature_name` if you want your feature
to be enabled either by using the `--enable-experimental-web-platform-features`
flag **or** the origin trial.

You may have a feature that is not available on all platforms, or need to limit
the trial to specific platforms. Use `origin_trial_os: [list]` to specify which
platforms will allow the trial to be enabled. The list values are case-
insensitive, but must match one of the defined `OS_<platform>` macros (see
[build_config.h]).

#### Examples

Flag name and trial name are the same:
```
{
  name: "MyFeature",
  origin_trial_feature_name: "MyFeature",
  status: "experimental",
},
```
Flag name and trial name are different:
```
{
  name: "MyFeature",
  origin_trial_feature_name: "MyFeatureTrial",
  status: "experimental",
},
```
Trial limited to specific platform:
``` json
{
  name: "MyFeature",
  origin_trial_feature_name: "MyFeature",
  origin_trial_os: ["android"],
  status: "experimental",
},
```

### CSS Properties

You can also run experiment for new CSS properties with origin trial. After you
have configured your feature in [runtime\_enabled\_features.json5] as above, head
to [css\_properties.json5]. As explained in the file, you use `runtime_flag` to associate
the CSS property with the feature you just defined. This will automatically link the CSS
property to the origin trial defined in the runtime feature. It will be available
in both JavaScript (`Element.style`) and CSS (including `@supports`) when the trial
is enabled.


**Example:** [origin-trial-test-property] defines a test css property controlled via
runtime feature `OriginTrialsSampleAPI` and subsequently an origin trial named `Frobulate`.

### Gating Access

Once configured, there are two mechanisms to gate access to your feature behind
an origin trial. You can use either mechanism, or both, as appropriate to your
feature implementation.

1. A native C++ method that you can call in Blink code at runtime to expose your
    feature: `bool RuntimeEnabledFeatures::MyFeatureEnabled(ExecutionContext*)`
2. An IDL attribute \[[RuntimeEnabled]\] that you can use to automatically
    generate code to expose and hide JavaScript methods/attributes/objects.
```
[RuntimeEnabled=MyFeature]
partial interface Navigator {
     readonly attribute MyFeatureManager myFeature;
}
```

**NOTE:** Your feature implementation must not persist the result of the enabled
check. Your code should simply call
`RuntimeEnabledFeatures::MyFeatureEnabled(ExecutionContext*)` as often as
necessary to gate access to your feature.

**NOTE:** For CSS properties, you do not need to edit the IDL files, as the exposure
on the [CSSStyleDeclaration] is handled at runtime.

**ISSUE:** In the rare cases where the origin trial token is added via script after
the css style declaration, the css property will be enabled and is fully functional,
however it will not appear on the [CSSStyleDeclaration] interface, i.e. not accessible
in `Element.style`. This issue is tracked in crbug/1041993.

### Web Feature Counting

Once the feature is created, in order to run the origin trial you need to track
how often users use your feature. You can do it in two ways.

#### Increment counter in your c++ code.

1. Add your feature counter to end of [web\_feature.mojom]:

```
enum WebFeature {
  // ...
  kLastFeatureBeforeYours = 1235,
  // Here, increment the last feature count before yours by 1.
  kMyFeature = 1236,

  kNumberOfFeatures,  // This enum value must be last.
};
```
2. Run [update\_use\_counter\_feature\_enum.py] to update the UMA mapping.

3. Increment your feature counter in c++ code.
```c++
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"

// ...

  if (RuntimeEnabledFeatures::MyFeatureEnabled(context)) {
    UseCounter::Count(context, WebFeature::kMyFeature);
  }
```

#### Update counter with \[Measure\] IDL attribute

1. Add \[[Measure]\] IDL attribute
```
partial interface Navigator {
  [RuntimeEnabled=MyFeature, Measure]
  readonly attribute MyFeatureManager myFeature;
```

2. The code to increment your feature counter will be generated in V8
    automatically. But it requires you to follow \[[Measure]\] IDL attribute
    naming convention when you will add your feature counter to
    [web\_feature.mojom].
```
enum WebFeature {
  // ...
  kLastFeatureBeforeYours = 1235,
  // Here, increment the last feature count before yours by 1.
  kV8Navigator_MyFeature_AttributeGetter = 1236,

  kNumberOfFeatures,  // This enum value must be last.
};
```

## Limitations

What you can't do, because of the nature of these origin trials, is know at
either browser or renderer startup time whether your feature is going to be used
in the current page/context. This means that if you require lots of expensive
processing to begin (say you index the user's hard drive, or scan an entire city
for interesting weather patterns,) that you will have to either do it on browser
startup for *all* users, just in case it's used, or do it on first access. (If
you go with first access, then only people trying the experiment will notice the
delay, and hopefully only the first time they use it.). We are investigating
providing a method like `OriginTrials::myFeatureShouldInitialize()` that will
hint if you should do startup initialization.  For example, this could include
checks for trials that have been revoked (or throttled) due to usage, if the
entire origin trials framework has been disabled, etc.  The method would be
conservative and assume initialization is required, but it could avoid expensive
startup in some known scenarios.

Similarly, if you need to know in the browser process whether a feature should
be enabled, then you will have to either have the renderer inform it at runtime,
or else just assume that it's always enabled, and gate access to the feature
from the renderer.

## Testing

To test an origin trial feature during development, follow these steps:

1. Use [generate_token.py] to generate a token signed with the test private key.
   You can generate signed tokens for any origin that you need to help you test,
   including localhost or 127.0.0.1. Example:

      ```
      tools/origin_trials/generate_token.py http://localhost:8000 MyFeature
      ```

2. Copy the token from the end of the output and use it in a `<meta>` tag or
   an `Origin-Trial` header as described in the [Developer Guide].

3. Run Chrome with the test public key by passing:
   `--origin-trial-public-key=dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=`

You can also run Chrome with both the test public key and the default public key along side by passing:
`--origin-trial-public-key=dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=,fMS4mpO6buLQ/QMd+zJmxzty/VQ6B1EUZqoCU04zoRU=`

The `--origin-trial-public-key` switch is not needed with `content_shell`, as it
uses the test public key by default.

The test private key is stored in the repo at `tools/origin_trials/eftest.key`.
It's also used by Origin Trials unit tests and web tests.

If you cannot set command-line switches (e.g., on Chrome OS), you can also
directly modify [chrome_origin_trial_policy.cc].

### Web Tests
When using the \[RuntimeEnabled\] IDL attribute, you should add web tests
to verify that the V8 bindings code is working as expected. Depending on how
your feature is exposed, you'll want tests for the exposed interfaces, as well
as tests for script-added tokens. For examples, refer to the existing tests in
[origin_trials/webexposed].

[build_config.h]: /build/build_config.h
[chrome_origin_trial_policy.cc]: /chrome/common/origin_trials/chrome_origin_trial_policy.cc
[generate_token.py]: /tools/origin_trials/generate_token.py
[Developer Guide]: https://github.com/jpchase/OriginTrials/blob/gh-pages/developer-guide.md
[RuntimeEnabled]: /third_party/blink/renderer/bindings/IDLExtendedAttributes.md#RuntimeEnabled_i_m_a_c
[origin_trials/webexposed]: /third_party/blink/web_tests/http/tests/origin_trials/webexposed/
[runtime\_enabled\_features.json5]: /third_party/blink/renderer/platform/runtime_enabled_features.json5
[trial_token_unittest.cc]: /third_party/blink/common/origin_trials/trial_token_unittest.cc
[web\_feature.mojom]: /third_party/blink/public/mojom/web_feature/web_feature.mojom
[update\_use\_counter\_feature\_enum.py]: /tools/metrics/histograms/update_use_counter_feature_enum.py
[Measure]: /third_party/blink/renderer/bindings/IDLExtendedAttributes.md#Measure_i_m_a_c
[css\_properties.json5]: /third_party/blink/renderer/core/css/css_properties.json5
[origin-trial-test-property]: https://chromium.googlesource.com/chromium/src/+/ff2ab8b89745602c8300322c2a0158e210178c7e/third_party/blink/renderer/core/css/css_properties.json5#2635
[CSSStyleDeclaration]: /third_party/blink/renderer/core/css/css_style_declaration.idl