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 { ...@@ -119,7 +119,7 @@ namespace service_manager {
class ServiceProcessLauncher; class ServiceProcessLauncher;
} }
namespace shell_integration { namespace shell_integration_linux {
class LaunchXdgUtilityScopedAllowBaseSyncPrimitives; class LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
} }
...@@ -329,7 +329,8 @@ class BASE_EXPORT ScopedAllowBaseSyncPrimitives { ...@@ -329,7 +329,8 @@ class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
friend class mojo::core::ScopedIPCSupport; friend class mojo::core::ScopedIPCSupport;
friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives; friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
friend class rlz_lib::FinancialPing; friend class rlz_lib::FinancialPing;
friend class shell_integration::LaunchXdgUtilityScopedAllowBaseSyncPrimitives; friend class shell_integration_linux::
LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
friend class webrtc::DesktopConfigurationMonitor; friend class webrtc::DesktopConfigurationMonitor;
friend class content::ServiceWorkerSubresourceLoader; friend class content::ServiceWorkerSubresourceLoader;
friend class viz::HostGpuMemoryBufferManager; friend class viz::HostGpuMemoryBufferManager;
......
...@@ -52,36 +52,7 @@ ...@@ -52,36 +52,7 @@
#include "ui/gfx/image/image_family.h" #include "ui/gfx/image/image_family.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace shell_integration { namespace shell_integration_linux {
// 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 {
const char kXdgSettings[] = "xdg-settings"; const char kXdgSettings[] = "xdg-settings";
const char kXdgSettingsDefaultBrowser[] = "default-web-browser"; const char kXdgSettingsDefaultBrowser[] = "default-web-browser";
...@@ -146,7 +117,7 @@ bool SetDefaultWebClient(const std::string& protocol) { ...@@ -146,7 +117,7 @@ bool SetDefaultWebClient(const std::string& protocol) {
argv.push_back(kXdgSettingsDefaultSchemeHandler); argv.push_back(kXdgSettingsDefaultSchemeHandler);
argv.push_back(protocol); argv.push_back(protocol);
} }
argv.push_back(shell_integration_linux::GetDesktopName(env.get())); argv.push_back(GetDesktopName(env.get()));
int exit_code; int exit_code;
bool ran_ok = LaunchXdgUtility(argv, &exit_code); bool ran_ok = LaunchXdgUtility(argv, &exit_code);
...@@ -163,9 +134,10 @@ bool SetDefaultWebClient(const std::string& protocol) { ...@@ -163,9 +134,10 @@ bool SetDefaultWebClient(const std::string& protocol) {
// If |protocol| is empty this function checks if Chrome is the default browser, // If |protocol| is empty this function checks if Chrome is the default browser,
// otherwise it checks if Chrome is the default handler application for // otherwise it checks if Chrome is the default handler application for
// |protocol|. // |protocol|.
DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) { shell_integration::DefaultWebClientState GetIsDefaultWebClient(
const std::string& protocol) {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
return UNKNOWN_DEFAULT; return shell_integration::UNKNOWN_DEFAULT;
#else #else
base::AssertBlockingAllowed(); base::AssertBlockingAllowed();
...@@ -180,7 +152,7 @@ DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) { ...@@ -180,7 +152,7 @@ DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) {
argv.push_back(kXdgSettingsDefaultSchemeHandler); argv.push_back(kXdgSettingsDefaultSchemeHandler);
argv.push_back(protocol); argv.push_back(protocol);
} }
argv.push_back(shell_integration_linux::GetDesktopName(env.get())); argv.push_back(GetDesktopName(env.get()));
std::string reply; std::string reply;
int success_code; int success_code;
...@@ -195,13 +167,13 @@ DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) { ...@@ -195,13 +167,13 @@ DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) {
if (!ran_ok || success_code != EXIT_SUCCESS) { if (!ran_ok || success_code != EXIT_SUCCESS) {
// xdg-settings failed: we can't determine or set the default browser. // 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". // Allow any reply that starts with "yes".
return base::StartsWith(reply, "yes", base::CompareCase::SENSITIVE) return base::StartsWith(reply, "yes", base::CompareCase::SENSITIVE)
? IS_DEFAULT ? shell_integration::IS_DEFAULT
: NOT_DEFAULT; : shell_integration::NOT_DEFAULT;
#endif #endif
} }
...@@ -220,54 +192,6 @@ std::string GetDesktopBaseName(const std::string& desktop_file_name) { ...@@ -220,54 +192,6 @@ std::string GetDesktopBaseName(const std::string& desktop_file_name) {
return 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 { namespace {
#if defined(USE_GLIB) #if defined(USE_GLIB)
...@@ -335,6 +259,39 @@ const char kAppListDesktopName[] = "chromium-app-list"; ...@@ -335,6 +259,39 @@ const char kAppListDesktopName[] = "chromium-app-list";
} // namespace } // 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) { base::FilePath GetDataWriteLocation(base::Environment* env) {
return base::nix::GetXDGDirectory(env, "XDG_DATA_HOME", ".local/share"); return base::nix::GetXDGDirectory(env, "XDG_DATA_HOME", ".local/share");
} }
...@@ -419,8 +376,7 @@ base::FilePath GetChromeExePath() { ...@@ -419,8 +376,7 @@ base::FilePath GetChromeExePath() {
std::string GetProgramClassName(const base::CommandLine& command_line, std::string GetProgramClassName(const base::CommandLine& command_line,
const std::string& desktop_file_name) { const std::string& desktop_file_name) {
std::string class_name = std::string class_name = GetDesktopBaseName(desktop_file_name);
shell_integration::GetDesktopBaseName(desktop_file_name);
std::string user_data_dir = std::string user_data_dir =
command_line.GetSwitchValueNative(switches::kUserDataDir); command_line.GetSwitchValueNative(switches::kUserDataDir);
// If the user launches with e.g. --user-data-dir=/tmp/my-user-data, set the // 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, ...@@ -436,8 +392,7 @@ std::string GetProgramClassClass(const base::CommandLine& command_line,
const std::string& desktop_file_name) { const std::string& desktop_file_name) {
if (command_line.HasSwitch(switches::kWmClass)) if (command_line.HasSwitch(switches::kWmClass))
return command_line.GetSwitchValueASCII(switches::kWmClass); return command_line.GetSwitchValueASCII(switches::kWmClass);
std::string class_class = std::string class_class = GetDesktopBaseName(desktop_file_name);
shell_integration::GetDesktopBaseName(desktop_file_name);
if (!class_class.empty()) { if (!class_class.empty()) {
// Capitalize the first character like gtk does. // Capitalize the first character like gtk does.
class_class[0] = base::ToUpperASCII(class_class[0]); class_class[0] = base::ToUpperASCII(class_class[0]);
...@@ -632,7 +587,7 @@ std::string GetDesktopFileContentsForCommand( ...@@ -632,7 +587,7 @@ std::string GetDesktopFileContentsForCommand(
if (no_display) if (no_display)
g_key_file_set_string(key_file, kDesktopEntry, "NoDisplay", "true"); 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", g_key_file_set_string(key_file, kDesktopEntry, "StartupWMClass",
wmclass.c_str()); wmclass.c_str());
...@@ -741,3 +696,43 @@ bool CreateAppListDesktopShortcut( ...@@ -741,3 +696,43 @@ bool CreateAppListDesktopShortcut(
#endif #endif
} // namespace shell_integration_linux } // 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; ...@@ -16,22 +16,6 @@ class CommandLine;
class Environment; 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 { namespace shell_integration_linux {
// Get the path to write user-specific application data files to, as specified // Get the path to write user-specific application data files to, as specified
...@@ -111,6 +95,17 @@ bool CreateAppListDesktopShortcut(const std::string& wm_class, ...@@ -111,6 +95,17 @@ bool CreateAppListDesktopShortcut(const std::string& wm_class,
const std::string& title); const std::string& title);
#endif #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 { namespace internal {
// Exposed for testing. Clients should use the corresponding functions in // Exposed for testing. Clients should use the corresponding functions in
......
...@@ -62,7 +62,7 @@ void ChromeNativeAppWindowViewsAura::OnBeforeWidgetInit( ...@@ -62,7 +62,7 @@ void ChromeNativeAppWindowViewsAura::OnBeforeWidgetInit(
// Set up a custom WM_CLASS for app windows. This allows task switchers in // Set up a custom WM_CLASS for app windows. This allows task switchers in
// X11 environments to distinguish them from main browser windows. // X11 environments to distinguish them from main browser windows.
init_params->wm_class_name = 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(); init_params->wm_class_class = shell_integration_linux::GetProgramClassClass();
const char kX11WindowRoleApp[] = "app"; const char kX11WindowRoleApp[] = "app";
init_params->wm_role_name = std::string(kX11WindowRoleApp); init_params->wm_role_name = std::string(kX11WindowRoleApp);
......
...@@ -36,7 +36,7 @@ views::Widget::InitParams DesktopBrowserFrameAuraX11::GetWidgetParams() { ...@@ -36,7 +36,7 @@ views::Widget::InitParams DesktopBrowserFrameAuraX11::GetWidgetParams() {
const Browser& browser = *browser_view()->browser(); const Browser& browser = *browser_view()->browser();
params.wm_class_name = params.wm_class_name =
browser.is_app() && !browser.is_devtools() 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. // This window is a hosted app or v1 packaged app.
// NOTE: v2 packaged app windows are created by // NOTE: v2 packaged app windows are created by
// ChromeNativeAppWindowViews. // ChromeNativeAppWindowViews.
......
...@@ -79,7 +79,8 @@ std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images, ...@@ -79,7 +79,8 @@ std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images,
argv.push_back(temp_file_path.value()); argv.push_back(temp_file_path.value());
argv.push_back(icon_name); argv.push_back(icon_name);
int exit_code; 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 " LOG(WARNING) << "Could not install icon " << icon_name << ".png at size "
<< width << "."; << width << ".";
} }
...@@ -172,7 +173,7 @@ bool CreateShortcutInApplicationsMenu(const base::FilePath& shortcut_filename, ...@@ -172,7 +173,7 @@ bool CreateShortcutInApplicationsMenu(const base::FilePath& shortcut_filename,
argv.push_back(temp_directory_path.value()); argv.push_back(temp_directory_path.value());
argv.push_back(temp_file_path.value()); argv.push_back(temp_file_path.value());
int exit_code; int exit_code;
shell_integration::LaunchXdgUtility(argv, &exit_code); shell_integration_linux::LaunchXdgUtility(argv, &exit_code);
return exit_code == 0; return exit_code == 0;
} }
...@@ -220,7 +221,7 @@ void DeleteShortcutInApplicationsMenu( ...@@ -220,7 +221,7 @@ void DeleteShortcutInApplicationsMenu(
argv.push_back(directory_filename.value()); argv.push_back(directory_filename.value());
argv.push_back(shortcut_filename.value()); argv.push_back(shortcut_filename.value());
int exit_code; int exit_code;
shell_integration::LaunchXdgUtility(argv, &exit_code); shell_integration_linux::LaunchXdgUtility(argv, &exit_code);
} }
bool CreateDesktopShortcut( 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