├── test.html
├── DefaultBrowser
├── Assets.xcassets
│ ├── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── DefaultBrowserPlain128@1x.png
│ │ ├── DefaultBrowserPlain128@2x.png
│ │ ├── DefaultBrowserPlain16@1x.png
│ │ ├── DefaultBrowserPlain16@2x.png
│ │ ├── DefaultBrowserPlain256@1x.png
│ │ ├── DefaultBrowserPlain256@2x.png
│ │ ├── DefaultBrowserPlain32@1x.png
│ │ ├── DefaultBrowserPlain32@2x.png
│ │ ├── DefaultBrowserPlain512@1x.png
│ │ ├── DefaultBrowserPlain512@2x.png
│ │ └── Contents.json
│ ├── StatusBarButtonImage.imageset
│ │ ├── DefaultBrowser@1x.png
│ │ ├── DefaultBrowser@2x.png
│ │ └── Contents.json
│ └── StatusBarButtonImageError.imageset
│ │ ├── DefaultBrowserError@1x.png
│ │ ├── DefaultBrowserError@2x.png
│ │ └── Contents.json
├── Bundle.swift
├── SystemUtilities.swift
├── Info.plist
├── Intents.swift
├── Defaults.swift
├── Intents.intentdefinition
├── ImageTransforms.swift
├── AppDelegate.swift
└── Base.lproj
│ └── MainMenu.xib
├── Default Browser.entitlements
├── .github
└── workflows
│ ├── release.yml
│ └── tag.yml
├── README.md
├── .gitignore
├── IconGenerator
└── main.swift
└── DefaultBrowser.xcodeproj
├── xcshareddata
└── xcschemes
│ └── IconGenerator.xcscheme
└── project.pbxproj
/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | It worked?
4 |
5 |
6 |
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain128@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain128@1x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain128@2x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain16@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain16@1x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain16@2x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain256@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain256@1x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain256@2x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain32@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain32@1x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain32@2x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain512@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain512@1x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/DefaultBrowserPlain512@2x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/StatusBarButtonImage.imageset/DefaultBrowser@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/StatusBarButtonImage.imageset/DefaultBrowser@1x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/StatusBarButtonImage.imageset/DefaultBrowser@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/StatusBarButtonImage.imageset/DefaultBrowser@2x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/StatusBarButtonImageError.imageset/DefaultBrowserError@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/StatusBarButtonImageError.imageset/DefaultBrowserError@1x.png
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/StatusBarButtonImageError.imageset/DefaultBrowserError@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apexskier/DefaultBrowser/HEAD/DefaultBrowser/Assets.xcassets/StatusBarButtonImageError.imageset/DefaultBrowserError@2x.png
--------------------------------------------------------------------------------
/Default Browser.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release management
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | release:
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - uses: apexskier/github-release-commenter@v1
13 | with:
14 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
15 | comment-template: This will be shipped in version {release_link}.
16 |
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/StatusBarButtonImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "DefaultBrowser@1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "DefaultBrowser@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
--------------------------------------------------------------------------------
/DefaultBrowser/Bundle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Bundle.swift
3 | // Default Browser
4 | //
5 | // Created by Cameron Little on 2022-11-26.
6 | // Copyright © 2022 Cameron Little. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Bundle {
12 | var appName: String? {
13 | let infoDict = (self.localizedInfoDictionary ?? self.infoDictionary)
14 | let localizedName = infoDict?["CFBundleDisplayName"] ?? infoDict?["CFBundleName"]
15 | return localizedName as? String
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/StatusBarButtonImageError.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "DefaultBrowserError@1x.png",
5 | "idiom" : "mac",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "DefaultBrowserError@2x.png",
10 | "idiom" : "mac",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "author" : "xcode",
16 | "version" : 1
17 | },
18 | "properties" : {
19 | "template-rendering-intent" : "template"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/.github/workflows/tag.yml:
--------------------------------------------------------------------------------
1 | name: Tag creation
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | release:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Get the version
14 | id: version
15 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
16 | shell: bash
17 |
18 | - uses: apexskier/github-semver-parse@v1
19 | id: semver
20 | with:
21 | version: ${{ steps.version.outputs.VERSION }}
22 |
23 | - name: Release
24 | if: ${{ steps.semver.outputs.version }}
25 | uses: softprops/action-gh-release@v1
26 | with:
27 | tag_name: ${{ steps.version.outputs.VERSION }}
28 | prerelease: ${{ !!steps.semver.outputs.prerelease }}
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Default Browser
2 |
3 | Default Browser replaces macOS's system web browser setting with a flexible, convenient utility that opens links with your most recently used browser.
4 |
5 | https://defaultbrowser.app
6 |
7 | ## Features
8 |
9 | - **Intelligent link handling** Opens external links with your last used browser.
10 | - **Quick browser toggle** Keyboard shortcuts from the menu bar.
11 | - **Menu bar preview** Quick reference of the currently active browser.
12 | - **Blocklist** Prevent browsers from automatically opening.
13 | - **Legacy behavior** Select your primary browser to simulate traditional behavior.
14 | - **Shortcuts support** Force a specific browser with Siri Shortcuts
15 |
16 | ## Notes
17 |
18 | - No longer can automatically register as `html` file handler. At some point in the past, Apple restricted the ability of apps to register as the default opener for the UTType `public.html` (https://github.com/Hammerspoon/hammerspoon/issues/2205#issuecomment-541972453). Please [do this manually](https://support.apple.com/guide/mac-help/choose-an-app-to-open-a-file-on-mac-mh35597/mac) now
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 | *.xcworkspace
26 | !default.xcworkspace
27 |
28 | ## Obj-C/Swift specific
29 | *.hmap
30 | *.ipa
31 |
32 | # CocoaPods
33 | #
34 | # We recommend against adding the Pods directory to your .gitignore. However
35 | # you should judge for yourself, the pros and cons are mentioned at:
36 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
37 | #
38 | # Pods/
39 |
40 | # Carthage
41 | #
42 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
43 | # Carthage/Checkouts
44 |
45 | Carthage/Build
46 |
47 | # fastlane
48 | #
49 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
50 | # screenshots whenever they are needed.
51 |
52 | fastlane/report.xml
53 | fastlane/screenshots
54 |
55 | # used when switching from/to gh-pages
56 | /node_modules
57 | /icons
58 |
--------------------------------------------------------------------------------
/DefaultBrowser/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "DefaultBrowserPlain16@1x.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "DefaultBrowserPlain16@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "DefaultBrowserPlain32@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "DefaultBrowserPlain32@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "DefaultBrowserPlain128@1x.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "DefaultBrowserPlain128@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "DefaultBrowserPlain256@1x.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "DefaultBrowserPlain256@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "DefaultBrowserPlain512@1x.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "DefaultBrowserPlain512@2x.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/IconGenerator/main.swift:
--------------------------------------------------------------------------------
1 | //
2 | // main.swift
3 | // IconGenerator
4 | //
5 | // Created by Cameron Little on 2025-05-08.
6 | // Copyright © 2025 Cameron Little. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import AppKit
11 |
12 | let browsers = getAllBrowsers()
13 |
14 | let workspace = NSWorkspace.shared
15 |
16 | print(CommandLine.arguments)
17 | if CommandLine.arguments.count < 3 {
18 | print("usage: \(CommandLine.arguments[0])