| // 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; |
| }); |
| }; |