# SDK Extended Preferences

> Configure browser instances, read and write application data, and understand the License and signature rules for Extended Preferences.

Source: https://console.getchrovia.com/en/docs/sdk-extended-preferences

**Extended Preferences** is a JSON file named exactly `Extended Preferences`, without `.json`, in the directory passed to `--user-data-dir`. It is separate from Chromium's ordinary `Preferences` file and from `Chrovia License`.

Start with the [SDK developer quickstart](https://console.getchrovia.com/en/docs/sdk-getting-started) if you do not yet have a browser instance and Provision extension.

## Document layout

Browser configuration belongs under the top-level `internal` object. Application-owned data can live alongside it. `signature`, when required, is a separate top-level object, not a child of `internal`.

This is a complete unsigned example for a License that grants `extendedPrefs` and `instanceAppearance` but does **not** grant `signedExtendedPrefs`:

```json
{
  "internal": {
    "instance_appearance": {
      "label": "SDK Example",
      "background_color": "#059669",
      "foreground_color": "#FFFFFF"
    }
  },
  "sdk_example": {
    "message": "Hello from Chrovia SDK",
    "counter": 0
  }
}
```

Write the file before launching. Each kernel feature still requires its own License capability: adding `instance_appearance` does not grant `instanceAppearance`. Treat kernel configuration as startup configuration unless a feature explicitly supports live updates; writing JSON through the API is not a universal hot-reload mechanism.

## Provision defaults versus instance data

You may distribute an initial `Extended Preferences` in the Provision root, alongside its `manifest.json` and `Extensions` directory.

On first startup, if the user-data directory has no `Extended Preferences`, the browser copies the Provision file there and loads the instance copy. An existing instance file is never overwritten. Changing the Provision seed therefore does not update existing instances. If copying fails, the browser logs a warning and continues as if the file were missing.

The copied file must also meet your License's signed-configuration requirements.

## JavaScript get, set, and remove

Requires `extendedPrefs` and an allowed execution context, normally a Provision Service Worker.

| Method | Result |
| --- | --- |
| `chrovia.prefs.get(key)` | Promise resolving to the stored value, or `undefined` when unavailable or missing |
| `chrovia.prefs.set(key, value)` | Promise resolving to `undefined` |
| `chrovia.prefs.remove(key)` | Promise resolving to `undefined` |

Keys are dotted paths from the **document root**. Include `internal.` when accessing kernel configuration:

```js
async function readAndWritePrefs() {
  const prefs = globalThis.chrovia?.prefs;
  if (!prefs) {
    throw new Error('extendedPrefs is unavailable');
  }

  const label = await prefs.get('internal.instance_appearance.label');
  await prefs.set('sdk_example.message', 'Updated by the extension');
  const message = await prefs.get('sdk_example.message');
  await prefs.remove('sdk_example.counter');
  console.log({ label, message });
}

readAndWritePrefs().catch(console.error);
```

Use JSON-compatible values. `set()` rejects with `DataCloneError` if the value cannot be converted to a storable value; catch the rejection and correct the input. These methods are not transactions, and a read followed by a write is not an atomic increment. A resolved write Promise is not proof that data has been saved to disk or authorization is valid: unavailable preferences and failed verification can make writes no-ops.

## Signed configuration

When the License grants `signedExtendedPrefs`, a valid signed file is required. Without that capability, the browser does not require an Extended Preferences signature, but still validates the License.

Obtain a complete signed file compatible with your License from your configuration provider. Do not construct or edit its `signature` object. Before changing protected settings, arrange to receive a replacement file; the browser does not provide a signing command or API.

Keep mutable application data outside `internal`, as with `sdk_example`. For signed files, changing `internal` through an editor or `prefs.set()` can make the file unusable on the next launch; obtain a replacement signed file instead.

If required verification fails, the browser blocks **all** Extended Preferences reads and writes, including unsigned application fields. `get()` can return `undefined`, while `set()` and `remove()` can resolve without changing anything. Do not interpret these return values as a signature-validation API.

## Set the download directory

`internal.profile_prefs` accepts a small allowlist of Chromium Profile preferences. It requires `extendedPrefs`; it is not a general Chrome policy or Local State API.

The supported directory keys are `download.default_directory` and `savefile.default_directory`. For a Windows instance, this fragment sets both independently:

```json
{
  "internal": {
    "profile_prefs": {
      "download.default_directory": "C:\\SDK\\downloads\\instance-01",
      "savefile.default_directory": "C:\\SDK\\downloads\\instance-01"
    }
  }
}
```

Merge this section into your configuration before obtaining a signed file if required. Use machine-absolute paths appropriate for the host OS; relative paths and paths containing `..` are rejected. Create the directory in your launcher if it must exist before a download.

Prefer a dedicated subdirectory, as in the example. On first setup, choosing exactly the Desktop directory—or exactly the home directory on Linux—can cause the browser to use its default download directory instead. A subdirectory does not have this exact-path exception. Verify the destination with a test download.

These directory settings apply at startup and remain saved for the profile. They do not lock the Settings UI, do not disable the download prompt, and do not automatically revert when the Extended Preferences entry is removed. Unsupported keys are skipped and logged. The two directory values are not automatically mirrored.

## Configure the startup page

`internal.profile_prefs` also accepts the integer key `session.restore_on_startup`: `1` continues the previous session, and `5` opens a new tab. Other values and types are rejected.

```json
{
  "internal": {
    "profile_prefs": {
      "session.restore_on_startup": 1
    }
  }
}
```

This setting applies at startup and remains saved for the profile. It does not lock the Settings UI and does not automatically revert when the entry is removed. Explicit startup URLs and command-line arguments still follow Chromium startup behavior.

For the dedicated signature-enforcement capability, see [Signed Extended Preferences](https://console.getchrovia.com/en/docs/sdk-signed-extended-prefs). To configure other kernel sections, use the [complete capability index](https://console.getchrovia.com/en/docs/sdk-capabilities).
