Help us shape the future of Go! Take the 2026 Go Developer Survey

sliccbrowsers

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

README

slicc-browsers

The browser catalog, JSON schemas and conformance corpus shared by the two programs that find and launch browsers for SLICC:

  • slicc browsers and slicc launch in slicc-cli (Go, CGO_ENABLED=0);
  • playwright-cli list and open in slicc-cdp (Rust, also built for wasm32-wasip1).

They can't share code, so they share data. Three packages wrap the same files, at one version:

package what it gives you
Go module github.com/ai-ecoverse/slicc-browsers (package sliccbrowsers) the files embedded, typed structs, and corpus helpers
Rust crate slicc-browsers (lib slicc_browsers) the files as &str constants, serde types behind features
npm package @ai-ecoverse/slicc-browsers the JSON files and the schemas
file what it is
catalog.json the browsers, Electron apps, ranking, discovery, seven flags and prefs, profile and platform paths
schema/catalog.schema.json JSON Schema (2020-12) for catalog.json
schema/browsers.schema.json JSON Schema for slicc browsers --json and playwright-cli list --json, schema 1
schema/corpus.schema.json JSON Schema for corpus.json
corpus/<case>/case.json, corpus/<case>/expected.json the conformance cases
corpus.json every case in one file, generated from corpus/ by npm run corpus

Go

import sliccbrowsers "github.com/ai-ecoverse/slicc-browsers"

c := sliccbrowsers.Default()
b, ok := c.Browser("chrome")
  • Default() *Catalog parses the embedded catalog.json once and panics if it doesn't parse (CI makes sure it does). Load() (*Catalog, error) is the same without the panic. Treat the result as read-only. Parse([]byte) parses another copy and rejects a schema other than 1.
  • (*Catalog).Browser(id) and (*Catalog).Priority(id), the index in browsers (its length for an unknown id).
  • CatalogJSON(), CatalogSchemaJSON(), BrowsersSchemaJSON() and CorpusJSON() return copies of the embedded files.
  • Corpus() ([]Case, error) returns the cases. See Running the corpus for the helpers.

Rust

[dependencies]
slicc-browsers = "1"

[dev-dependencies]
slicc-browsers = { version = "1", features = ["corpus"] }
  • Always: CATALOG, CATALOG_SCHEMA, BROWSERS_SCHEMA and CORPUS_SCHEMA, each the file's text via include_str!, and SCHEMA (1). No dependencies.
  • Feature serde: Catalog and the other types, Catalog::parse(&str), catalog() (parses CATALOG), Catalog::browser and Catalog::priority. It pulls in serde and serde_json.
  • Feature corpus (implies serde): CORPUS, the text of corpus.json, and the module corpus with corpus(), Case, Layout and the helpers below. Use it from [dev-dependencies] only; with resolver 2 it stays out of normal builds.

Every feature builds for wasm32-wasip1.

npm

import catalog from '@ai-ecoverse/slicc-browsers' with { type: 'json' }. The exports are . (catalog.json), ./catalog.json, ./corpus.json, ./schema/catalog.schema.json, ./schema/browsers.schema.json and ./schema/corpus.schema.json.

catalog.json

