diff options
Diffstat (limited to 'chrome/browser/shell_integration_linux.cc')
| -rw-r--r-- | chrome/browser/shell_integration_linux.cc | 359 |
1 files changed, 176 insertions, 183 deletions
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc index c521d292..4e540b2 100644 --- a/chrome/browser/shell_integration_linux.cc +++ b/chrome/browser/shell_integration_linux.cc @@ -55,11 +55,9 @@ using content::BrowserThread; -namespace { +namespace shell_integration { -// The Categories for the App Launcher desktop shortcut. Should be the same as -// the Chrome desktop shortcut, so they are in the same sub-menu. -const char kAppListCategories[] = "Network;WebBrowser;"; +namespace { // 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 @@ -87,6 +85,174 @@ bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) { return process.WaitForExit(exit_code); } +const char kXdgSettings[] = "xdg-settings"; +const char kXdgSettingsDefaultBrowser[] = "default-web-browser"; +const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler"; + +// Utility function to get the path to the version of a script shipped with +// Chrome. |script| gives the name of the script. |chrome_version| returns the +// path to the Chrome version of the script, and the return value of the +// function is true if the function is successful and the Chrome version is +// not the script found on the PATH. +bool GetChromeVersionOfScript(const std::string& script, + std::string* chrome_version) { + // Get the path to the Chrome version. + base::FilePath chrome_dir; + if (!PathService::Get(base::DIR_EXE, &chrome_dir)) + return false; + + base::FilePath chrome_version_path = chrome_dir.Append(script); + *chrome_version = chrome_version_path.value(); + + // Check if this is different to the one on path. + std::vector<std::string> argv; + argv.push_back("which"); + argv.push_back(script); + std::string path_version; + if (base::GetAppOutput(base::CommandLine(argv), &path_version)) { + // Remove trailing newline + path_version.erase(path_version.length() - 1, 1); + base::FilePath path_version_path(path_version); + return (chrome_version_path != path_version_path); + } + return false; +} + +// Value returned by xdg-settings if it can't understand our request. +const int EXIT_XDG_SETTINGS_SYNTAX_ERROR = 1; + +// We delegate the difficulty of setting the default browser and default url +// scheme handler in Linux desktop environments to an xdg utility, xdg-settings. + +// When calling this script we first try to use the script on PATH. If that +// fails we then try to use the script that we have included. This gives +// scripts on the system priority over ours, as distribution vendors may have +// tweaked the script, but still allows our copy to be used if the script on the +// system fails, as the system copy may be missing capabilities of the Chrome +// copy. + +// If |protocol| is empty this function sets Chrome as the default browser, +// otherwise it sets Chrome as the default handler application for |protocol|. +bool SetDefaultWebClient(const std::string& protocol) { +#if defined(OS_CHROMEOS) + return true; +#else + scoped_ptr<base::Environment> env(base::Environment::Create()); + + std::vector<std::string> argv; + argv.push_back(kXdgSettings); + argv.push_back("set"); + if (protocol.empty()) { + argv.push_back(kXdgSettingsDefaultBrowser); + } else { + argv.push_back(kXdgSettingsDefaultSchemeHandler); + argv.push_back(protocol); + } + argv.push_back(shell_integration_linux::GetDesktopName(env.get())); + + int exit_code; + bool ran_ok = LaunchXdgUtility(argv, &exit_code); + if (ran_ok && exit_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { + if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { + ran_ok = LaunchXdgUtility(argv, &exit_code); + } + } + + return ran_ok && exit_code == EXIT_SUCCESS; +#endif +} + +// 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) { +#if defined(OS_CHROMEOS) + return UNKNOWN_DEFAULT; +#else + base::ThreadRestrictions::AssertIOAllowed(); + + scoped_ptr<base::Environment> env(base::Environment::Create()); + + std::vector<std::string> argv; + argv.push_back(kXdgSettings); + argv.push_back("check"); + if (protocol.empty()) { + argv.push_back(kXdgSettingsDefaultBrowser); + } else { + argv.push_back(kXdgSettingsDefaultSchemeHandler); + argv.push_back(protocol); + } + argv.push_back(shell_integration_linux::GetDesktopName(env.get())); + + std::string reply; + int success_code; + bool ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, + &success_code); + if (ran_ok && success_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { + if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { + ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, + &success_code); + } + } + + if (!ran_ok || success_code != EXIT_SUCCESS) { + // xdg-settings failed: we can't determine or set the default browser. + return UNKNOWN_DEFAULT; + } + + // Allow any reply that starts with "yes". + return (reply.find("yes") == 0) ? IS_DEFAULT : NOT_DEFAULT; +#endif +} + +} // namespace + +bool SetAsDefaultBrowser() { + return SetDefaultWebClient(std::string()); +} + +bool SetAsDefaultProtocolClient(const std::string& protocol) { + return SetDefaultWebClient(protocol); +} + +DefaultWebClientSetPermission CanSetAsDefaultBrowser() { + 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); +} + +} // namespace shell_integration + +namespace shell_integration_linux { + +namespace { + +// The Categories for the App Launcher desktop shortcut. Should be the same as +// the Chrome desktop shortcut, so they are in the same sub-menu. +const char kAppListCategories[] = "Network;WebBrowser;"; + std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images, const base::FilePath& shortcut_filename) { if (icon_images.empty()) @@ -133,7 +299,7 @@ std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images, argv.push_back(temp_file_path.value()); argv.push_back(icon_name); int exit_code; - if (!LaunchXdgUtility(argv, &exit_code) || exit_code) { + if (!shell_integration::LaunchXdgUtility(argv, &exit_code) || exit_code) { LOG(WARNING) << "Could not install icon " << icon_name << ".png at size " << width << "."; } @@ -232,7 +398,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; - LaunchXdgUtility(argv, &exit_code); + shell_integration::LaunchXdgUtility(argv, &exit_code); return exit_code == 0; } @@ -255,7 +421,7 @@ void DeleteShortcutInApplicationsMenu( argv.push_back(directory_filename.value()); argv.push_back(shortcut_filename.value()); int exit_code; - LaunchXdgUtility(argv, &exit_code); + shell_integration::LaunchXdgUtility(argv, &exit_code); } #if defined(USE_GLIB) @@ -311,10 +477,6 @@ const char kDesktopEntry[] = "Desktop Entry"; const char kXdgOpenShebang[] = "#!/usr/bin/env xdg-open"; #endif -const char kXdgSettings[] = "xdg-settings"; -const char kXdgSettingsDefaultBrowser[] = "default-web-browser"; -const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler"; - const char kDirectoryFilename[] = "chrome-apps.directory"; #if defined(GOOGLE_CHROME_BUILD) @@ -323,124 +485,6 @@ const char kAppListDesktopName[] = "chrome-app-list"; const char kAppListDesktopName[] = "chromium-app-list"; #endif -// Utility function to get the path to the version of a script shipped with -// Chrome. |script| gives the name of the script. |chrome_version| returns the -// path to the Chrome version of the script, and the return value of the -// function is true if the function is successful and the Chrome version is -// not the script found on the PATH. -bool GetChromeVersionOfScript(const std::string& script, - std::string* chrome_version) { - // Get the path to the Chrome version. - base::FilePath chrome_dir; - if (!PathService::Get(base::DIR_EXE, &chrome_dir)) - return false; - - base::FilePath chrome_version_path = chrome_dir.Append(script); - *chrome_version = chrome_version_path.value(); - - // Check if this is different to the one on path. - std::vector<std::string> argv; - argv.push_back("which"); - argv.push_back(script); - std::string path_version; - if (base::GetAppOutput(base::CommandLine(argv), &path_version)) { - // Remove trailing newline - path_version.erase(path_version.length() - 1, 1); - base::FilePath path_version_path(path_version); - return (chrome_version_path != path_version_path); - } - return false; -} - -// Value returned by xdg-settings if it can't understand our request. -const int EXIT_XDG_SETTINGS_SYNTAX_ERROR = 1; - -// We delegate the difficulty of setting the default browser and default url -// scheme handler in Linux desktop environments to an xdg utility, xdg-settings. - -// When calling this script we first try to use the script on PATH. If that -// fails we then try to use the script that we have included. This gives -// scripts on the system priority over ours, as distribution vendors may have -// tweaked the script, but still allows our copy to be used if the script on the -// system fails, as the system copy may be missing capabilities of the Chrome -// copy. - -// If |protocol| is empty this function sets Chrome as the default browser, -// otherwise it sets Chrome as the default handler application for |protocol|. -bool SetDefaultWebClient(const std::string& protocol) { -#if defined(OS_CHROMEOS) - return true; -#else - scoped_ptr<base::Environment> env(base::Environment::Create()); - - std::vector<std::string> argv; - argv.push_back(kXdgSettings); - argv.push_back("set"); - if (protocol.empty()) { - argv.push_back(kXdgSettingsDefaultBrowser); - } else { - argv.push_back(kXdgSettingsDefaultSchemeHandler); - argv.push_back(protocol); - } - argv.push_back(shell_integration_linux::GetDesktopName(env.get())); - - int exit_code; - bool ran_ok = LaunchXdgUtility(argv, &exit_code); - if (ran_ok && exit_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { - if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { - ran_ok = LaunchXdgUtility(argv, &exit_code); - } - } - - return ran_ok && exit_code == EXIT_SUCCESS; -#endif -} - -// 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|. -ShellIntegration::DefaultWebClientState GetIsDefaultWebClient( - const std::string& protocol) { -#if defined(OS_CHROMEOS) - return ShellIntegration::UNKNOWN_DEFAULT; -#else - base::ThreadRestrictions::AssertIOAllowed(); - - scoped_ptr<base::Environment> env(base::Environment::Create()); - - std::vector<std::string> argv; - argv.push_back(kXdgSettings); - argv.push_back("check"); - if (protocol.empty()) { - argv.push_back(kXdgSettingsDefaultBrowser); - } else { - argv.push_back(kXdgSettingsDefaultSchemeHandler); - argv.push_back(protocol); - } - argv.push_back(shell_integration_linux::GetDesktopName(env.get())); - - std::string reply; - int success_code; - bool ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, - &success_code); - if (ran_ok && success_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { - if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { - ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, - &success_code); - } - } - - if (!ran_ok || success_code != EXIT_SUCCESS) { - // xdg-settings failed: we can't determine or set the default browser. - return ShellIntegration::UNKNOWN_DEFAULT; - } - - // Allow any reply that starts with "yes". - return (reply.find("yes") == 0) ? ShellIntegration::IS_DEFAULT : - ShellIntegration::NOT_DEFAULT; -#endif -} - // Get the value of NoDisplay from the [Desktop Entry] section of a .desktop // file, given in |shortcut_contents|. If the key is not found, returns false. bool GetNoDisplayFromDesktopFile(const std::string& shortcut_contents) { @@ -497,56 +541,6 @@ base::FilePath GetChromeExePath() { } // namespace -// static -bool ShellIntegration::SetAsDefaultBrowser() { - return SetDefaultWebClient(std::string()); -} - -// static -bool ShellIntegration::SetAsDefaultProtocolClient( - const std::string& protocol) { - return SetDefaultWebClient(protocol); -} - -// static -ShellIntegration::DefaultWebClientSetPermission -ShellIntegration::CanSetAsDefaultBrowser() { - return SET_DEFAULT_UNATTENDED; -} - -// static -base::string16 ShellIntegration::GetApplicationNameForProtocol( - const GURL& url) { - return base::ASCIIToUTF16("xdg-open"); -} - -// static -ShellIntegration::DefaultWebClientState -ShellIntegration::GetDefaultBrowser() { - return GetIsDefaultWebClient(std::string()); -} - -// static -bool ShellIntegration::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; -} - -// static -ShellIntegration::DefaultWebClientState -ShellIntegration::IsDefaultProtocolClient(const std::string& protocol) { - return GetIsDefaultWebClient(protocol); -} - -namespace shell_integration_linux { - base::FilePath GetDataWriteLocation(base::Environment* env) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); @@ -756,9 +750,8 @@ std::string GetDesktopFileContents( const base::FilePath& profile_path, const std::string& categories, bool no_display) { - base::CommandLine cmd_line = - ShellIntegration::CommandLineArgsForLauncher(url, extension_id, - profile_path); + base::CommandLine cmd_line = shell_integration::CommandLineArgsForLauncher( + url, extension_id, profile_path); cmd_line.SetProgram(chrome_exe_path); return GetDesktopFileContentsForCommand(cmd_line, app_name, url, title, icon_name, categories, no_display); @@ -951,7 +944,7 @@ bool CreateDesktopShortcut( case web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS: directory_filename = base::FilePath(kDirectoryFilename); directory_contents = GetDirectoryFileContents( - ShellIntegration::GetAppShortcutsSubdirName(), ""); + shell_integration::GetAppShortcutsSubdirName(), ""); break; default: NOTREACHED(); |
