├── .prettierrc.yml
├── FUNDING.yml
├── changelog_generator
├── .gitignore
├── Cargo.toml
├── src
│ └── main.rs
└── Cargo.lock
├── assets
├── bichrome_icon.icns
├── bichrome_icon.ico
├── bichrome_icon.png
├── bichrome.app
│ └── Contents
│ │ ├── MacOS
│ │ └── bichrome
│ │ ├── Resources
│ │ └── bichrome_icon.icns
│ │ └── Info.plist
├── README.md
└── changelog-template.md
├── .vscode
├── extensions.json
├── settings.json
└── launch.json
├── sign.ps1
├── .gitignore
├── .changelog.yml
├── .github
└── workflows
│ ├── checks.yml
│ ├── build.yml
│ └── publish.yml
├── src
├── main.rs
├── chrome_local_state.rs
├── config.rs
├── macos.rs
└── windows.rs
├── Cargo.toml
├── LICENSE-MIT
├── example_config
└── bichrome_config.json
├── README.md
├── LICENSE-APACHE
└── Cargo.lock
/.prettierrc.yml:
--------------------------------------------------------------------------------
1 | tabWidth: 4
--------------------------------------------------------------------------------
/FUNDING.yml:
--------------------------------------------------------------------------------
1 | ko_fi: jorgenpt
2 | github: jorgenpt
3 |
--------------------------------------------------------------------------------
/changelog_generator/.gitignore:
--------------------------------------------------------------------------------
1 | ## Rust
2 | /target
--------------------------------------------------------------------------------
/assets/bichrome_icon.icns:
--------------------------------------------------------------------------------
1 | bichrome.app/Contents/Resources/bichrome_icon.icns
--------------------------------------------------------------------------------
/assets/bichrome_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jorgenpt/bichrome/HEAD/assets/bichrome_icon.ico
--------------------------------------------------------------------------------
/assets/bichrome_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jorgenpt/bichrome/HEAD/assets/bichrome_icon.png
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "matklad.rust-analyzer"
4 | ]
5 | }
--------------------------------------------------------------------------------
/assets/bichrome.app/Contents/MacOS/bichrome:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jorgenpt/bichrome/HEAD/assets/bichrome.app/Contents/MacOS/bichrome
--------------------------------------------------------------------------------
/assets/bichrome.app/Contents/Resources/bichrome_icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jorgenpt/bichrome/HEAD/assets/bichrome.app/Contents/Resources/bichrome_icon.icns
--------------------------------------------------------------------------------
/assets/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | Big thanks to Krista A. Leemhuis for the amazing icon!
4 |
5 | The icon is copyright (c) 2021-2023 [Jørgen P. Tjernø](mailto:jorgen@tjer.no). All Rights Reserved.
6 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "rust-analyzer.files.excludeDirs": [
3 | "windows_bindings"
4 | ],
5 | "rust-analyzer.checkOnSave.command": "clippy",
6 | "yaml.schemas": {
7 | "https://json.schemastore.org/github-workflow.json": ".github/workflows/build.yml"
8 | }
9 | }
--------------------------------------------------------------------------------
/changelog_generator/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "changelog_generator"
3 | version = "0.1.0"
4 | authors = ["Jørgen P. Tjernø "]
5 | edition = "2018"
6 |
7 | [dependencies]
8 | anyhow = "^1"
9 | tinytemplate = "1.2"
10 | serde = "1.0"
11 | serde_derive = "1.0"
12 |
13 | [dependencies.git-changelog]
14 | default-features = false
15 | git = "https://github.com/aldrin/git-changelog"
--------------------------------------------------------------------------------
/sign.ps1:
--------------------------------------------------------------------------------
1 | # Determine the path of the latest installed Windows 10 SDK by sorting the names of the directories as if they are version objects
2 | $latestSdkPath = Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin" -Filter "10.*" | Sort "{[version] $_}" | Select-Object -Last 1
3 | $signToolExe = $latestSdkPath.FullName + "\x64\signtool.exe"
4 |
5 | & $signToolExe sign /n "Open Source Developer, Joergen Tjernoe" /t http://time.certum.pl/ /fd sha1 /v @args
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Bichrome
2 | /bichrome.log
3 |
4 | ## Rust
5 | /target
6 |
7 | ## Entries from https://github.com/github/gitignore/blob/eefa65c924329ad918985713cdb195e6bc68744b/Global/VisualStudioCode.gitignore
8 | .vscode/*
9 | !.vscode/settings.json
10 | !.vscode/tasks.json
11 | !.vscode/launch.json
12 | !.vscode/extensions.json
13 | *.code-workspace
14 |
15 | # Local History for Visual Studio Code
16 | .history/
17 |
18 | # Release body for GH releases
19 | gh-release.md
--------------------------------------------------------------------------------
/.changelog.yml:
--------------------------------------------------------------------------------
1 | # Configuration for git-changelog (https://github.com/aldrin/git-changelog)
2 | conventions:
3 | categories:
4 | - {tag: "break", title: "Breaking Change"}
5 | - {tag: "feature", title: "Feature"}
6 | - {tag: "improve", title: "Improvement"}
7 | - {tag: "fix", title: "Fix"}
8 | scopes:
9 | - {tag: "", title: "General"}
10 | - {tag: "win", title: "Windows"}
11 | - {tag: "mac", title: "macOS"}
12 | output:
13 | post_processors:
14 | - {lookup: "GH-(?P\\d+)", replace: "[GH-$id](https://github.com/jorgenpt/bichrome/issues/$id)"}
15 |
--------------------------------------------------------------------------------
/.github/workflows/checks.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | pull_request:
4 |
5 | name: Clippy check
6 | jobs:
7 | clippy_check:
8 | runs-on: ${{ matrix.os }}
9 |
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | os: [windows-latest, macos-latest]
14 |
15 | steps:
16 | - uses: actions/checkout@v4
17 | - uses: actions/cache@v4
18 | with:
19 | path: |
20 | ~/.cargo/registry
21 | ~/.cargo/git
22 | target
23 | changelog_generator/target
24 | key: ${{ runner.os }}-clippy_cargo-${{ hashFiles('**/Cargo.lock') }}
25 | restore-keys: |
26 | ${{ runner.os }}-clippy_cargo-
27 | - run: rustup component add clippy
28 | - uses: actions-rs/clippy-check@v1
29 | with:
30 | token: ${{ secrets.GITHUB_TOKEN }}
31 | args: --all-features
32 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | env:
8 | CARGO_TERM_COLOR: always
9 |
10 | jobs:
11 | build:
12 | runs-on: ${{ matrix.os }}
13 |
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | os: [windows-latest, macos-latest]
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 | - uses: actions/cache@v4
22 | with:
23 | path: |
24 | ~/.cargo/registry
25 | ~/.cargo/git
26 | target
27 | changelog_generator/target
28 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
29 | restore-keys: |
30 | ${{ runner.os }}-cargo-
31 | - name: Build (bichrome)
32 | run: cargo build --verbose
33 | - name: Build (changelog_generator)
34 | run: cargo build --verbose --manifest-path changelog_generator/Cargo.toml
35 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | #![deny(clippy::all)]
2 | // We use the console subsystem in debug builds, but use the Windows subsystem in release
3 | // builds so we don't have to allocate a console and pop up a command line window.
4 | // This needs to live in main.rs rather than windows.rs because it needs to be a crate-level
5 | // attribute, and it doesn't affect the mac build at all, so it's innocuous to leave for
6 | // both target_os.
7 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
8 | #![cfg_attr(debug_assertions, windows_subsystem = "console")]
9 |
10 | mod chrome_local_state;
11 | mod config;
12 |
13 | #[cfg(target_os = "macos")]
14 | mod macos;
15 | #[cfg(target_os = "macos")]
16 | use crate::macos as os;
17 |
18 | #[cfg(target_os = "windows")]
19 | mod windows;
20 | #[cfg(target_os = "windows")]
21 | use crate::windows as os;
22 |
23 | use anyhow::Result;
24 | use log::error;
25 |
26 | fn main() -> Result<()> {
27 | let result = os::main();
28 | if let Err(error) = &result {
29 | error!("Encountered error: {error:?}");
30 | }
31 | result
32 | }
33 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "bichrome"
3 | version = "0.8.0"
4 | authors = ["Jørgen P. Tjernø "]
5 | edition = "2021"
6 | license = "MIT OR Apache-2.0"
7 |
8 | [dependencies]
9 | anyhow = "^1"
10 | const_format = "0.2"
11 | log = "0.4"
12 | serde = { version = "1.0", features = ["derive"] }
13 | serde_json = "1.0"
14 | simplelog = "^0.12.1"
15 | structopt = "0.3"
16 | thiserror = "^1"
17 | url = "^2.2.0"
18 | webextension_pattern = { version = "0.3", features = ["serde"] }
19 |
20 | [target.'cfg(windows)'.dependencies]
21 | winreg = "^0.52.0"
22 |
23 | [target.'cfg(windows)'.dependencies.windows]
24 | version = "^0.52.0"
25 | features = [
26 | "Storage",
27 | "Win32_Foundation",
28 | "Win32_UI_Shell",
29 | "Win32_UI_WindowsAndMessaging",
30 | ]
31 |
32 | [target.'cfg(target_os = "macos")'.dependencies]
33 | fruitbasket = "0.10.0"
34 |
35 | [target.'cfg(windows)'.build-dependencies]
36 | winres = "^0.1"
37 |
38 | [package.metadata.winres]
39 | OriginalFilename = "bichrome.exe"
40 | FileDescription = "bichrome"
41 | ProductName = "bichrome"
42 | LegalCopyright = "© Jørgen Tjernø "
43 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-2023 Jørgen Tjernø
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "lldb",
9 | "request": "launch",
10 | "name": "Debug executable 'bichrome'",
11 | "cargo": {
12 | "args": [
13 | "build",
14 | "--bin=bichrome",
15 | "--package=bichrome"
16 | ],
17 | "filter": {
18 | "name": "bichrome",
19 | "kind": "bin"
20 | }
21 | },
22 | "args": [
23 | "--debug",
24 | "--dry-run"
25 | ],
26 | "cwd": "${workspaceFolder}"
27 | },
28 | {
29 | "type": "lldb",
30 | "request": "launch",
31 | "name": "Debug unit tests in executable 'bichrome'",
32 | "cargo": {
33 | "args": [
34 | "test",
35 | "--no-run",
36 | "--bin=bichrome",
37 | "--package=bichrome"
38 | ],
39 | "filter": {
40 | "name": "bichrome",
41 | "kind": "bin"
42 | }
43 | },
44 | "args": [],
45 | "cwd": "${workspaceFolder}"
46 | }
47 | ]
48 | }
--------------------------------------------------------------------------------
/example_config/bichrome_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "default_profile": "Fallback",
3 | "profiles": {
4 | "Fallback": {
5 | "browser": "OsDefault"
6 | },
7 | "Personal": {
8 | "browser": "Firefox"
9 | },
10 | "Work": {
11 | "browser": "Chrome",
12 | "hosted_domain": "mycorp.com"
13 | },
14 | "After Dark": {
15 | "browser": "Chrome",
16 | "profile": "Profile 1"
17 | },
18 | "Most Recent Chrome Window": {
19 | "browser": "Chrome"
20 | },
21 | "That One Profile For Edge": {
22 | "browser": "Edge",
23 | "profile": "Profile 2"
24 | },
25 | "Video Player": {
26 | "browser": "Executable",
27 | "path": "C:/Program Files/mpv/mpv.exe"
28 | }
29 | },
30 | "profile_selection": [
31 | {
32 | "profile": "Personal",
33 | "pattern": "*.facebook.com"
34 | },
35 | {
36 | "profile": "Personal",
37 | "pattern": "*.messenger.com"
38 | },
39 | {
40 | "profile": "Work",
41 | "pattern": "*.mycorp.net"
42 | },
43 | {
44 | "profile": "Work",
45 | "pattern": "mycorp.atlassian.net"
46 | },
47 | {
48 | "profile": "Work",
49 | "pattern": "https://github.com/MyCorp/*"
50 | },
51 | {
52 | "profile": "Personal",
53 | "pattern": "*.github.com"
54 | },
55 | {
56 | "profile": "Video Player",
57 | "pattern": "*.youtube.com"
58 | },
59 | {
60 | "profile": "Video Player",
61 | "pattern": "youtu.be"
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/changelog_generator/src/main.rs:
--------------------------------------------------------------------------------
1 | use anyhow::{anyhow, Result};
2 | use changelog::{ChangeLog, Configuration};
3 | use serde_derive::Serialize;
4 | use std::env;
5 | use tinytemplate::TinyTemplate;
6 |
7 | #[derive(Serialize)]
8 | struct Context {
9 | this_version: String,
10 | repo_url: String,
11 | commits_link: String,
12 | changelog: ChangeLog,
13 | }
14 |
15 | fn main() -> Result<()> {
16 | let mut args = env::args();
17 | let exe = args.next().expect("could not retrieve exe name");
18 | let previous_version = args.next().ok_or(anyhow!(
19 | "usage: {} [repo base url]",
20 | exe
21 | ))?;
22 | let this_version = args.next().ok_or(anyhow!(
23 | "usage: {} [repo base url]",
24 | exe
25 | ))?;
26 | let repo_url = args.next();
27 |
28 | let range = format!("{}..{}", previous_version, this_version);
29 | let (commits_link, repo_url) = if let Some(repo_url) = repo_url {
30 | let repo_url = repo_url.trim_end_matches('/');
31 |
32 | (
33 | format!(
34 | "{}/compare/{}...{}",
35 | repo_url, previous_version, this_version
36 | ),
37 | repo_url.to_string(),
38 | )
39 | } else {
40 | (String::from("#"), String::from("."))
41 | };
42 |
43 | let config = Configuration::from_yaml(include_str!("../../.changelog.yml"))?;
44 | let changelog = ChangeLog::from_range(&range, &config);
45 |
46 | let mut tt = TinyTemplate::new();
47 | tt.add_template(
48 | "changelog_template",
49 | include_str!("../../assets/changelog-template.md"),
50 | )?;
51 |
52 | let context = Context {
53 | this_version,
54 | repo_url,
55 | commits_link,
56 | changelog,
57 | };
58 |
59 | let rendered = tt.render("changelog_template", &context)?;
60 | println!("{}", rendered);
61 |
62 | Ok(())
63 | }
64 |
--------------------------------------------------------------------------------
/src/chrome_local_state.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 |
3 | use serde::{Deserialize, Serialize};
4 | use std::collections::HashMap;
5 | use std::fs::File;
6 | use std::io::BufReader;
7 | use std::path::Path;
8 | use thiserror::Error;
9 |
10 | #[derive(Error, Debug)]
11 | pub enum Error {
12 | #[error("could not read Chrome Local State")]
13 | InvalidFile(#[source] std::io::Error),
14 | #[error("could not parse Chrome Local State")]
15 | InvalidJson(#[source] serde_json::Error),
16 | }
17 |
18 | type Result = std::result::Result;
19 |
20 | #[derive(Serialize, Deserialize, Debug)]
21 | pub struct ChromeProfile {
22 | hosted_domain: String,
23 | name: Option,
24 | shortcut_name: Option,
25 | }
26 |
27 | #[derive(Serialize, Deserialize, Debug)]
28 | pub struct ProfilesData {
29 | info_cache: HashMap,
30 | }
31 |
32 | impl ProfilesData {
33 | pub fn profiles_by_hosted_domain(&self, hosted_domain: &str) -> Vec<&String> {
34 | self.info_cache
35 | .iter()
36 | .filter_map(|(profile_name, profile)| {
37 | if profile.hosted_domain == hosted_domain {
38 | Some(profile_name)
39 | } else {
40 | None
41 | }
42 | })
43 | .collect()
44 | }
45 | pub fn profile_by_name(&self, name: &str) -> Option<&str> {
46 | // Prefer direct profile name matches
47 | if let Some((profile_name, _)) = self.info_cache.get_key_value(name) {
48 | return Some(profile_name);
49 | }
50 |
51 | let matched_name = Some(name.to_owned());
52 | let found = self.info_cache.iter().find(|(_, profile)| {
53 | profile.name == matched_name || profile.shortcut_name == matched_name
54 | });
55 |
56 | if let Some((profile_name, _)) = found {
57 | Some(profile_name)
58 | } else {
59 | None
60 | }
61 | }
62 | }
63 |
64 | #[derive(Serialize, Deserialize)]
65 | struct State {
66 | profile: ProfilesData,
67 | }
68 |
69 | pub fn read_profiles_from_file>(path: P) -> Result {
70 | let state: State = {
71 | let file = File::open(path).map_err(Error::InvalidFile)?;
72 | let reader = BufReader::new(file);
73 | serde_json::from_reader(reader).map_err(Error::InvalidJson)?
74 | };
75 |
76 | Ok(state.profile)
77 | }
78 |
--------------------------------------------------------------------------------
/assets/changelog-template.md:
--------------------------------------------------------------------------------
1 | #
bichrome {this_version}
2 |
3 | bichrome is a simple utility for Windows and macOS that you configure as your default browser, which then will choose which browser to open a URL in based on the configuration you specify. It also supports picking a particular Chrome profile -- either by specifying a profile name, or by specifying the "hosted domain" of your profile if you're using Google Workspace. You can read more in the
4 |
5 | ## Installation
6 |
7 | ### Windows
8 |
9 | 1. Download `bichrome-win64.exe` from [this release][windows_download].
10 | 2. Move it to its permanent home -- e.g. creating a directory in `%localappdata%\Programs` called bichrome and putting it there.
11 | 3. Run `bichrome-win64.exe` once by double clicking it. This will register bichrome as a potential browser.
12 | 4. Configure bichrome as your default browser by opening "Default Apps" (You can open your start menu and just type "Default Apps") and clicking the icon under "Web browser", and picking bichrome.
13 |
14 | That's it! Now just create a configuration file named `bichrome_config.json` next to `bichrome-win64.exe` (see [the configuration section][config_readme] for details) -- a good starting place is to download & edit the [example config][example_config]]
15 |
16 |
17 | ### macOS
18 |
19 | 1. Download `bichrome-macos.zip` from [this release][macos_download].
20 | 2. Extract it and copy the `bichrome` app e.g. to `/Applications`
21 | 3. Open System Preferences and search for "Default Browser"
22 | 4. Pick bichrome as your default browser.
23 |
24 | That's it! Now just create a configuration file named `bichrome_config.json` in `~/Library/Application Support/com.bitspatter.bichrome/bichrome_config.json` (see [the configuration section][config_readme] for details) -- a good starting place is to download & edit the [example config][example_config].
25 |
26 | ## Changes in {this_version}
27 | {{ if changelog.scopes }}
28 | {{ for scope in changelog.scopes }}
29 | ### {scope.title}
30 |
31 | {{ for category in scope.categories -}}
32 | {{ for change in category.changes -}}
33 | * **{category.title}**: {change}
34 | {{ endfor -}}
35 | {{- endfor -}}
36 | {{ endfor }}
37 |
38 | See [the full list of changes][commits_link].
39 | {{ else }}
40 | No significant user changes, see [the full list of changes][commits_link].
41 | {{ endif }}
42 |
43 | [commits_link]: {commits_link}
44 | [windows_download]: {repo_url}/releases/download/{this_version}/bichrome-win64.exe
45 | [macos_download]: {repo_url}/releases/download/{this_version}/bichrome-macos.zip
46 | [example_config]: {repo_url}/releases/download/{this_version}/bichrome_example_config.json
47 | [config_readme]: {repo_url}/blob/{this_version}/README.md#bichrome_configjson
--------------------------------------------------------------------------------
/src/config.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 |
3 | use log::trace;
4 | use webextension_pattern::Pattern;
5 |
6 | use crate::{
7 | chrome_local_state::{self, read_profiles_from_file},
8 | os::get_chrome_local_state_path,
9 | };
10 | use serde::{Deserialize, Serialize};
11 | use std::{collections::HashMap, path::PathBuf};
12 | use std::fs::File;
13 | use std::io::BufReader;
14 | use std::path::Path;
15 | use thiserror::Error;
16 | use url::Url;
17 |
18 | #[derive(Error, Debug)]
19 | pub enum Error {
20 | #[error("could not read configuration file")]
21 | InvalidFile(#[source] std::io::Error),
22 | #[error("could not parse configuration file")]
23 | InvalidJson(#[source] serde_json::Error),
24 | #[error("could not find declaration of profile {0}")]
25 | MissingProfile(String),
26 | #[error("unable to retrieve path for Chrome's Local State")]
27 | CantLocateChromeLocalState,
28 | #[error("unable to parse Chrome's Local State")]
29 | CantParseChromeLocalState(#[source] chrome_local_state::Error),
30 | #[error("no profile in Chrome's Local State matched domain '{0}' specified in config")]
31 | InvalidHostedDomain(String),
32 | #[error("no profile in Chrome's Local State matched name '{0}' specified in config")]
33 | InvalidProfileName(String),
34 | #[error("failed to parse received url {0:?}")]
35 | InvalidUrlPassedIn(String, #[source] url::ParseError),
36 | }
37 |
38 | type Result = std::result::Result;
39 |
40 | #[derive(Serialize, Deserialize, Debug, Clone)]
41 | #[serde(untagged)]
42 | pub enum ChromeProfile {
43 | ByName {
44 | #[serde(rename = "profile")]
45 | name: String,
46 | },
47 | ByHostedDomain {
48 | hosted_domain: String,
49 | },
50 | None {},
51 | }
52 |
53 | impl ChromeProfile {
54 | pub fn get_argument(&self) -> Result