Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8924)

Unified Diff: chrome/browser/shell_integration_linux.cc

Issue 12208085: On Linux, automatically create app shortcuts on install or update. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Work around obscure crash due to bug in glib <= 2.32. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/shell_integration_linux.h ('k') | chrome/browser/shell_integration_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/shell_integration_linux.cc
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index d8f7d7bbe0aa9857d75eee0ee70184c72ca95ca2..25f7401cbd0488beec12ac7a84106310df17e202 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -394,6 +394,37 @@ ShellIntegration::DefaultWebClientState GetIsDefaultWebClient(
#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) {
+ // An empty file causes a crash with glib <= 2.32, so special case here.
+ if (shortcut_contents.empty())
+ return false;
+
+ GKeyFile* key_file = g_key_file_new();
+ GError* err = NULL;
+ if (!g_key_file_load_from_data(key_file, shortcut_contents.c_str(),
+ shortcut_contents.size(), G_KEY_FILE_NONE,
+ &err)) {
+ LOG(WARNING) << "Unable to read desktop file template: " << err->message;
+ g_error_free(err);
+ g_key_file_free(key_file);
+ return false;
+ }
+
+ bool nodisplay = false;
+ char* nodisplay_c_string = g_key_file_get_string(key_file, kDesktopEntry,
+ "NoDisplay", &err);
+ if (nodisplay_c_string) {
+ if (!g_strcmp0(nodisplay_c_string, "true"))
+ nodisplay = true;
+ g_free(nodisplay_c_string);
+ }
+
+ g_key_file_free(key_file);
+ return nodisplay;
+}
+
} // namespace
// static
@@ -457,8 +488,52 @@ std::string GetDesktopName(base::Environment* env) {
#endif
}
-bool GetDesktopShortcutTemplate(base::Environment* env,
- std::string* output) {
+ShellIntegration::ShortcutLocations GetExistingShortcutLocations(
+ base::Environment* env,
+ const base::FilePath& profile_path,
+ const std::string& extension_id) {
+ base::FilePath desktop_path;
+ // If Get returns false, just leave desktop_path empty.
+ PathService::Get(base::DIR_USER_DESKTOP, &desktop_path);
+ return GetExistingShortcutLocations(env, profile_path, extension_id,
+ desktop_path);
+}
+
+ShellIntegration::ShortcutLocations GetExistingShortcutLocations(
+ base::Environment* env,
+ const base::FilePath& profile_path,
+ const std::string& extension_id,
+ const base::FilePath& desktop_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ base::FilePath shortcut_filename = GetExtensionShortcutFilename(
+ profile_path, extension_id);
+ DCHECK(!shortcut_filename.empty());
+ ShellIntegration::ShortcutLocations locations;
+
+ // Determine whether there is a shortcut on desktop.
+ if (!desktop_path.empty()) {
+ locations.on_desktop =
+ file_util::PathExists(desktop_path.Append(shortcut_filename));
+ }
+
+ // Determine whether there is a shortcut in the applications directory.
+ std::string shortcut_contents;
+ if (GetExistingShortcutContents(env, shortcut_filename, &shortcut_contents)) {
+ // Whether this counts as "hidden" or "in_applications_menu" depends on
+ // whether it contains NoDisplay=true.
+ if (GetNoDisplayFromDesktopFile(shortcut_contents))
+ locations.hidden = true;
+ else
+ locations.in_applications_menu = true;
+ }
+
+ return locations;
+}
+
+bool GetExistingShortcutContents(base::Environment* env,
+ const base::FilePath& desktop_filename,
+ std::string* output) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
std::vector<base::FilePath> search_paths;
@@ -488,21 +563,31 @@ bool GetDesktopShortcutTemplate(base::Environment* env,
search_paths.push_back(base::FilePath("/usr/share"));
}
- std::string template_filename(GetDesktopName(env));
for (std::vector<base::FilePath>::const_iterator i = search_paths.begin();
i != search_paths.end(); ++i) {
- base::FilePath path = i->Append("applications").Append(template_filename);
- VLOG(1) << "Looking for desktop file template in " << path.value();
+ base::FilePath path = i->Append("applications").Append(desktop_filename);
+ VLOG(1) << "Looking for desktop file in " << path.value();
if (file_util::PathExists(path)) {
- VLOG(1) << "Found desktop file template at " << path.value();
+ VLOG(1) << "Found desktop file at " << path.value();
return file_util::ReadFileToString(path, output);
}
}
- LOG(ERROR) << "Could not find desktop file template.";
return false;
}
+bool GetDesktopShortcutTemplate(base::Environment* env,
+ std::string* output) {
+ base::FilePath template_filename(GetDesktopName(env));
+ if (GetExistingShortcutContents(env, template_filename, output)) {
+ return true;
+ } else {
+ LOG(ERROR) << "Could not find desktop file " << template_filename.value()
+ << ".";
+ return false;
+ }
+}
+
base::FilePath GetWebShortcutFilename(const GURL& url) {
// Use a prefix, because xdg-desktop-menu requires it.
std::string filename =
@@ -549,7 +634,8 @@ std::string GetDesktopFileContents(
const base::FilePath& extension_path,
const string16& title,
const std::string& icon_name,
- const base::FilePath& profile_path) {
+ const base::FilePath& profile_path,
+ bool no_display) {
// 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 = std::string(kXdgOpenShebang) + "\n";
@@ -650,6 +736,10 @@ std::string GetDesktopFileContents(
if (!icon_name.empty())
g_key_file_set_string(key_file, kDesktopEntry, "Icon", icon_name.c_str());
+ // Set the "NoDisplay" key.
+ if (no_display)
+ g_key_file_set_string(key_file, kDesktopEntry, "NoDisplay", "true");
+
#if defined(TOOLKIT_GTK)
std::string wmclass = web_app::GetWMClassFromAppName(app_name);
g_key_file_set_string(key_file, kDesktopEntry, "StartupWMClass",
@@ -688,7 +778,7 @@ bool CreateDesktopShortcut(
// already exist and replace them.
if (creation_locations.on_desktop)
DeleteShortcutOnDesktop(shortcut_filename);
- if (creation_locations.in_applications_menu)
+ if (creation_locations.in_applications_menu || creation_locations.hidden)
DeleteShortcutInApplicationsMenu(shortcut_filename);
} else {
shortcut_filename = GetWebShortcutFilename(shortcut_info.url);
@@ -700,24 +790,41 @@ bool CreateDesktopShortcut(
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.extension_path,
- shortcut_info.title,
- icon_name,
- shortcut_info.profile_path);
bool success = true;
- if (creation_locations.on_desktop)
+ if (creation_locations.on_desktop) {
+ std::string contents = ShellIntegrationLinux::GetDesktopFileContents(
+ shortcut_template,
+ app_name,
+ shortcut_info.url,
+ shortcut_info.extension_id,
+ shortcut_info.extension_path,
+ shortcut_info.title,
+ icon_name,
+ shortcut_info.profile_path,
+ false);
success = CreateShortcutOnDesktop(shortcut_filename, contents);
+ }
- if (creation_locations.in_applications_menu)
+ // The 'in_applications_menu' and 'hidden' locations are actually the same
+ // place ('applications').
+ if (creation_locations.in_applications_menu || creation_locations.hidden) {
+ // Set NoDisplay=true if hidden but not in_applications_menu. This will hide
+ // the application from user-facing menus.
+ std::string contents = ShellIntegrationLinux::GetDesktopFileContents(
+ shortcut_template,
+ app_name,
+ shortcut_info.url,
+ shortcut_info.extension_id,
+ shortcut_info.extension_path,
+ shortcut_info.title,
+ icon_name,
+ shortcut_info.profile_path,
+ !creation_locations.in_applications_menu);
success = CreateShortcutInApplicationsMenu(shortcut_filename, contents) &&
success;
+ }
return success;
}
« no previous file with comments | « chrome/browser/shell_integration_linux.h ('k') | chrome/browser/shell_integration_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698