feat: add app.getApplicationNameForProtocol API (#20399)
* Add GetApplicationNameForProtocol. * Fix Windows implementation. * Fix up test. * Add documentation. * Implement for real on Linux using xdg-mime. Also ensure we allow blocking calls here to avoid errant DCHECKing. * Improve docs for Linux. * Clean up tests. * Add a note about not relying on the precise format. * Update docs/api/app.md Co-Authored-By: Shelley Vohr <codebytere@github.com> * Remove needless `done()`s from tests. * Use vector list initialization. * Add a simple test for isDefaultProtocolClient. * Remove unneeded include and skip a test on Linux CI. * We no longer differentiate between CI and non-CI test runs.
This commit is contained in:
parent
24939e8fa4
commit
9b01bb00d2
7 changed files with 183 additions and 20 deletions
|
@ -25,6 +25,14 @@ namespace electron {
|
|||
const char kXdgSettings[] = "xdg-settings";
|
||||
const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler";
|
||||
|
||||
// The use of the ForTesting flavors is a hack workaround to avoid having to
|
||||
// patch these as friends into the associated guard classes.
|
||||
class LaunchXdgUtilityScopedAllowBaseSyncPrimitives
|
||||
: public base::ScopedAllowBaseSyncPrimitivesForTesting {};
|
||||
|
||||
class GetXdgAppOutputScopedAllowBlocking
|
||||
: public base::ScopedAllowBlockingForTesting {};
|
||||
|
||||
bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) {
|
||||
*exit_code = EXIT_FAILURE;
|
||||
int devnull = open("/dev/null", O_RDONLY);
|
||||
|
@ -39,24 +47,37 @@ bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) {
|
|||
|
||||
if (!process.IsValid())
|
||||
return false;
|
||||
LaunchXdgUtilityScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
|
||||
return process.WaitForExit(exit_code);
|
||||
}
|
||||
|
||||
base::Optional<std::string> GetXdgAppOutput(
|
||||
const std::vector<std::string>& argv) {
|
||||
std::string reply;
|
||||
int success_code;
|
||||
GetXdgAppOutputScopedAllowBlocking allow_blocking;
|
||||
bool ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply,
|
||||
&success_code);
|
||||
|
||||
if (!ran_ok || success_code != EXIT_SUCCESS)
|
||||
return base::Optional<std::string>();
|
||||
|
||||
return base::make_optional(reply);
|
||||
}
|
||||
|
||||
bool SetDefaultWebClient(const std::string& protocol) {
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
|
||||
std::vector<std::string> argv;
|
||||
argv.emplace_back(kXdgSettings);
|
||||
argv.emplace_back("set");
|
||||
std::vector<std::string> argv = {kXdgSettings, "set"};
|
||||
if (!protocol.empty()) {
|
||||
argv.emplace_back(kXdgSettingsDefaultSchemeHandler);
|
||||
argv.push_back(protocol);
|
||||
argv.emplace_back(protocol);
|
||||
}
|
||||
std::string desktop_name;
|
||||
if (!env->GetVar("CHROME_DESKTOP", &desktop_name)) {
|
||||
return false;
|
||||
}
|
||||
argv.push_back(desktop_name);
|
||||
argv.emplace_back(desktop_name);
|
||||
|
||||
int exit_code;
|
||||
bool ran_ok = LaunchXdgUtility(argv, &exit_code);
|
||||
|
@ -91,27 +112,18 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol,
|
|||
if (protocol.empty())
|
||||
return false;
|
||||
|
||||
std::vector<std::string> argv;
|
||||
argv.emplace_back(kXdgSettings);
|
||||
argv.emplace_back("check");
|
||||
argv.emplace_back(kXdgSettingsDefaultSchemeHandler);
|
||||
argv.push_back(protocol);
|
||||
std::string desktop_name;
|
||||
if (!env->GetVar("CHROME_DESKTOP", &desktop_name))
|
||||
return false;
|
||||
argv.push_back(desktop_name);
|
||||
|
||||
std::string reply;
|
||||
int success_code;
|
||||
bool ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply,
|
||||
&success_code);
|
||||
|
||||
if (!ran_ok || success_code != EXIT_SUCCESS)
|
||||
const std::vector<std::string> argv = {kXdgSettings, "check",
|
||||
kXdgSettingsDefaultSchemeHandler,
|
||||
protocol, desktop_name};
|
||||
const auto output = GetXdgAppOutput(argv);
|
||||
if (!output)
|
||||
return false;
|
||||
|
||||
// Allow any reply that starts with "yes".
|
||||
return base::StartsWith(reply, "yes", base::CompareCase::SENSITIVE) ? true
|
||||
: false;
|
||||
return base::StartsWith(output.value(), "yes", base::CompareCase::SENSITIVE);
|
||||
}
|
||||
|
||||
// Todo implement
|
||||
|
@ -120,6 +132,14 @@ bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,
|
|||
return false;
|
||||
}
|
||||
|
||||
base::string16 Browser::GetApplicationNameForProtocol(const GURL& url) {
|
||||
const std::vector<std::string> argv = {
|
||||
"xdg-mime", "query", "default",
|
||||
std::string("x-scheme-handler/") + url.scheme()};
|
||||
|
||||
return base::ASCIIToUTF16(GetXdgAppOutput(argv).value_or(std::string()));
|
||||
}
|
||||
|
||||
bool Browser::SetBadgeCount(int count) {
|
||||
if (IsUnityRunning()) {
|
||||
unity::SetDownloadCount(count);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue