// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/shell_integration_linux.h"

#include <fcntl.h>
#include <glib.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/eintr_wrapper.h"
#include "base/environment.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/i18n/file_util_icu.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_temp_dir.h"
#include "base/string_number_conversions.h"
#include "base/string_tokenizer.h"
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/browser_thread.h"
#include "googleurl/src/gurl.h"
#include "ui/gfx/codec/png_codec.h"

using content::BrowserThread;

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
// cleanly, in which case |exit_code| returns the utility's exit code.
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::FileHandleMappingVector no_stdin;
  no_stdin.push_back(std::make_pair(devnull, STDIN_FILENO));

  base::ProcessHandle handle;
  base::LaunchOptions options;
  options.fds_to_remap = &no_stdin;
  if (!base::LaunchProcess(argv, options, &handle)) {
    close(devnull);
    return false;
  }
  close(devnull);

  return base::WaitForExitCode(handle, exit_code);
}

std::string CreateShortcutIcon(
    const ShellIntegration::ShortcutInfo& shortcut_info,
    const FilePath& shortcut_filename) {
  if (shortcut_info.favicon.IsEmpty())
    return std::string();

  // TODO(phajdan.jr): Report errors from this function, possibly as infobars.
  ScopedTempDir temp_dir;
  if (!temp_dir.CreateUniqueTempDir())
    return std::string();

  FilePath temp_file_path = temp_dir.path().Append(
      shortcut_filename.ReplaceExtension("png"));

  std::vector<unsigned char> png_data;
  const SkBitmap* bitmap = shortcut_info.favicon.ToSkBitmap();
  gfx::PNGCodec::EncodeBGRASkBitmap(*bitmap, false, &png_data);
  int bytes_written = file_util::WriteFile(temp_file_path,
      reinterpret_cast<char*>(png_data.data()), png_data.size());

  if (bytes_written != static_cast<int>(png_data.size()))
    return std::string();

  std::vector<std::string> argv;
  argv.push_back("xdg-icon-resource");
  argv.push_back("install");

  // Always install in user mode, even if someone runs the browser as root
  // (people do that).
  argv.push_back("--mode");
  argv.push_back("user");

  argv.push_back("--size");
  argv.push_back(base::IntToString(bitmap->width()));

  argv.push_back(temp_file_path.value());
  std::string icon_name = temp_file_path.BaseName().RemoveExtension().value();
  argv.push_back(icon_name);
  int exit_code;
  LaunchXdgUtility(argv, &exit_code);
  return icon_name;
}

bool CreateShortcutOnDesktop(const FilePath& shortcut_filename,
                             const std::string& contents) {
  // Make sure that we will later call openat in a secure way.
  DCHECK_EQ(shortcut_filename.BaseName().value(), shortcut_filename.value());

  FilePath desktop_path;
  if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_path))
    return false;

  int desktop_fd = open(desktop_path.value().c_str(), O_RDONLY | O_DIRECTORY);
  if (desktop_fd < 0)
    return false;

  int fd = openat(desktop_fd, shortcut_filename.value().c_str(),
                  O_CREAT | O_EXCL | O_WRONLY,
                  S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
  if (fd < 0) {
    if (HANDLE_EINTR(close(desktop_fd)) < 0)
      PLOG(ERROR) << "close";
    return false;
  }

  ssize_t bytes_written = file_util::WriteFileDescriptor(fd, contents.data(),
                                                         contents.length());
  if (HANDLE_EINTR(close(fd)) < 0)
    PLOG(ERROR) << "close";

  if (bytes_written != static_cast<ssize_t>(contents.length())) {
    // Delete the file. No shortuct is better than corrupted one. Use unlinkat
    // to make sure we're deleting the file in the directory we think we are.
    // Even if an attacker manager to put something other at
    // |shortcut_filename| we'll just undo his action.
    unlinkat(desktop_fd, shortcut_filename.value().c_str(), 0);
  }

  if (HANDLE_EINTR(close(desktop_fd)) < 0)
    PLOG(ERROR) << "close";

  return true;
}

