Commit b13491b7 authored by Alexey Baskakov's avatar Alexey Baskakov Committed by Commit Bot

WebApp: Move linux helpers to shell_integration_linux namespace.

Bug: 860581
Change-Id: Id8a879d680bf220d46930543a43b92b1d74d6bcf
Reviewed-on: https://chromium-review.googlesource.com/1159550
Commit-Queue: Alexey Baskakov <loyso@chromium.org>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580469}
parent 91470e7e
......@@ -119,7 +119,7 @@ namespace service_manager {
class ServiceProcessLauncher;
}
namespace shell_integration {
namespace shell_integration_linux {
class LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
}
......@@ -329,7 +329,8 @@ class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
friend class mojo::core::ScopedIPCSupport;
friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
friend class rlz_lib::FinancialPing;
friend class shell_integration::LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
friend class shell_integration_linux::
LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
friend class webrtc::DesktopConfigurationMonitor;
friend class content::ServiceWorkerSubresourceLoader;
friend class viz::HostGpuMemoryBufferManager;
......
......@@ -52,36 +52,7 @@
#include "ui/gfx/image/image_family.h"
#include "url/gurl.h"
namespace shell_integration {
// Allows LaunchXdgUtility to join a process.
// thread_restrictions.h assumes it to be in shell_integration namespace.
class LaunchXdgUtilityScopedAllowBaseSyncPrimitives
: public base::ScopedAllowBaseSyncPrimitives {};
bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) {
// xdg-settings internally runs xdg-mime, which uses mv to move newly-created
// files on top of originals after making changes to them. In the event that
// the original files are owned by another user (e.g. root, which can happen
// if they are updated within sudo), mv will prompt the user to confirm if
// standard input is a terminal (otherwise it just does it). So make sure it's
// not, to avoid locking everything up waiting for mv.
*exit_code = EXIT_FAILURE;
int devnull = open("/dev/null", O_RDONLY);
if (devnull < 0)
return false;
base::LaunchOptions options;
options.fds_to_remap.push_back(std::make_pair(devnull, STDIN_FILENO));
base::Process process = base::LaunchProcess(argv, options);
close(devnull);
if (!process.IsValid())
return false;
LaunchXdgUtilityScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
return process.WaitForExit(exit_code);
}
namespace {
namespace shell_integration_linux {
const char kXdgSettings[] = "xdg-settings";
const char kXdgSettingsDefaultBrowser[] = "default-web-browser";
......@@ -146,7 +117,7 @@ bool SetDefaultWebClient(const std::string& protocol) {
argv.push_back(kXdgSettingsDefaultSchemeHandler);
argv.push_back(protocol);
}
argv.push_back(shell_integration_linux::GetDesktopName(env.get()));
argv.push_back(GetDesktopName(env.get()));
int exit_code;
bool ran_ok = LaunchXdgUtility(argv, &exit_code);
......@@ -163,9 +134,10 @@ bool SetDefaultWebClient(const std::string& protocol) {
// If |protocol| is empty this function checks if Chrome is the default browser,
// otherwise it checks if Chrome is the default handler application for
// |protocol|.
DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) {
shell_integration::DefaultWebClientState GetIsDefaultWebClient(
const std::string& protocol) {
#if defined(OS_CHROMEOS)
return UNKNOWN_DEFAULT;
return shell_integration::UNKNOWN_DEFAULT;
#else
base::AssertBlockingAllowed();
......@@ -180,7 +152,7 @@ DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) {
argv.push_back(kXdgSettingsDefaultSchemeHandler);
argv.push_back(protocol);
}
argv.push_back(shell_integration_linux::GetDesktopName(env.get()));
argv.push_back(GetDesktopName(env.get()));
std::string reply;
int success_code;
......@@ -195,13 +167,13 @@ DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) {
if (!ran_ok || success_code != EXIT_SUCCESS) {
// xdg-settings failed: we can't determine or set the default browser.
return UNKNOWN_DEFAULT;
return shell_integration::UNKNOWN_DEFAULT;
}
// Allow any reply that starts with "yes".
return base::StartsWith(reply, "yes", base::CompareCase::SENSITIVE)
? IS_DEFAULT
: NOT_DEFAULT;
? shell_integration::IS_DEFAULT
: shell_integration::NOT_DEFAULT;
#endif
}
......@@ -220,54 +192,6 @@ std::string GetDesktopBaseName(const std::string& desktop_file_name) {
return desktop_file_name;
}
} // namespace
bool SetAsDefaultBrowser() {
return SetDefaultWebClient(std::string());
}
bool SetAsDefaultProtocolClient(const std::string& protocol) {
return SetDefaultWebClient(protocol);
}
DefaultWebClientSetPermission GetDefaultWebClientSetPermission() {
return SET_DEFAULT_UNATTENDED;
}
base::string16 GetApplicationNameForProtocol(const GURL& url) {
return base::ASCIIToUTF16("xdg-open");
}
DefaultWebClientState GetDefaultBrowser() {
return GetIsDefaultWebClient(std::string());
}
bool IsFirefoxDefaultBrowser() {
std::vector<std::string> argv;
argv.push_back(kXdgSettings);
argv.push_back("get");
argv.push_back(kXdgSettingsDefaultBrowser);
std::string browser;
// We don't care about the return value here.
base::GetAppOutput(base::CommandLine(argv), &browser);
return browser.find("irefox") != std::string::npos;
}
DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol) {
return GetIsDefaultWebClient(protocol);
}
std::string GetWMClassFromAppName(std::string app_name) {
base::i18n::ReplaceIllegalCharactersInPath(&app_name, '_');
base::TrimString(app_name, "_", &app_name);
return app_name;
}
} // namespace shell_integration
namespace shell_integration_linux {
namespace {
#if defined(USE_GLIB)
......@@ -335,6 +259,39 @@ const char kAppListDesktopName[] = "chromium-app-list";
} // namespace
// Allows LaunchXdgUtility to join a process.
// thread_restrictions.h assumes it to be in shell_integration_linux namespace.
class LaunchXdgUtilityScopedAllowBaseSyncPrimitives
: public base::ScopedAllowBaseSyncPrimitives {};
bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) {
// xdg-settings internally runs xdg-mime, which uses mv to move newly-created
// files on top of originals after making changes to them. In the event that
// the original files are owned by another user (e.g. root, which can happen
// if they are updated within sudo), mv will prompt the user to confirm if
// standard input is a terminal (otherwise it just does it). So make sure it's
// not, to avoid locking everything up waiting for mv.
*exit_code = EXIT_FAILURE;
int devnull = open("/dev/null", O_RDONLY);
if (devnull < 0)
return false;
base::LaunchOptions options;
options.fds_to_remap.push_back(std::make_pair(devnull, STDIN_FILENO));
base::Process process = base::LaunchProcess(argv, options);
close(devnull);
if (!process.IsValid())
return false;
LaunchXdgUtilityScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
return process.WaitForExit(exit_code);
}
std::string GetWMClassFromAppName(std::string app_name) {
base::i18n::ReplaceIllegalCharactersInPath(&app_name, '_');
base::TrimString(app_name, "_", &app_name);
return app_name;
}
base::FilePath GetDataWriteLocation(base::Environment* env) {
return base::nix::GetXDGDirectory(env, "XDG_DATA_HOME", ".local/share");
}
......@@ -419,8 +376,7 @@ base::FilePath GetChromeExePath() {
std::string GetProgramClassName(const base::CommandLine& command_line,
const std::string& desktop_file_name) {
std::string class_name =
shell_integration::GetDesktopBaseName(desktop_file_name);
std::string class_name = GetDesktopBaseName(desktop_file_name);
std::string user_data_dir =
command_line.GetSwitchValueNative(switches::kUserDataDir);
// If the user launches with e.g. --user-data-dir=/tmp/my-user-data, set the
......@@ -436,8 +392,7 @@ std::string GetProgramClassClass(const base::CommandLine& command_line,
const std::string& desktop_file_name) {
if (command_line.HasSwitch(switches::kWmClass))
return command_line.GetSwitchValueASCII(switches::kWmClass);
std::string class_class =
shell_integration::GetDesktopBaseName(desktop_file_name);
std::string class_class = GetDesktopBaseName(desktop_file_name);
if (!class_class.empty()) {
// Capitalize the first character like gtk does.
class_class[0] = base::ToUpperASCII(class_class[0]);
......@@ -632,7 +587,7 @@ std::string GetDesktopFileContentsForCommand(
if (no_display)
g_key_file_set_string(key_file, kDesktopEntry, "NoDisplay", "true");
std::string wmclass = shell_integration::GetWMClassFromAppName(app_name);
std::string wmclass = GetWMClassFromAppName(app_name);
g_key_file_set_string(key_file, kDesktopEntry, "StartupWMClass",
wmclass.c_str());
......@@ -741,3 +696,43 @@ bool CreateAppListDesktopShortcut(
#endif
} // namespace shell_integration_linux
namespace shell_integration {
bool SetAsDefaultBrowser() {
return shell_integration_linux::SetDefaultWebClient(std::string());
}
bool SetAsDefaultProtocolClient(const std::string& protocol) {
return shell_integration_linux::SetDefaultWebClient(protocol);
}
DefaultWebClientSetPermission GetDefaultWebClientSetPermission() {
return SET_DEFAULT_UNATTENDED;
}
base::string16 GetApplicationNameForProtocol(const GURL& url) {
return base::ASCIIToUTF16("xdg-open");
}
DefaultWebClientState GetDefaultBrowser() {
return shell_integration_linux::GetIsDefaultWebClient(std::string());
}
bool IsFirefoxDefaultBrowser() {
std::vector<std::string> argv;
argv.push_back(shell_integration_linux::kXdgSettings);
argv.push_back("get");
argv.push_back(shell_integration_linux::kXdgSettingsDefaultBrowser);
std::string browser;
// We don't care about the return value here.
base::GetAppOutput(base::CommandLine(argv), &browser);
return browser.find("irefox") != std::string::npos;
}
DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol) {
return shell_integration_linux::GetIsDefaultWebClient(protocol);
}
} // namespace shell_integration
......@@ -16,22 +16,6 @@ class CommandLine;
class Environment;
}
// TODO(loyso): Move these helpers to shell_integration_linux namespace.
namespace shell_integration {
// Helper to launch xdg scripts. We don't want them to ask any questions on the
// terminal etc. The function returns true if the utility launches and exits
// cleanly, in which case |exit_code| returns the utility's exit code.
// thread_restrictions.h assumes it to be in shell_integration namespace.
bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code);
// Windows that correspond to web apps need to have a deterministic (and
// different) WMClass than normal chrome windows so the window manager groups
// them as a separate application.
std::string GetWMClassFromAppName(std::string app_name);
} // namespace shell_integration
namespace shell_integration_linux {
// Get the path to write user-specific application data files to, as specified
......@@ -111,6 +95,17 @@ bool CreateAppListDesktopShortcut(const std::string& wm_class,
const std::string& title);
#endif
// Windows that correspond to web apps need to have a deterministic (and
// different) WMClass than normal chrome windows so the window manager groups
// them as a separate application.
std::string GetWMClassFromAppName(std::string app_name);
// Helper to launch xdg scripts. We don't want them to ask any questions on the
// terminal etc. The function returns true if the utility launches and exits
// cleanly, in which case |exit_code| returns the utility's exit code.
// thread_restrictions.h assumes it to be in shell_integration namespace.
bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code);
namespace internal {
// Exposed for testing. Clients should use the corresponding functions in
......
......@@ -62,7 +62,7 @@ void ChromeNativeAppWindowViewsAura::OnBeforeWidgetInit(
// Set up a custom WM_CLASS for app windows. This allows task switchers in
// X11 environments to distinguish them from main browser windows.
init_params->wm_class_name =
shell_integration::GetWMClassFromAppName(app_name);
shell_integration_linux::GetWMClassFromAppName(app_name);
init_params->wm_class_class = shell_integration_linux::GetProgramClassClass();
const char kX11WindowRoleApp[] = "app";
init_params->wm_role_name = std::string(kX11WindowRoleApp);
......
......@@ -36,7 +36,7 @@ views::Widget::InitParams DesktopBrowserFrameAuraX11::GetWidgetParams() {
const Browser& browser = *browser_view()->browser();
params.wm_class_name =
browser.is_app() && !browser.is_devtools()
? shell_integration::GetWMClassFromAppName(browser.app_name())
? shell_integration_linux::GetWMClassFromAppName(browser.app_name())
// This window is a hosted app or v1 packaged app.
// NOTE: v2 packaged app windows are created by
// ChromeNativeAppWindowViews.
......
......@@ -79,7 +79,8 @@ std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images,
argv.push_back(temp_file_path.value());
argv.push_back(icon_name);
int exit_code;
if (!shell_integration::LaunchXdgUtility(argv, &exit_code) || exit_code) {
if (!shell_integration_linux::LaunchXdgUtility(argv, &exit_code) ||
exit_code) {
LOG(WARNING) << "Could not install icon " << icon_name << ".png at size "
<< width << ".";
}
......@@ -172,7 +173,7 @@ bool CreateShortcutInApplicationsMenu(const base::FilePath& shortcut_filename,
argv.push_back(temp_directory_path.value());
argv.push_back(temp_file_path.value());
int exit_code;
shell_integration::LaunchXdgUtility(argv, &exit_code);
shell_integration_linux::LaunchXdgUtility(argv, &exit_code);
return exit_code == 0;
}
......@@ -220,7 +221,7 @@ void DeleteShortcutInApplicationsMenu(
argv.push_back(directory_filename.value());
argv.push_back(shortcut_filename.value());
int exit_code;
shell_integration::LaunchXdgUtility(argv, &exit_code);
shell_integration_linux::LaunchXdgUtility(argv, &exit_code);
}
bool CreateDesktopShortcut(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment