in src/modules/launcher/Wox.Plugin/SharedCommands/DefaultBrowserInfo.cs [66:223]
public static void Update()
{
lock (_updateLock)
{
try
{
string progId = GetRegistryValue(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice",
"ProgId");
// The `?` argument doesn't work on opera, so we get the user's default search engine:
if (progId.StartsWith("Opera", StringComparison.OrdinalIgnoreCase))
{
// Opera user preferences file:
string prefFile;
if (progId.Contains("GX", StringComparison.OrdinalIgnoreCase))
{
Name = "Opera GX";
prefFile = System.IO.File.ReadAllText($"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\Opera Software\\Opera GX Stable\\Preferences");
}
else
{
Name = "Opera";
prefFile = System.IO.File.ReadAllText($"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\Opera Software\\Opera Stable\\Preferences");
}
// "default_search_provider_data" doesn't exist if the user hasn't searched for the first time,
// therefore we set `url` to opera's default search engine:
string url = "https://www.google.com/search?client=opera&q={0}&sourceid=opera";
using (System.Text.Json.JsonDocument doc = System.Text.Json.JsonDocument.Parse(prefFile))
{
if (doc.RootElement.TryGetProperty("default_search_provider_data", out var element))
{
if (element.TryGetProperty("template_url_data", out element))
{
if (element.TryGetProperty("url", out element))
{
url = element.GetString();
}
}
}
}
url = url
.Replace("{searchTerms}", "{0}", StringComparison.Ordinal)
.Replace("{inputEncoding}", "UTF-8", StringComparison.Ordinal)
.Replace("{outputEncoding}", "UTF-8", StringComparison.Ordinal);
int startIndex = url.IndexOf('}', StringComparison.Ordinal) + 1;
// In case there are other url parameters (e.g. `&foo={bar}`), remove them:
for (int i = url.IndexOf("}", startIndex, StringComparison.Ordinal);
i != -1;
i = url.IndexOf("}", startIndex, StringComparison.Ordinal))
{
for (int j = i - 1; j > 0; --j)
{
if (url[j] == '&')
{
url = url.Remove(j, i - j + 1);
break;
}
}
}
SearchEngineUrl = url;
}
else
{
string appName = GetRegistryValue($@"HKEY_CLASSES_ROOT\{progId}\Application", "ApplicationName")
?? GetRegistryValue($@"HKEY_CLASSES_ROOT\{progId}", "FriendlyTypeName");
if (appName != null)
{
// Handle indirect strings:
if (appName.StartsWith("@", StringComparison.Ordinal))
{
appName = GetIndirectString(appName);
}
appName = appName
.Replace("URL", null, StringComparison.OrdinalIgnoreCase)
.Replace("HTML", null, StringComparison.OrdinalIgnoreCase)
.Replace("Document", null, StringComparison.OrdinalIgnoreCase)
.TrimEnd();
}
Name = appName;
SearchEngineUrl = null;
}
string programLocation =
// Resolve App Icon (UWP)
GetRegistryValue(
$@"HKEY_CLASSES_ROOT\{progId}\Application",
"ApplicationIcon")
// Resolves default file association icon (UWP + Normal)
?? GetRegistryValue($@"HKEY_CLASSES_ROOT\{progId}\DefaultIcon", null);
// "Handles 'Indirect Strings' (UWP programs)"
// Using Ordinal since this is internal and used with a symbol
if (programLocation.StartsWith("@", StringComparison.Ordinal))
{
string directProgramLocation = GetIndirectString(programLocation);
Path = string.Equals(FilePath.GetExtension(directProgramLocation), ".exe", StringComparison.Ordinal)
? directProgramLocation
: null;
}
else
{
// Using Ordinal since this is internal and used with a symbol
var indexOfComma = programLocation.IndexOf(',', StringComparison.Ordinal);
Path = indexOfComma > 0
? programLocation.Substring(0, indexOfComma)
: programLocation;
}
if (string.IsNullOrEmpty(Path))
{
throw new Exception("Browser path is null or empty.");
}
}
catch (Exception e)
{
Path = null;
Name = null;
SearchEngineUrl = null;
Log.Exception("Exception when retrieving browser path/name. Path and Name are null.", e, typeof(DefaultBrowserInfo));
}
string GetRegistryValue(string registryLocation, string valueName)
{
return Microsoft.Win32.Registry.GetValue(registryLocation, valueName, null) as string;
}
string GetIndirectString(string str)
{
var stringBuilder = new StringBuilder(128);
if (NativeMethods.SHLoadIndirectString(
str,
stringBuilder,
(uint)stringBuilder.Capacity,
IntPtr.Zero)
== HRESULT.S_OK)
{
return stringBuilder.ToString();
}
throw new Exception("Could not load indirect string.");
}
}
}