bool CreateShortcutInApplicationsMenu(const FilePath& shortcut_filename,
                                      const std::string& contents) {
  ScopedTempDir temp_dir;
  if (!temp_dir.CreateUniqueTempDir())
    return false;

  FilePath temp_file_path = temp_dir.path().Append(shortcut_filename);

  int bytes_written = file_util::WriteFile(temp_file_path, contents.data(),
                                           contents.length());

  if (bytes_written != static_cast<int>(contents.length()))
    return false;

  std::vector<std::string> argv;
  argv.push_back("xdg-desktop-menu");
  argv.push_back("install");

  // Always install in user mode, even if someone runs the browser as root
  // (people do that).
  argv.push_back("--mode");
  argv.push_back("user");

  argv.push_back(temp_file_path.value());
  int exit_code;
  LaunchXdgUtility(argv, &exit_code);
  return exit_code == 0;
}

// Quote a string such that it appears as one verbatim argument for the Exec
// key in a desktop file.
std::string QuoteArgForDesktopFileExec(const std::string& arg) {
  // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html

  // Quoting is only necessary if the argument has a reserved character.
  if (arg.find_first_of(" \t\n\"'\\><~|&;$*?#()`") == std::string::npos)
    return arg;  // No quoting necessary.

  std::string quoted = "\"";
  for (size_t i = 0; i < arg.size(); ++i) {
    // Note that the set of backslashed characters is smaller than the
    // set of reserved characters.
    switch (arg[i]) {
      case '"':
      case '`':
      case '$':
      case '\\':
        quoted += '\\';
        break;
    }
    quoted += arg[i];
  }
  quoted += '"';

  return quoted;
}

// Remove keys from the [Desktop Entry] that would be wrong if copied verbatim
// into the new .desktop file.
const char* kDesktopKeysToDelete[] = {
  "GenericName",
  "Comment",
  "MimeType",
  "X-Ayatana-Desktop-Shortcuts",
  "StartupWMClass",
  NULL
};

const char kDesktopEntry[] = "Desktop Entry";

const char kXdgOpenShebang[] = "#!/usr/bin/env xdg-open";

const char kXdgSettings[] = "xdg-settings";
const char kXdgSettingsDefaultBrowser[] = "default-web-browser";
const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler";

}  // namespace

namespace {

// 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.
  FilePath chrome_dir;
  if (!PathService::Get(base::DIR_EXE, &chrome_dir))
    return false;

  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(CommandLine(argv), &path_version)) {
    // Remove trailing newline
    path_version.erase(path_version.length() - 1, 1);
    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
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  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(ShellIntegrationLinux::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::IS_DEFAULT_WEB_CLIENT;
#else
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  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(ShellIntegrationLinux::GetDesktopName(env.get()));

  std::string reply;
  int success_code;
  bool ran_ok = base::GetAppOutputWithExitCode(CommandLine(argv), &reply,
                                               &success_code);
  if (ran_ok && success_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) {
    if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) {
      ran_ok = base::GetAppOutputWithExitCode(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_WEB_CLIENT;
  }

  // Allow any reply that starts with "yes".
  return (reply.find("yes") == 0) ? ShellIntegration::IS_DEFAULT_WEB_CLIENT :
                                    ShellIntegration::NOT_DEFAULT_WEB_CLIENT;
#endif
}

} // namespace

// static
bool ShellIntegration::CanSetAsDefaultBrowser() {
  return true;
}

// static
bool ShellIntegration::SetAsDefaultBrowser() {
  return SetDefaultWebClient("");
}

// static
bool ShellIntegration::SetAsDefaultProtocolClient(const std::string& protocol) {
  return SetDefaultWebClient(protocol);
}

// static
ShellIntegration::DefaultWebClientState ShellIntegration::IsDefaultBrowser() {
  return GetIsDefaultWebClient("");
}

// static
ShellIntegration::DefaultWebClientState
ShellIntegration::IsDefaultProtocolClient(const std::string& protocol) {
  return GetIsDefaultWebClient(protocol);
}

// 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(CommandLine(argv), &browser);
  return browser.find("irefox") != std::string::npos;
}

namespace ShellIntegrationLinux {

std::string GetDesktopName(base::Environment* env) {
#if defined(GOOGLE_CHROME_BUILD)
  return "google-chrome.desktop";
#else  // CHROMIUM_BUILD
  // Allow $CHROME_DESKTOP to override the built-in value, so that development
  // versions can set themselves as the default without interfering with
  // non-official, packaged versions using the built-in value.
  std::string name;
  if (env->GetVar("CHROME_DESKTOP", &name) && !name.empty())
    return name;
  return "chromium-browser.desktop";
#endif
}

bool GetDesktopShortcutTemplate(base::Environment* env,
                                std::string* output) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  std::vector<FilePath> search_paths;

  std::string xdg_data_home;
  if (env->GetVar("XDG_DATA_HOME", &xdg_data_home) &&
      !xdg_data_home.empty()) {
    search_paths.push_back(FilePath(xdg_data_home));
  }

  std::string xdg_data_dirs;
  if (env->GetVar("XDG_DATA_DIRS", &xdg_data_dirs) &&
      !xdg_data_dirs.empty()) {
    StringTokenizer tokenizer(xdg_data_dirs, ":");
    while (tokenizer.GetNext()) {
      FilePath data_dir(tokenizer.token());
      search_paths.push_back(data_dir);
      search_paths.push_back(data_dir.Append("applications"));
    }
  }

  // Add some fallback paths for systems which don't have XDG_DATA_DIRS or have
  // it incomplete.
  search_paths.push_back(FilePath("/usr/share/applications"));
  search_paths.push_back(FilePath("/usr/local/share/applications"));

  std::string template_filename(GetDesktopName(env));
  for (std::vector<FilePath>::const_iterator i = search_paths.begin();
       i != search_paths.end(); ++i) {
    FilePath path = (*i).Append(template_filename);
    VLOG(1) << "Looking for desktop file template in " << path.value();
    if (file_util::PathExists(path)) {
      VLOG(1) << "Found desktop file template at " << path.value();
      return file_util::ReadFileToString(path, output);
    }
  }

  LOG(ERROR) << "Could not find desktop file template.";
  return false;
}

FilePath GetDesktopShortcutFilename(const GURL& url) {
  // Use a prefix, because xdg-desktop-menu requires it.
  std::string filename =
      std::string(chrome::kBrowserProcessExecutableName) + "-" + url.spec();
  file_util::ReplaceIllegalCharactersInPath(&filename, '_');

  FilePath desktop_path;
  if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_path))
    return FilePath();

  FilePath filepath = desktop_path.Append(filename);
  FilePath alternative_filepath(filepath.value() + ".desktop");
  for (size_t i = 1; i < 100; ++i) {
    if (file_util::PathExists(FilePath(alternative_filepath))) {
      alternative_filepath = FilePath(
          filepath.value() + "_" + base::IntToString(i) + ".desktop");
    } else {
      return FilePath(alternative_filepath).BaseName();
    }
  }

  return FilePath();
}

