rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 1 | # Extension Features Files |
| 2 | |
| 3 | [TOC] |
| 4 | |
| 5 | ## Summary |
| 6 | |
| 7 | The Extension features files specify the different requirements for extension |
| 8 | feature availability. |
| 9 | |
| 10 | An **extension feature** can be any component of extension capabilities. Most |
| 11 | notably, this includes extension APIs, but there are also more structural or |
| 12 | behavioral features, such as web accessible resources or event pages. |
| 13 | |
| 14 | ## Files |
| 15 | |
| 16 | There are four different feature files used: |
| 17 | * [\_api\_features](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/_api_features.json): |
| 18 | Specifies the requirements for API availability. If an extension doesn't satisfy |
| 19 | the requirements, the API will not be accessible in the extension's code. |
| 20 | * [\_permission\_features](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/_permission_features.json): |
| 21 | Specifies the requirements for permission availability. If an extension doesn't |
| 22 | satisfy the requirements, the permission will not be granted and the extension |
| 23 | will have an install warning. |
| 24 | * [\_manifest\_features](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/_manifest_features.json): |
| 25 | Specifies the requirements for manifest entry availability. If an extension |
| 26 | doesn't satisfy the requirements, the extension will fail to load with an error. |
emaxx | 08b41b0 | 2017-05-22 20:38:45 | [diff] [blame] | 27 | * [\_behavior\_features](https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/_behavior_features.json): |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 28 | Specifies the requirements for miscellaneous extension behaviors. This should |
| 29 | typically not be used. |
| 30 | |
| 31 | Note that these files may be present under chrome/common/extensions/api, as well |
| 32 | as under extensions/common/api and extensions/shell/common/api. |
| 33 | |
| 34 | ## Grammar |
| 35 | |
| 36 | The feature files are written in JSON. Each file contains a single JSON object |
| 37 | with properties for each feature. |
| 38 | |
| 39 | ``` |
| 40 | { |
| 41 | "feature1": <definition>, |
| 42 | "feature2": <definition>, |
| 43 | ... |
| 44 | } |
| 45 | ``` |
| 46 | |
| 47 | ### Simple and Complex Features |
| 48 | |
| 49 | Most features are known as "simple" features. These are features whose |
| 50 | definition is a single object that contains the properties describing the |
| 51 | criteria for availability. A simple feature might look like this: |
| 52 | ``` |
| 53 | "feature1": { |
| 54 | "dependencies": ["permission:feature1"], |
| 55 | "contexts": ["blessed_extension"] |
| 56 | } |
| 57 | ``` |
| 58 | `feature1` has a single definition, which says for it to be available, a |
| 59 | permission must be present and it must be executed from a blessed context. |
| 60 | (These concepts are covered more later in this document.) |
| 61 | |
| 62 | Features can also be "complex". A complex feature has a list of objects to |
| 63 | specify multiple groups of possible properties. A complex feature could look |
| 64 | like this: |
| 65 | ``` |
| 66 | "feature1": [{ |
| 67 | "dependencies": ["permission:feature1"], |
| 68 | "contexts": ["blessed_extension"] |
| 69 | }, { |
| 70 | "dependencies": ["permission:otherPermission"], |
| 71 | "contexts": ["blessed_extension", "unblessed_extension"] |
| 72 | }] |
| 73 | ``` |
| 74 | |
| 75 | With complex features, if either of the definitions are matched, the feature |
| 76 | is available (in other words, the feature definitions are logically OR'd |
| 77 | together). Complex features should frequently be avoided, as it makes the |
| 78 | logic more involved and slower. |
| 79 | |
| 80 | ### Inheritance |
| 81 | |
| 82 | By default, features inherit from parents. A feature's ancestry is specified by |
| 83 | its name, where a child feature is the parent's name followed by a '.' and the |
| 84 | child's name. That is, `feature1.child` is the child of `feature1`. Inheritance |
| 85 | can carry for multiple levels (e.g. `feature1.child.child`), but this is rarely |
| 86 | (if ever) useful. |
| 87 | |
| 88 | A child feature inherits all the properties of its parent, but can choose to |
| 89 | override them or add additional properties. Take the example: |
| 90 | ``` |
| 91 | "feature1": { |
| 92 | "dependencies": ["permission:feature1"], |
| 93 | "contexts": ["blessed_extension"] |
| 94 | }, |
| 95 | "feature1.child": { |
| 96 | "contexts": ["unblessed_extension"], |
| 97 | "extension_types": ["extension"] |
| 98 | } |
| 99 | ``` |
| 100 | |
| 101 | In this case, `feature1.child` will effectively have the properties |
| 102 | ``` |
| 103 | "dependencies": ["permission:feature1"], # inherited from feature1 |
| 104 | "contexts": ["unblessed_extension"], # inherited value overridden by child |
| 105 | "extension_types": ["extension] # specified by child |
| 106 | ``` |
| 107 | |
| 108 | If you don't want a child to inherit any features from the parent, add the |
| 109 | property `"noparent": true`. This is useful if, for instance, you have a |
| 110 | prefixed API name that isn't dependent on the prefix, such as app.window |
| 111 | (which is fully separate from the app API). |
| 112 | |
| 113 | If the parent of a feature is a complex feature, the feature system needs to |
| 114 | know which parent to inherit from. To do this, add the property |
| 115 | `"default_parent": true` to one of the feature definitions in the parent |
| 116 | feature. |
| 117 | |
| 118 | ## Properties |
| 119 | |
| 120 | The following properties are supported in the feature system. |
| 121 | |
tbarzic | feb4b05 | 2016-11-29 18:23:09 | [diff] [blame] | 122 | ### alias |
| 123 | |
| 124 | The `alias` property specifies that the feature has an associated alias feature. |
| 125 | An alias feature is a feature that provides the same functionality as it's |
| 126 | source feature (i.e. the feature referenced by the alias). For example, an API |
| 127 | alias provides bindings for the source API under a different name. If one wanted |
| 128 | to declare an API alias, they would have to introduce an API alias feature - |
| 129 | defined as a feature that has `source` property, and set `alias` property on |
| 130 | the original feature. For example, the following would introduce an API alias |
| 131 | feature named `featureAlias` for API `feature`: |
| 132 | ```none |
| 133 | { |
| 134 | "feature": { |
| 135 | "contexts": ["blessed_extension"], |
| 136 | "channel": "dev", |
| 137 | "alias": "featureAlias" |
| 138 | }, |
| 139 | "featureAlias": { |
| 140 | "contexts": ["blessed_extension"], |
| 141 | "channel": "dev", |
| 142 | "source": "feature" |
| 143 | } |
| 144 | } |
| 145 | ``` |
| 146 | `featureAlias[source]` value specifies that `featureAlias` is an alias for API |
| 147 | feature `feature` |
| 148 | |
| 149 | `feature[alias]` value specifies that `feature` API has an API alias |
| 150 | `featureAlias` |
| 151 | |
| 152 | When feature `featureAlias` is available, `feature` bindings would be accessible |
| 153 | using `feauteAlias`. In other words `chrome.featureAlias` would point to an API |
| 154 | with the bindings equivalent to the bindings of `feature` API. |
| 155 | |
| 156 | The alias API will inherit the schema from the source API, but it will not |
| 157 | respect the source API child features. To accomplish parity with the source API |
| 158 | feature children, identical child features should be added for the alias API. |
| 159 | |
| 160 | Note that to properly create an alias, both `source` property on the alias |
| 161 | feature and `alias` property on the aliased feature have to be set. |
| 162 | |
| 163 | Alias features are only available for API features, and each API can have at |
| 164 | most one alias. |
| 165 | For complex features, `alias` property will be set to the `alias` value of the |
| 166 | first component simple feature that has it set. |
| 167 | |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 168 | ### blacklist |
| 169 | |
| 170 | The `blacklist` property specifies a list of ID hashes for extensions that |
rdevlin.cronin | 1d458519 | 2016-08-22 22:34:28 | [diff] [blame] | 171 | cannot access a feature. See ID Hashes in this document for how to generate |
| 172 | these hashes. |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 173 | |
| 174 | Accepted values are lists of id hashes. |
| 175 | |
| 176 | ### channel |
| 177 | |
| 178 | The `channel` property specifies a maximum channel for the feature availability. |
| 179 | That is, specifying `dev` means that the feature is available on `dev`, |
| 180 | `canary`, and `trunk`. |
| 181 | |
| 182 | Accepted values are a single string from `trunk`, `canary`, `dev`, `beta`, and |
| 183 | `stable`. |
| 184 | |
| 185 | ### command\_line\_switch |
| 186 | |
| 187 | The `command_line_switch` property specifies a command line switch that must be |
| 188 | present for the feature to be available. |
| 189 | |
| 190 | Accepted values are a single string for the command line switch (without the |
| 191 | preceeding '--'). |
| 192 | |
| 193 | ### component\_extensions\_auto\_granted |
| 194 | |
| 195 | The `component_extensions_auto_granted` specifies whether or not component |
| 196 | extensions should be automatically granted access to the feature. By default, |
| 197 | this is `true`. |
| 198 | |
| 199 | The only accepted value is the bool `false` (since true is the default). |
| 200 | |
| 201 | ### contexts |
| 202 | |
| 203 | The `contexts` property specifies which JavaScript contexts can access the |
| 204 | feature. All API features must specify at least one context, and only API |
| 205 | features can specify contexts. |
| 206 | |
| 207 | Accepted values are a list of strings from `blessed_extension`, |
| 208 | `blessed_web_page`, `content_script`, `extension_service_worker`, |
tbarzic | 8e89b0b1 | 2017-06-10 03:25:51 | [diff] [blame] | 209 | `lock_screen_extension`, `web_page`, `webui`, and `unblessed_extension`. |
| 210 | |
| 211 | The `lock_screen_extension` context is used instead of `blessed_extension` |
| 212 | context for extensions on the Chrome OS lock screen. Other extensions related |
| 213 | contexts (`blessed_web_page`, `content_script`, `extension_service_worker`, |
| 214 | `unblessed_extension`) are not expected to be present on the lock screen. |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 215 | |
| 216 | ### default\_parent |
| 217 | |
| 218 | The `default_parent` property specifies a feature definition from a complex |
| 219 | feature to be used as the parent for any children. See also Inheritance. |
| 220 | |
| 221 | The only accepted value is the bool `true`. |
| 222 | |
| 223 | ### dependencies |
| 224 | |
| 225 | The `dependencies` property specifies which other features must be present in |
| 226 | order to access this feature. This is useful so that you don't have to |
| 227 | re-specify all the same properties on an API feature and a permission feature. |
| 228 | |
| 229 | A common practice is to put as many restrictions as possible in the |
| 230 | permission or manifest feature so that we warn at extension load, and put |
| 231 | relatively limited properties in an API feature with a dependency on the |
| 232 | manifest or permission feature. |
| 233 | |
| 234 | To specify a dependent feature, use the prefix the feature name with the type |
| 235 | of feature it is, followed by a colon. For example, in order to specify a |
| 236 | dependency on a permission feature `foo`, we would add the dependency entry |
| 237 | `permission:foo`. |
| 238 | |
| 239 | Accepted values are lists of strings specifying the dependent features. |
| 240 | |
| 241 | ### extension\_types |
| 242 | |
| 243 | The `extension_types` properties specifies the different classes of extensions |
| 244 | that can use the feature. It is very common for certain features to only be |
| 245 | allowed in certain extension classes, rather than available to all types. |
| 246 | |
| 247 | Accepted values are lists of strings from `extension`, `hosted_app`, |
Alexander Hendrich | 33ec65ee | 2019-05-21 09:29:13 | [diff] [blame] | 248 | `legacy_packaged_app`, `platform_app`, `shared_module`, `theme`, and |
| 249 | `login_screen_extension`. |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 250 | |
| 251 | ### location |
| 252 | |
| 253 | The `location` property specifies the required install location of the |
| 254 | extension. |
| 255 | |
Kelvin Jiang | 3808510 | 2019-11-01 19:16:39 | [diff] [blame] | 256 | Accepted values are a single string from `component`, `external_component`, |
| 257 | `policy`, and `unpacked`. |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 258 | |
| 259 | ### internal |
| 260 | |
| 261 | The `internal` property specifies whether or not a feature is considered |
| 262 | internal to Chromium. Internal features are not exposed to extensions, and can |
| 263 | only be used from Chromium code. |
| 264 | |
| 265 | The only accepted value is the bool `true`. |
| 266 | |
| 267 | ### matches |
| 268 | |
| 269 | The `matches` property specifies url patterns which should be allowed to access |
| 270 | the feature. Only API features may specify `matches`, and `matches` only make |
| 271 | sense with a context of either `webui` or `web_page`. |
| 272 | |
| 273 | Accepted values are a list of strings specifying the match patterns. |
| 274 | |
| 275 | ### max\_manifest\_version |
| 276 | |
| 277 | The `max_manifest_version` property specifies the maximum manifest version to be |
| 278 | allowed to access a feature. Extensions with a greater manifest version cannot |
| 279 | access the feature. |
| 280 | |
| 281 | The only accepted value is `1`, as currently the highest possible manifest |
| 282 | version is `2`. |
| 283 | |
| 284 | ### min\_manifest\_version |
| 285 | |
| 286 | The `min_manifest_version` property specifies the minimum manifest version to be |
| 287 | allowed to access a feature. Extensions with a lesser manifest version cannot |
| 288 | access the feature. |
| 289 | |
Kelvin Jiang | 8cb8151 | 2019-04-17 19:02:57 | [diff] [blame] | 290 | Accepted values are `2` and `3`, as 3 is currently the highest possible manifest |
| 291 | version. |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 292 | |
| 293 | ### noparent |
| 294 | |
| 295 | The `noparent` property specifies that a feature should not inherit any |
| 296 | properties from a derived parent. See also Inheritance. |
| 297 | |
| 298 | The only accepted value is the bool `true`. |
| 299 | |
| 300 | ### platforms |
| 301 | |
| 302 | The `platforms` property specifies the properties the feature should be |
| 303 | available on. |
| 304 | |
| 305 | The accepted values are lists of strings from `chromeos`, `mac`, `linux`, and |
| 306 | `win`. |
| 307 | |
tbarzic | 64bf38de | 2016-09-15 19:58:14 | [diff] [blame] | 308 | ### session\_types |
| 309 | |
| 310 | The `session_types` property specifies in which types of sessions a feature |
| 311 | should be available. The session type describes the type of user that is |
| 312 | logged in the current session. Session types to which feature can be restricted |
| 313 | are only supported on Chrome OS - features restricted to set of session types |
| 314 | will be disabled on other platforms. Also, note that all currently supported |
| 315 | session types imply that a user is logged into the session (i.e. features that |
tbarzic | feb4b05 | 2016-11-29 18:23:09 | [diff] [blame] | 316 | use `session_types` property will be disabled when a user is not logged in). |
tbarzic | 64bf38de | 2016-09-15 19:58:14 | [diff] [blame] | 317 | |
tbarzic | 5babfd31 | 2017-01-10 20:13:18 | [diff] [blame] | 318 | The accepted values are lists of strings from `regular`, `kiosk` and |
| 319 | `kiosk.autolaunched`. |
| 320 | |
| 321 | `regular` session is a session launched for a regular, authenticated user. |
| 322 | |
| 323 | `kiosk` session is a session launched for a kiosk app - an app that runs on its |
Alexander Hendrich | 33ec65ee | 2019-05-21 09:29:13 | [diff] [blame] | 324 | own, in full control of the current session. |
tbarzic | 5babfd31 | 2017-01-10 20:13:18 | [diff] [blame] | 325 | |
| 326 | `kiosk.autolaunched` represents auto-launched kiosk session - a kiosk session |
| 327 | that is launched automatically from Chrome OS login screen, without any user |
| 328 | interaction. Note that allowing `kiosk` session implies allowing |
| 329 | `kiosk.autolaunched` session. |
tbarzic | 64bf38de | 2016-09-15 19:58:14 | [diff] [blame] | 330 | |
tbarzic | feb4b05 | 2016-11-29 18:23:09 | [diff] [blame] | 331 | ### source |
| 332 | |
| 333 | The `source` property specifies that the feature is an alias for the feature |
| 334 | specified by the property value, and is only allowed for API features. |
tbarzic | 5babfd31 | 2017-01-10 20:13:18 | [diff] [blame] | 335 | For more information about alias features, see [alias](#alias) property |
| 336 | documentation. |
tbarzic | feb4b05 | 2016-11-29 18:23:09 | [diff] [blame] | 337 | |
| 338 | For complex features, `source` property will be set to the `source` value of the |
| 339 | first component simple feature that has it set. |
| 340 | |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 341 | ### whitelist |
| 342 | |
| 343 | The `whitelist` property specifies a list of ID hashes for extensions that |
| 344 | are the only extensions allowed to access a feature. |
| 345 | |
| 346 | Accepted values are lists of id hashes. |
| 347 | |
rdevlin.cronin | 1d458519 | 2016-08-22 22:34:28 | [diff] [blame] | 348 | ## ID Hashes |
| 349 | |
| 350 | Instead of listing the ID directly in the whitelist or blacklist section, we |
| 351 | use an uppercased SHA1 hash of the id. |
| 352 | |
| 353 | To generate a new whitelisted ID for an extension ID, do the following in bash: |
| 354 | ``` |
| 355 | $ echo -n "aaaabbbbccccddddeeeeffffgggghhhh" | \ |
| 356 | sha1sum | tr '[:lower:]' '[:upper:]' |
| 357 | ``` |
| 358 | (Replacing `aaaabbbbccccddddeeeeffffgggghhhh` with your extension ID.) |
| 359 | |
| 360 | The output should be something like: |
| 361 | ``` |
| 362 | 9A0417016F345C934A1A88F55CA17C05014EEEBA - |
| 363 | ``` |
| 364 | |
| 365 | Add the ID to the whitelist or blacklist for the desired feature. It is also |
| 366 | often useful to link the crbug next to the id hash, e.g.: |
| 367 | ``` |
| 368 | "whitelist": [ |
| 369 | "9A0417016F345C934A1A88F55CA17C05014EEEBA" // crbug.com/<num> |
| 370 | ] |
| 371 | ``` |
| 372 | |
| 373 | Google employees: please update http://go/chrome-api-whitelist to map hashes |
| 374 | back to ids. |
| 375 | |
rdevlin.cronin | 06d4e58 | 2016-08-25 20:13:11 | [diff] [blame] | 376 | ## Feature Contexts |
| 377 | |
| 378 | A Feature Context is the type of JavaScript context that a feature can be made |
| 379 | available in. This allows us to restrict certain features to only being |
| 380 | accessible in more secure contexts, or to expose features to contexts outside |
| 381 | of extensions. |
| 382 | |
| 383 | For each of these contexts, an "extension" context can refer to a context of |
| 384 | either an app or an extension. |
| 385 | |
| 386 | ### Blessed Extension Contexts |
| 387 | |
| 388 | The `blessed_extension` context refers to a JavaScript context running from an |
| 389 | extension process. These are typically the most secure JavaScript contexts, as |
| 390 | it reduces the likelihood that a compromised web page renderer will have access |
| 391 | to secure APIs. |
| 392 | |
| 393 | Traditionally, only pages with a top-level extension frame (with a |
| 394 | `chrome-extension://` scheme), extension popups, and app windows were blessed |
| 395 | extension contexts. With [site isolation](https://www.chromium.org/developers/design-documents/site-isolation), |
| 396 | extension frames running in web pages are also considered blessed extension |
| 397 | contexts, since they are running in the extension process (rather than in the |
| 398 | same process as the web page). |
| 399 | |
| 400 | ### Blessed Web Page Contexts |
| 401 | |
| 402 | The `blessed_web_page` context refers to a JavaScript context running from a |
| 403 | hosted app. These are similar to blessed extension contexts in that they are |
| 404 | (partially) isolated from other processes, but are typically more restricted |
| 405 | than blessed extension processes, since hosted apps generally have fewer |
| 406 | permissions. Note that these contexts are unaffected by the `matches` property. |
| 407 | |
| 408 | ### Content Script Contexts |
| 409 | |
| 410 | The `content_script` context refers to a JavaScript context for an extension |
| 411 | content script. Since content scripts share a process with (and run on the same |
| 412 | content as) web pages, these are considered very insecure contexts. Very few |
| 413 | features should be exposed to these contexts. |
| 414 | |
| 415 | ### Service Worker Contexts |
| 416 | |
| 417 | The `extension_service_worker` context refers to a JavaScript context for an |
| 418 | extension's service worker. An extension can only register a service worker for |
| 419 | it's own domain, and these should only be run within an extension process. Thus, |
| 420 | these have similar privilege levels to blessed extension processes. |
| 421 | |
| 422 | ### Web Page Contexts |
| 423 | |
| 424 | The `web_page` context refers to a JavaScript context for a simple web page, |
| 425 | completely separate from extensions. This is the least secure of all contexts, |
| 426 | and very few features should be exposed to these contexts. When specifying this |
| 427 | context, an accompanying URL pattern should be provided with the `matches` |
| 428 | property. |
| 429 | |
| 430 | ### WebUI Contexts |
| 431 | |
| 432 | The `webui` context refers to a JavaScript context for a page with WebUI |
| 433 | bindings, such as internal chrome pages like chrome://settings or |
| 434 | chrome://extensions. These are considered secure contexts, since they are |
| 435 | an internal part of chrome. When specifying this context, an accompanying URL |
| 436 | pattern should be provided with the `matches` property. |
| 437 | |
| 438 | ### Unblessed Extension Contexts |
| 439 | |
| 440 | The `unblessed_extension` context refers to a JavaScript context for an |
| 441 | extension frame that is embedded in an external page, like a web page, and |
| 442 | runs in the same process as the embedder. Given the limited separation between |
| 443 | the (untrusted) embedder and the extension frame, relatively few features are |
| 444 | exposed in these contexts. Note that with [site isolation](https://www.chromium.org/developers/design-documents/site-isolation), |
| 445 | extension frames (even those embedded in web pages) run in the trusted |
| 446 | extension process, and become blessed extension contexts. |
| 447 | |
rdevlin.cronin | 1d458519 | 2016-08-22 22:34:28 | [diff] [blame] | 448 | ## Compilation |
| 449 | |
| 450 | The feature files are compiled as part of the suite of tools in |
| 451 | //tools/json\_schema\_compiler/. The output is a set of FeatureProviders that |
| 452 | contain a mapping of all features. |
| 453 | |
| 454 | In addition to being significantly more performant than parsing the JSON files |
| 455 | at runtime, this has the added benefit of allowing us to validate at compile |
| 456 | time rather than needing a unittest (or allowing incorrect features). |
| 457 | |
| 458 | In theory, invalid features should result in a compilation failure; in practice, |
| 459 | the compiler is probably missing some cases. |
| 460 | |
rdevlin.cronin | 8a23c0c | 2016-08-19 21:44:24 | [diff] [blame] | 461 | ## Still to come |
| 462 | |
rdevlin.cronin | 06d4e58 | 2016-08-25 20:13:11 | [diff] [blame] | 463 | TODO(devlin): Add documentation for extension types. Probably also more on |
| 464 | requirements for individual features. |