"schema": 1. A minor release only adds fields; a field that changes meaning or goes away needs schema 2 and a major release. Relative paths are arrays of path segments, joined with the platform's separator. Top-level fields:

  • minChromiumMajor (116): endpoints whose user agent's Chrome/<major> (discovery.chromeMajorPattern) is lower are left out, and so are installed browsers with chromiumVersion: true whose version's leading number is lower. A version that doesn't start with a number is kept.
  • browsers: every known Chromium browser, in rank priority order. Each has:
    • id, name, channel (stable, beta, dev, canary, nightly, snapshot, testing), engine (chromium), and chromiumVersion: whether its version is the Chromium version (Chrome, Edge, Chromium) or its own (Brave, Opera, Vivaldi, Arc).
    • macos: bundleId, app (the bundle's file name), executable (under Contents/MacOS), and dataDir?, the default user-data dir under ~/Library/Application Support.
    • windows?: roots (names from platforms.windows.roots, searched in order) and executables (each tried under each root); dataRoot and dataDir, the default user-data dir; startMenuInternet?, the browser's key names under the StartMenuInternet registry keys.
    • linux?: bins (names on PATH), desktopIds (.desktop file names without the suffix), flatpak? (the app id), snap? (the snap name), snapDataDir? (the user-data dir under ~/snap/<snap>/common), configDir (the user-data dir under the config dir, also under ~/.var/app/<flatpak>/config for a flatpak), and debs (dpkg package names for the version).
  • electron: macosApps (known Electron apps by bundle id, with display names), debugBlocked (app names that block remote debugging; they're listed with debugSupport: "disabled" and never launched), and idPrefix (electron:, followed by the slug of the name: lower case, runs of other characters as one -).
  • rank: tiers, 1 to 5: sevenOpen (an endpoint with a seven tab), endpoint (any other endpoint), chrome (installed chromeId), chromium (other installed Chromium browsers), electron (installed Electron apps).
  • discovery:
    • activePortFile (DevToolsActivePort) and probePorts (9222 to 9229, probed by slicc only);
    • sourceRank: when two sources find the same host and port, the lower rank wins, and on a tie the first found;
    • names: an endpoint's name when it isn't from a known browser's user-data dir: electron when the user agent contains electronUserAgent, else products[<product>] for the product before the / in /json/version's Browser, else that product, else fallback;
    • process: the process scan, see The process source.
  • seven:
    • originScheme and originHostPattern: a seven origin is https://<host> with a host matching the pattern, except for the excludedLabels (www);
    • sitePattern ([*.]sliccy.ai);
    • switches and disabledFeatures: the seven flags, all --disable-features values merged into one switch;
    • prefs: values merged into a profile's Default/Preferences at the path of keys;
    • discardExceptions: where the site pattern and the extra origins' hosts go, as a list of strings or as a chrome-time-map, a map from site to the time it was added (microseconds since 1601-01-01 UTC, as a decimal string);
    • cleanExit: values that mark the last exit clean;
    • form says where a key comes from: six (SLICC six's keys) or chrome-154 (what Chrome 154 reads).
  • profiles: SLICC profiles live in <config dir>/<root>/<name>, and a snap's in ~/snap/<snap>/common/<snapRoot>/<name>. legacyRoot is the old root, which SLICC six also uses, and sixProfilePattern matches six's profile names; neither is ever scanned. namePattern is a valid profile name.
  • launch: chromiumArgs (with {profile} for the profile dir), then the seven flags, then headless with --headless. Electron apps get electron.portFlag with the first free port from electron.minPort up that isn't in electron.reservedPorts.
  • platforms: the config dir per OS, the Windows roots, and the Windows registry keys. A location is the environment variable env when it's set (on Linux only an absolute path counts), else absolute, else home under the home dir. registry: under each of hives, every subkey of each startMenuInternet key, with its openCommand default value, and the default value of appPaths\<name> for each of appPathNames.

The process source

The process scan finds browsers started with a debugging port by something else:

  • Process list. On Unix it's discovery.process.unix (ps -ax -o pid= -o command=): one process a line, the pid, whitespace, and the command line. On Windows it's discovery.process.windows, which prints a JSON array (or one object) of ProcessId and CommandLine; entries with no command line are skipped.
  • What's skipped: pid 0, the scanning process itself, and commands whose first token is a wrapper. The first token is the quoted string when the command starts with a quote. A wrapper is a token whose base name, without .exe, .cmd or .bat, is one of wrappers, case-insensitively. A command with no executable before its first - token is skipped too.
  • The port comes from the first --remote-debugging-port followed by = or whitespace and then digits. A port above 65535 drops the process.
  • The dir is --user-data-dir at the start of a token, followed by = or whitespace, then one token (or a quoted string).
  • Port 0 means the port is in the dir's DevToolsActivePort, checked like any other. With no dir, or a dir under the legacy profile root (a slicc segment followed by profiles, case-insensitively), the process is skipped.
  • Any other port is probed on 127.0.0.1. An endpoint from the process scan has source: "process" and userDataDir set to the dir when there is one.
  • Tests must fake the process list: never scan the real one in a test.

Output schema 1

schema/browsers.schema.json describes slicc browsers --json, which playwright-cli list --json also prints. slicc-cli's README is the authoritative spec for it; this schema is a copy and follows it. Fields can be added; source is one of devtools-active-port, flag, probe and process.

The corpus

Each case is a fake machine: a home tree, DevToolsActivePort files, fake /json/version and /json/list answers, a fake process list, --cdp URLs, and installed browsers, with the ranked list it must produce in expected.json. corpus.json holds every case as { "name", "case", "expected" }.

case.json:

  • description, and os?: the OSes the case runs on (darwin, linux, windows; default all).
  • needs: what a program must support to run the case: user-data-dirs (DevToolsActivePort in browsers' default user-data dirs), seven-profiles (in the profile roots), flag (--cdp URLs), process, probe (port probes, slicc only), origins (extra seven origins), installed (ranking installed browsers). A program skips a case that needs something it doesn't do.
  • env?: environment variables for discovery, which sees nothing else from the real environment.
  • files?: file contents by path. Every path starts with a token.
  • cdp?, origins?, probePorts?: --cdp URLs, extra seven origins, and the ports to probe.
  • processes?: { "pid", "command" }, or { "self": true, "command" } for the scanning process, whose pid the harness fills in.
  • http?: fake servers by host:port. localhost and [::1] are 127.0.0.1. A listed port accepts TCP connections. /json/version answers 200 with version, /json/list (and /json) with list. A missing body, or any other path, answers 404. An unlisted port refuses connections.
  • installed?: installed browsers in the shape of output schema 1's installed, ranked along with the endpoints.

Tokens. {home} (the fake home), {config} (the config dir), {sevenProfiles} (the profile root) and {userData:<id>} (the browser's first default user-data dir on this OS) stand for directories. In files, env, cdp, process commands and expected.json, a token and the path characters after it (up to whitespace, ", ' or ,) become a path on the OS under test, with \ on Windows. The token values come from catalog.json, with the case's env.

Never 9222 to 9229. A developer's own Chrome listens there. The corpus schema refuses those ports, npm run validate refuses them anywhere in the corpus, and the fakes never serve them.

Running the corpus

A harness, per case it runs:

  1. makes a temporary home and writes each of files;
  2. points discovery at that home and the case's env only, so no real user-data dir, profile or process is ever read;
  3. feeds the fake process list (Unix: PSOutput, Windows: CIMOutput) and routes every HTTP request and TCP dial to the fakes, so discovery never touches the network;
  4. discovers endpoints, ranks them with installed, and compares the JSON with expected.json after token expansion, as parsed JSON.

Go (slicc-cli does this in test/integration/corpus_test.go):

cases, _ := sliccbrowsers.Corpus()
for _, c := range cases {
    if !c.Runs(runtime.GOOS, sliccbrowsers.NeedFlag, sliccbrowsers.NeedProcess /* … */) {
        continue
    }
    l := sliccbrowsers.Layout{OS: runtime.GOOS, Home: t.TempDir(), Getenv: func(k string) string { return c.Input.Env[k] }}
    // write c.Files(l); use c.CDP(l), c.PSOutput(l, os.Getpid()) or c.CIMOutput(l, os.Getpid()),
    // c.Transport() as the http.RoundTripper and c.DialContext for TCP; compare with c.ExpectedJSON(l)
}

Rust, with the corpus feature:

use slicc_browsers::corpus::{corpus, Layout, NEED_PROCESS, NEED_PROFILES};

let cat = slicc_browsers::catalog();
let os = match std::env::consts::OS { "macos" => "darwin", other => other };
for case in corpus().cases {
    if !case.runs(os, &[NEED_PROFILES, NEED_PROCESS]) {
        continue;
    }
    let home = tempdir.path().to_str().unwrap();
    let env = |k: &str| case.input.env.get(k).cloned();
    let layout = Layout { os, home, env: &env, catalog: &cat };
    // write case.files(&layout); case.ps_output(&layout, std::process::id()) or case.cim_output(…);
    // answer HTTP with case.http_get(host_port, path) and TCP with case.server(host_port).is_some();
    // compare with case.expected(&layout)
}

Layout also gives Config, SevenProfiles, UserDataDirs(id), Token(name) and Expand(text) (Rust: config, seven_profiles, user_data_dirs, token, expand). Their results for a few homes are pinned in test/integration/layout.json, which the Go and Rust tests both check.

Development

Go 1.26, Rust stable with wasm32-wasip1, Node ≥ 24.

  • npm run corpus regenerates corpus.json from corpus/; the pre-commit hook and CI fail when it's stale.
  • npm run validate checks catalog.json and corpus.json against the schemas, plus what a schema can't say: unique ids, bundle ids and names, known Windows roots, rising tiers, compiling patterns, known tokens, tier order and sevenOpen in each expected.json, and no port from 9222 to 9229.
  • npm run lint: the slicc lint tools (Biome, no comments, no unit tests in git, AGENTS.md), gofmt, go mod tidy -diff, go vet, golangci-lint, cargo fmt --check and clippy.
  • npm test: validate, the Go tests in test/integration/, and cargo test --all-features.
  • npm run build: the Go module, the crate (also for wasm32-wasip1), and npm pack --dry-run.

Changing a table in slicc-cli/internal/browser means changing catalog.json here, releasing, and bumping the dependency; slicc-cli has no tables of its own. A new behaviour gets a corpus case.

Releases

semantic-release cuts one version from main for all three packages (.github/workflows/release.yml):

  1. The tag vX.Y.Z and a GitHub release are the Go module's release. scripts/major-guard.mjs fails the release when the major doesn't fit the module path in go.mod (no suffix allows v0 and v1, /vN only vN). The workflow then asks proxy.golang.org for the new version and pkg.go.dev to fetch it; both only warn.
  2. npm: with the repository variable SLICC_BROWSERS_NPM_PUBLISH set to true, the package is stamped with the version and published through npm trusted publishing (OIDC, with provenance). A version that is already on npm is skipped.
  3. crates.io: with the repository variable SLICC_BROWSERS_CRATES_PUBLISH set to true, Cargo.toml is stamped with the version and cargo publish runs with a short-lived token from crates.io trusted publishing (rust-lang/crates-io-auth-action). A version that is already on crates.io is skipped.

A run started by hand (gh workflow run release.yml --ref main) on a commit that already has its tag publishes what's missing without a new release.

Go module versions. A pushed tag is the release: proxy.golang.org caches it and sum.golang.org records its hash for good. Never move or delete a pushed tag; retract a bad version in go.mod and release anew. A BREAKING CHANGE needs a /vN module path first.

First publish (by a maintainer with 2FA):

  1. npm: npx fledgling add --new @ai-ecoverse/slicc-browsers claims the name with a 0.0.0 placeholder and trusts ai-ecoverse/slicc-browsers' release.yml. Then set SLICC_BROWSERS_NPM_PUBLISH to true.
  2. crates.io: trusted publishing needs the crate to exist. Publish it once by hand from the latest tag: git checkout vX.Y.Z && node scripts/set-crate-version.mjs X.Y.Z && cargo publish --allow-dirty, logged in with cargo login. Then, on crates.io, add a trusted publisher to slicc-browsers: GitHub, owner ai-ecoverse, repository slicc-browsers, workflow release.yml, no environment. Then set SLICC_BROWSERS_CRATES_PUBLISH to true.

Documentation

Index

Constants

View Source
const (
	NeedUserDataDirs = "user-data-dirs"
	NeedProfiles     = "seven-profiles"
	NeedFlag         = "flag"
	NeedProcess      = "process"
	NeedProbe        = "probe"
	NeedOrigins      = "origins"
	NeedInstalled    = "installed"
)
View Source
const Schema = 1

Variables

This section is empty.

Functions

func BrowsersSchemaJSON

func BrowsersSchemaJSON() []byte

func CatalogJSON

func CatalogJSON() []byte

func CatalogSchemaJSON

func CatalogSchemaJSON() []byte

func CorpusJSON

func CorpusJSON() []byte

Types

type App

type App struct {
	BundleID string `json:"bundleId"`
	Name     string `json:"name"`
}

type Browser

type Browser struct {
	ID              string  `json:"id"`
	Name            string  `json:"name"`
	Channel         string  `json:"channel"`
	Engine          string  `json:"engine"`
	ChromiumVersion bool    `json:"chromiumVersion"`
	MacOS           MacOS   `json:"macos"`
	Windows         Windows `json:"windows,omitzero"`
	Linux           Linux   `json:"linux,omitzero"`
}

type Case

type Case struct {
	Name     string          `json:"name"`
	Input    Input           `json:"case"`
	Expected json.RawMessage `json:"expected"`
}

func Corpus

func Corpus() ([]Case, error)

func (Case) CDP

func (c Case) CDP(l Layout) []string

func (Case) CIMOutput

func (c Case) CIMOutput(l Layout, self int) string

func (Case) Commands

func (c Case) Commands(l Layout, self int) []FakeProcess

func (Case) DialContext

func (c Case) DialContext(_ context.Context, network, addr string) (net.Conn, error)

func (Case) Env

func (c Case) Env(l Layout) map[string]string

func (Case) ExpectedJSON

func (c Case) ExpectedJSON(l Layout) ([]byte, error)

func (Case) Files

func (c Case) Files(l Layout) map[string]string

func (Case) PSOutput

func (c Case) PSOutput(l Layout, self int) string

func (Case) Runs

func (c Case) Runs(goos string, supported ...string) bool

func (Case) Server

func (c Case) Server(hostPort string) (Server, bool)

func (Case) Transport

func (c Case) Transport() http.RoundTripper

type Catalog

type Catalog struct {
	Schema           int       `json:"schema"`
	MinChromiumMajor int       `json:"minChromiumMajor"`
	Browsers         []Browser `json:"browsers"`
	Electron         Electron  `json:"electron"`
	Rank             Rank      `json:"rank"`
	Discovery        Discovery `json:"discovery"`
	Seven            Seven     `json:"seven"`
	Profiles         Profiles  `json:"profiles"`
	Launch           Launch    `json:"launch"`
	Platforms        Platforms `json:"platforms"`
}

func Default

func Default() *Catalog

func Load

func Load() (*Catalog, error)

func Parse

func Parse(b []byte) (*Catalog, error)

func (*Catalog) Browser

func (c *Catalog) Browser(id string) (Browser, bool)

func (*Catalog) Priority

func (c *Catalog) Priority(id string) int

type DiscardException

type DiscardException struct {
	Path []string `json:"path"`
	Type string   `json:"type"`
	Form string   `json:"form"`
}

type Discovery

type Discovery struct {
	ActivePortFile     string         `json:"activePortFile"`
	ProbePorts         []int          `json:"probePorts"`
	SourceRank         map[string]int `json:"sourceRank"`
	ChromeMajorPattern string         `json:"chromeMajorPattern"`
	Names              Names          `json:"names"`
	Process            Process        `json:"process"`
}

type Electron

type Electron struct {
	MacOSApps    []App    `json:"macosApps"`
	DebugBlocked []string `json:"debugBlocked"`
	IDPrefix     string   `json:"idPrefix"`
}

type ElectronLaunch

type ElectronLaunch struct {
	PortFlag      string `json:"portFlag"`
	MinPort       int    `json:"minPort"`
	ReservedPorts []int  `json:"reservedPorts"`
}

type FakeProcess

type FakeProcess struct {
	PID     int    `json:"pid"`
	Self    bool   `json:"self,omitempty"`
	Command string `json:"command"`
}

type Input

type Input struct {
	Description string            `json:"description"`
	OS          []string          `json:"os,omitempty"`
	Needs       []string          `json:"needs"`
	Env         map[string]string `json:"env,omitempty"`
	Files       map[string]string `json:"files,omitempty"`
	CDP         []string          `json:"cdp,omitempty"`
	Origins     []string          `json:"origins,omitempty"`
	ProbePorts  []int             `json:"probePorts,omitempty"`
	Processes   []FakeProcess     `json:"processes,omitempty"`
	HTTP        map[string]Server `json:"http,omitempty"`
	Installed   json.RawMessage   `json:"installed,omitempty"`
}

type Launch

type Launch struct {
	ChromiumArgs        []string       `json:"chromiumArgs"`
	Headless            string         `json:"headless"`
	DisableFeaturesFlag string         `json:"disableFeaturesFlag"`
	Electron            ElectronLaunch `json:"electron"`
}

type Layout

type Layout struct {
	OS      string
	Home    string
	Getenv  func(string) string
	Catalog *Catalog
}

func (Layout) Config

func (l Layout) Config() string

func (Layout) Expand

func (l Layout) Expand(s string) string

func (Layout) Join

func (l Layout) Join(parts ...string) string

func (Layout) SevenProfiles

func (l Layout) SevenProfiles() string

func (Layout) Token

func (l Layout) Token(name string) (string, bool)

func (Layout) UserDataDirs

func (l Layout) UserDataDirs(id string) []string

func (Layout) WindowsRoot

func (l Layout) WindowsRoot(name string) string

type Linux

type Linux struct {
	Bins        []string `json:"bins,omitempty"`
	DesktopIDs  []string `json:"desktopIds,omitempty"`
	Flatpak     string   `json:"flatpak,omitempty"`
	Snap        string   `json:"snap,omitempty"`
	SnapDataDir []string `json:"snapDataDir,omitempty"`
	ConfigDir   []string `json:"configDir,omitempty"`
	Debs        []string `json:"debs,omitempty"`
}

type LinuxPlatform

type LinuxPlatform struct {
	Config Location `json:"config"`
}

type Location

type Location struct {
	Env      string   `json:"env,omitempty"`
	Home     []string `json:"home,omitempty"`
	Absolute string   `json:"absolute,omitempty"`
}

type MacOS

type MacOS struct {
	BundleID   string   `json:"bundleId"`
	App        string   `json:"app"`
	Executable string   `json:"executable"`
	DataDir    []string `json:"dataDir,omitempty"`
}

type MacOSPlatform

type MacOSPlatform struct {
	Config Location `json:"config"`
}

type Names

type Names struct {
	ElectronUserAgent string            `json:"electronUserAgent"`
	Electron          string            `json:"electron"`
	Products          map[string]string `json:"products"`
	Fallback          string            `json:"fallback"`
}

type Platforms

type Platforms struct {
	MacOS   MacOSPlatform   `json:"macos"`
	Windows WindowsPlatform `json:"windows"`
	Linux   LinuxPlatform   `json:"linux"`
}

type Pref

type Pref struct {
	Path  []string        `json:"path"`
	Value json.RawMessage `json:"value"`
	Form  string          `json:"form,omitempty"`
}

type Process

type Process struct {
	Unix            []string `json:"unix"`
	Windows         []string `json:"windows"`
	PortFlag        string   `json:"portFlag"`
	UserDataDirFlag string   `json:"userDataDirFlag"`
	Wrappers        []string `json:"wrappers"`
	WrapperSuffixes []string `json:"wrapperSuffixes"`
}

type Profiles

type Profiles struct {
	Root              []string `json:"root"`
	SnapRoot          []string `json:"snapRoot"`
	LegacyRoot        []string `json:"legacyRoot"`
	SixProfilePattern string   `json:"sixProfilePattern"`
	NamePattern       string   `json:"namePattern"`
}

type Rank

type Rank struct {
	Tiers    Tiers  `json:"tiers"`
	ChromeID string `json:"chromeId"`
}

type Registry

type Registry struct {
	Hives             []string `json:"hives"`
	StartMenuInternet []string `json:"startMenuInternet"`
	OpenCommand       string   `json:"openCommand"`
	AppPaths          string   `json:"appPaths"`
	AppPathNames      []string `json:"appPathNames"`
}

type Server

type Server struct {
	Version json.RawMessage `json:"version,omitempty"`
	List    json.RawMessage `json:"list,omitempty"`
}

type Seven

type Seven struct {
	OriginScheme      string             `json:"originScheme"`
	OriginHostPattern string             `json:"originHostPattern"`
	ExcludedLabels    []string           `json:"excludedLabels"`
	SitePattern       string             `json:"sitePattern"`
	Switches          []string           `json:"switches"`
	DisabledFeatures  []string           `json:"disabledFeatures"`
	Prefs             []Pref             `json:"prefs"`
	DiscardExceptions []DiscardException `json:"discardExceptions"`
	CleanExit         []Pref             `json:"cleanExit"`
}

type Tiers

type Tiers struct {
	SevenOpen int `json:"sevenOpen"`
	Endpoint  int `json:"endpoint"`
	Chrome    int `json:"chrome"`
	Chromium  int `json:"chromium"`
	Electron  int `json:"electron"`
}

type Windows

type Windows struct {
	Roots             []string   `json:"roots,omitempty"`
	Executables       [][]string `json:"executables,omitempty"`
	DataRoot          string     `json:"dataRoot,omitempty"`
	DataDir           []string   `json:"dataDir,omitempty"`
	StartMenuInternet []string   `json:"startMenuInternet,omitempty"`
}

type WindowsPlatform

type WindowsPlatform struct {
	Config   Location            `json:"config"`
	Roots    map[string]Location `json:"roots"`
	Registry Registry            `json:"registry"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL