blob: 8462757ad2d84f84877011131f68ca17a9138351 [file] [log] [blame] [view]
# Component sandbox features
This section provides guidance on migrating additional CMX
`sandbox` features.
Note: If there's a feature in your CMX file that's not in this list,
please reach out to [component-framework-dev][cf-dev-list].
## Storage features {#storage-features}
If your component uses any of the following features, follow the instructions in
this section to migrate storage access:
| Feature | Description | Storage Capability | Path |
| ----------------------------- | ----------- | ------------------ | -------- |
| `isolated-persistent-storage` | Isolated | `data` | `/data` |
: : persistent : : :
: : storage : : :
: : directory : : :
| `isolated-cache-storage` | Managed | `cache` | `/cache` |
: : persistent : : :
: : storage : : :
: : directory : : :
| `isolated-temp` | Managed | `tmp` | `/tmp` |
: : in-memory : : :
: : storage : : :
: : directory : : :
These features are supported in v2 components using
[storage capabilities][storage-capabilities].
### Declare the required storage capabilities
When [migrating your component manifest][migrate-components], add the
following to your CML file:
```json5
// my_component.cml
{
use: [
...
{
storage: "{{ '<var label="storage">data</var>' }}",
path: "{{ '<var label="storage path">/data</var>' }}",
},
],
}
```
### Route storage from the parent realm
When [adding your component][migrate-components-add], you'll need to offer
the appropriate storage path to your component from its parent realm.
```json5
// core.cml / component.core_shard.cml
{
children: [
...
{
name: "my_component",
url: "fuchsia-pkg://fuchsia.com/my-package#meta/my_component.cm",
},
],
offer: [
...
{{ '<strong>' }}{
storage: "{{ '<var label="storage">data</var>' }}",
from: "self",
to: [ "#my_component" ],
},{{ '</strong>' }}
]
}
```
Note: If the appropriate storage capability is not currently provided by your
component's parent realm, reach out to [component-framework-dev][cf-dev-list]
for assistance.
### Update component ID index
Components that use storage use a [component ID index][component-id-index] to
preserve access to persistent storage contents across the migration, such as
[`core_component_id_index.json5`][example-component-id-index]. You must update
the component index to map the new component moniker to the same instance within
the component that provides the storage capability.
Find any instances of your current v1 component in component index files:
```json5
// core_component_id_index.json5
{
instances: [
...
{
instance_id: "...",
appmgr_moniker: {
url: "fuchsia-pkg://fuchsia.com/my-package#meta/my_component.cmx",
realm_path: [ ... ]
},
},
],
}
```
Replace the `appmgr_moniker` for your component instance with the new moniker in
the migrated v2 realm, keeping the same `instance_id`:
```json5
// core_component_id_index.json5
{
instances: [
...
{
instance_id: "...",
moniker: "/core/my_component",
},
],
}
```
Note: If you are migrating your component to a realm other than `core`, the
moniker should reflect that.
### (Optional) Enable `persistent_storage` for collection descendants using storage
If the component or any of its ancestors, such as the session component, is part
of a collection, and the component requires storage contents to exist after a
component instance has been destroyed, add the
[`persistent_storage`][collection-persistent-storage] setting to the collection
decl:
```json5
{
collections: [
{
name: "my_collection",
durability: "{{ '<var label="durability">durability</var>' }}",
persistent_storage: true,
}
],
}
```
This setting allows collection descendants using the component ID index to
preserve storage content across [dynamic component instances][dynamic-children].
Note: the `persistent_storage` setting will apply to all descendants of the
collection.
### Storage capabilities in tests
When [migrating tests][migrate-tests], you will need to route storage access
to your test component if any of the components in the test realm access a
storage path.
Following the example in [Test uses injected services][migrate-tests-inject],
add the following to route storage access to your test component:
```json5
// my_component_test.cml (test component)
}
use: [
...
{{ '<strong>' }}{
storage: "{{ '<var label="storage">data</var>' }}",
path: "{{ '<var label="storage path">/data</var>' }}",
},{{ '</strong>' }}
],
}
```
Note: Storage capabilities are backed by in-memory storage in tests and contents
will not persist once the test exits.
## Directory features {#directory-features}
If your component uses any of the following features, follow the instructions in
this section to migrate directory access:
Feature | Description | Directory Capability | Path
----------------------- | ------------------------------------------- | ----------------------- | ----
`shell-commands` | Executable directory of shell binaries | `bin` | `/bin`
`root-ssl-certificates` | Read-only root certificate data | `root-ssl-certificates` | `/config/ssl`
These features are supported in v2 components using
[directory capabilities][directory-capabilities].
### Declare the required directory capabilities
When [migrating your component manifest][migrate-components], add the
following to your CML file:
```json5
// my_component.cml
{
use: [
...
{
directory: "{{ '<var label="directory">root-ssl-certificates</var>' }}",
rights: [ "r*" ],
path: "{{ '<var label="directory path">/config/ssl</var>' }}",
},
],
}
```
Note: Unlike storage locations, which are isolated per-component, directories
are a shared resource. You may need to also determine the **subdirectory** your
component needs to access in order to complete this migration.
### Route directory from the parent realm
When [adding your component][migrate-components-add], you'll need to offer
the directory capabilities to your component.
```json5
// core.cml / component.core_shard.cml
{
children: [
...
{
name: "my_component",
url: "fuchsia-pkg://fuchsia.com/my-package#meta/my_component.cm",
},
],
offer: [
...
{{ '<strong>' }}{
directory: "{{ '<var label="directory">root-ssl-certificates</var>' }}",
from: "parent",
to: [ "#my_component" ],
},{{ '</strong>' }}
],
}
```
Note: If the appropriate directory capability is not currently provided by your
component's parent realm, reach out to [component-framework-dev][cf-dev-list]
for assistance.
### Directory paths in tests
When [migrating tests][migrate-tests], you need to route the directory
capabilities to your test component if any of the components in the test realm
require directory access.
Test Runner Framework only allows the following directory capabilities to be
used by non-hermetic tests:
Capability | Description | Path
----------------------- | ------------------------------- | -------------
`root-ssl-certificates` | Read-only root certificate data | `/config/ssl`
Following the example in [Test uses injected services][migrate-tests-inject],
add the following to route directory access to your test component:
```json5
// my_component_test.cml (test component)
{
use: [
...
{{ '<strong>' }}{
directory: "{{ '<var label="directory">root-ssl-certificates</var>' }}",
rights: [ "r*" ],
path: "{{ '<var label="directory path">/config/ssl</var>' }}",
},{{ '</strong>' }}
],
}
```
Note: If the appropriate directory capability is not currently provided by the
Test Runner Framework, reach out to [component-framework-dev][cf-dev-list] for
assistance.
## Configuration data {#config-data}
If your component uses any of the following features, follow the instructions in
this section to migrate directory access:
| Feature | Description | Directory Capability | Path |
| ------------- | ------------------ | -------------------- | -------------- |
| `config-data` | Read-only | `config-data` | `/config/data` |
: : configuration data : : :
These features are supported in v2 components using
[directory capabilities][directory-capabilities].
For more details using data files, see
[product-specific configuration with `config_data()`][config-data].
Consider [packaging your data files hermetically with `resource()`][resource-data]
if your component doesn't need to accept data files from arbitrary parts of the
source tree. Using `resource()` is simpler and more efficient.
### Declare the required directory capabilities
When [migrating your component manifest][migrate-components], add the
following to your CML file:
```json5
// my_component.cml
{
use: [
...
{
directory: "config-data",
rights: [ "r*" ],
path: "/config/data",
},
],
}
```
### Route directory from the parent realm
When [adding your component][migrate-components-add], you'll need to offer
the directory capability with the appropriate subdirectory to your component.
```json5
// core.cml / component.core_shard.cml
{
children: [
...
{
name: "my_component",
url: "fuchsia-pkg://fuchsia.com/my-package#meta/my_component.cm",
},
],
offer: [
...
{{ '<strong>' }}{
directory: "config-data",
from: "parent",
to: [ "#my_component" ],
subdir: "{{ '<var label="package name">my-package</var>' }}",
},{{ '</strong>' }}
],
}
```
### Configuration data in tests
When [migrating tests][migrate-tests], you need to route the directory
capability with the appropriate subdirectory to your test component if any of
the components in the test realm require directory access.
The name of the subdirectory should match the name of the package that contains
the component.
Following the example in [Test uses injected services][migrate-tests-inject],
add the following to route directory access to your test component:
```json5
// my_component_test.cml (test component)
{
use: [
...
{{ '<strong>' }}{
directory: "config-data",
rights: [ "r*" ],
path: "/config/data",
subdir: "{{ '<var label="package name">my-package</var>' }}",
},{{ '</strong>' }}
],
}
```
## Device directories {#devices}
If your component uses any of the following features, follow the instructions in
this section to migrate device access:
Feature | Description | Path
------- | ------------------------------------------------ | -------------------------
`dev` | Entries in `devfs` | `/dev/*`
`dev` | [Legacy device entries](#legacy-device-entries) | `/dev/null`, `/dev/zero`
[Device filesystem][device-model] access is supported in Components v2 using
[directory capabilities][directory-capabilities].
Consider the following example using Components v1 to access
`/dev/class/input-report`:
```json
// my_component.cmx
{
"program": { ... },
"sandbox": {
"dev": [
"{{ '<var label="device subpath">class/input-report</var>' }}"
]
}
}
```
### Declare the required device capabilities
When [migrating your component manifest][migrate-components], add the
device path as a directory capability to your CML file:
```json5
// my_component.cml
{
use: [
...
{
directory: "{{ '<var label="device">dev-input-report</var>' }}",
rights: [ "r*" ],
path: "/dev/{{ '<var label="device subpath">class/input-report</var>' }}",
},
],
}
```
### Route device subdirectory from the parent realm
When [adding your component][migrate-components-add], you'll need to offer
the appropriate device path to your component from its parent realm.
```json5
// core.cml / component.core_shard.cml
{
children: [
...
{
name: "my_component",
url: "fuchsia-pkg://fuchsia.com/my-package#meta/my_component.cm",
},
],
offer: [
...
{{ '<strong>' }}{
directory: "dev-dev",
from: "parent",
as: "{{ '<var label="device">dev-input-report</var>' }}",
to: [ "#my_component" ],
subdir: "{{ '<var label="device subpath">input-report</var>' }}",
},{{ '</strong>' }}
],
}
```
### Legacy device entries {#legacy-device-entries}
Components v2 does not route the following pseudo-device entries to components:
* `/dev/zero`: Create an equivalent (pseudo-)file in your code if necessary.
For example, see the Chromium [`ScopedDevZero`][scoped-dev-zero-fuchsia]
implementation.
* `/dev/null`: Use [fdio_fd_null_create] to get a file descriptor to a file
that acts like `/dev/null`.
### Device directories in tests
When [migrating tests][migrate-tests], you need to route the directory
capabilities to your test component if any of the components in the test realm
require directory access.
Test Runner Framework only allows the following device directories to be used by
non-hermetic tests:
Capability | Description
------------------------------ | -----------------------------
`dev-input` | Input
`dev-input-report` | Input method events
`dev-display-controller` | Graphical display controller
`dev-goldfish-address-space` | Goldfish address space device
`dev-goldfish-control` | Goldfish control device
`dev-goldfish-pipe` | Goldfish pipe device
`dev-gpu` | GPU device
`dev-gpu-performance-counters` | GPU performance counters device
Following the example in [Test uses injected services][migrate-tests-inject],
add the following to route directory access to your test component:
```json5
// my_component_test.cml (test component)
{
use: [
...
{{ '<strong>' }}{
directory: "{{ '<var label="device">dev-input-report</var>' }}",
rights: [ "r*" ],
path: "/dev/{{ '<var label="device subpath">class/input-report</var>' }}",
},{{ '</strong>' }}
],
}
```
Note: If the appropriate device directory is not currently provided by the Test
Runner Framework, reach out to [component-framework-dev][cf-dev-list] for
assistance.
## Event capabilities {#events}
If your component uses any of the following features, follow the instructions in
this section:
Feature | Description | Path
------- | -------------------------------- | ----------
`hub` | Observing component path changes | `/hub/c/*`
`hub` | Observing realm path changes | `/hub/r/*`
These features are supported in v2 components using
[event capabilities][event-capabilities].
### Event sources in tests
When [migrating tests][migrate-tests], you'll need to inject any components you
wish to observe into the test realm and route the appropriate lifecycle events
for those components to your test component.
Following the example in [Test uses injected services][migrate-tests-inject],
route the `fuchsia.sys2.EventSource` capability and the appropriate events to
your test component:
```json5
// my_component_test.cml (test component)
{
children: [
{
name: "my_component",
url: "fuchsia-pkg://fuchsia.com/my-package#meta/my_component.cm",
},
],
use: [
{
protocol: [ "fuchsia.sys2.EventSource" ],
},
{
event: [ "{{ '<var label="event name">started</var>' }}" ],
from: "framework",
modes: [ "async" ],
},
],
}
```
Note: The `EventSource` capability comes from the test realm (`parent`), but the
events come from the Component Manager (`framework`). This sets the event scope
to only components in the test realm. For more details on event scope,
see [event-capabilities][event-capabilities].
## Build Info {#build-info}
When migrating the `build-info` feature, instead use the
`fuchsia.buildinfo.Provider` [protocol][build-info-fidl]. This protocol is the
only supported method of retrieving build information moving forward. To use
this protocol, add it [while declaring required services][migrate-components-services].
## Vulkan {#vulkan}
When migrating the `vulkan` feature or code that uses a `//src/lib/vulkan/*.shard.cmx`
shard, instead use the `vulkan/client.shard.cml` [shard][manifests-shard] as
described in the [Vulkan documentation][vulkan].
## What's next {#next}
Explore the following sections for additional migration guidance on
specific features your components may support:
- [Diagnostics capabilities](diagnostics.md)
- [Other common situations](common.md)
[build-info-fidl]: https://fuchsia.dev/reference/fidl/fuchsia.buildinfo#Provider
[cf-dev-list]: https://groups.google.com/a/fuchsia.dev/g/component-framework-dev
[collection-persistent-storage]: https://fuchsia.dev/reference/fidl/fuchsia.component.decl#Collection.persistent_storage
[component-id-index]: /docs/development/components/component_id_index.md
[config-data]: /docs/development/components/configuration/config_data.md
[device-model]: /docs/development/drivers/concepts/device_driver_model/device-model.md
[directory-capabilities]: /docs/concepts/components/v2/capabilities/directory.md
[dynamic-children]: /docs/concepts/components/v2/realms.md#dynamic-children
[event-capabilities]: /docs/concepts/components/v2/capabilities/event.md
[example-component-id-index]: /src/sys/core/core_component_id_index.json5
[fdio_fd_null_create]: /sdk/lib/fdio/include/lib/fdio/fdio.h#48
[manifests-shard]: /docs/development/components/build.md#component-manifest-shards
[migrate-components]: /docs/development/components/v2/migration/components.md
[migrate-components-add]: /docs/development/components/v2/migration/components.md#add-component-to-topology
[migrate-components-services]: /docs/development/components/v2/migration/components.md#required-services
[migrate-tests]: /docs/development/components/v2/migration/tests.md
[migrate-tests-inject]: /docs/development/components/v2/migration/tests.md#injected-services
[resource-data]: /docs/development/components/data.md#hermetic_data_files_with_resource
[scoped-dev-zero-fuchsia]: https://source.chromium.org/chromium/chromium/src/+/main:base/test/scoped_dev_zero_fuchsia.cc
[storage-capabilities]: /docs/concepts/components/v2/capabilities/storage.md
[vulkan]: /docs/development/graphics/magma/concepts/vulkan.md#components_v2