| Index: chrome/browser/shell_integration_linux.cc
|
| diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
|
| index be33d73f790e4683e71d5de118f071c7f644d617..7b2088dd7ac65096cabf5f365468c245c9b97f47 100644
|
| --- a/chrome/browser/shell_integration_linux.cc
|
| +++ b/chrome/browser/shell_integration_linux.cc
|
| @@ -173,12 +173,30 @@ void DeleteShortcutOnDesktop(const base::FilePath& shortcut_filename) {
|
| file_util::Delete(desktop_path.Append(shortcut_filename), false);
|
| }
|
|
|
| +// Creates a shortcut with |shortcut_filename| and |contents| in the system
|
| +// applications menu. If |directory_filename| is non-empty, creates a sub-menu
|
| +// with |directory_filename| and |directory_contents|, and stores the shortcut
|
| +// under the sub-menu.
|
| bool CreateShortcutInApplicationsMenu(const base::FilePath& shortcut_filename,
|
| - const std::string& contents) {
|
| + const std::string& contents,
|
| + const base::FilePath& directory_filename,
|
| + const std::string& directory_contents) {
|
| base::ScopedTempDir temp_dir;
|
| if (!temp_dir.CreateUniqueTempDir())
|
| return false;
|
|
|
| + base::FilePath temp_directory_path;
|
| + if (!directory_filename.empty()) {
|
| + temp_directory_path = temp_dir.path().Append(directory_filename);
|
| +
|
| + int bytes_written = file_util::WriteFile(temp_directory_path,
|
| + directory_contents.data(),
|
| + directory_contents.length());
|
| +
|
| + if (bytes_written != static_cast<int>(directory_contents.length()))
|
| + return false;
|
| + }
|
| +
|
| base::FilePath temp_file_path = temp_dir.path().Append(shortcut_filename);
|
|
|
| int bytes_written = file_util::WriteFile(temp_file_path, contents.data(),
|
| @@ -196,13 +214,18 @@ bool CreateShortcutInApplicationsMenu(const base::FilePath& shortcut_filename,
|
| argv.push_back("--mode");
|
| argv.push_back("user");
|
|
|
| + // If provided, install the shortcut file inside the given directory.
|
| + if (!directory_filename.empty())
|
| + argv.push_back(temp_directory_path.value());
|
| argv.push_back(temp_file_path.value());
|
| int exit_code;
|
| LaunchXdgUtility(argv, &exit_code);
|
| return exit_code == 0;
|
| }
|
|
|
| -void DeleteShortcutInApplicationsMenu(const base::FilePath& shortcut_filename) {
|
| +void DeleteShortcutInApplicationsMenu(
|
| + const base::FilePath& shortcut_filename,
|
| + const base::FilePath& directory_filename) {
|
| std::vector<std::string> argv;
|
| argv.push_back("xdg-desktop-menu");
|
| argv.push_back("uninstall");
|
| @@ -213,6 +236,10 @@ void DeleteShortcutInApplicationsMenu(const base::FilePath& shortcut_filename) {
|
|
|
| // The file does not need to exist anywhere - xdg-desktop-menu will uninstall
|
| // items from the menu with a matching name.
|
| + // If |directory_filename| is supplied, this will also remove the item from
|
| + // the directory, and remove the directory if it is empty.
|
| + if (!directory_filename.empty())
|
| + argv.push_back(directory_filename.value());
|
| argv.push_back(shortcut_filename.value());
|
| int exit_code;
|
| LaunchXdgUtility(argv, &exit_code);
|
| @@ -254,6 +281,8 @@ const char kXdgSettings[] = "xdg-settings";
|
| const char kXdgSettingsDefaultBrowser[] = "default-web-browser";
|
| const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler";
|
|
|
| +const char kDirectoryFilename[] = "chrome-apps.directory";
|
| +
|
| } // namespace
|
|
|
| namespace {
|
| @@ -694,6 +723,41 @@ std::string GetDesktopFileContents(
|
| return output_buffer;
|
| }
|
|
|
| +std::string GetDirectoryFileContents(const string16& title,
|
| + const std::string& icon_name) {
|
| + // See http://standards.freedesktop.org/desktop-entry-spec/latest/
|
| + GKeyFile* key_file = g_key_file_new();
|
| +
|
| + g_key_file_set_string(key_file, kDesktopEntry, "Version", "1.0");
|
| + g_key_file_set_string(key_file, kDesktopEntry, "Type", "Directory");
|
| + std::string final_title = UTF16ToUTF8(title);
|
| + g_key_file_set_string(key_file, kDesktopEntry, "Name", final_title.c_str());
|
| + if (!icon_name.empty()) {
|
| + g_key_file_set_string(key_file, kDesktopEntry, "Icon", icon_name.c_str());
|
| + } else {
|
| + g_key_file_set_string(key_file, kDesktopEntry, "Icon",
|
| + GetIconName().c_str());
|
| + }
|
| +
|
| + gsize length = 0;
|
| + gchar* data_dump = g_key_file_to_data(key_file, &length, NULL);
|
| + std::string output_buffer;
|
| + if (data_dump) {
|
| + // If strlen(data_dump[0]) == 0, this check will fail.
|
| + if (data_dump[0] == '\n') {
|
| + // Older versions of glib produce a leading newline. If this is the case,
|
| + // remove it to avoid double-newline after the shebang.
|
| + output_buffer += (data_dump + 1);
|
| + } else {
|
| + 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 ShellIntegration::ShortcutLocations& creation_locations) {
|
| @@ -708,7 +772,7 @@ bool CreateDesktopShortcut(
|
| if (creation_locations.on_desktop)
|
| DeleteShortcutOnDesktop(shortcut_filename);
|
| if (creation_locations.in_applications_menu || creation_locations.hidden)
|
| - DeleteShortcutInApplicationsMenu(shortcut_filename);
|
| + DeleteShortcutInApplicationsMenu(shortcut_filename, base::FilePath());
|
| } else {
|
| shortcut_filename = GetWebShortcutFilename(shortcut_info.url);
|
| }
|
| @@ -746,6 +810,13 @@ bool CreateDesktopShortcut(
|
| // The 'in_applications_menu' and 'hidden' locations are actually the same
|
| // place ('applications').
|
| if (creation_locations.in_applications_menu || creation_locations.hidden) {
|
| + base::FilePath directory_filename;
|
| + std::string directory_contents;
|
| + if (!creation_locations.applications_menu_subdir.empty()) {
|
| + directory_filename = base::FilePath(kDirectoryFilename);
|
| + directory_contents = ShellIntegrationLinux::GetDirectoryFileContents(
|
| + creation_locations.applications_menu_subdir, "");
|
| + }
|
| // Set NoDisplay=true if hidden but not in_applications_menu. This will hide
|
| // the application from user-facing menus.
|
| std::string contents = ShellIntegrationLinux::GetDesktopFileContents(
|
| @@ -758,8 +829,9 @@ bool CreateDesktopShortcut(
|
| icon_name,
|
| shortcut_info.profile_path,
|
| !creation_locations.in_applications_menu);
|
| - success = CreateShortcutInApplicationsMenu(shortcut_filename, contents) &&
|
| - success;
|
| + success = CreateShortcutInApplicationsMenu(
|
| + shortcut_filename, contents, directory_filename, directory_contents) &&
|
| + success;
|
| }
|
|
|
| return success;
|
| @@ -774,7 +846,13 @@ void DeleteDesktopShortcuts(const base::FilePath& profile_path,
|
| DCHECK(!shortcut_filename.empty());
|
|
|
| DeleteShortcutOnDesktop(shortcut_filename);
|
| - DeleteShortcutInApplicationsMenu(shortcut_filename);
|
| + // Delete shortcuts from |kDirectoryFilename|.
|
| + // Note that it is possible that shortcuts were not created in the Chrome Apps
|
| + // directory (depending on the value of |applications_menu_subdir| when they
|
| + // were created). It doesn't matter: this will still delete the shortcut even
|
| + // if it isn't in the directory.
|
| + DeleteShortcutInApplicationsMenu(shortcut_filename,
|
| + base::FilePath(kDirectoryFilename));
|
| }
|
|
|
| } // namespace ShellIntegrationLinux
|
|
|