blob: 0b5c387296cbea5c97d66205c17dd5bb9e3e419a [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.component.sandbox;
using zx;
using fuchsia.io;
using fuchsia.unknown;
/// Maximum number of bytes in a [DataCapability].
const MAX_DATA_LENGTH uint32 = 8192;
/// Maximum number of items returned by [DictionaryIterator].
const MAX_DICTIONARY_ITEMS_CHUNK uint32 = 128;
@available(added=HEAD)
closed protocol HandleCapability {
compose fuchsia.unknown.Cloneable;
strict GetHandle() -> (resource struct {
handle zx.Handle;
}) error @generated_name("HandleCapabilityError") strict enum {
UNAVAILABLE = 1;
};
};
@available(added=HEAD)
type DataCapability = flexible union {
1: bytes vector<byte>:MAX_DATA_LENGTH;
2: string string:MAX_DATA_LENGTH;
3: int64 int64;
4: uint64 uint64;
};
@available(added=HEAD)
type Capability = flexible resource union {
1: unit @generated_name("UnitCapability") struct {};
2: handle client_end:HandleCapability;
3: data DataCapability;
4: cloneable client_end:fuchsia.unknown.Cloneable;
5: dictionary client_end:Dictionary;
6: sender client_end:Sender;
7: directory client_end:fuchsia.io.Directory;
};
/// The maximum length of a dictionary key. This should coincide with
/// fuchsia.component.MAX_NAME_LENGTH.
@available(added=HEAD)
const MAX_NAME_LENGTH uint64 = fuchsia.io.MAX_NAME_LENGTH;
/// The key of a [`DictionaryItem`]. The constraints for valid keys are documented at
/// https://fuchsia.dev/reference/cml#names.
@available(added=HEAD)
alias DictionaryKey = string:MAX_NAME_LENGTH;
/// A key-value pair in a [`Dictionary`].
@available(added=HEAD)
type DictionaryItem = resource struct {
key DictionaryKey;
value Capability;
};
/// Error returned from methods in [`Dictionary`].
@available(added=HEAD)
type DictionaryError = flexible enum {
/// The Dictionary does not contain an item with the given key.
NOT_FOUND = 1;
/// The Dictionary already contains an item with the given key.
ALREADY_EXISTS = 2;
/// The Capability is invalid.
///
/// Capabilites must be created by sandbox, via
/// `fuchsia.component.sandbox.Factory` or returned from other
/// Component Framework APIs.
BAD_CAPABILITY = 3;
/// The key is invalid. The constraints for valid keys are documented at
/// https://fuchsia.dev/reference/cml#names.
INVALID_KEY = 4;
};
@discoverable
@available(added=20)
open protocol Dictionary {
/// Creates a new connection to the same underlying dictionary.
///
/// Use `Copy` to a new dictionary with clones of all the exiting entries.
compose fuchsia.unknown.Cloneable;
/// Inserts a key-value pair into the dictionary.
///
/// * error `DictionaryError.ALREADY_EXISTS` if the dictionary already contains an
/// item with the same key.
@available(added=HEAD)
flexible Insert(DictionaryItem) -> () error DictionaryError;
/// Get a clone of a capability from this dictionary.
///
/// * error `DictionaryError.NOT_FOUND` if the dictionary does not contain the key.
@available(added=HEAD)
flexible Get(struct {
key DictionaryKey;
}) -> (resource struct {
capability Capability;
}) error DictionaryError;
/// Removes a key from the dictionary, returning the [`Capability`] value.
///
/// * error `DictionaryError.NOT_FOUND` if the dictionary does not contain the key.
@available(added=HEAD)
flexible Remove(struct {
key DictionaryKey;
}) -> (resource struct {
capability Capability;
}) error DictionaryError;
/// Returns all items in this dictionary, sorted by key in natural order.
///
/// This operation creates shallow clones of values.
// TODO(b/314361448): Remove once callers use Dictionary.Enumerate instead
@available(added=HEAD)
flexible Read() -> (resource struct {
items vector<DictionaryItem>:MAX;
});
/// Create a new dictionary that contains a clone of all the entries in
/// this dictionary.
///
/// For example, if this dictionary contains nested dictionaries, the newly
/// created dictionary will contain references to those same nested
/// dictionaries because the entries are cloned rather than copied.
@available(added=HEAD)
flexible Copy(resource struct {
request server_end:Dictionary;
});
/// Enumerates the entries in this dictionary.
///
/// Creates a clone of each item during enumeration.
@available(added=HEAD)
flexible Enumerate(resource struct {
contents server_end:DictionaryIterator;
});
/// Removes all the entries in this dictionary.
///
/// If `contents` is not provided, all the items are discarded without
/// enumerating them.
@available(added=HEAD)
flexible Drain(resource struct {
contents server_end:<DictionaryIterator, optional>;
});
};
@available(added=HEAD)
open protocol DictionaryIterator {
flexible GetNext() -> (resource struct {
items vector<DictionaryItem>:MAX_DICTIONARY_ITEMS_CHUNK;
});
};
/// A sender allows a client to send a channel to the framework
/// so that it can be connected.
@discoverable
@available(added=HEAD)
open protocol Sender {
compose fuchsia.unknown.Cloneable;
/// Sends a channel over this sender.
flexible Send(ProtocolPayload);
};
/// A receiver is served by clients and allows them to receive channels
/// from the framework.
@discoverable
@available(added=HEAD)
open protocol Receiver {
/// Sends a channel to this receiver.
flexible Receive(ProtocolPayload);
};
/// Contains a protocol open request.
@available(added=HEAD)
type ProtocolPayload = resource struct {
channel zx.Handle:CHANNEL;
};
/// Entrypoint for instantiation of sandbox types.
@discoverable
@available(added=HEAD)
open protocol Factory {
/// Creates a `Sender` from a client served `Receiver`.
flexible CreateSender(resource struct {
receiver client_end:Receiver;
}) -> (resource struct {
sender client_end:Sender;
});
/// Creates a new empty [`Dictionary`].
flexible CreateDictionary() -> (resource struct {
dictionary client_end:Dictionary;
});
/// Creates a [`Directory`] capability from a [`client_end:fuchsia.io.Directory`], and
/// registers it as a sandbox capability.
// TODO(https://fxbug.dev/329496030): Currently if users want to create a `Directory` capability
// externally, they have to use this, they can't just create a `Capability::Directory` directly.
// Decide what the policy should be.
flexible CreateDirectory(resource struct {
client_end client_end:fuchsia.io.Directory;
}) -> (resource struct {
capability Capability;
});
};