├── BDDefaultBrowser.h ├── BDDefaultBrowser.m ├── BrowserDefault.plist ├── Makefile ├── PrivateFrameworkHeaders.h ├── StableBuilds └── com.lpane.browserdefault_1.9.9_iphoneos-arm.deb ├── Tweak.xm ├── browserdefaultprefs ├── BDPRootListController.h ├── BDPRootListController.m ├── Makefile ├── Resources │ ├── Info.plist │ ├── Root.plist │ ├── icon.png │ ├── icon@2x.png │ └── icon@3x.png ├── entry.plist └── icon_hi-rez.png ├── control └── readme.md /BDDefaultBrowser.h: -------------------------------------------------------------------------------- 1 | @interface BDDefaultBrowser : NSObject 2 | 3 | @property (readonly) bool percentEscapes; 4 | @property (readonly) NSString *scheme; 5 | @property (readonly) NSString *bundleID; 6 | 7 | + (instancetype)browserFromPrefs:(NSMutableDictionary *)prefs; 8 | - (instancetype)initWithBundle:(NSString *)bundle scheme:(NSString *)scheme percentEscapes:(bool)percentEscapes; 9 | - (NSURL *)modifiedURL:(NSURL *)url; 10 | @end 11 | -------------------------------------------------------------------------------- /BDDefaultBrowser.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "BDDefaultBrowser.h" 3 | 4 | @implementation BDDefaultBrowser 5 | 6 | + (instancetype)browserFromPrefs:(NSMutableDictionary *)prefs { 7 | NSString *bundle = [prefs valueForKey:@"bundle"]; 8 | BDDefaultBrowser *browser = [[self class] alloc]; 9 | 10 | //presets 11 | if([bundle isEqualToString:@"com.apple.mobilesafari"]) return [browser initWithBundle:bundle scheme:@"" percentEscapes:false]; 12 | if([bundle isEqualToString:@"org.mozilla.ios.Firefox"]) return [browser initWithBundle:bundle scheme:@"firefox://open-url?url=https://" percentEscapes:true]; 13 | if([bundle isEqualToString:@"org.mozilla.ios.Focus"]) return [browser initWithBundle:bundle scheme:@"firefox-focus://open-url?url=" percentEscapes:true]; 14 | if([bundle isEqualToString:@"com.google.chrome.ios"]) return [browser initWithBundle:bundle scheme:@"googlechromes://" percentEscapes:false]; 15 | if([bundle isEqualToString:@"com.brave.ios.browser"]) return [browser initWithBundle:bundle scheme:@"brave://open-url?url=https://" percentEscapes:true]; 16 | if([bundle isEqualToString:@"com.cloudmosa.PuffinFree"]) return [browser initWithBundle:bundle scheme:@"" percentEscapes:false]; 17 | if([bundle isEqualToString:@"RAPS.appstore.com.dolphin.browser.iphone"]) return [browser initWithBundle:bundle scheme:@"" percentEscapes:false]; 18 | if([bundle isEqualToString:@"com.lipslabs.cake"]) return [browser initWithBundle:bundle scheme:@"cakebrowser://open-url?url=" percentEscapes:true]; 19 | if([bundle isEqualToString:@"com.opera.OperaTouch"]) return [browser initWithBundle:bundle scheme:@"touch-https://" percentEscapes:true]; 20 | if([bundle isEqualToString:@"com.duckduckgo.mobile.ios"]) return [browser initWithBundle:bundle scheme:@"ddgQuickLink://" percentEscapes:false]; 21 | if([bundle isEqualToString:@"de.icab.iCabMobile"]) return [browser initWithBundle:bundle scheme:@"x-icabmobile://x-callback-url/open?destination=newTab&fullscreen=no&url=" percentEscapes:true]; 22 | 23 | //custom browser 24 | return [browser initWithBundle:[prefs valueForKey:@"customBundleID"] scheme:[prefs valueForKey:@"customScheme"] percentEscapes:[[prefs valueForKey:@"customPercentEscapes"] boolValue]]; 25 | } 26 | 27 | - (instancetype)initWithBundle:(NSString *)bundle scheme:(NSString *)scheme percentEscapes:(bool)percentEscapes { 28 | _bundleID = bundle; 29 | _scheme = scheme; 30 | _percentEscapes = percentEscapes; 31 | 32 | return self; 33 | } 34 | 35 | - (NSURL *)modifiedURL:(NSURL *)url { 36 | if([[url scheme] isEqualToString:@"x-web-search"]) { 37 | NSString *query = [[url absoluteString] substringFromIndex:16]; 38 | url = [NSURL URLWithString:[NSString stringWithFormat:@"google.com/search?q=%@", query]]; 39 | } 40 | 41 | NSString *strungURL = [url absoluteString]; 42 | 43 | //strip url of schemes 44 | while([url scheme] != nil) { 45 | strungURL = [strungURL substringFromIndex:[[url scheme] length] + 3]; 46 | url = [NSURL URLWithString:strungURL]; 47 | } 48 | 49 | if(_percentEscapes) 50 | strungURL = [strungURL stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@""]]; 51 | return [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", _scheme, strungURL]]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /BrowserDefault.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.apple.FrontBoardServices" 5 | ); 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = armv7 arm64 arm64e 2 | include $(THEOS)/makefiles/common.mk 3 | 4 | TWEAK_NAME = BrowserDefault 5 | BrowserDefault_FILES = Tweak.xm 6 | 7 | ADDITIONAL_OBJCFLAGS = -fobjc-arc 8 | 9 | include $(THEOS_MAKE_PATH)/tweak.mk 10 | 11 | after-install:: 12 | install.exec "killall -9 SpringBoard" 13 | 14 | SUBPROJECTS += browserdefaultprefs 15 | include $(THEOS_MAKE_PATH)/aggregate.mk 16 | -------------------------------------------------------------------------------- /PrivateFrameworkHeaders.h: -------------------------------------------------------------------------------- 1 | @interface FBSOpenApplicationOptions : NSObject 2 | @property (nonatomic,copy) NSDictionary * dictionary; 3 | @end 4 | 5 | @interface FBSystemServiceOpenApplicationRequest : NSObject 6 | @property (nonatomic,copy) NSString * bundleIdentifier; 7 | @end 8 | 9 | -------------------------------------------------------------------------------- /StableBuilds/com.lpane.browserdefault_1.9.9_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LorenzoPane/browserdefault/36e4e01b5ac97ebf96530f7acb8ad4dd666a8574/StableBuilds/com.lpane.browserdefault_1.9.9_iphoneos-arm.deb -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import "BDDefaultBrowser.m" 2 | #import "PrivateFrameworkHeaders.h" 3 | 4 | %hook FBSystemServiceOpenApplicationRequest 5 | 6 | - (void)setBundleIdentifier:(NSString *)arg1 { 7 | if([arg1 isEqualToString:@"com.apple.mobilesafari"]) 8 | arg1 = [[%c(BDDefaultBrowser) browserFromPrefs:[[NSMutableDictionary alloc] initWithContentsOfFile: @"/var/mobile/Library/Preferences/com.lpane.browserdefaultpref.plist"]] bundleID]; 9 | %orig; 10 | } 11 | 12 | - (void)setOptions:(FBSOpenApplicationOptions *)arg1 { 13 | BDDefaultBrowser *defaultBrowser = [%c(BDDefaultBrowser) browserFromPrefs:[[NSMutableDictionary alloc] initWithContentsOfFile: @"/var/mobile/Library/Preferences/com.lpane.browserdefaultpref.plist"]]; 14 | if(([[self bundleIdentifier] isEqualToString:@"com.apple.mobilesafari"] || [[self bundleIdentifier] isEqualToString:[defaultBrowser bundleID]]) && [[arg1 dictionary] objectForKey:@"__PayloadURL"]) { 15 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 16 | [dict addEntriesFromDictionary: [arg1 dictionary]]; 17 | [dict setObject:[defaultBrowser modifiedURL:[dict objectForKey:@"__PayloadURL"]] forKey:@"__PayloadURL"]; 18 | 19 | [arg1 setDictionary:dict]; 20 | } 21 | %orig; 22 | } 23 | 24 | %end 25 | -------------------------------------------------------------------------------- /browserdefaultprefs/BDPRootListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface BDPRootListController : PSListController 4 | - (void)openLink; 5 | - (NSArray *)specifiers; 6 | @end 7 | -------------------------------------------------------------------------------- /browserdefaultprefs/BDPRootListController.m: -------------------------------------------------------------------------------- 1 | #include "BDPRootListController.h" 2 | 3 | @implementation BDPRootListController 4 | 5 | - (NSArray *)specifiers { 6 | if (!_specifiers) { 7 | _specifiers = [[self loadSpecifiersFromPlistName:@"Root" target:self] retain]; 8 | } 9 | return _specifiers; 10 | } 11 | 12 | - (void)openLink { 13 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://github.com/LorenzoPane/browserdefault"] 14 | options:@{} 15 | completionHandler:nil]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /browserdefaultprefs/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | BUNDLE_NAME = BrowserDefaultPrefs 4 | BrowserDefaultPrefs_FILES = BDPRootListController.m 5 | BrowserDefaultPrefs_INSTALL_PATH = /Library/PreferenceBundles 6 | BrowserDefaultPrefs_FRAMEWORKS = UIKit 7 | BrowserDefaultPrefs_PRIVATE_FRAMEWORKS = Preferences 8 | 9 | include $(THEOS_MAKE_PATH)/bundle.mk 10 | 11 | internal-stage:: 12 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 13 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/BrowserDefaultPrefs.plist$(ECHO_END) 14 | -------------------------------------------------------------------------------- /browserdefaultprefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | BrowserDefaultPrefs 9 | CFBundleIdentifier 10 | com.lpane.browserdefaultprefs 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | NSPrincipalClass 22 | BDPRootListController 23 | 24 | 25 | -------------------------------------------------------------------------------- /browserdefaultprefs/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | title 6 | Browser Default 7 | items 8 | 9 | 10 | cell 11 | PSGroupCell 12 | label 13 | Preset Browser 14 | 15 | 16 | cell 17 | PSLinkListCell 18 | label 19 | Default Browser 20 | key 21 | bundle 22 | defaults 23 | com.lpane.browserdefaultpref 24 | default 25 | 0 26 | detail 27 | PSListItemsController 28 | validValues 29 | 30 | com.apple.mobilesafari 31 | org.mozilla.ios.Firefox 32 | org.mozilla.ios.Focus 33 | com.google.chrome.ios 34 | com.brave.ios.browser 35 | com.cloudmosa.PuffinFree 36 | RAPS.appstore.com.dolphin.browser.iphone 37 | com.lipslabs.cake 38 | com.opera.OperaTouch 39 | com.duckduckgo.mobile.ios 40 | de.icab.iCabMobile 41 | custom 42 | 43 | validTitles 44 | 45 | Safari 46 | Firefox 47 | Firefox Focus 48 | Google Chrome 49 | Brave 50 | Puffin 51 | Dolphin X 52 | Cake 53 | Opera Touch 54 | DuckDuckGo 55 | iCabMobile 56 | Custom (specify options below) 57 | 58 | 59 | 60 | cell 61 | PSGroupCell 62 | label 63 | Custom Browser 64 | 65 | 66 | defaults 67 | com.lpane.browserdefaultpref 68 | key 69 | customBundleID 70 | cell 71 | PSEditTextCell 72 | label 73 | Bundle ID 74 | placeholder 75 | com.apple.safari 76 | 77 | 78 | defaults 79 | com.lpane.browserdefaultpref 80 | key 81 | customScheme 82 | cell 83 | PSEditTextCell 84 | placeholder 85 | scheme:// 86 | label 87 | URL Scheme (if applicable) 88 | 89 | 90 | defaults 91 | com.lpane.browserdefaultpref 92 | key 93 | customPercentEscapes 94 | default 95 | 96 | cell 97 | PSSwitchCell 98 | label 99 | Use Percent Escapes 100 | 101 | 102 | cell 103 | PSGroupCell 104 | label 105 | Test Selection 106 | 107 | 108 | cell 109 | PSButtonCell 110 | label 111 | Open Github 112 | action 113 | openLink 114 | 115 | 116 | cell 117 | PSGroupCell 118 | footerText 119 | It may take a moment to update 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /browserdefaultprefs/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LorenzoPane/browserdefault/36e4e01b5ac97ebf96530f7acb8ad4dd666a8574/browserdefaultprefs/Resources/icon.png -------------------------------------------------------------------------------- /browserdefaultprefs/Resources/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LorenzoPane/browserdefault/36e4e01b5ac97ebf96530f7acb8ad4dd666a8574/browserdefaultprefs/Resources/icon@2x.png -------------------------------------------------------------------------------- /browserdefaultprefs/Resources/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LorenzoPane/browserdefault/36e4e01b5ac97ebf96530f7acb8ad4dd666a8574/browserdefaultprefs/Resources/icon@3x.png -------------------------------------------------------------------------------- /browserdefaultprefs/entry.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | BrowserDefaultPrefs 9 | cell 10 | PSLinkCell 11 | detail 12 | BDPRootListController 13 | icon 14 | icon.png 15 | isController 16 | 17 | label 18 | Default Browser 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /browserdefaultprefs/icon_hi-rez.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LorenzoPane/browserdefault/36e4e01b5ac97ebf96530f7acb8ad4dd666a8574/browserdefaultprefs/icon_hi-rez.png -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.lpane.browserdefault 2 | Name: BrowserDefault 3 | Depends: mobilesubstrate,preferenceloader 4 | Version: 1.9.9 5 | Architecture: iphoneos-arm 6 | Description: BrowserDefault allows users to choose the browser links are opened in. 7 | Maintainer: lpane 8 | Author: lpane 9 | Section: Tweaks 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # BrowserDefault 2 | BrowserDefault allows users to choose the browser links are opened in. 3 | 4 | # Support 5 | BrowserDefault currently includes presets for the following browsers: 6 | - Safari (obviously) 7 | - Firefox 8 | - Firefox Focus 9 | - Google Chrome 10 | - Brave 11 | - Puffin 12 | - Dolphin X 13 | - Cake 14 | - Opera 15 | - DuckDuckGo 16 | - iCabMobile 17 | 18 | # Usage 19 | Users can change their default browser to a preset by going to the BrowserDefault panel in the stock Settings app. Note that it may take several seconds for the settings to update. 20 | To use a browser that does not have a preset, it is a bit more complex. First input the bundle ID for the browser. If you aren't sure of the bundle ID, you can find it with the BundleIDXI cydia tweak. After that, test to see if it works using the button at the bottom of the preference pane. If nothing happens, the app likely requires a custom URL scheme. These typically look something like `appname://open-url?url=`. Lastly, some browsers require custom encoding of the url that replaces punctuation with escape sequences. It is fastest to just test clicking a link with both values of the final toggle. If you have tried these steps to no avail, get in touch with me using the issues tab on github and I will look into it once I have some time. 21 | 22 | # Installation 23 | This package can be installed from the [Packix](https://repo.packix.com) repo or downloaded directly as a deb from the `StableBuilds` directory. 24 | 25 | # Thanks 26 | This tweak was suggested by [u/iTsJavi](https://www.reddit.com/user/iTsJavi) on their [r/TweakBounty](https://www.reddit.com/r/TweakBounty) post: [Change Default Browser](https://www.reddit.com/r/TweakBounty/comments/b2yj6t/101211_change_default_browser/). The bounty was also supported by [u/kurtistrippisdead](https://www.reddit.com/u/kurtistrippisdead). 27 | --------------------------------------------------------------------------------