std::string GetDesktopFileContents(
    const std::string& template_contents,
    const std::string& app_name,
    const GURL& url,
    const std::string& extension_id,
    const bool is_platform_app,
    const FilePath& web_app_path,
    const FilePath& extension_path,
    const string16& title,
    const std::string& icon_name) {
  if (template_contents.empty())
    return std::string(kXdgOpenShebang) + "\n";

  // See http://standards.freedesktop.org/desktop-entry-spec/latest/
  // http://developer.gnome.org/glib/unstable/glib-Key-value-file-parser.html
  GKeyFile* key_file = g_key_file_new();
  GError* err = NULL;
  // Loading the data will strip translations and comments from the desktop
  // file (which we want to do!)
  if (!g_key_file_load_from_data(
          key_file,
          template_contents.c_str(),
          template_contents.size(),
          G_KEY_FILE_NONE,
          &err)) {
    NOTREACHED() << "Unable to read desktop file template:" << err->message;
    g_error_free(err);
    return std::string(kXdgOpenShebang) + "\n";
  }

  // Remove all sections except for the Desktop Entry
  gsize length = 0;
  gchar** groups = g_key_file_get_groups(key_file, &length);
  for (gsize i = 0; i < length; ++i) {
    if (strcmp(groups[i], kDesktopEntry) != 0) {
      g_key_file_remove_group(key_file, groups[i], NULL);
    }
  }
  g_strfreev(groups);

  // Remove keys that we won't need.
  for (const char** current_key = kDesktopKeysToDelete; *current_key;
       ++current_key) {
    g_key_file_remove_key(key_file, kDesktopEntry, *current_key, NULL);
  }

  // Set the "Name" key.
  std::string final_title = UTF16ToUTF8(title);
  // Make sure no endline characters can slip in and possibly introduce
  // additional lines (like Exec, which makes it a security risk). Also
  // use the URL as a default when the title is empty.
  if (final_title.empty() ||
      final_title.find("\n") != std::string::npos ||
      final_title.find("\r") != std::string::npos) {
    final_title = url.spec();
  }
  g_key_file_set_string(key_file, kDesktopEntry, "Name", final_title.c_str());

  // Set the "Exec" key.
  char* exec_c_string = g_key_file_get_string(key_file, kDesktopEntry, "Exec",
                                              NULL);
  if (exec_c_string) {
    std::string exec_string(exec_c_string);
    g_free(exec_c_string);
    StringTokenizer exec_tokenizer(exec_string, " ");

    std::string final_path;
    while (exec_tokenizer.GetNext() && exec_tokenizer.token() != "%U") {
      if (!final_path.empty())
        final_path += " ";
      final_path += exec_tokenizer.token();
    }
    CommandLine cmd_line(CommandLine::NO_PROGRAM);
    if (is_platform_app) {
      cmd_line = ShellIntegration::CommandLineArgsForPlatformApp(
          extension_id, web_app_path, extension_path);
    } else {
      cmd_line = ShellIntegration::CommandLineArgsForLauncher(
          url, extension_id);
    }
    const CommandLine::SwitchMap& switch_map = cmd_line.GetSwitches();
    for (CommandLine::SwitchMap::const_iterator i = switch_map.begin();
         i != switch_map.end(); ++i) {
      if (i->second.empty()) {
        final_path += " --" + i->first;
      } else {
        final_path += " " + QuoteArgForDesktopFileExec("--" + i->first +
                                                       "=" + i->second);
      }
    }

    g_key_file_set_string(key_file, kDesktopEntry, "Exec", final_path.c_str());
  }

  // Set the "Icon" key.
  if (!icon_name.empty())
    g_key_file_set_string(key_file, kDesktopEntry, "Icon", icon_name.c_str());

#if defined(TOOLKIT_GTK)
  std::string wmclass = web_app::GetWMClassFromAppName(app_name);
  g_key_file_set_string(key_file, kDesktopEntry, "StartupWMClass",
                        wmclass.c_str());
#endif

  // Although not required by the spec, Nautilus on Ubuntu Karmic creates its
  // launchers with an xdg-open shebang. Follow that convention.
  std::string output_buffer = kXdgOpenShebang;
  length = 0;
  gchar* data_dump = g_key_file_to_data(key_file, &length, NULL);
  if (data_dump) {
    output_buffer += data_dump;
    g_free(data_dump);
  }

  g_key_file_free(key_file);
  return output_buffer;
}

bool CreateDesktopShortcut(
    const ShellIntegration::ShortcutInfo& shortcut_info,
    const std::string& shortcut_template) {
  DCHECK(!shortcut_info.is_platform_app);
  DCHECK(shortcut_info.extension_id.empty());

  return ShellIntegrationLinux::CreateDesktopShortcutForChromeApp(
      shortcut_info, FilePath(), shortcut_template);
}

bool CreateDesktopShortcutForChromeApp(
    const ShellIntegration::ShortcutInfo& shortcut_info,
    const FilePath& web_app_path,
    const std::string& shortcut_template) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  FilePath shortcut_filename =
      ShellIntegrationLinux::GetDesktopShortcutFilename(shortcut_info.url);
  if (shortcut_filename.empty())
    return false;

  std::string icon_name =CreateShortcutIcon(shortcut_info, shortcut_filename);

  std::string app_name =
      web_app::GenerateApplicationNameFromInfo(shortcut_info);
  std::string contents = ShellIntegrationLinux::GetDesktopFileContents(
      shortcut_template,
      app_name,
      shortcut_info.url,
      shortcut_info.extension_id,
      shortcut_info.is_platform_app,
      web_app_path,
      shortcut_info.extension_path,
      shortcut_info.title,
      icon_name);

  bool success = true;

  if (shortcut_info.create_on_desktop)
    success = CreateShortcutOnDesktop(shortcut_filename, contents);

  if (shortcut_info.create_in_applications_menu)
    success = CreateShortcutInApplicationsMenu(shortcut_filename, contents) &&
              success;

  return success;
}

}  // namespace ShellIntegrationLinux
